@hasna/skills 0.10.27 → 0.10.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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.10.27",
20022
+ version: "0.10.30",
20023
20023
  description: "Skills library for AI coding agents",
20024
20024
  type: "module",
20025
20025
  bin: {
@@ -38184,6 +38184,8 @@ var init_native_discovery_roots = __esm(() => {
38184
38184
  ["codex", ".codex/skills"],
38185
38185
  ["codex", ".agents/skills"],
38186
38186
  ["gemini", ".gemini/skills"],
38187
+ ["sumi", ".sumi/skills"],
38188
+ ["sumi", ".sumi/skill"],
38187
38189
  ["codewith", ".codewith/skills"],
38188
38190
  ["opencode", ".config/opencode/skills"],
38189
38191
  ["opencode", ".opencode/skills"],
@@ -38201,7 +38203,7 @@ var init_native_discovery_roots = __esm(() => {
38201
38203
  // src/lib/agent-adapters.ts
38202
38204
  var INTEGRATION_AGENTS;
38203
38205
  var init_agent_adapters = __esm(() => {
38204
- INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes"];
38206
+ INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes", "sumi"];
38205
38207
  });
38206
38208
 
38207
38209
  // src/lib/agent-policy-limits.ts
@@ -47926,12 +47928,14 @@ function disablesOneSkill(entry) {
47926
47928
  return selector.length === 1 && typeof entry[selector[0]] === "string" && entry[selector[0]].length > 0;
47927
47929
  }
47928
47930
  function inference(target, version2) {
47929
- const keys = version2 === 3 ? [...INFERENCE, "service_tier", "plan_mode_reasoning_effort"] : INFERENCE;
47931
+ const keys = version2 === 3 ? [...INFERENCE, "service_tier", "plan_mode_reasoning_effort", "personality"] : INFERENCE;
47930
47932
  for (const key of keys)
47931
47933
  if (Object.hasOwn(target, key)) {
47932
47934
  const value = target[key];
47933
47935
  if (key === "model")
47934
47936
  need4(typeof value === "string" && MODEL.test(value));
47937
+ else if (key === "personality")
47938
+ need4(typeof value === "string" && ["none", "friendly", "pragmatic"].includes(value));
47935
47939
  else if (version2 === 3 && key !== "model_verbosity") {
47936
47940
  need4(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
47937
47941
  if (key !== "service_tier")
@@ -48090,6 +48094,38 @@ var init_agent_bridge = __esm(() => {
48090
48094
  // src/lib/agent-codex.ts
48091
48095
  var init_agent_codex = () => {};
48092
48096
 
48097
+ // src/lib/agent-sumi.ts
48098
+ import { existsSync as existsSync8, lstatSync as lstatSync13, realpathSync as realpathSync4 } from "fs";
48099
+ import { join as join18, resolve as resolve10 } from "path";
48100
+ function sumiConfigDirectory(home, env = process.env) {
48101
+ for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
48102
+ if (env[key] !== undefined)
48103
+ throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
48104
+ const selected = (key) => env[key]?.trim() ? env[key] : undefined;
48105
+ const expand = (value) => resolve10(value === "~" ? home : value.startsWith("~/") ? join18(home, value.slice(2)) : value);
48106
+ const explicit = selected("SUMI_CONFIG_DIR");
48107
+ const xdg = selected("XDG_CONFIG_HOME");
48108
+ const custom2 = selected("SUMI_HOME");
48109
+ const canonical5 = explicit ? expand(explicit) : xdg ? join18(expand(xdg), "sumi") : join18(custom2 ? expand(custom2) : join18(home, ".hasna-internal/sumi"), "config");
48110
+ if (explicit || xdg || custom2)
48111
+ return canonical5;
48112
+ const legacy = join18(home, ".config/sumi");
48113
+ const a = lstatSync13(canonical5, { throwIfNoEntry: false }), b = lstatSync13(legacy, { throwIfNoEntry: false });
48114
+ if (a && b && realpathSync4(canonical5) !== realpathSync4(legacy))
48115
+ throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
48116
+ const path = a ? canonical5 : b ? legacy : canonical5;
48117
+ if (!existsSync8(path))
48118
+ return path;
48119
+ const physical = realpathSync4(path);
48120
+ if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical5, legacy].includes(physical))
48121
+ throw new Error("Sumi config alias must resolve to its canonical or legacy root");
48122
+ return physical;
48123
+ }
48124
+ function sumiConfigPath(home) {
48125
+ return join18(sumiConfigDirectory(home), "sumi.json");
48126
+ }
48127
+ var init_agent_sumi = () => {};
48128
+
48093
48129
  // src/lib/agent-integration.ts
48094
48130
  var init_agent_integration = __esm(() => {
48095
48131
  init_codex_plugin_skill_controls();
@@ -48103,6 +48139,7 @@ var init_agent_integration = __esm(() => {
48103
48139
  init_agent_discovery();
48104
48140
  init_agent_adapters();
48105
48141
  init_agent_codex();
48142
+ init_agent_sumi();
48106
48143
  init_agent_hermes();
48107
48144
  init_claude_settings_witness();
48108
48145
  });
@@ -48140,17 +48177,17 @@ var init_skill_aliases = __esm(() => {
48140
48177
  });
48141
48178
 
48142
48179
  // src/lib/project-state.ts
48143
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
48144
- import { join as join18 } from "path";
48180
+ import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
48181
+ import { join as join19 } from "path";
48145
48182
  function getProjectStateDir(targetDir = process.cwd()) {
48146
- return join18(targetDir, SKILLS_PROJECT_DIR);
48183
+ return join19(targetDir, SKILLS_PROJECT_DIR);
48147
48184
  }
48148
48185
  function getProjectConfigPath(targetDir = process.cwd()) {
48149
- return join18(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
48186
+ return join19(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
48150
48187
  }
48151
48188
  function loadProjectConfig(targetDir = process.cwd()) {
48152
48189
  const path = getProjectConfigPath(targetDir);
48153
- if (!existsSync8(path))
48190
+ if (!existsSync9(path))
48154
48191
  return null;
48155
48192
  try {
48156
48193
  return normalizeProjectConfig(JSON.parse(readFileSync12(path, "utf-8")));
@@ -48261,8 +48298,8 @@ var init_project_state = __esm(() => {
48261
48298
  });
48262
48299
 
48263
48300
  // src/lib/installer.ts
48264
- import { existsSync as existsSync9, readFileSync as readFileSync13, rmSync } from "fs";
48265
- import { join as join19 } from "path";
48301
+ import { existsSync as existsSync10, readFileSync as readFileSync13, rmSync } from "fs";
48302
+ import { join as join20 } from "path";
48266
48303
  import { homedir as homedir2 } from "os";
48267
48304
  function getSkillPath(name) {
48268
48305
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
@@ -48272,7 +48309,7 @@ function getSkillPath(name) {
48272
48309
  const extensionPath = findExtensionSkillPath(skillName);
48273
48310
  if (extensionPath)
48274
48311
  return extensionPath;
48275
- return join19(getPortableSkillsRoot(), skillName);
48312
+ return join20(getPortableSkillsRoot(), skillName);
48276
48313
  }
48277
48314
  function getCanonicalSkillName(name) {
48278
48315
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -48281,7 +48318,7 @@ function installSkill(name, options = {}) {
48281
48318
  const { targetDir = process.cwd(), overwrite = false } = options;
48282
48319
  const canonicalName = getCanonicalSkillName(name);
48283
48320
  const skillName = normalizeSkillName(canonicalName);
48284
- if (!existsSync9(getSkillPath(name))) {
48321
+ if (!existsSync10(getSkillPath(name))) {
48285
48322
  const knownOfficial = Boolean(getSkill(name));
48286
48323
  return {
48287
48324
  skill: canonicalName,
@@ -48326,11 +48363,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
48326
48363
  const base = projectDir || process.cwd();
48327
48364
  switch (agent) {
48328
48365
  case "pi":
48329
- return scope === "project" ? join19(base, ".pi", "skills") : join19(homedir2(), ".pi", "agent", "skills");
48366
+ return scope === "project" ? join20(base, ".pi", "skills") : join20(homedir2(), ".pi", "agent", "skills");
48330
48367
  case "opencode":
48331
- return scope === "project" ? join19(base, ".opencode", "skills") : join19(homedir2(), ".config", "opencode", "skills");
48368
+ return scope === "project" ? join20(base, ".opencode", "skills") : join20(homedir2(), ".config", "opencode", "skills");
48332
48369
  default:
48333
- return scope === "project" ? join19(base, `.${agent}`, "skills") : join19(homedir2(), `.${agent}`, "skills");
48370
+ return scope === "project" ? join20(base, `.${agent}`, "skills") : join20(homedir2(), `.${agent}`, "skills");
48334
48371
  }
48335
48372
  }
48336
48373
  function warnMissingDependencies(name, targetDir) {
@@ -48345,8 +48382,8 @@ function warnMissingDependencies(name, targetDir) {
48345
48382
  }
48346
48383
  }
48347
48384
  function readBundledSkillVersion(name) {
48348
- const pkgPath = join19(getSkillPath(name), "package.json");
48349
- if (!existsSync9(pkgPath))
48385
+ const pkgPath = join20(getSkillPath(name), "package.json");
48386
+ if (!existsSync10(pkgPath))
48350
48387
  return "unknown";
48351
48388
  try {
48352
48389
  const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
@@ -48413,13 +48450,13 @@ var init_skill_doc_file = __esm(() => {
48413
48450
  });
48414
48451
 
48415
48452
  // src/lib/skillinfo.ts
48416
- import { existsSync as existsSync10, readFileSync as readFileSync14 } from "fs";
48417
- import { join as join20 } from "path";
48453
+ import { existsSync as existsSync11, readFileSync as readFileSync14 } from "fs";
48454
+ import { join as join21 } from "path";
48418
48455
  function isInstructionSkillDir(skillPath, meta3) {
48419
48456
  if (meta3?.kind === "instruction")
48420
48457
  return true;
48421
- const skillMdPath = join20(skillPath, "SKILL.md");
48422
- if (!existsSync10(skillMdPath))
48458
+ const skillMdPath = join21(skillPath, "SKILL.md");
48459
+ if (!existsSync11(skillMdPath))
48423
48460
  return false;
48424
48461
  try {
48425
48462
  return parseSkillFrontmatter(readFileSync14(skillMdPath, "utf-8"))?.kind === "instruction";
@@ -48429,12 +48466,12 @@ function isInstructionSkillDir(skillPath, meta3) {
48429
48466
  }
48430
48467
  function getSkillDocs(name) {
48431
48468
  const skillPath = getSkillPath(name);
48432
- if (!existsSync10(skillPath))
48469
+ if (!existsSync11(skillPath))
48433
48470
  return null;
48434
48471
  return {
48435
- skillMd: readIfExists(join20(skillPath, "SKILL.md")),
48436
- readme: readIfExists(join20(skillPath, "README.md")),
48437
- claudeMd: readIfExists(join20(skillPath, "CLAUDE.md"))
48472
+ skillMd: readIfExists(join21(skillPath, "SKILL.md")),
48473
+ readme: readIfExists(join21(skillPath, "README.md")),
48474
+ claudeMd: readIfExists(join21(skillPath, "CLAUDE.md"))
48438
48475
  };
48439
48476
  }
48440
48477
  function getSkillBestDoc(name, file2) {
@@ -48446,18 +48483,18 @@ function getSkillBestDoc(name, file2) {
48446
48483
  }
48447
48484
  function getSkillRequirements(name) {
48448
48485
  const skillPath = getSkillPath(name);
48449
- if (!existsSync10(skillPath))
48486
+ if (!existsSync11(skillPath))
48450
48487
  return null;
48451
48488
  const texts = [];
48452
48489
  for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
48453
- const content = readIfExists(join20(skillPath, file2));
48490
+ const content = readIfExists(join21(skillPath, file2));
48454
48491
  if (content)
48455
48492
  texts.push(content);
48456
48493
  }
48457
48494
  const meta3 = getSkill(name);
48458
48495
  let dependencies = {};
48459
48496
  try {
48460
- dependencies = JSON.parse(readFileSync14(join20(skillPath, "package.json"), "utf8")).dependencies || {};
48497
+ dependencies = JSON.parse(readFileSync14(join21(skillPath, "package.json"), "utf8")).dependencies || {};
48461
48498
  } catch {}
48462
48499
  return getSkillRequirementsFromContent(name, texts, dependencies, meta3);
48463
48500
  }
@@ -48510,7 +48547,7 @@ async function runSkill(name, args, options = {}) {
48510
48547
  const meta3 = getSkill(name);
48511
48548
  const canonicalName = meta3?.name ?? name;
48512
48549
  const skillPath = getSkillPath(canonicalName);
48513
- if (!existsSync10(skillPath)) {
48550
+ if (!existsSync11(skillPath)) {
48514
48551
  return { exitCode: 1, error: `Skill '${name}' not found` };
48515
48552
  }
48516
48553
  if (isInstructionSkillDir(skillPath, meta3)) {
@@ -48519,8 +48556,8 @@ async function runSkill(name, args, options = {}) {
48519
48556
  error: `Skill '${name}' is an instruction skill (kind: instruction) and is not runnable. Instruction skills are consumed by coding agents via SKILL.md, not executed with 'skills run'.`
48520
48557
  };
48521
48558
  }
48522
- const pkgPath = join20(skillPath, "package.json");
48523
- if (!existsSync10(pkgPath)) {
48559
+ const pkgPath = join21(skillPath, "package.json");
48560
+ if (!existsSync11(pkgPath)) {
48524
48561
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
48525
48562
  }
48526
48563
  let entryPoint2;
@@ -48539,12 +48576,12 @@ async function runSkill(name, args, options = {}) {
48539
48576
  } catch {
48540
48577
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
48541
48578
  }
48542
- const entryPath = join20(skillPath, entryPoint2);
48543
- if (!existsSync10(entryPath)) {
48579
+ const entryPath = join21(skillPath, entryPoint2);
48580
+ if (!existsSync11(entryPath)) {
48544
48581
  return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
48545
48582
  }
48546
48583
  const env = { ...process.env, ...options.env };
48547
- if (!existsSync10(join20(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
48584
+ if (!existsSync11(join21(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
48548
48585
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
48549
48586
  if (failure)
48550
48587
  return failure;
@@ -48570,7 +48607,7 @@ async function runSkill(name, args, options = {}) {
48570
48607
  function detectProjectSkills(cwd = process.cwd()) {
48571
48608
  let pkg;
48572
48609
  try {
48573
- pkg = JSON.parse(readFileSync14(join20(cwd, "package.json"), "utf8"));
48610
+ pkg = JSON.parse(readFileSync14(join21(cwd, "package.json"), "utf8"));
48574
48611
  } catch {
48575
48612
  return { detected: [], recommended: [] };
48576
48613
  }
@@ -48608,7 +48645,7 @@ function extractEnvVars(text2) {
48608
48645
  }
48609
48646
  function readIfExists(path) {
48610
48647
  try {
48611
- if (existsSync10(path)) {
48648
+ if (existsSync11(path)) {
48612
48649
  return readFileSync14(path, "utf-8");
48613
48650
  }
48614
48651
  } catch {}
@@ -48665,6 +48702,8 @@ var init_selected_document = __esm(() => {
48665
48702
  async function resolveSelectionContext(profileId, options = {}) {
48666
48703
  const sessionState = options.sessionId ? readSkillSessionSnapshotIfExists(options.sessionId, options) : null;
48667
48704
  const session = sessionState?.receipt ?? null;
48705
+ if (options.nativeParentSessionId !== undefined && session && (session.parent?.sessionId ?? null) !== options.nativeParentSessionId)
48706
+ throw new SkillSelectionError("SESSION_PARENT_MISMATCH", "The native session id is already bound to different parent custody.");
48668
48707
  const parentState = !session && options.parentSessionId ? readSkillSessionSnapshotIfExists(options.parentSessionId, options) : null;
48669
48708
  if (!session && options.parentSessionId && !parentState) {
48670
48709
  throw new SkillSelectionError("SESSION_PARENT_NOT_FOUND", "A child Skills session requires an existing parent receipt so its inherited pin can be bound exactly.");
@@ -48858,11 +48897,11 @@ var init_plugin_projection = __esm(() => {
48858
48897
  });
48859
48898
 
48860
48899
  // src/lib/plugin-projection-store.ts
48861
- import { constants as constants7, closeSync as closeSync10, fchmodSync, fstatSync as fstatSync10, fsyncSync as fsyncSync2, linkSync, lstatSync as lstatSync13, mkdirSync as mkdirSync6, openSync as openSync10, opendirSync as opendirSync2, readSync as readSync6, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
48862
- import { dirname as dirname11, isAbsolute as isAbsolute9, join as join21, parse as parse9, resolve as resolve10 } from "path";
48900
+ import { constants as constants7, closeSync as closeSync10, fchmodSync, fstatSync as fstatSync10, fsyncSync as fsyncSync2, linkSync, lstatSync as lstatSync14, mkdirSync as mkdirSync6, openSync as openSync10, opendirSync as opendirSync2, readSync as readSync6, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
48901
+ import { dirname as dirname11, isAbsolute as isAbsolute9, join as join22, parse as parse9, resolve as resolve11 } from "path";
48863
48902
  function stat(path) {
48864
48903
  try {
48865
- return lstatSync13(path, { bigint: true });
48904
+ return lstatSync14(path, { bigint: true });
48866
48905
  } catch (error61) {
48867
48906
  if (missing(error61))
48868
48907
  return null;
@@ -48870,7 +48909,7 @@ function stat(path) {
48870
48909
  }
48871
48910
  }
48872
48911
  function canonical5(path) {
48873
- pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute9(path) && resolve10(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
48912
+ pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute9(path) && resolve11(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
48874
48913
  }
48875
48914
  function owner(stats, system = false) {
48876
48915
  const current = uid();
@@ -48885,7 +48924,7 @@ function ancestors(path, create = false) {
48885
48924
  let current = filesystemRoot;
48886
48925
  for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
48887
48926
  if (segment)
48888
- current = join21(current, segment);
48927
+ current = join22(current, segment);
48889
48928
  let currentStat = stat(current);
48890
48929
  if (!currentStat && create) {
48891
48930
  try {
@@ -48993,7 +49032,7 @@ function snapshotPluginTree(root, options = {}) {
48993
49032
  pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
48994
49033
  const path = relative5 ? `${relative5}/${name}` : name;
48995
49034
  pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
48996
- const absolute = join21(directory, name), entryStat = stat(absolute);
49035
+ const absolute = join22(directory, name), entryStat = stat(absolute);
48997
49036
  pluginNeed(entryStat, "Plugin tree member disappeared");
48998
49037
  if (relative5 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
48999
49038
  const bytes2 = readBytes(absolute, 32, "native-pin");
@@ -49010,7 +49049,7 @@ function snapshotPluginTree(root, options = {}) {
49010
49049
  directories.push({ path: absolute, stat: entryStat, names: pins });
49011
49050
  for (const pin of pins) {
49012
49051
  pluginNeed(/^[1-9][0-9]{0,9}$/.test(pin) && Number(pin) <= 2147483647, "Unrecognized native plugin pin name");
49013
- const pinPath = join21(absolute, pin), pinStat = stat(pinPath);
49052
+ const pinPath = join22(absolute, pin), pinStat = stat(pinPath);
49014
49053
  pluginNeed(pinStat, "Native plugin pin disappeared");
49015
49054
  const bytes2 = readBytes(pinPath, 4096, "native-pin");
49016
49055
  let value;
@@ -49107,7 +49146,7 @@ var init_selected_manifest = __esm(() => {
49107
49146
  });
49108
49147
 
49109
49148
  // src/lib/plugin-admission.ts
49110
- import { isAbsolute as isAbsolute10, join as join22, resolve as resolve11 } from "path";
49149
+ import { isAbsolute as isAbsolute10, join as join23, resolve as resolve12 } from "path";
49111
49150
  function validatePluginTarget(value) {
49112
49151
  pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
49113
49152
  pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
@@ -49117,7 +49156,7 @@ function validatePluginTarget(value) {
49117
49156
  for (const registration of value.registrations) {
49118
49157
  pluginKeys(registration, ["scope", "projectPath"]);
49119
49158
  pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
49120
- pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute10(registration.projectPath) && resolve11(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
49159
+ pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute10(registration.projectPath) && resolve12(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
49121
49160
  const key = JSON.stringify([registration.scope, registration.projectPath]);
49122
49161
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
49123
49162
  scopes.add(key);
@@ -49125,7 +49164,7 @@ function validatePluginTarget(value) {
49125
49164
  for (const key of ["native", "resolver"]) {
49126
49165
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
49127
49166
  pluginText(value[key].executable);
49128
- pluginNeed(isAbsolute10(value[key].executable) && resolve11(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
49167
+ pluginNeed(isAbsolute10(value[key].executable) && resolve12(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
49129
49168
  pluginDigest(value[key].digest);
49130
49169
  }
49131
49170
  pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
@@ -49268,12 +49307,12 @@ function pluginResolverCommand(binding) {
49268
49307
  }
49269
49308
  function pluginBindingPath(storeRoot, id) {
49270
49309
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
49271
- return join22(storeRoot, "bindings", `${id}.json`);
49310
+ return join23(storeRoot, "bindings", `${id}.json`);
49272
49311
  }
49273
49312
  function pluginReceiptPath(storeRoot, id, digest) {
49274
49313
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
49275
49314
  pluginDigest(digest);
49276
- return join22(storeRoot, "receipts", id, `${digest.slice(7)}.json`);
49315
+ return join23(storeRoot, "receipts", id, `${digest.slice(7)}.json`);
49277
49316
  }
49278
49317
  function readPluginBinding(storeRoot, id) {
49279
49318
  const value = readPluginJson(pluginBindingPath(storeRoot, id));
@@ -49293,7 +49332,7 @@ function readPluginAdmissionReceipt(storeRoot, id, digest) {
49293
49332
  pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest, "Plugin receipt identity differs from its filename");
49294
49333
  const binding = readPluginBinding(storeRoot, id);
49295
49334
  pluginNeed(canonicalJson(binding) === canonicalJson(receipt.plan.binding) && receipt.plan.sourceCommand === pluginResolverCommand(binding), "Plugin receipt binding changed");
49296
- pluginNeed(receipt.materializedPath === join22(storeRoot, "objects", id, digest.slice(7)), "Plugin receipt points outside its immutable materialization");
49335
+ pluginNeed(receipt.materializedPath === join23(storeRoot, "objects", id, digest.slice(7)), "Plugin receipt points outside its immutable materialization");
49297
49336
  pluginText(receipt.admittedAt, 64);
49298
49337
  pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
49299
49338
  return receipt;
@@ -49310,8 +49349,8 @@ var init_plugin_admission = __esm(() => {
49310
49349
  });
49311
49350
 
49312
49351
  // src/lib/plugin-discovery.ts
49313
- import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSync11, lstatSync as lstatSync14, openSync as openSync11, opendirSync as opendirSync3, readSync as readSync7 } from "fs";
49314
- import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute11, join as join23, resolve as resolve12 } from "path";
49352
+ import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSync11, lstatSync as lstatSync15, openSync as openSync11, opendirSync as opendirSync3, readSync as readSync7 } from "fs";
49353
+ import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute11, join as join24, resolve as resolve13 } from "path";
49315
49354
  function validateManagedPluginWitnesses(value) {
49316
49355
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
49317
49356
  const seen = new Set;
@@ -49320,21 +49359,21 @@ function validateManagedPluginWitnesses(value) {
49320
49359
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
49321
49360
  seen.add(item.bindingId);
49322
49361
  pluginText(item.storeRoot);
49323
- pluginNeed(isAbsolute11(item.storeRoot) && resolve12(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
49362
+ pluginNeed(isAbsolute11(item.storeRoot) && resolve13(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
49324
49363
  }
49325
49364
  }
49326
49365
  function safe3(path) {
49327
49366
  pluginText(path);
49328
- pluginNeed(isAbsolute11(path) && resolve12(path) === path, "Invalid plugin registry path");
49367
+ pluginNeed(isAbsolute11(path) && resolve13(path) === path, "Invalid plugin registry path");
49329
49368
  for (let at = path;; at = dirname12(at)) {
49330
- pluginNeed(!lstatSync14(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
49369
+ pluginNeed(!lstatSync15(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
49331
49370
  if (at === dirname12(at))
49332
49371
  break;
49333
49372
  }
49334
49373
  }
49335
49374
  function readRegistry(path) {
49336
49375
  safe3(path);
49337
- const initial = lstatSync14(path);
49376
+ const initial = lstatSync15(path);
49338
49377
  pluginNeed(initial.isFile() && initial.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
49339
49378
  const fd = openSync11(path, constants8.O_RDONLY | constants8.O_NOFOLLOW | constants8.O_NONBLOCK);
49340
49379
  try {
@@ -49348,7 +49387,7 @@ function readRegistry(path) {
49348
49387
  break;
49349
49388
  length += count;
49350
49389
  }
49351
- const after = fstatSync11(fd), current = lstatSync14(path);
49390
+ const after = fstatSync11(fd), current = lstatSync15(path);
49352
49391
  safe3(path);
49353
49392
  pluginNeed(length <= 1024 * 1024 && length === opened.size && after.size === opened.size && after.mtimeMs === opened.mtimeMs && after.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "Plugin registry changed during read");
49354
49393
  let value;
@@ -49378,7 +49417,7 @@ function hashManagedPluginRegistry(path, managed) {
49378
49417
  seen.add(target.pluginId);
49379
49418
  const rows = plugins[target.pluginId];
49380
49419
  pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
49381
- const [name, market] = target.pluginId.split("@"), cacheRoot = join23(dirname12(path), "cache", market, name);
49420
+ const [name, market] = target.pluginId.split("@"), cacheRoot = join24(dirname12(path), "cache", market, name);
49382
49421
  const scopes = new Set, approvals = new Map, currentFiles = new Map;
49383
49422
  plugins[target.pluginId] = rows.map((row) => {
49384
49423
  pluginNeed(pluginObject(row), "Invalid managed plugin registration");
@@ -49391,7 +49430,7 @@ function hashManagedPluginRegistry(path, managed) {
49391
49430
  pluginText(row.sourceProducerPath);
49392
49431
  pluginText(row.lastUpdated, 64);
49393
49432
  pluginNeed(Number.isFinite(Date.parse(row.lastUpdated)), "Invalid managed plugin update timestamp");
49394
- pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join23(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
49433
+ pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join24(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
49395
49434
  const approval = (producer) => {
49396
49435
  pluginText(producer);
49397
49436
  const digest = `sha256:${basename6(producer)}`;
@@ -49421,7 +49460,7 @@ function hashManagedPluginRegistry(path, managed) {
49421
49460
  return Object.fromEntries(Object.entries(row).filter(([key]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key)));
49422
49461
  });
49423
49462
  safe3(cacheRoot);
49424
- const before = lstatSync14(cacheRoot);
49463
+ const before = lstatSync15(cacheRoot);
49425
49464
  pluginNeed(before.isDirectory(), "Invalid managed plugin cache root");
49426
49465
  const directory = opendirSync3(cacheRoot), names = [];
49427
49466
  try {
@@ -49434,17 +49473,17 @@ function hashManagedPluginRegistry(path, managed) {
49434
49473
  directory.closeSync();
49435
49474
  }
49436
49475
  for (const version2 of names.sort()) {
49437
- const files = pluginFileWitnesses(snapshotPluginTree(join23(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
49476
+ const files = pluginFileWitnesses(snapshotPluginTree(join24(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
49438
49477
  verifiedBytes += files.reduce((total, file2) => total + file2.size, 0);
49439
49478
  pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
49440
49479
  const serialized = JSON.stringify(files);
49441
- const expected = currentFiles.get(join23(cacheRoot, version2));
49480
+ const expected = currentFiles.get(join24(cacheRoot, version2));
49442
49481
  pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
49443
49482
  pluginNeed([...approvals.values()].some((receipt) => nativeVersionMatches(version2, receipt) && JSON.stringify(receipt.plan.files) === serialized), "A retained native plugin cache version differs from every approved projection");
49444
49483
  }
49445
49484
  for (const row of rows)
49446
49485
  pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
49447
- const after = lstatSync14(cacheRoot);
49486
+ const after = lstatSync15(cacheRoot);
49448
49487
  safe3(cacheRoot);
49449
49488
  pluginNeed(before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs, "Managed cache version membership changed during verification");
49450
49489
  }
@@ -49459,19 +49498,19 @@ var init_plugin_discovery = __esm(() => {
49459
49498
 
49460
49499
  // src/lib/claude-marketplace-registry.ts
49461
49500
  import { createHash as createHash13 } from "crypto";
49462
- import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync15, openSync as openSync12, readSync as readSync8 } from "fs";
49463
- import { basename as basename7, dirname as dirname13, isAbsolute as isAbsolute12, resolve as resolve13 } from "path";
49501
+ import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync16, openSync as openSync12, readSync as readSync8 } from "fs";
49502
+ import { basename as basename7, dirname as dirname13, isAbsolute as isAbsolute12, resolve as resolve14 } from "path";
49464
49503
  function need5(value, reason) {
49465
49504
  if (!value)
49466
49505
  throw new Error(`Claude marketplace registry ${reason}`);
49467
49506
  }
49468
49507
  function absolutePath2(value) {
49469
- need5(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value) && resolve13(value) === value, "requires a normalized absolute path");
49508
+ need5(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value) && resolve14(value) === value, "requires a normalized absolute path");
49470
49509
  }
49471
49510
  function parents2(path) {
49472
49511
  const result = [];
49473
49512
  for (let at = dirname13(path);; at = dirname13(at)) {
49474
- const stat2 = lstatSync15(at, { bigint: true });
49513
+ const stat2 = lstatSync16(at, { bigint: true });
49475
49514
  need5(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
49476
49515
  result.push([at, stat2]);
49477
49516
  if (at === dirname13(at))
@@ -49482,7 +49521,7 @@ function readRegistry2(path, budget) {
49482
49521
  absolutePath2(path);
49483
49522
  need5(basename7(path) === "known_marketplaces.json", "requires known_marketplaces.json");
49484
49523
  need5(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
49485
- const ancestors2 = parents2(path), initial = lstatSync15(path, { bigint: true });
49524
+ const ancestors2 = parents2(path), initial = lstatSync16(path, { bigint: true });
49486
49525
  need5(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
49487
49526
  need5(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
49488
49527
  const fd = openSync12(path, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
@@ -49497,10 +49536,10 @@ function readRegistry2(path, budget) {
49497
49536
  break;
49498
49537
  length += count;
49499
49538
  }
49500
- const after = fstatSync12(fd, { bigint: true }), current = lstatSync15(path, { bigint: true });
49539
+ const after = fstatSync12(fd, { bigint: true }), current = lstatSync16(path, { bigint: true });
49501
49540
  need5(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
49502
49541
  for (const [ancestor, before] of ancestors2) {
49503
- const now = lstatSync15(ancestor, { bigint: true });
49542
+ const now = lstatSync16(ancestor, { bigint: true });
49504
49543
  need5(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
49505
49544
  }
49506
49545
  budget.remaining -= length;
@@ -49640,7 +49679,7 @@ var init_claude_marketplace_registry = __esm(() => {
49640
49679
  });
49641
49680
 
49642
49681
  // src/lib/codex-hook-trust-files.ts
49643
- import { closeSync as closeSync13, constants as constants10, fstatSync as fstatSync13, fsyncSync as fsyncSync3, lstatSync as lstatSync16, openSync as openSync13, readSync as readSync9, writeFileSync as writeFileSync5 } from "fs";
49682
+ import { closeSync as closeSync13, constants as constants10, fstatSync as fstatSync13, fsyncSync as fsyncSync3, lstatSync as lstatSync17, openSync as openSync13, readSync as readSync9, writeFileSync as writeFileSync5 } from "fs";
49644
49683
  import { createHash as createHash14 } from "crypto";
49645
49684
  import { dirname as dirname14 } from "path";
49646
49685
  function need6(value, code) {
@@ -49649,7 +49688,7 @@ function need6(value, code) {
49649
49688
  }
49650
49689
  function safeParents(file2) {
49651
49690
  for (let p = dirname14(file2);; p = dirname14(p)) {
49652
- const s = lstatSync16(p);
49691
+ const s = lstatSync17(p);
49653
49692
  need6(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
49654
49693
  need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
49655
49694
  if (dirname14(p) === p)
@@ -49659,7 +49698,7 @@ function safeParents(file2) {
49659
49698
  function snapshot(file2, privateFile = false, options = {}) {
49660
49699
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
49661
49700
  safeParents(file2);
49662
- const initial = lstatSync16(file2, { bigint: true });
49701
+ const initial = lstatSync17(file2, { bigint: true });
49663
49702
  need6(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
49664
49703
  need6(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
49665
49704
  const fd = openSync13(file2, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
@@ -49674,7 +49713,7 @@ function snapshot(file2, privateFile = false, options = {}) {
49674
49713
  break;
49675
49714
  length += n2;
49676
49715
  }
49677
- need6(length === Number(before.size) && sameStat(before, fstatSync13(fd, { bigint: true })) && sameStat(before, lstatSync16(file2, { bigint: true })), "INPUT_CHANGED");
49716
+ need6(length === Number(before.size) && sameStat(before, fstatSync13(fd, { bigint: true })) && sameStat(before, lstatSync17(file2, { bigint: true })), "INPUT_CHANGED");
49678
49717
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
49679
49718
  return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash14("sha256").update(content).digest("hex") };
49680
49719
  } finally {
@@ -49729,8 +49768,8 @@ var init_codex_hook_discovery_recovery = __esm(() => {
49729
49768
 
49730
49769
  // src/lib/agent-discovery.ts
49731
49770
  import { createHash as createHash16 } from "crypto";
49732
- import { lstatSync as lstatSync17, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync4 } from "fs";
49733
- import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute13, join as join24, resolve as resolve14, sep as sep5 } from "path";
49771
+ import { lstatSync as lstatSync18, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync5 } from "fs";
49772
+ import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute13, join as join25, resolve as resolve15, sep as sep5 } from "path";
49734
49773
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
49735
49774
  function parseConfig(text2, path, toml = false) {
49736
49775
  try {
@@ -49746,7 +49785,7 @@ function safe4(path) {
49746
49785
  if (!isAbsolute13(path) || path.includes("\x00"))
49747
49786
  throw new Error("Expected an absolute native discovery path");
49748
49787
  for (let cursor = path;; cursor = dirname15(cursor)) {
49749
- if (lstatSync17(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
49788
+ if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
49750
49789
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
49751
49790
  if (dirname15(cursor) === cursor)
49752
49791
  break;
@@ -49756,7 +49795,7 @@ function read(path, changes) {
49756
49795
  safe4(path);
49757
49796
  if (changes?.has(path))
49758
49797
  return changes.get(path);
49759
- const stat2 = lstatSync17(path, { throwIfNoEntry: false });
49798
+ const stat2 = lstatSync18(path, { throwIfNoEntry: false });
49760
49799
  if (!stat2)
49761
49800
  return null;
49762
49801
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
@@ -49867,12 +49906,12 @@ function codexInstallationRoots(binding) {
49867
49906
  if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version !== "codex-cli 0.160.0" || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
49868
49907
  throw new Error("Invalid native installation input proof");
49869
49908
  const cache = dirname15(dirname15(proof.plugins[0].pluginParent));
49870
- const config2 = join24(dirname15(dirname15(cache)), "config.toml"), home = dirname15(dirname15(dirname15(cache)));
49909
+ const config2 = join25(dirname15(dirname15(cache)), "config.toml"), home = dirname15(dirname15(dirname15(cache)));
49871
49910
  const configSource = binding.sources.find((source) => source.path === config2 && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
49872
- const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join24(home, path));
49911
+ const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join25(home, path));
49873
49912
  if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep5) || input2.sourceRoot.startsWith(root + sep5)) || binding.sources.some((source) => basename8(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep5)))))
49874
49913
  throw new Error("Native installation input overlaps configuration or loading roots");
49875
- if (proof.plugins.some((input2) => dirname15(dirname15(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join24(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
49914
+ if (proof.plugins.some((input2) => dirname15(dirname15(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join25(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
49876
49915
  throw new Error("Missing native installation input source witness");
49877
49916
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
49878
49917
  const text2 = read(path);
@@ -49890,10 +49929,12 @@ function assertMarketplaceBinding(binding, source) {
49890
49929
  throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
49891
49930
  }
49892
49931
  function agentDiscoveryConfigPath(home, agent) {
49893
- return join24(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
49932
+ if (agent === "sumi")
49933
+ return sumiConfigPath(home);
49934
+ return join25(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
49894
49935
  }
49895
49936
  function resolveAgentDiscovery(options) {
49896
- const canonical6 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
49937
+ const canonical6 = options.canonical ?? resolve15, home = resolve15(options.home), agent = options.agent;
49897
49938
  const sources = [], roots = new Set, builtinNames = [];
49898
49939
  const witness = (path, format, fields2) => {
49899
49940
  const source = { path: canonical6(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
@@ -49904,13 +49945,49 @@ function resolveAgentDiscovery(options) {
49904
49945
  if (agent === "hermes")
49905
49946
  assertHermesEnvironment(home);
49906
49947
  const configPath = agentDiscoveryConfigPath(home, agent);
49907
- const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : ["version"]);
49948
+ const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? ["skills", "plugin", "plugins", "permissions"] : ["version"]);
49908
49949
  const config2 = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
49909
49950
  const unresolved = (detail) => {
49910
49951
  throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
49911
49952
  };
49953
+ if (agent === "sumi") {
49954
+ const directory = sumiConfigDirectory(home);
49955
+ if (witness(join25(directory, "sumi.jsonc")) !== null)
49956
+ unresolved("JSONC configuration requires a supported format adapter");
49957
+ for (const root of [directory, join25(home, ".claude"), join25(home, ".agents")])
49958
+ for (const name of ["skill", "skills"])
49959
+ roots.add(join25(root, name));
49960
+ if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
49961
+ unresolved("skills must be a string array");
49962
+ for (const value of config2.skills ?? []) {
49963
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute13(value) || value.startsWith("~/")))
49964
+ unresolved("remote or relative skill sources need a dedicated discovery adapter");
49965
+ roots.add(value.startsWith("~/") ? join25(home, value.slice(2)) : value);
49966
+ }
49967
+ for (const key of ["plugin", "plugins"])
49968
+ if (config2[key] !== undefined && !Array.isArray(config2[key]))
49969
+ unresolved(`${key} must be an array`);
49970
+ const plugins = [join25(directory, "plugin"), join25(directory, "plugins")];
49971
+ for (const path of plugins) {
49972
+ safe4(path);
49973
+ if (lstatSync18(path, { throwIfNoEntry: false })?.isDirectory())
49974
+ for (const name of readdirSync7(path).sort()) {
49975
+ if (name === "skills-cli.js" && path === plugins[1])
49976
+ continue;
49977
+ const target = join25(path, name);
49978
+ if (!lstatSync18(target).isFile())
49979
+ unresolved("local plugin packages need a dedicated discovery adapter");
49980
+ witness(target);
49981
+ }
49982
+ }
49983
+ for (const root of roots) {
49984
+ safe4(root);
49985
+ if (lstatSync18(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(root).some((name) => name.endsWith(".md")))
49986
+ unresolved("flat markdown skills require a dedicated native migration adapter");
49987
+ }
49988
+ }
49912
49989
  if (agent === "hermes") {
49913
- const profile = witness(join24(home, ".hermes/active_profile"));
49990
+ const profile = witness(join25(home, ".hermes/active_profile"));
49914
49991
  if (profile?.trim() && profile.trim() !== "default")
49915
49992
  unresolved("a non-default profile is active");
49916
49993
  const declared = config2.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -49924,7 +50001,7 @@ function resolveAgentDiscovery(options) {
49924
50001
  continue;
49925
50002
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
49926
50003
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
49927
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join24(home, normalized.slice(2)) : resolve14(home, ".hermes", normalized);
50004
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join25(home, normalized.slice(2)) : resolve15(home, ".hermes", normalized);
49928
50005
  safe4(path);
49929
50006
  roots.add(path);
49930
50007
  }
@@ -49933,8 +50010,8 @@ function resolveAgentDiscovery(options) {
49933
50010
  const executable = Bun.which("gemini");
49934
50011
  if (executable) {
49935
50012
  let packageRoot;
49936
- for (let directory = dirname15(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname15(directory), depth++) {
49937
- const path = join24(directory, "package.json"), raw = read(path);
50013
+ for (let directory = dirname15(realpathSync5(executable)), depth = 0;depth < 8; directory = dirname15(directory), depth++) {
50014
+ const path = join25(directory, "package.json"), raw = read(path);
49938
50015
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
49939
50016
  packageRoot = directory;
49940
50017
  witness(path);
@@ -49945,12 +50022,12 @@ function resolveAgentDiscovery(options) {
49945
50022
  }
49946
50023
  if (!packageRoot)
49947
50024
  unresolved("installed Gemini package layout is not recognized");
49948
- const builtinRoot = join24(packageRoot, "bundle/builtin");
50025
+ const builtinRoot = join25(packageRoot, "bundle/builtin");
49949
50026
  safe4(builtinRoot);
49950
- if (!lstatSync17(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
50027
+ if (!lstatSync18(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
49951
50028
  unresolved("installed Gemini builtin root is missing");
49952
50029
  for (const name of readdirSync7(builtinRoot).sort()) {
49953
- const text2 = witness(join24(builtinRoot, name, "SKILL.md"));
50030
+ const text2 = witness(join25(builtinRoot, name, "SKILL.md"));
49954
50031
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
49955
50032
  if (!match?.[1] || builtinNames.includes(match[1]))
49956
50033
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -49992,39 +50069,39 @@ function resolveAgentDiscovery(options) {
49992
50069
  function plugin(root) {
49993
50070
  root = canonical6(root);
49994
50071
  safe4(root);
49995
- const manifestPath = join24(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
50072
+ const manifestPath = join25(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
49996
50073
  const raw = witness(manifestPath);
49997
50074
  if (raw === null)
49998
50075
  unresolved("plugin manifest missing");
49999
50076
  const manifest = parseConfig(raw, manifestPath);
50000
- const hooks = witness(join24(root, "hooks/hooks.json"));
50077
+ const hooks = witness(join25(root, "hooks/hooks.json"));
50001
50078
  if (manifest.hooks !== undefined || hooks !== null)
50002
50079
  unresolved("plugin hooks require a separate no-skill-injection review");
50003
- const commands = join24(root, "commands");
50080
+ const commands = join25(root, "commands");
50004
50081
  safe4(commands);
50005
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
50082
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
50006
50083
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
50007
- const rootSkill = witness(join24(root, "SKILL.md"));
50084
+ const rootSkill = witness(join25(root, "SKILL.md"));
50008
50085
  if (rootSkill !== null)
50009
50086
  roots.add(root);
50010
50087
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
50011
50088
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
50012
50089
  unresolved("unsupported plugin skill paths");
50013
50090
  if (agent === "claude")
50014
- roots.add(join24(root, "skills"));
50091
+ roots.add(join25(root, "skills"));
50015
50092
  for (const value of declared) {
50016
- const path = resolve14(root, value);
50093
+ const path = resolve15(root, value);
50017
50094
  if (path !== root && !path.startsWith(root + sep5))
50018
50095
  unresolved("plugin skill path escapes its root");
50019
50096
  roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname15(path) : path);
50020
50097
  }
50021
50098
  }
50022
50099
  if (agent === "claude") {
50023
- const registrations = witness(join24(home, ".claude/plugins/installed_plugins.json"));
50024
- const installed = registrations === null ? {} : parseConfig(registrations, join24(home, ".claude/plugins/installed_plugins.json")).plugins;
50025
- const commands = canonical6(join24(home, ".claude/commands"));
50100
+ const registrations = witness(join25(home, ".claude/plugins/installed_plugins.json"));
50101
+ const installed = registrations === null ? {} : parseConfig(registrations, join25(home, ".claude/plugins/installed_plugins.json")).plugins;
50102
+ const commands = canonical6(join25(home, ".claude/commands"));
50026
50103
  safe4(commands);
50027
- if (lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
50104
+ if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
50028
50105
  unresolved("legacy home command discovery requires a dedicated format adapter");
50029
50106
  for (const [id, enabled] of Object.entries(config2.enabledPlugins ?? {})) {
50030
50107
  if (enabled === false)
@@ -50046,16 +50123,16 @@ function resolveAgentDiscovery(options) {
50046
50123
  const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
50047
50124
  if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute13(market.source))
50048
50125
  unresolved("enabled plugin marketplace is not an explicit local source");
50049
- const catalogText = witness(join24(market.source, ".agents/plugins/marketplace.json"));
50126
+ const catalogText = witness(join25(market.source, ".agents/plugins/marketplace.json"));
50050
50127
  if (catalogText === null)
50051
50128
  unresolved("marketplace catalog missing");
50052
- const catalog = parseConfig(catalogText, join24(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
50129
+ const catalog = parseConfig(catalogText, join25(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
50053
50130
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
50054
50131
  unresolved("plugin catalog source is missing or ambiguous");
50055
- plugin(resolve14(market.source, matches[0].source.path));
50132
+ plugin(resolve15(market.source, matches[0].source.path));
50056
50133
  }
50057
50134
  } else if (agent === "opencode") {
50058
- if (witness(join24(home, ".config/opencode/opencode.jsonc")) !== null || witness(join24(home, ".config/opencode/config.json")) !== null)
50135
+ if (witness(join25(home, ".config/opencode/opencode.jsonc")) !== null || witness(join25(home, ".config/opencode/config.json")) !== null)
50059
50136
  unresolved("additional config layers require review");
50060
50137
  if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
50061
50138
  unresolved("external plugin or remote skill source");
@@ -50064,14 +50141,17 @@ function resolveAgentDiscovery(options) {
50064
50141
  unresolved("relative or malformed added skill root");
50065
50142
  roots.add(path);
50066
50143
  }
50067
- const localPlugins = join24(home, ".config/opencode/plugins");
50144
+ const localPlugins = join25(home, ".config/opencode/plugins");
50068
50145
  safe4(localPlugins);
50069
- if (lstatSync17(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
50146
+ if (lstatSync18(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
50070
50147
  unresolved("additional local plugin hooks require review");
50148
+ } else if (agent === "sumi") {
50149
+ if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical6(configPath) && source.path !== canonical6(join25(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
50150
+ unresolved("external or foreign local plugins require review");
50071
50151
  } else if (agent === "hermes") {
50072
- for (const directory of [join24(home, ".hermes/plugins"), join24(home, ".hermes/hermes-agent")]) {
50152
+ for (const directory of [join25(home, ".hermes/plugins"), join25(home, ".hermes/hermes-agent")]) {
50073
50153
  safe4(directory);
50074
- if (lstatSync17(directory, { throwIfNoEntry: false }))
50154
+ if (lstatSync18(directory, { throwIfNoEntry: false }))
50075
50155
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
50076
50156
  }
50077
50157
  if (Bun.which("hermes") || Object.keys(config2.plugins ?? {}).length)
@@ -50079,24 +50159,24 @@ function resolveAgentDiscovery(options) {
50079
50159
  } else if (agent === "gemini") {
50080
50160
  if (Object.keys(config2.extensions ?? {}).length || config2.skills?.paths?.length)
50081
50161
  unresolved("custom extension or skill paths");
50082
- const directory = join24(home, ".gemini/extensions");
50162
+ const directory = join25(home, ".gemini/extensions");
50083
50163
  safe4(directory);
50084
- if (lstatSync17(directory, { throwIfNoEntry: false }))
50164
+ if (lstatSync18(directory, { throwIfNoEntry: false }))
50085
50165
  for (const name of readdirSync7(directory)) {
50086
- const root = join24(directory, name);
50166
+ const root = join25(directory, name);
50087
50167
  safe4(root);
50088
- if (!lstatSync17(root)?.isDirectory())
50168
+ if (!lstatSync18(root)?.isDirectory())
50089
50169
  continue;
50090
- const raw = witness(join24(root, "gemini-extension.json"));
50170
+ const raw = witness(join25(root, "gemini-extension.json"));
50091
50171
  if (raw === null)
50092
50172
  unresolved("extension registration missing");
50093
- const manifest = parseConfig(raw, join24(root, "gemini-extension.json"));
50094
- if (manifest.hooks !== undefined || witness(join24(root, "hooks/hooks.json")) !== null || witness(join24(root, ".gemini-extension-install.json")) !== null)
50173
+ const manifest = parseConfig(raw, join25(root, "gemini-extension.json"));
50174
+ if (manifest.hooks !== undefined || witness(join25(root, "hooks/hooks.json")) !== null || witness(join25(root, ".gemini-extension-install.json")) !== null)
50095
50175
  unresolved("extension hooks or linked registration require review");
50096
- roots.add(join24(root, "skills"));
50176
+ roots.add(join25(root, "skills"));
50097
50177
  }
50098
50178
  }
50099
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join24(home, ".hermes/plugins"), join24(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
50179
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join25(home, ".hermes/plugins"), join25(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
50100
50180
  }
50101
50181
  var digest = (text2) => createHash16("sha256").update(text2).digest("hex");
50102
50182
  var init_agent_discovery = __esm(() => {
@@ -50112,16 +50192,17 @@ var init_agent_discovery = __esm(() => {
50112
50192
  init_codex_hook_discovery_recovery();
50113
50193
  init_codex_settings_witness();
50114
50194
  init_codex_plugin_skill_controls();
50195
+ init_agent_sumi();
50115
50196
  init_native_discovery_roots();
50116
50197
  init_agent_discovery_directories();
50117
50198
  });
50118
50199
 
50119
50200
  // src/lib/authoring-path.ts
50120
- import { lstatSync as lstatSync18, realpathSync as realpathSync5 } from "fs";
50201
+ import { lstatSync as lstatSync19, realpathSync as realpathSync6 } from "fs";
50121
50202
  import { homedir as homedir3 } from "os";
50122
- import { basename as basename9, dirname as dirname16, join as join25, resolve as resolve15, sep as sep6 } from "path";
50203
+ import { basename as basename9, dirname as dirname16, join as join26, resolve as resolve16, sep as sep6 } from "path";
50123
50204
  function pathParts(path) {
50124
- return resolve15(path).split(sep6).filter(Boolean);
50205
+ return resolve16(path).split(sep6).filter(Boolean);
50125
50206
  }
50126
50207
  function nativeRootMatch(path) {
50127
50208
  const parts = pathParts(path);
@@ -50135,24 +50216,24 @@ function nativeRootMatch(path) {
50135
50216
  return;
50136
50217
  }
50137
50218
  function physicalPath(path) {
50138
- let cursor = resolve15(path);
50219
+ let cursor = resolve16(path);
50139
50220
  const suffix = [];
50140
- while (!lstatSync18(cursor, { throwIfNoEntry: false })) {
50221
+ while (!lstatSync19(cursor, { throwIfNoEntry: false })) {
50141
50222
  suffix.unshift(basename9(cursor));
50142
50223
  const parent = dirname16(cursor);
50143
50224
  if (parent === cursor)
50144
- return resolve15(path);
50225
+ return resolve16(path);
50145
50226
  cursor = parent;
50146
50227
  }
50147
- return resolve15(realpathSync5(cursor), ...suffix);
50228
+ return resolve16(realpathSync6(cursor), ...suffix);
50148
50229
  }
50149
50230
  function contains(root, path) {
50150
50231
  return path === root || path.startsWith(root + sep6);
50151
50232
  }
50152
50233
  function configuredRoots(home, explicitHome) {
50153
- const homeData = join25(home, ".hasna", "skills");
50234
+ const homeData = join26(home, ".hasna", "skills");
50154
50235
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
50155
- const configuredPolicy = !explicitHome && resolve15(getDataDirReadOnly()) !== resolve15(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
50236
+ const configuredPolicy = !explicitHome && resolve16(getDataDirReadOnly()) !== resolve16(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
50156
50237
  const policy = homePolicy ?? configuredPolicy;
50157
50238
  const bridge = policy?.value.bridge;
50158
50239
  if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
@@ -50181,8 +50262,8 @@ function configuredRoots(home, explicitHome) {
50181
50262
  admitBinding(binding);
50182
50263
  continue;
50183
50264
  }
50184
- const nativeHome = join25(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
50185
- if (!lstatSync18(nativeHome, { throwIfNoEntry: false }))
50265
+ const nativeHome = join26(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
50266
+ if (!lstatSync19(nativeHome, { throwIfNoEntry: false }))
50186
50267
  continue;
50187
50268
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
50188
50269
  }
@@ -50191,22 +50272,22 @@ function configuredRoots(home, explicitHome) {
50191
50272
  function assertPortableAuthoringPath(path, options = {}) {
50192
50273
  if (typeof path !== "string" || !path || path.includes("\x00"))
50193
50274
  throw new Error("Invalid portable authoring path");
50194
- const lexical = resolve15(path);
50275
+ const lexical = resolve16(path);
50195
50276
  const physical = physicalPath(lexical);
50196
50277
  const candidates = [lexical, physical];
50197
50278
  let native = candidates.map(nativeRootMatch).find(Boolean);
50198
- const home = resolve15(options.homeDir ?? homedir3());
50199
- const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join25(home, ...parts));
50200
- defaults.push(join25(home, ".codex/plugins/cache"), join25(home, ".claude/plugins/cache"), join25(home, ".claude/plugins/synced"), join25(home, ".gemini/extensions"));
50279
+ const home = resolve16(options.homeDir ?? homedir3());
50280
+ const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join26(home, ...parts));
50281
+ defaults.push(join26(home, ".codex/plugins/cache"), join26(home, ".claude/plugins/cache"), join26(home, ".claude/plugins/synced"), join26(home, ".gemini/extensions"));
50201
50282
  for (const root of defaults) {
50202
- if (candidates.some((candidate) => contains(resolve15(root), candidate) || contains(physicalPath(root), candidate)))
50283
+ if (candidates.some((candidate) => contains(resolve16(root), candidate) || contains(physicalPath(root), candidate)))
50203
50284
  native ??= root;
50204
50285
  }
50205
50286
  if (native) {
50206
50287
  throw new Error(`Refusing portable Skills authoring below native discovery root '${native}': ${lexical}. Set HASNA_SKILLS_DIR to a private authoring corpus outside native roots.`);
50207
50288
  }
50208
50289
  for (const root of configuredRoots(home, options.homeDir !== undefined)) {
50209
- if (candidates.some((candidate) => contains(resolve15(root), candidate) || contains(physicalPath(root), candidate))) {
50290
+ if (candidates.some((candidate) => contains(resolve16(root), candidate) || contains(physicalPath(root), candidate))) {
50210
50291
  throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
50211
50292
  }
50212
50293
  }
@@ -50223,32 +50304,32 @@ var init_authoring_path = __esm(() => {
50223
50304
 
50224
50305
  // src/lib/portable-skills.ts
50225
50306
  import {
50226
- existsSync as existsSync11,
50307
+ existsSync as existsSync12,
50227
50308
  mkdirSync as mkdirSync7,
50228
50309
  mkdtempSync,
50229
50310
  readdirSync as readdirSync8,
50230
- realpathSync as realpathSync6,
50311
+ realpathSync as realpathSync7,
50231
50312
  renameSync as renameSync3,
50232
50313
  rmSync as rmSync3,
50233
50314
  statSync as statSync7,
50234
50315
  writeFileSync as writeFileSync6
50235
50316
  } from "fs";
50236
- import { basename as basename10, dirname as dirname17, isAbsolute as isAbsolute14, join as join26, normalize as normalize3, relative as relative5, resolve as resolve16, sep as sep7 } from "path";
50317
+ import { basename as basename10, dirname as dirname17, isAbsolute as isAbsolute14, join as join27, normalize as normalize3, relative as relative5, resolve as resolve17, sep as sep7 } from "path";
50237
50318
  function getPortableSkillsRoot(options = {}) {
50238
50319
  return resolvePortableSkillsRoot(options, true);
50239
50320
  }
50240
50321
  function resolvePortableSkillsRoot(options, migrate) {
50241
50322
  if (options.rootDir)
50242
50323
  return options.rootDir;
50243
- const appDir = options.homeDir ? join26(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
50244
- const cache = join26(appDir, SKILLS_CACHE_DIRNAME);
50324
+ const appDir = options.homeDir ? join27(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
50325
+ const cache = join27(appDir, SKILLS_CACHE_DIRNAME);
50245
50326
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
50246
50327
  return cache;
50247
- const installed = join26(appDir, INSTALLED_SKILLS_DIRNAME);
50328
+ const installed = join27(appDir, INSTALLED_SKILLS_DIRNAME);
50248
50329
  return installed;
50249
50330
  }
50250
50331
  function getPortableSkillPath(name, options = {}) {
50251
- return join26(getPortableSkillsRoot(options), normalizePortableSkillName(name));
50332
+ return join27(getPortableSkillsRoot(options), normalizePortableSkillName(name));
50252
50333
  }
50253
50334
  function findPortableSkill(name, options = {}) {
50254
50335
  let normalized;
@@ -50258,7 +50339,7 @@ function findPortableSkill(name, options = {}) {
50258
50339
  return null;
50259
50340
  }
50260
50341
  const path = getPortableSkillPath(normalized, options);
50261
- if (!existsSync11(path) || !statSync7(path).isDirectory())
50342
+ if (!existsSync12(path) || !statSync7(path).isDirectory())
50262
50343
  return null;
50263
50344
  try {
50264
50345
  return summarizePortableSkill(path, normalized);
@@ -50274,7 +50355,7 @@ function listPortableSkills(options = {}) {
50274
50355
  for (const entry of readdirSync8(root).sort()) {
50275
50356
  if (entry.startsWith("."))
50276
50357
  continue;
50277
- const path = join26(root, entry);
50358
+ const path = join27(root, entry);
50278
50359
  if (!safeIsDirectory(path))
50279
50360
  continue;
50280
50361
  try {
@@ -50307,11 +50388,11 @@ function isOfficialSkillName(name) {
50307
50388
  function scaffoldPortableSkill(name, options = {}) {
50308
50389
  const skillName = normalizeNewPortableSkillName(name);
50309
50390
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
50310
- assertPortableAuthoringPath(join26(readOnlyRoot, skillName), options);
50391
+ assertPortableAuthoringPath(join27(readOnlyRoot, skillName), options);
50311
50392
  const root = getPortableSkillsRoot(options);
50312
- const skillPath = join26(root, skillName);
50393
+ const skillPath = join27(root, skillName);
50313
50394
  assertPortableAuthoringPath(skillPath, options);
50314
- if (existsSync11(skillPath)) {
50395
+ if (existsSync12(skillPath)) {
50315
50396
  if (!options.overwrite)
50316
50397
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
50317
50398
  rmSync3(skillPath, { recursive: true, force: true });
@@ -50328,16 +50409,16 @@ function scaffoldPortableSkill(name, options = {}) {
50328
50409
  return { name: skillName, path: skillPath, manifest, created: true };
50329
50410
  }
50330
50411
  function physicalImportPath(path) {
50331
- let ancestor = resolve16(path);
50412
+ let ancestor = resolve17(path);
50332
50413
  const suffix = [];
50333
- while (!existsSync11(ancestor)) {
50414
+ while (!existsSync12(ancestor)) {
50334
50415
  suffix.unshift(basename10(ancestor));
50335
50416
  ancestor = dirname17(ancestor);
50336
50417
  }
50337
- return join26(realpathSync6(ancestor), ...suffix);
50418
+ return join27(realpathSync7(ancestor), ...suffix);
50338
50419
  }
50339
50420
  function assertDisjointImportPaths(source, destination) {
50340
- const sourcePath = realpathSync6(source);
50421
+ const sourcePath = realpathSync7(source);
50341
50422
  const destinationPath = physicalImportPath(destination);
50342
50423
  const contains2 = (parent, child) => {
50343
50424
  const path = relative5(parent, child);
@@ -50349,7 +50430,7 @@ function assertDisjointImportPaths(source, destination) {
50349
50430
  }
50350
50431
  function portPortableSkill(sourcePath, options = {}) {
50351
50432
  const absoluteSource = normalize3(sourcePath);
50352
- if (!existsSync11(absoluteSource) || !statSync7(absoluteSource).isDirectory()) {
50433
+ if (!existsSync12(absoluteSource) || !statSync7(absoluteSource).isDirectory()) {
50353
50434
  throw new Error(`Skill source directory not found: ${sourcePath}`);
50354
50435
  }
50355
50436
  const inferred = readPortableSkillManifestForImport(absoluteSource);
@@ -50360,14 +50441,14 @@ function portPortableSkill(sourcePath, options = {}) {
50360
50441
  const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename10(absoluteSource)}')` : ""} matches a bundled official skill.`;
50361
50442
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
50362
50443
  }
50363
- const readOnlyDestination = join26(resolvePortableSkillsRoot(options, false), skillName);
50444
+ const readOnlyDestination = join27(resolvePortableSkillsRoot(options, false), skillName);
50364
50445
  assertPortableAuthoringPath(readOnlyDestination, options);
50365
50446
  assertDisjointImportPaths(absoluteSource, readOnlyDestination);
50366
50447
  const root = getPortableSkillsRoot(options);
50367
- const destination = join26(root, skillName);
50448
+ const destination = join27(root, skillName);
50368
50449
  assertPortableAuthoringPath(destination, options);
50369
50450
  assertDisjointImportPaths(absoluteSource, destination);
50370
- if (existsSync11(destination)) {
50451
+ if (existsSync12(destination)) {
50371
50452
  if (!options.overwrite)
50372
50453
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
50373
50454
  rmSync3(destination, { recursive: true, force: true });
@@ -50395,10 +50476,10 @@ function validatePortableSkillDirectory(name, skillPath) {
50395
50476
  const issues = [...base.issues];
50396
50477
  const warnings = [...base.warnings];
50397
50478
  let manifest;
50398
- if (existsSync11(skillPath)) {
50399
- const skillJsonPath = join26(skillPath, "skill.json");
50400
- const skillMdPath = join26(skillPath, "SKILL.md");
50401
- if (!existsSync11(skillJsonPath) && !existsSync11(skillMdPath)) {
50479
+ if (existsSync12(skillPath)) {
50480
+ const skillJsonPath = join27(skillPath, "skill.json");
50481
+ const skillMdPath = join27(skillPath, "SKILL.md");
50482
+ if (!existsSync12(skillJsonPath) && !existsSync12(skillMdPath)) {
50402
50483
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
50403
50484
  }
50404
50485
  try {
@@ -50417,7 +50498,7 @@ function validatePortableSkillDirectory(name, skillPath) {
50417
50498
  add3(issues, "portable.version_missing", "Portable manifest missing version");
50418
50499
  }
50419
50500
  const contractIssues = validatePortableManifestContract(manifest, {
50420
- strict: existsSync11(join26(skillPath, "skill.json")),
50501
+ strict: existsSync12(join27(skillPath, "skill.json")),
50421
50502
  skillPath
50422
50503
  });
50423
50504
  for (const issue2 of contractIssues)
@@ -50457,8 +50538,8 @@ function validatePortableSkillDirectory(name, skillPath) {
50457
50538
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
50458
50539
  continue;
50459
50540
  }
50460
- const entryPath = join26(skillPath, command.entry);
50461
- if (!existsSync11(entryPath))
50541
+ const entryPath = join27(skillPath, command.entry);
50542
+ if (!existsSync12(entryPath))
50462
50543
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
50463
50544
  else if (statSync7(entryPath).isDirectory())
50464
50545
  add3(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
@@ -50468,7 +50549,7 @@ function validatePortableSkillDirectory(name, skillPath) {
50468
50549
  } catch (error61) {
50469
50550
  add3(issues, "portable.manifest_invalid", error61.message);
50470
50551
  }
50471
- if (manifest?.kind !== "instruction" && !existsSync11(join26(skillPath, "AGENTS.md"))) {
50552
+ if (manifest?.kind !== "instruction" && !existsSync12(join27(skillPath, "AGENTS.md"))) {
50472
50553
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
50473
50554
  }
50474
50555
  }
@@ -50695,8 +50776,8 @@ var init_search = __esm(() => {
50695
50776
  });
50696
50777
 
50697
50778
  // src/lib/registry.ts
50698
- import { existsSync as existsSync12, readFileSync as readFileSync16, readdirSync as readdirSync9 } from "fs";
50699
- import { join as join27 } from "path";
50779
+ import { existsSync as existsSync13, readFileSync as readFileSync16, readdirSync as readdirSync9 } from "fs";
50780
+ import { join as join28 } from "path";
50700
50781
  function parseSkillMdFrontmatter(content) {
50701
50782
  const match = content.match(/^---\n([\s\S]*?)\n---/);
50702
50783
  if (!match)
@@ -50729,7 +50810,7 @@ function parseSkillMdFrontmatter(content) {
50729
50810
  return Object.keys(result).length > 0 ? result : null;
50730
50811
  }
50731
50812
  function discoverSkillsInDir(dir, source = "custom") {
50732
- if (!existsSync12(dir))
50813
+ if (!existsSync13(dir))
50733
50814
  return [];
50734
50815
  const result = [];
50735
50816
  try {
@@ -50737,8 +50818,8 @@ function discoverSkillsInDir(dir, source = "custom") {
50737
50818
  for (const entry of entries) {
50738
50819
  if (!entry.isDirectory())
50739
50820
  continue;
50740
- const skillMdPath = join27(dir, entry.name, "SKILL.md");
50741
- if (!existsSync12(skillMdPath))
50821
+ const skillMdPath = join28(dir, entry.name, "SKILL.md");
50822
+ if (!existsSync13(skillMdPath))
50742
50823
  continue;
50743
50824
  let content;
50744
50825
  try {
@@ -50757,7 +50838,7 @@ function discoverSkillsInDir(dir, source = "custom") {
50757
50838
  category: fm.category || "Development Tools",
50758
50839
  tags: fm.tags || [],
50759
50840
  ...fm.kind ? { kind: fm.kind } : {},
50760
- ...isHostedMetadataSkillDir(join27(dir, entry.name)) ? { serverOwned: true } : {},
50841
+ ...isHostedMetadataSkillDir(join28(dir, entry.name)) ? { serverOwned: true } : {},
50761
50842
  source
50762
50843
  });
50763
50844
  }
@@ -50766,16 +50847,16 @@ function discoverSkillsInDir(dir, source = "custom") {
50766
50847
  }
50767
50848
  function findExtensionSkillPath(name) {
50768
50849
  const config2 = loadConfig();
50769
- if (!config2.extensionsDir || !existsSync12(config2.extensionsDir))
50850
+ if (!config2.extensionsDir || !existsSync13(config2.extensionsDir))
50770
50851
  return null;
50771
50852
  try {
50772
50853
  const entries = readdirSync9(config2.extensionsDir, { withFileTypes: true });
50773
50854
  for (const entry of entries) {
50774
50855
  if (!entry.isDirectory())
50775
50856
  continue;
50776
- const skillDir = join27(config2.extensionsDir, entry.name);
50777
- const skillMdPath = join27(skillDir, "SKILL.md");
50778
- if (!existsSync12(skillMdPath))
50857
+ const skillDir = join28(config2.extensionsDir, entry.name);
50858
+ const skillMdPath = join28(skillDir, "SKILL.md");
50859
+ if (!existsSync13(skillMdPath))
50779
50860
  continue;
50780
50861
  let content;
50781
50862
  try {
@@ -50818,8 +50899,8 @@ function clearRegistryCache() {
50818
50899
  registryCacheTime = 0;
50819
50900
  registryCacheKey = null;
50820
50901
  }
50821
- function getSkillsByCategory(category) {
50822
- return loadRegistry().filter((s) => s.category === category);
50902
+ function getSkillsByCategory(category, catalog) {
50903
+ return (catalog ?? loadRegistry()).filter((s) => s.category === category);
50823
50904
  }
50824
50905
  function getSkill(name) {
50825
50906
  const registry2 = loadRegistry();
@@ -51971,14 +52052,14 @@ var init_remote_workspace_leave = __esm(() => {
51971
52052
  });
51972
52053
 
51973
52054
  // src/lib/auth-store.ts
51974
- import { chmodSync, existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync17, renameSync as renameSync4, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
51975
- import { basename as basename11, dirname as dirname18, join as join28 } from "path";
52055
+ import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync17, renameSync as renameSync4, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
52056
+ import { basename as basename11, dirname as dirname18, join as join29 } from "path";
51976
52057
  function getAuthFilePath(env = process.env) {
51977
52058
  return skillsCredentialFilePath(env);
51978
52059
  }
51979
52060
  function getIdentityFilePath(env = process.env) {
51980
52061
  const file2 = skillsCredentialFilePath(env);
51981
- return join28(dirname18(file2), basename11(file2).replace(/^credentials/, "identity") + ".json");
52062
+ return join29(dirname18(file2), basename11(file2).replace(/^credentials/, "identity") + ".json");
51982
52063
  }
51983
52064
  function getApiUrl(action, env = process.env, options = {}) {
51984
52065
  return requireSkillsApiOrigin(action, env, options);
@@ -52206,10 +52287,10 @@ async function readQuoteUnavailableCode(response) {
52206
52287
  let timer;
52207
52288
  let deadlineExceeded = false;
52208
52289
  const expired = Symbol("quote body deadline");
52209
- const deadline = new Promise((resolve17) => {
52290
+ const deadline = new Promise((resolve18) => {
52210
52291
  timer = setTimeout(() => {
52211
52292
  deadlineExceeded = true;
52212
- resolve17(expired);
52293
+ resolve18(expired);
52213
52294
  reader.cancel().catch(() => {});
52214
52295
  }, 1500);
52215
52296
  });
@@ -53692,12 +53773,12 @@ class RemotePrivatePublicationsClient {
53692
53773
  previous = view;
53693
53774
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
53694
53775
  return view;
53695
- await new Promise((resolve17) => {
53776
+ await new Promise((resolve18) => {
53696
53777
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
53697
53778
  function done() {
53698
53779
  clearTimeout(timer);
53699
53780
  options.signal?.removeEventListener("abort", done);
53700
- resolve17();
53781
+ resolve18();
53701
53782
  }
53702
53783
  options.signal?.addEventListener("abort", done, { once: true });
53703
53784
  });
@@ -53985,10 +54066,10 @@ var init_remote_auth = __esm(() => {
53985
54066
  });
53986
54067
 
53987
54068
  // src/lib/workspace-profile.ts
53988
- import { constants as constants11, closeSync as closeSync14, fstatSync as fstatSync14, lstatSync as lstatSync19, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync2, openSync as openSync14, readFileSync as readFileSync18, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
54069
+ import { constants as constants11, closeSync as closeSync14, fstatSync as fstatSync14, lstatSync as lstatSync20, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync2, openSync as openSync14, readFileSync as readFileSync18, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
53989
54070
  function stat2(path) {
53990
54071
  try {
53991
- return lstatSync19(path);
54072
+ return lstatSync20(path);
53992
54073
  } catch (error61) {
53993
54074
  if (error61.code === "ENOENT")
53994
54075
  return null;
@@ -54217,8 +54298,8 @@ var init_recurring_customer = __esm(() => {
54217
54298
  });
54218
54299
 
54219
54300
  // src/lib/recurring-recovery.ts
54220
- import { constants as constants12, closeSync as closeSync15, fsyncSync as fsyncSync4, fstatSync as fstatSync15, lstatSync as lstatSync20, mkdirSync as mkdirSync10, openSync as openSync15, readSync as readSync10, realpathSync as realpathSync7, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
54221
- import { dirname as dirname19, isAbsolute as isAbsolute15, join as join29, resolve as resolve17 } from "path";
54301
+ import { constants as constants12, closeSync as closeSync15, fsyncSync as fsyncSync4, fstatSync as fstatSync15, lstatSync as lstatSync21, mkdirSync as mkdirSync10, openSync as openSync15, readSync as readSync10, realpathSync as realpathSync8, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
54302
+ import { dirname as dirname19, isAbsolute as isAbsolute15, join as join30, resolve as resolve18 } from "path";
54222
54303
  import { randomUUID as randomUUID2 } from "crypto";
54223
54304
 
54224
54305
  class RecoveryOwner {
@@ -54226,10 +54307,10 @@ class RecoveryOwner {
54226
54307
  parents = [];
54227
54308
  constructor(directory) {
54228
54309
  this.directory = directory;
54229
- if (!isAbsolute15(directory) || resolve17(directory) !== directory || realpathSync7(directory) !== directory)
54310
+ if (!isAbsolute15(directory) || resolve18(directory) !== directory || realpathSync8(directory) !== directory)
54230
54311
  invalid5();
54231
54312
  for (let path = directory;; path = dirname19(path)) {
54232
- const stat3 = lstatSync20(path);
54313
+ const stat3 = lstatSync21(path);
54233
54314
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
54234
54315
  invalid5();
54235
54316
  this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
@@ -54239,20 +54320,20 @@ class RecoveryOwner {
54239
54320
  this.assert();
54240
54321
  }
54241
54322
  assert() {
54242
- if (realpathSync7(this.directory) !== this.directory)
54323
+ if (realpathSync8(this.directory) !== this.directory)
54243
54324
  invalid5();
54244
54325
  for (const prior of this.parents) {
54245
- const now = lstatSync20(prior.path);
54326
+ const now = lstatSync21(prior.path);
54246
54327
  if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
54247
54328
  invalid5();
54248
54329
  }
54249
- const own2 = lstatSync20(this.directory);
54330
+ const own2 = lstatSync21(this.directory);
54250
54331
  if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
54251
54332
  invalid5();
54252
54333
  }
54253
54334
  read(name) {
54254
54335
  this.assert();
54255
- const fd = openSync15(join29(this.directory, name), constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
54336
+ const fd = openSync15(join30(this.directory, name), constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
54256
54337
  try {
54257
54338
  const before = fstatSync15(fd);
54258
54339
  if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
@@ -54265,7 +54346,7 @@ class RecoveryOwner {
54265
54346
  break;
54266
54347
  size += n2;
54267
54348
  }
54268
- const after = fstatSync15(fd), path = lstatSync20(join29(this.directory, name));
54349
+ const after = fstatSync15(fd), path = lstatSync21(join30(this.directory, name));
54269
54350
  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())
54270
54351
  invalid5();
54271
54352
  this.assert();
@@ -54278,7 +54359,7 @@ class RecoveryOwner {
54278
54359
  this.assert();
54279
54360
  const bytes = canonicalJson2(value, 8192) + `
54280
54361
  `;
54281
- const fd = openSync15(join29(this.directory, name), constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
54362
+ const fd = openSync15(join30(this.directory, name), constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
54282
54363
  try {
54283
54364
  writeFileSync9(fd, bytes);
54284
54365
  fsyncSync4(fd);
@@ -54305,14 +54386,14 @@ class RecoveryOwner {
54305
54386
  if (this.read("state.json") !== expected)
54306
54387
  invalid5();
54307
54388
  this.assert();
54308
- renameSync6(join29(this.directory, name), join29(this.directory, "state.json"));
54389
+ renameSync6(join30(this.directory, name), join30(this.directory, "state.json"));
54309
54390
  this.sync();
54310
54391
  }
54311
54392
  async locked(action) {
54312
54393
  this.assert();
54313
54394
  let fd;
54314
54395
  try {
54315
- fd = openSync15(join29(this.directory, "operation.lock"), constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
54396
+ fd = openSync15(join30(this.directory, "operation.lock"), constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
54316
54397
  } catch {
54317
54398
  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.");
54318
54399
  }
@@ -54325,10 +54406,10 @@ class RecoveryOwner {
54325
54406
  } finally {
54326
54407
  closeSync15(fd);
54327
54408
  this.assert();
54328
- const now = lstatSync20(join29(this.directory, "operation.lock"));
54409
+ const now = lstatSync21(join30(this.directory, "operation.lock"));
54329
54410
  if (owner2.dev !== now.dev || owner2.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
54330
54411
  invalid5();
54331
- unlinkSync5(join29(this.directory, "operation.lock"));
54412
+ unlinkSync5(join30(this.directory, "operation.lock"));
54332
54413
  this.sync();
54333
54414
  }
54334
54415
  }
@@ -54361,7 +54442,7 @@ function base(customer, organizationId) {
54361
54442
  };
54362
54443
  }
54363
54444
  function create(directory, intent) {
54364
- if (!isAbsolute15(directory) || resolve17(directory) !== directory || realpathSync7(dirname19(directory)) !== dirname19(directory))
54445
+ if (!isAbsolute15(directory) || resolve18(directory) !== directory || realpathSync8(dirname19(directory)) !== dirname19(directory))
54365
54446
  invalid5();
54366
54447
  mkdirSync10(directory, { mode: 448 });
54367
54448
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -56459,20 +56540,20 @@ var init_credential_state = __esm(() => {
56459
56540
 
56460
56541
  // src/lib/run-state.ts
56461
56542
  import { createHash as createHash19, randomBytes } from "crypto";
56462
- import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync19, readdirSync as readdirSync10, statSync as statSync9, writeFileSync as writeFileSync10 } from "fs";
56463
- import { extname, join as join30, relative as relative6 } from "path";
56543
+ import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync19, readdirSync as readdirSync10, statSync as statSync9, writeFileSync as writeFileSync10 } from "fs";
56544
+ import { extname, join as join31, relative as relative6 } from "path";
56464
56545
  function createSkillRun(params, targetDir = process.cwd()) {
56465
56546
  const now = new Date;
56466
56547
  const id = createRunId(now);
56467
56548
  const day = now.toISOString().slice(0, 10);
56468
56549
  const skillName = normalizeSkillName(params.skill);
56469
56550
  const root = getProjectStateDir(targetDir);
56470
- const runDir = join30(root, "runs", day, id);
56471
- const logsDir = join30(runDir, "logs");
56472
- const exportDir = join30(root, "exports", skillName, id);
56551
+ const runDir = join31(root, "runs", day, id);
56552
+ const logsDir = join31(runDir, "logs");
56553
+ const exportDir = join31(root, "exports", skillName, id);
56473
56554
  mkdirSync11(logsDir, { recursive: true });
56474
56555
  mkdirSync11(exportDir, { recursive: true });
56475
- mkdirSync11(join30(root, "tmp"), { recursive: true });
56556
+ mkdirSync11(join31(root, "tmp"), { recursive: true });
56476
56557
  const record11 = {
56477
56558
  id,
56478
56559
  skill: skillName,
@@ -56524,22 +56605,22 @@ function updateSkillRun(context2, patch) {
56524
56605
  return context2.record;
56525
56606
  }
56526
56607
  function writeRunLogs(context2, stdout = "", stderr = "") {
56527
- writeFileSync10(join30(context2.logsDir, "stdout.log"), stdout);
56528
- writeFileSync10(join30(context2.logsDir, "stderr.log"), stderr);
56608
+ writeFileSync10(join31(context2.logsDir, "stdout.log"), stdout);
56609
+ writeFileSync10(join31(context2.logsDir, "stderr.log"), stderr);
56529
56610
  }
56530
56611
  function appendRunEvent(context2, event, data = {}) {
56531
56612
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
56532
56613
  `;
56533
- const path = join30(context2.runDir, "events.ndjson");
56534
- const previous = existsSync14(path) ? readFileSync19(path, "utf-8") : "";
56614
+ const path = join31(context2.runDir, "events.ndjson");
56615
+ const previous = existsSync15(path) ? readFileSync19(path, "utf-8") : "";
56535
56616
  writeFileSync10(path, previous + line);
56536
56617
  }
56537
56618
  function findSkillRun(runId, targetDir = process.cwd()) {
56538
- const runsRoot = join30(getProjectStateDir(targetDir), "runs");
56539
- if (!existsSync14(runsRoot))
56619
+ const runsRoot = join31(getProjectStateDir(targetDir), "runs");
56620
+ if (!existsSync15(runsRoot))
56540
56621
  return null;
56541
56622
  for (const day of readdirSync10(runsRoot)) {
56542
- const record11 = readRunRecord(join30(runsRoot, day, runId));
56623
+ const record11 = readRunRecord(join31(runsRoot, day, runId));
56543
56624
  if (record11)
56544
56625
  return record11;
56545
56626
  }
@@ -56556,15 +56637,15 @@ function skillRunEnv(context2) {
56556
56637
  };
56557
56638
  }
56558
56639
  function writeRunRecord(context2) {
56559
- writeFileSync10(join30(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
56640
+ writeFileSync10(join31(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
56560
56641
  `);
56561
56642
  }
56562
56643
  function writeArtifactsManifest(context2, artifacts) {
56563
- writeFileSync10(join30(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
56644
+ writeFileSync10(join31(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
56564
56645
  `);
56565
56646
  }
56566
56647
  function collectRunArtifacts(context2) {
56567
- if (!existsSync14(context2.exportDir))
56648
+ if (!existsSync15(context2.exportDir))
56568
56649
  return [];
56569
56650
  const artifacts = [];
56570
56651
  for (const path of walkFiles(context2.exportDir)) {
@@ -56580,8 +56661,8 @@ function collectRunArtifacts(context2) {
56580
56661
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
56581
56662
  }
56582
56663
  function readRunRecord(runDir) {
56583
- const path = join30(runDir, "run.json");
56584
- if (!existsSync14(path))
56664
+ const path = join31(runDir, "run.json");
56665
+ if (!existsSync15(path))
56585
56666
  return null;
56586
56667
  try {
56587
56668
  return JSON.parse(readFileSync19(path, "utf-8"));
@@ -56592,7 +56673,7 @@ function readRunRecord(runDir) {
56592
56673
  function walkFiles(dir) {
56593
56674
  const files = [];
56594
56675
  for (const entry of readdirSync10(dir)) {
56595
- const full = join30(dir, entry);
56676
+ const full = join31(dir, entry);
56596
56677
  if (statSync9(full).isDirectory())
56597
56678
  files.push(...walkFiles(full));
56598
56679
  else
@@ -56849,7 +56930,7 @@ import { closeSync as closeSync16, fstatSync as fstatSync16, openSync as openSyn
56849
56930
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
56850
56931
  import { createRequire as createRequire2 } from "module";
56851
56932
  import { hostname as osHostname2 } from "os";
56852
- import { isAbsolute as isAbsolute17, join as join31 } from "path";
56933
+ import { isAbsolute as isAbsolute17, join as join32 } from "path";
56853
56934
  import { createRequire as createRequire22 } from "module";
56854
56935
  function envToken2(name) {
56855
56936
  return name.toUpperCase().replace(/-/g, "_");
@@ -56880,14 +56961,14 @@ function hasnaHomeDir2(env) {
56880
56961
  if (override)
56881
56962
  return override;
56882
56963
  const home = homeDir2(env);
56883
- return home ? join31(home, HASNA_HOME_DIR2) : null;
56964
+ return home ? join32(home, HASNA_HOME_DIR2) : null;
56884
56965
  }
56885
56966
  function appConfigDir2(name, env) {
56886
56967
  const configRoot = absoluteOverride2(env, HASNA_CONFIG_HOME_ENV_KEY2);
56887
56968
  if (configRoot)
56888
- return join31(configRoot, name);
56969
+ return join32(configRoot, name);
56889
56970
  const root = hasnaHomeDir2(env);
56890
- return root ? join31(root, name, CONFIG_SUBDIR2) : null;
56971
+ return root ? join32(root, name, CONFIG_SUBDIR2) : null;
56891
56972
  }
56892
56973
  function credentialDiskSourceList2(name, env, profile = null) {
56893
56974
  if (!SAFE_APP_SLUG2.test(name))
@@ -56896,7 +56977,7 @@ function credentialDiskSourceList2(name, env, profile = null) {
56896
56977
  if (!directory2)
56897
56978
  return [];
56898
56979
  const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
56899
- return [{ path: join31(directory2, file2), tier: "disk" }];
56980
+ return [{ path: join32(directory2, file2), tier: "disk" }];
56900
56981
  }
56901
56982
  function credentialDiskSources2(name, env) {
56902
56983
  return credentialDiskSourceList2(name, env, null).map((s) => s.path);
@@ -58010,7 +58091,7 @@ function createSecretsClientFromEnv(env = process.env, overrides = {}) {
58010
58091
  });
58011
58092
  return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
58012
58093
  }
58013
- 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((resolve18) => setTimeout(resolve18, 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;
58094
+ 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((resolve19) => setTimeout(resolve19, 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;
58014
58095
  var init_sdk = __esm(() => {
58015
58096
  init_transport2 = __esm2(() => {
58016
58097
  CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
@@ -58145,7 +58226,7 @@ var init_sdk = __esm(() => {
58145
58226
  });
58146
58227
 
58147
58228
  // src/lib/execution-secrets.ts
58148
- import { constants as constants13, closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSync17, readSync as readSync11, realpathSync as realpathSync8 } from "fs";
58229
+ import { constants as constants13, closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSync17, readSync as readSync11, realpathSync as realpathSync9 } from "fs";
58149
58230
  import { hostname as stationHostname } from "os";
58150
58231
  function selectedSecretBindingsTemplate(scope, names, createClient = createSecretsClientFromEnv) {
58151
58232
  let secretsAuthority;
@@ -58158,7 +58239,7 @@ function selectedSecretBindingsTemplate(scope, names, createClient = createSecre
58158
58239
  return {
58159
58240
  schema: "hasna.skills-secret-bindings.v1",
58160
58241
  selection: { authority, workspaceId, profileId: scope.profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
58161
- consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory: realpathSync8(scope.cwd) },
58242
+ consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory: realpathSync9(scope.cwd) },
58162
58243
  secretsAuthority,
58163
58244
  bindings: Object.fromEntries(names.map((name) => [name, ""]))
58164
58245
  };
@@ -58196,7 +58277,7 @@ function validateSelectedSecretBindings(value, scope, names) {
58196
58277
  }
58197
58278
  let workspaceDirectory;
58198
58279
  try {
58199
- workspaceDirectory = realpathSync8(scope.cwd);
58280
+ workspaceDirectory = realpathSync9(scope.cwd);
58200
58281
  } catch {
58201
58282
  return refuse2("SECRET_BINDING_CONSUMER_MISMATCH", "The execution workspace cannot be resolved.");
58202
58283
  }
@@ -58389,8 +58470,8 @@ __export(exports_selected_run, {
58389
58470
  });
58390
58471
  import { createHash as createHash20 } from "crypto";
58391
58472
  import { spawn } from "child_process";
58392
- import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync9 } from "fs";
58393
- import { dirname as dirname20, join as join32, resolve as resolve18 } from "path";
58473
+ import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync10 } from "fs";
58474
+ import { dirname as dirname20, join as join33, resolve as resolve19 } from "path";
58394
58475
  import { tmpdir, hostname as stationHostname2 } from "os";
58395
58476
  async function resolveSelectedRun(spec, profileId, options = {}) {
58396
58477
  const context2 = await resolveSelectionContext(profileId, options);
@@ -58470,7 +58551,7 @@ async function executeSelectedLocal(selected, options = {}) {
58470
58551
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
58471
58552
  secretEnv[name] = value;
58472
58553
  }
58473
- const runDirectory = mkdtempSync3(join32(tmpdir(), "skills-execution-"));
58554
+ const runDirectory = mkdtempSync3(join33(tmpdir(), "skills-execution-"));
58474
58555
  const paths = new SkillEntryPaths;
58475
58556
  for (const entry of entries) {
58476
58557
  paths.add(entry.path, 100, () => {
@@ -58478,12 +58559,12 @@ async function executeSelectedLocal(selected, options = {}) {
58478
58559
  }, () => {
58479
58560
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
58480
58561
  });
58481
- const destination = join32(runDirectory, entry.path);
58562
+ const destination = join33(runDirectory, entry.path);
58482
58563
  mkdirSync12(dirname20(destination), { recursive: true, mode: 448 });
58483
58564
  writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
58484
58565
  }
58485
58566
  env.SKILLS_INPUT_JSON = input2;
58486
- env.SKILLS_WORKSPACE_DIR = resolve18(options.cwd ?? process.cwd());
58567
+ env.SKILLS_WORKSPACE_DIR = resolve19(options.cwd ?? process.cwd());
58487
58568
  env.SKILLS_RUN_DIR = runDirectory;
58488
58569
  if (runtime.version) {
58489
58570
  const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
@@ -58496,7 +58577,7 @@ async function executeSelectedLocal(selected, options = {}) {
58496
58577
  const { authority: authority2, workspaceId, profileRevision, slug: slug2, version: version2, bundleDigest } = selection2;
58497
58578
  const request2 = {
58498
58579
  selection: { authority: authority2, workspaceId, profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
58499
- consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync9(options.cwd ?? process.cwd()) }
58580
+ consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync10(options.cwd ?? process.cwd()) }
58500
58581
  };
58501
58582
  const grant = await (options.resolveExecutionGrant ?? resolveExecutionGrant)(request2);
58502
58583
  if (!grant || !grantIdentifier(grant.policyRevision) || !grantIdentifier(grant.grantId))
@@ -58506,7 +58587,7 @@ async function executeSelectedLocal(selected, options = {}) {
58506
58587
  }
58507
58588
  if (bindings)
58508
58589
  secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
58509
- const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join32(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
58590
+ const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join33(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
58510
58591
  result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
58511
58592
  result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
58512
58593
  const receipt = {
@@ -58519,7 +58600,7 @@ async function executeSelectedLocal(selected, options = {}) {
58519
58600
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
58520
58601
  ...result
58521
58602
  };
58522
- writeFileSync11(join32(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
58603
+ writeFileSync11(join33(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
58523
58604
  return receipt;
58524
58605
  }
58525
58606
  async function subprocess(command, cwd, env, input2, timeoutMs) {
@@ -58708,8 +58789,8 @@ var init_blog_article = __esm(() => {
58708
58789
  });
58709
58790
 
58710
58791
  // src/mcp/operation-tools.ts
58711
- import { existsSync as existsSync15, readdirSync as readdirSync11, statSync as statSync10 } from "fs";
58712
- import { join as join33 } from "path";
58792
+ import { existsSync as existsSync16, readdirSync as readdirSync11, statSync as statSync10 } from "fs";
58793
+ import { join as join34 } from "path";
58713
58794
  function registerOperationTools(server) {
58714
58795
  server.registerTool("cloud_skill_eligibility", {
58715
58796
  title: "Cloud Skill Eligibility",
@@ -59181,12 +59262,12 @@ function registerOperationTools(server) {
59181
59262
  const agents = [];
59182
59263
  for (const agent of AGENT_TARGETS) {
59183
59264
  const agentSkillsPath = getAgentSkillsDir(agent, "global");
59184
- const exists = existsSync15(agentSkillsPath);
59265
+ const exists = existsSync16(agentSkillsPath);
59185
59266
  let skillCount = 0;
59186
59267
  if (exists) {
59187
59268
  try {
59188
59269
  skillCount = readdirSync11(agentSkillsPath).filter((f) => {
59189
- const full = join33(agentSkillsPath, f);
59270
+ const full = join34(agentSkillsPath, f);
59190
59271
  return !f.startsWith(".") && statSync10(full).isDirectory();
59191
59272
  }).length;
59192
59273
  } catch {}
@@ -59253,16 +59334,16 @@ var init_operation_tools = __esm(() => {
59253
59334
  });
59254
59335
 
59255
59336
  // src/lib/feedback.ts
59256
- import { appendFileSync, existsSync as existsSync16, mkdirSync as mkdirSync13 } from "fs";
59257
- import { dirname as dirname21, join as join34 } from "path";
59337
+ import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync13 } from "fs";
59338
+ import { dirname as dirname21, join as join35 } from "path";
59258
59339
  import { Database } from "bun:sqlite";
59259
59340
  function getFeedbackDbPath() {
59260
- return join34(getDataDir(), "skills.db");
59341
+ return join35(getDataDir(), "skills.db");
59261
59342
  }
59262
59343
  function getFeedbackDb() {
59263
59344
  const dbPath = getFeedbackDbPath();
59264
59345
  const dir = dirname21(dbPath);
59265
- if (!existsSync16(dir))
59346
+ if (!existsSync17(dir))
59266
59347
  mkdirSync13(dir, { recursive: true });
59267
59348
  const db = new Database(dbPath);
59268
59349
  db.exec("PRAGMA journal_mode = WAL");
@@ -59289,9 +59370,9 @@ function saveFeedback(input2) {
59289
59370
  throw new Error("Feedback message is required");
59290
59371
  const category = input2.category ?? "general";
59291
59372
  if (isApiMode()) {
59292
- const path = join34(getDataDir(), "feedback.jsonl");
59373
+ const path = join35(getDataDir(), "feedback.jsonl");
59293
59374
  const dir = dirname21(path);
59294
- if (!existsSync16(dir))
59375
+ if (!existsSync17(dir))
59295
59376
  mkdirSync13(dir, { recursive: true });
59296
59377
  appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
59297
59378
  `);
@@ -59453,14 +59534,14 @@ var init_resource_meta_tools = __esm(() => {
59453
59534
  });
59454
59535
 
59455
59536
  // src/lib/scheduler.ts
59456
- import { existsSync as existsSync17, readFileSync as readFileSync21, writeFileSync as writeFileSync12, mkdirSync as mkdirSync14 } from "fs";
59457
- import { join as join35 } from "path";
59537
+ import { existsSync as existsSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync12, mkdirSync as mkdirSync14 } from "fs";
59538
+ import { join as join36 } from "path";
59458
59539
  function getSchedulesPath(targetDir = process.cwd()) {
59459
- return join35(targetDir, ".skills", "schedules.json");
59540
+ return join36(targetDir, ".skills", "schedules.json");
59460
59541
  }
59461
59542
  function loadSchedules(targetDir = process.cwd()) {
59462
59543
  const path = getSchedulesPath(targetDir);
59463
- if (existsSync17(path)) {
59544
+ if (existsSync18(path)) {
59464
59545
  try {
59465
59546
  return JSON.parse(readFileSync21(path, "utf-8"));
59466
59547
  } catch {}
@@ -59469,8 +59550,8 @@ function loadSchedules(targetDir = process.cwd()) {
59469
59550
  }
59470
59551
  function saveSchedules(data, targetDir = process.cwd()) {
59471
59552
  const path = getSchedulesPath(targetDir);
59472
- const dir = join35(targetDir, ".skills");
59473
- if (!existsSync17(dir))
59553
+ const dir = join36(targetDir, ".skills");
59554
+ if (!existsSync18(dir))
59474
59555
  mkdirSync14(dir, { recursive: true });
59475
59556
  writeFileSync12(path, JSON.stringify(data, null, 2));
59476
59557
  }
@@ -59743,14 +59824,14 @@ var init_schedule_tools = __esm(() => {
59743
59824
  // src/lib/native-storage.ts
59744
59825
  import { createHash as createHash21, createHmac } from "crypto";
59745
59826
  import {
59746
- existsSync as existsSync18,
59827
+ existsSync as existsSync19,
59747
59828
  mkdirSync as mkdirSync15,
59748
59829
  readFileSync as readFileSync22,
59749
59830
  readdirSync as readdirSync12,
59750
59831
  statSync as statSync11,
59751
59832
  writeFileSync as writeFileSync13
59752
59833
  } from "fs";
59753
- import { dirname as dirname22, join as join36, normalize as normalize4, relative as relative7, sep as sep8 } from "path";
59834
+ import { dirname as dirname22, join as join37, normalize as normalize4, relative as relative7, sep as sep8 } from "path";
59754
59835
  function resolveSkillsNativeStorageConfig(env = process.env) {
59755
59836
  assertNoRetiredModeEnvVars(env, {
59756
59837
  app: SKILLS_ENV_NAMESPACE,
@@ -59791,7 +59872,7 @@ function getSkillsNativeStorageStatus(options = {}) {
59791
59872
  local: {
59792
59873
  dataDir: getDataDir(),
59793
59874
  projectStateDir: getProjectStateDir(targetDir),
59794
- feedbackDbPath: join36(getDataDir(), "skills.db")
59875
+ feedbackDbPath: join37(getDataDir(), "skills.db")
59795
59876
  },
59796
59877
  remote: {
59797
59878
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -59811,7 +59892,7 @@ function getStorageStatus(options = {}) {
59811
59892
  function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
59812
59893
  const projectStateDir = getProjectStateDir(targetDir);
59813
59894
  const files = [];
59814
- if (existsSync18(projectStateDir)) {
59895
+ if (existsSync19(projectStateDir)) {
59815
59896
  for (const filePath of walkFiles2(projectStateDir)) {
59816
59897
  const bytes = readFileSync22(filePath);
59817
59898
  const relativePath = toPosix(relative7(targetDir, filePath));
@@ -59872,7 +59953,7 @@ function parsePositiveInteger(value) {
59872
59953
  function walkFiles2(dir) {
59873
59954
  const files = [];
59874
59955
  for (const entry of readdirSync12(dir)) {
59875
- const full = join36(dir, entry);
59956
+ const full = join37(dir, entry);
59876
59957
  const stats = statSync11(full);
59877
59958
  if (stats.isDirectory())
59878
59959
  files.push(...walkFiles2(full));
@@ -60110,20 +60191,20 @@ var init_private_publication_customer = __esm(() => {
60110
60191
  });
60111
60192
 
60112
60193
  // src/lib/private-publication-recovery.ts
60113
- import { constants as constants14, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync21, mkdirSync as mkdirSync16, openSync as openSync18, readSync as readSync12, realpathSync as realpathSync10, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
60114
- import { dirname as dirname23, isAbsolute as isAbsolute18, join as join37, resolve as resolve19 } from "path";
60194
+ import { constants as constants14, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync22, mkdirSync as mkdirSync16, openSync as openSync18, readSync as readSync12, realpathSync as realpathSync11, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
60195
+ import { dirname as dirname23, isAbsolute as isAbsolute18, join as join38, resolve as resolve20 } from "path";
60115
60196
  import { randomUUID as randomUUID3 } from "crypto";
60116
60197
  function safeDirectory(directory2) {
60117
- if (!isAbsolute18(directory2) || directory2 !== resolve19(directory2) || realpathSync10(directory2) !== directory2)
60198
+ if (!isAbsolute18(directory2) || directory2 !== resolve20(directory2) || realpathSync11(directory2) !== directory2)
60118
60199
  return fail2();
60119
60200
  for (let path = directory2;; path = dirname23(path)) {
60120
- const stat3 = lstatSync21(path);
60201
+ const stat3 = lstatSync22(path);
60121
60202
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
60122
60203
  return fail2();
60123
60204
  if (path === dirname23(path))
60124
60205
  break;
60125
60206
  }
60126
- const own2 = lstatSync21(directory2);
60207
+ const own2 = lstatSync22(directory2);
60127
60208
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
60128
60209
  return fail2();
60129
60210
  return { dev: own2.dev, ino: own2.ino };
@@ -60134,7 +60215,7 @@ function unchangedDirectory(directory2, identity3) {
60134
60215
  return fail2();
60135
60216
  }
60136
60217
  function readOwned(directory2, name, max) {
60137
- const identity3 = safeDirectory(directory2), file2 = join37(directory2, name);
60218
+ const identity3 = safeDirectory(directory2), file2 = join38(directory2, name);
60138
60219
  const fd = openSync18(file2, constants14.O_RDONLY | constants14.O_NOFOLLOW);
60139
60220
  try {
60140
60221
  const stat3 = fstatSync18(fd);
@@ -60158,7 +60239,7 @@ function readOwned(directory2, name, max) {
60158
60239
  }
60159
60240
  }
60160
60241
  function writeOwned(directory2, name, bytes) {
60161
- const fd = openSync18(join37(directory2, name), constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
60242
+ const fd = openSync18(join38(directory2, name), constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
60162
60243
  try {
60163
60244
  writeFileSync14(fd, bytes);
60164
60245
  fsyncSync5(fd);
@@ -60171,7 +60252,7 @@ function save(directory2, value) {
60171
60252
  writeOwned(directory2, temporary, JSON.stringify(value) + `
60172
60253
  `);
60173
60254
  unchangedDirectory(directory2, identity3);
60174
- renameSync7(join37(directory2, temporary), join37(directory2, "receipt.json"));
60255
+ renameSync7(join38(directory2, temporary), join38(directory2, "receipt.json"));
60175
60256
  const fd = openSync18(directory2, constants14.O_RDONLY | constants14.O_NOFOLLOW);
60176
60257
  try {
60177
60258
  fsyncSync5(fd);
@@ -60184,7 +60265,7 @@ function bind(client, receipt) {
60184
60265
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
60185
60266
  }
60186
60267
  async function locked(directory2, action) {
60187
- const identity3 = safeDirectory(directory2), file2 = join37(directory2, "operation.lock");
60268
+ const identity3 = safeDirectory(directory2), file2 = join38(directory2, "operation.lock");
60188
60269
  let fd;
60189
60270
  try {
60190
60271
  fd = openSync18(file2, constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
@@ -60200,7 +60281,7 @@ async function locked(directory2, action) {
60200
60281
  } finally {
60201
60282
  closeSync18(fd);
60202
60283
  unchangedDirectory(directory2, identity3);
60203
- const now = lstatSync21(file2);
60284
+ const now = lstatSync22(file2);
60204
60285
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
60205
60286
  fail2();
60206
60287
  unlinkSync6(file2);
@@ -60252,7 +60333,7 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
60252
60333
  phase: "prepared",
60253
60334
  intent: null
60254
60335
  };
60255
- if (!isAbsolute18(recoveryDirectory) || resolve19(recoveryDirectory) !== recoveryDirectory || realpathSync10(dirname23(recoveryDirectory)) !== dirname23(recoveryDirectory))
60336
+ if (!isAbsolute18(recoveryDirectory) || resolve20(recoveryDirectory) !== recoveryDirectory || realpathSync11(dirname23(recoveryDirectory)) !== dirname23(recoveryDirectory))
60256
60337
  return fail2();
60257
60338
  mkdirSync16(recoveryDirectory, { mode: 448 });
60258
60339
  safeDirectory(recoveryDirectory);
@@ -61068,7 +61149,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
61068
61149
  request2[bodyBufferKey] = buffered;
61069
61150
  return Promise.resolve(buffered);
61070
61151
  }
61071
- const promise3 = new Promise((resolve20, reject) => {
61152
+ const promise3 = new Promise((resolve21, reject) => {
61072
61153
  const chunks = [];
61073
61154
  let settled = false;
61074
61155
  const finish = (callback) => {
@@ -61090,7 +61171,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
61090
61171
  reject(error61 ?? normalizeAbortError(request2, incoming));
61091
61172
  else {
61092
61173
  request2[bodyBufferKey] = recovered;
61093
- resolve20(recovered);
61174
+ resolve21(recovered);
61094
61175
  }
61095
61176
  });
61096
61177
  return true;
@@ -61102,7 +61183,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
61102
61183
  finish(() => {
61103
61184
  const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
61104
61185
  request2[bodyBufferKey] = buffer;
61105
- resolve20(buffer);
61186
+ resolve21(buffer);
61106
61187
  });
61107
61188
  };
61108
61189
  const onError = (error61) => {
@@ -61376,7 +61457,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
61376
61457
  });
61377
61458
  if (!chunk) {
61378
61459
  if (i === 1) {
61379
- await new Promise((resolve20) => setTimeout(resolve20));
61460
+ await new Promise((resolve21) => setTimeout(resolve21));
61380
61461
  maxReadCount = 3;
61381
61462
  continue;
61382
61463
  }
@@ -62606,9 +62687,9 @@ data:
62606
62687
  const initRequest = messages.find((m) => isInitializeRequest(m));
62607
62688
  const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
62608
62689
  if (this._enableJsonResponse) {
62609
- return new Promise((resolve20) => {
62690
+ return new Promise((resolve21) => {
62610
62691
  this._streamMapping.set(streamId, {
62611
- resolveJson: resolve20,
62692
+ resolveJson: resolve21,
62612
62693
  cleanup: () => {
62613
62694
  this._streamMapping.delete(streamId);
62614
62695
  }
@@ -62977,19 +63058,19 @@ async function connectMcpForNode() {
62977
63058
  return { server: server2, transport };
62978
63059
  }
62979
63060
  function readBody(req) {
62980
- return new Promise((resolve20, reject) => {
63061
+ return new Promise((resolve21, reject) => {
62981
63062
  const chunks = [];
62982
63063
  req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
62983
63064
  req.on("end", () => {
62984
63065
  const raw = Buffer.concat(chunks).toString("utf-8");
62985
63066
  if (!raw.trim()) {
62986
- resolve20(undefined);
63067
+ resolve21(undefined);
62987
63068
  return;
62988
63069
  }
62989
63070
  try {
62990
- resolve20(JSON.parse(raw));
63071
+ resolve21(JSON.parse(raw));
62991
63072
  } catch {
62992
- resolve20(undefined);
63073
+ resolve21(undefined);
62993
63074
  }
62994
63075
  });
62995
63076
  req.on("error", reject);
@@ -63031,9 +63112,9 @@ async function startSkillsMcpHttpServer(options = {}) {
63031
63112
  }
63032
63113
  }
63033
63114
  });
63034
- await new Promise((resolve20, reject) => {
63115
+ await new Promise((resolve21, reject) => {
63035
63116
  httpServer.once("error", reject);
63036
- httpServer.listen(port, hostname4, () => resolve20());
63117
+ httpServer.listen(port, hostname4, () => resolve21());
63037
63118
  });
63038
63119
  const address = httpServer.address();
63039
63120
  const listenPort = typeof address === "object" && address ? address.port : port;