@hasna/skills 0.10.10 → 0.10.13

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.10",
20022
+ version: "0.10.13",
20023
20023
  description: "Skills library for AI coding agents",
20024
20024
  type: "module",
20025
20025
  bin: {
package/bin/migrate.js CHANGED
@@ -7,7 +7,7 @@ import { join as join5 } from "path";
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "@hasna/skills",
10
- version: "0.10.10",
10
+ version: "0.10.13",
11
11
  description: "Skills library for AI coding agents",
12
12
  type: "module",
13
13
  bin: {
package/bin/server.js CHANGED
@@ -24122,7 +24122,7 @@ var init_dist_es9 = __esm(() => {
24122
24122
  // package.json
24123
24123
  var package_default = {
24124
24124
  name: "@hasna/skills",
24125
- version: "0.10.10",
24125
+ version: "0.10.13",
24126
24126
  description: "Skills library for AI coding agents",
24127
24127
  type: "module",
24128
24128
  bin: {
@@ -43384,9 +43384,9 @@ class PostgresSkillsStore {
43384
43384
  }
43385
43385
  backend = { kind: "postgres", durable: true, label: "postgres" };
43386
43386
  sql;
43387
- constructor(databaseUrl) {
43387
+ constructor(databaseUrl, connectionOptions = {}) {
43388
43388
  const bunWithSql = Bun;
43389
- this.sql = new bunWithSql.SQL(databaseUrl, { max: resolvePoolMax() });
43389
+ this.sql = new bunWithSql.SQL(databaseUrl, { max: resolvePoolMax(), ...connectionOptions });
43390
43390
  }
43391
43391
  async verifyConnectivity() {
43392
43392
  try {
@@ -43481,7 +43481,7 @@ class PostgresSkillsStore {
43481
43481
  }
43482
43482
  await tx`
43483
43483
  INSERT INTO skills_audit_events (org_id, user_id, api_key_id, action, target_type, target_id, metadata_json)
43484
- VALUES (${actor.orgId}, ${actor.userId}, ${actor.apiKeyId}, ${"api_key_scopes_added"}, ${"api_key"}, ${keyId}, ${JSON.stringify({ added: addScopes, scopes: parseJsonArray(updated[0].scopes_json) })}::jsonb)
43484
+ VALUES (${actor.orgId}, ${actor.userId}, ${actor.apiKeyId}, ${"api_key_scopes_added"}, ${"api_key"}, ${keyId}, ${JSON.stringify({ added: addScopes, scopes: parseJsonArray(updated[0].scopes_json) })}::text::jsonb)
43485
43485
  `;
43486
43486
  return { kind: "updated", scopes: parseJsonArray(updated[0].scopes_json) };
43487
43487
  });
@@ -43490,9 +43490,9 @@ class PostgresSkillsStore {
43490
43490
  const current = expectedScopes;
43491
43491
  const scopes = [...current, ...addScopes.filter((scope2) => !current.includes(scope2))];
43492
43492
  return tx`
43493
- UPDATE api_keys SET scopes_json = ${JSON.stringify(scopes)}::jsonb
43493
+ UPDATE api_keys SET scopes_json = ${JSON.stringify(scopes)}::text::jsonb
43494
43494
  WHERE id = ${keyId} AND org_id = ${orgId} AND revoked_at IS NULL
43495
- AND scopes_json = ${JSON.stringify(expectedScopes)}::jsonb
43495
+ AND scopes_json = ${JSON.stringify(expectedScopes)}::text::jsonb
43496
43496
  RETURNING scopes_json
43497
43497
  `;
43498
43498
  }
@@ -43552,7 +43552,7 @@ class PostgresSkillsStore {
43552
43552
  operator_task_arn: input.operatorTaskArn,
43553
43553
  target_manifest_digest: input.manifestDigest,
43554
43554
  station_id: input.stationId
43555
- })}::jsonb)
43555
+ })}::text::jsonb)
43556
43556
  `;
43557
43557
  return { kind: "updated", scopes };
43558
43558
  });
package/bin/worker.js CHANGED
@@ -24125,7 +24125,7 @@ import { randomUUID as randomUUID6 } from "crypto";
24125
24125
  // package.json
24126
24126
  var package_default = {
24127
24127
  name: "@hasna/skills",
24128
- version: "0.10.10",
24128
+ version: "0.10.13",
24129
24129
  description: "Skills library for AI coding agents",
24130
24130
  type: "module",
24131
24131
  bin: {
@@ -36913,9 +36913,9 @@ class PostgresSkillsStore {
36913
36913
  }
36914
36914
  backend = { kind: "postgres", durable: true, label: "postgres" };
36915
36915
  sql;
36916
- constructor(databaseUrl) {
36916
+ constructor(databaseUrl, connectionOptions = {}) {
36917
36917
  const bunWithSql = Bun;
36918
- this.sql = new bunWithSql.SQL(databaseUrl, { max: resolvePoolMax() });
36918
+ this.sql = new bunWithSql.SQL(databaseUrl, { max: resolvePoolMax(), ...connectionOptions });
36919
36919
  }
36920
36920
  async verifyConnectivity() {
36921
36921
  try {
@@ -37010,7 +37010,7 @@ class PostgresSkillsStore {
37010
37010
  }
37011
37011
  await tx`
37012
37012
  INSERT INTO skills_audit_events (org_id, user_id, api_key_id, action, target_type, target_id, metadata_json)
37013
- VALUES (${actor.orgId}, ${actor.userId}, ${actor.apiKeyId}, ${"api_key_scopes_added"}, ${"api_key"}, ${keyId}, ${JSON.stringify({ added: addScopes, scopes: parseJsonArray(updated[0].scopes_json) })}::jsonb)
37013
+ VALUES (${actor.orgId}, ${actor.userId}, ${actor.apiKeyId}, ${"api_key_scopes_added"}, ${"api_key"}, ${keyId}, ${JSON.stringify({ added: addScopes, scopes: parseJsonArray(updated[0].scopes_json) })}::text::jsonb)
37014
37014
  `;
37015
37015
  return { kind: "updated", scopes: parseJsonArray(updated[0].scopes_json) };
37016
37016
  });
@@ -37019,9 +37019,9 @@ class PostgresSkillsStore {
37019
37019
  const current = expectedScopes;
37020
37020
  const scopes = [...current, ...addScopes.filter((scope) => !current.includes(scope))];
37021
37021
  return tx`
37022
- UPDATE api_keys SET scopes_json = ${JSON.stringify(scopes)}::jsonb
37022
+ UPDATE api_keys SET scopes_json = ${JSON.stringify(scopes)}::text::jsonb
37023
37023
  WHERE id = ${keyId} AND org_id = ${orgId} AND revoked_at IS NULL
37024
- AND scopes_json = ${JSON.stringify(expectedScopes)}::jsonb
37024
+ AND scopes_json = ${JSON.stringify(expectedScopes)}::text::jsonb
37025
37025
  RETURNING scopes_json
37026
37026
  `;
37027
37027
  }
@@ -37081,7 +37081,7 @@ class PostgresSkillsStore {
37081
37081
  operator_task_arn: input.operatorTaskArn,
37082
37082
  target_manifest_digest: input.manifestDigest,
37083
37083
  station_id: input.stationId
37084
- })}::jsonb)
37084
+ })}::text::jsonb)
37085
37085
  `;
37086
37086
  return { kind: "updated", scopes };
37087
37087
  });
package/dist/index.js CHANGED
@@ -9611,7 +9611,7 @@ import { isAbsolute as isAbsolute11, join as join23, resolve as resolve11 } from
9611
9611
  // package.json
9612
9612
  var package_default = {
9613
9613
  name: "@hasna/skills",
9614
- version: "0.10.10",
9614
+ version: "0.10.13",
9615
9615
  description: "Skills library for AI coding agents",
9616
9616
  type: "module",
9617
9617
  bin: {
@@ -12812,6 +12812,196 @@ function isOwnedCliBridge(path, expectedPaths) {
12812
12812
  // src/lib/agent-codex.ts
12813
12813
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
12814
12814
  var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^\n]*)*/gm;
12815
+ var codexPathConfigRefusal = () => new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables or a native single-line inline array; preserve and review unsupported inline, dotted, or malformed definitions before running skills hook install");
12816
+ function splitTopLevel(value, delimiter) {
12817
+ const result = [];
12818
+ let start = 0, square = 0, curly = 0, quote = null, escaped = false;
12819
+ for (let index = 0;index < value.length; index++) {
12820
+ const char = value[index];
12821
+ if (quote === "double") {
12822
+ if (escaped)
12823
+ escaped = false;
12824
+ else if (char === "\\")
12825
+ escaped = true;
12826
+ else if (char === '"')
12827
+ quote = null;
12828
+ continue;
12829
+ }
12830
+ if (quote === "literal") {
12831
+ if (char === "'")
12832
+ quote = null;
12833
+ continue;
12834
+ }
12835
+ if (char === '"') {
12836
+ quote = "double";
12837
+ continue;
12838
+ }
12839
+ if (char === "'") {
12840
+ quote = "literal";
12841
+ continue;
12842
+ }
12843
+ if (char === "[")
12844
+ square++;
12845
+ else if (char === "]") {
12846
+ if (--square < 0)
12847
+ return null;
12848
+ } else if (char === "{")
12849
+ curly++;
12850
+ else if (char === "}") {
12851
+ if (--curly < 0)
12852
+ return null;
12853
+ } else if (char === delimiter && square === 0 && curly === 0) {
12854
+ result.push(value.slice(start, index));
12855
+ start = index + 1;
12856
+ }
12857
+ }
12858
+ if (quote !== null || square !== 0 || curly !== 0)
12859
+ return null;
12860
+ result.push(value.slice(start));
12861
+ return result;
12862
+ }
12863
+ function inlineArrayEnd(value) {
12864
+ if (!value.startsWith("["))
12865
+ return null;
12866
+ let square = 0, curly = 0, quote = null, escaped = false;
12867
+ for (let index = 0;index < value.length; index++) {
12868
+ const char = value[index];
12869
+ if (quote === "double") {
12870
+ if (escaped)
12871
+ escaped = false;
12872
+ else if (char === "\\")
12873
+ escaped = true;
12874
+ else if (char === '"')
12875
+ quote = null;
12876
+ continue;
12877
+ }
12878
+ if (quote === "literal") {
12879
+ if (char === "'")
12880
+ quote = null;
12881
+ continue;
12882
+ }
12883
+ if (char === '"') {
12884
+ quote = "double";
12885
+ continue;
12886
+ }
12887
+ if (char === "'") {
12888
+ quote = "literal";
12889
+ continue;
12890
+ }
12891
+ if (char === "[")
12892
+ square++;
12893
+ else if (char === "]") {
12894
+ if (--square < 0)
12895
+ return null;
12896
+ if (square === 0 && curly === 0)
12897
+ return index;
12898
+ } else if (char === "{")
12899
+ curly++;
12900
+ else if (char === "}") {
12901
+ if (--curly < 0)
12902
+ return null;
12903
+ }
12904
+ }
12905
+ return null;
12906
+ }
12907
+ function inlineRowsAsTables(value, newline) {
12908
+ const end = inlineArrayEnd(value);
12909
+ if (end === null || value.slice(end + 1).trim() !== "" || value.includes(`
12910
+ `) || value.includes("\r"))
12911
+ return null;
12912
+ const elements = splitTopLevel(value.slice(1, end), ",");
12913
+ if (!elements)
12914
+ return null;
12915
+ const rows = elements.map((element) => element.trim()).filter(Boolean);
12916
+ if (rows.length === 0)
12917
+ return "";
12918
+ const sections = [];
12919
+ for (const row of rows) {
12920
+ if (!row.startsWith("{") || !row.endsWith("}"))
12921
+ return null;
12922
+ const fields = splitTopLevel(row.slice(1, -1), ",");
12923
+ if (!fields)
12924
+ return null;
12925
+ const lines = fields.map((field) => field.trim()).filter(Boolean);
12926
+ if (lines.some((line) => !/^(?:path|name|enabled)\s*=/.test(line)))
12927
+ return null;
12928
+ const keys = lines.map((line) => line.slice(0, line.indexOf("=")).trim());
12929
+ if (new Set(keys).size !== keys.length)
12930
+ return null;
12931
+ sections.push(`[[skills.config]]${newline}${lines.join(newline)}${newline}`);
12932
+ }
12933
+ return sections.join("");
12934
+ }
12935
+ function normalizeCodexInlinePathConfig(text2) {
12936
+ const before = Bun.TOML.parse(text2);
12937
+ if (!Array.isArray(before.skills?.config))
12938
+ return text2;
12939
+ if (before.skills.config.length === 0)
12940
+ throw codexPathConfigRefusal();
12941
+ const expectedWithoutConfig = structuredClone(before);
12942
+ delete expectedWithoutConfig.skills.config;
12943
+ try {
12944
+ if (isDeepStrictEqual2(Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, "")), expectedWithoutConfig))
12945
+ return text2;
12946
+ } catch {}
12947
+ const matches = [];
12948
+ for (const assignment of text2.matchAll(/^([ \t]*config[ \t]*=[ \t]*)(.*?)(\r?)$/gm)) {
12949
+ const rawValue = assignment[2].trimEnd();
12950
+ let quote = null, escaped = false, comment = "";
12951
+ for (let index = 0;index < rawValue.length; index++) {
12952
+ const char = rawValue[index];
12953
+ if (quote === "double") {
12954
+ if (escaped)
12955
+ escaped = false;
12956
+ else if (char === "\\")
12957
+ escaped = true;
12958
+ else if (char === '"')
12959
+ quote = null;
12960
+ continue;
12961
+ }
12962
+ if (quote === "literal") {
12963
+ if (char === "'")
12964
+ quote = null;
12965
+ continue;
12966
+ }
12967
+ if (char === '"')
12968
+ quote = "double";
12969
+ else if (char === "'")
12970
+ quote = "literal";
12971
+ else if (char === "#") {
12972
+ comment = rawValue.slice(index);
12973
+ break;
12974
+ }
12975
+ }
12976
+ const value = comment ? rawValue.slice(0, rawValue.length - comment.length).trimEnd() : rawValue;
12977
+ const tableSections = inlineRowsAsTables(value, text2.includes(`\r
12978
+ `) ? `\r
12979
+ ` : `
12980
+ `);
12981
+ if (tableSections === null)
12982
+ continue;
12983
+ const start = assignment.index;
12984
+ const end = start + assignment[0].length;
12985
+ const withoutAssignment = text2.slice(0, start) + (comment ? comment : "") + assignment[3] + text2.slice(end);
12986
+ const separator = withoutAssignment.endsWith(`
12987
+ `) ? withoutAssignment.endsWith(`
12988
+
12989
+ `) ? "" : `
12990
+ ` : `
12991
+
12992
+ `;
12993
+ const candidate = withoutAssignment + (tableSections ? separator + tableSections : "");
12994
+ try {
12995
+ const after = Bun.TOML.parse(candidate);
12996
+ const expected = structuredClone(before);
12997
+ if (isDeepStrictEqual2(after, expected))
12998
+ matches.push(candidate);
12999
+ } catch {}
13000
+ }
13001
+ if (matches.length !== 1)
13002
+ throw codexPathConfigRefusal();
13003
+ return matches[0];
13004
+ }
12815
13005
  function assertCodexPathConfigEditable(text2) {
12816
13006
  const before = Bun.TOML.parse(text2);
12817
13007
  if (before.skills?.config === undefined)
@@ -12822,8 +13012,12 @@ function assertCodexPathConfigEditable(text2) {
12822
13012
  const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
12823
13013
  if (isDeepStrictEqual2(withoutSections, expected))
12824
13014
  return;
13015
+ const normalized = normalizeCodexInlinePathConfig(text2);
13016
+ const withoutNormalizedSections = Bun.TOML.parse(normalized.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
13017
+ if (isDeepStrictEqual2(withoutNormalizedSections, expected))
13018
+ return;
12825
13019
  } catch {}
12826
- throw new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables; preserve and convert inline or dotted config arrays before running skills hook install");
13020
+ throw codexPathConfigRefusal();
12827
13021
  }
12828
13022
  function disableCodexBundledSkills(text2) {
12829
13023
  const before = Bun.TOML.parse(text2);
@@ -13227,6 +13421,33 @@ function canonicalAgentPath(path, aliases) {
13227
13421
  const absolute = resolve9(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep4));
13228
13422
  return binding ? join16(binding.target, relative4(binding.alias, absolute)) : absolute;
13229
13423
  }
13424
+ function disabledCodexSkillPaths(config, aliases) {
13425
+ const skills = config.skills;
13426
+ if (!skills || typeof skills !== "object" || Array.isArray(skills))
13427
+ return [];
13428
+ const rows = skills.config;
13429
+ if (!Array.isArray(rows))
13430
+ return [];
13431
+ if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined && (typeof entry.path !== "string" || !isAbsolute9(entry.path)) || entry.name !== undefined && typeof entry.name !== "string"))
13432
+ return [];
13433
+ if (rows.some((entry) => entry.name !== undefined))
13434
+ return [];
13435
+ const settings = new Map;
13436
+ for (const entry of rows) {
13437
+ if (typeof entry.path !== "string" || !isAbsolute9(entry.path))
13438
+ continue;
13439
+ let document2;
13440
+ try {
13441
+ document2 = realpathSync3(canonicalAgentPath(entry.path, aliases));
13442
+ } catch {
13443
+ continue;
13444
+ }
13445
+ if (!document2.endsWith(`${sep4}SKILL.md`))
13446
+ continue;
13447
+ settings.set(document2, [...settings.get(document2) ?? [], entry.enabled === false]);
13448
+ }
13449
+ return [...settings].filter(([, values]) => values.length === 1 && values[0] === true).map(([document2]) => dirname10(document2));
13450
+ }
13230
13451
  function recheckRootAliases(aliases) {
13231
13452
  for (const binding of aliases) {
13232
13453
  if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join16(binding.home, `.${binding.agent}`))
@@ -13336,6 +13557,9 @@ function projectAncestorDirectories(projects) {
13336
13557
  function inventoryNativeSkills(home = homedir2(), options = {}) {
13337
13558
  if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute9(options.reviewedCacheAlias) || resolve9(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
13338
13559
  throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
13560
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute9(path) || resolve9(path) !== path))
13561
+ throw new Error("Disabled vendor paths must be exact absolute paths");
13562
+ const disabledVendorPaths = new Set(options.disabledVendorPaths ?? []);
13339
13563
  const aliases = rootAliases(home, options.allowRootAliases);
13340
13564
  const selectedAgents = options.agents ? new Set(options.agents) : undefined;
13341
13565
  const includesAgent = (agent) => !selectedAgents || selectedAgents.has(agent);
@@ -13357,7 +13581,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
13357
13581
  throw new Error("Native skill discovery metadata limit exceeded");
13358
13582
  }
13359
13583
  let reviewedCacheAliasFound = false;
13360
- function verifiedSiblingCacheAlias(path, parent) {
13584
+ function verifiedSiblingCacheAlias(agent, path, parent) {
13361
13585
  const link = readlinkSync3(path), target = resolve9(parent, link);
13362
13586
  if (dirname10(target) !== parent || (isAbsolute9(link) ? link !== target : dirname10(link) !== "."))
13363
13587
  return false;
@@ -13367,9 +13591,13 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
13367
13591
  if (!scan?.complete || scan.entries > maxAliasProofEntries)
13368
13592
  return false;
13369
13593
  if (scan.hasSkills) {
13594
+ const targetSkills = entries.filter((entry) => entry.agent === agent && entry.vendor && (entry.path === target || entry.path.startsWith(target + sep4)));
13595
+ if (path === options.reviewedCacheAlias && targetSkills.length > 0)
13596
+ reviewedCacheAliasFound = true;
13597
+ if (agent === "codex" && targetSkills.length > 0 && targetSkills.every((entry) => disabledVendorPaths.has(entry.path)))
13598
+ return true;
13370
13599
  if (path !== options.reviewedCacheAlias)
13371
13600
  return false;
13372
- reviewedCacheAliasFound = true;
13373
13601
  }
13374
13602
  return true;
13375
13603
  }
@@ -13428,7 +13656,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
13428
13656
  const child = join16(path, name);
13429
13657
  if (isVendor && lstatSync14(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
13430
13658
  const target = statSync7(child, { throwIfNoEntry: false });
13431
- if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(child, path)) {
13659
+ if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child, path)) {
13432
13660
  scan.entries++;
13433
13661
  continue;
13434
13662
  }
@@ -13568,7 +13796,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
13568
13796
  }
13569
13797
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
13570
13798
  const bundled = disableCodexBundledSkills(text2);
13571
- let result = bundled;
13799
+ let result = normalizeCodexInlinePathConfig(bundled);
13572
13800
  const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve9(bridgePath), resolve9(join16(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
13573
13801
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
13574
13802
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
@@ -13636,7 +13864,8 @@ function planAgentIntegration(options) {
13636
13864
  }
13637
13865
  return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases) });
13638
13866
  });
13639
- const nativeSkills = inventoryNativeSkills(home, { includeVendor: true, guardHermes: options.agents.includes("hermes"), agents: options.agents, projectDir: options.projectDir, agentRoots: discoveries.flatMap((binding) => binding.roots.map((path) => ({ agent: binding.agent, path }))), allowRootAliases: options.allowRootAliases });
13867
+ const codexConfig = options.agents.includes("codex") ? Bun.TOML.parse(readOptional(canonicalAgentPath(join16(home, ".codex", "config.toml"), aliases)) ?? "") : {};
13868
+ const nativeSkills = inventoryNativeSkills(home, { includeVendor: true, guardHermes: options.agents.includes("hermes"), agents: options.agents, projectDir: options.projectDir, agentRoots: discoveries.flatMap((binding) => binding.roots.map((path) => ({ agent: binding.agent, path }))), allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, disabledVendorPaths: disabledCodexSkillPaths(codexConfig, aliases) });
13640
13869
  const changes = [];
13641
13870
  for (const agent of [...new Set(options.agents)]) {
13642
13871
  if (!INTEGRATION_AGENTS.includes(agent))
@@ -14158,7 +14387,7 @@ function assertManagedAgentBridge(agent, options = {}) {
14158
14387
  } catch (error) {
14159
14388
  throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
14160
14389
  }
14161
- const inventory = inventoryNativeSkills(home, { includeVendor: true, guardHermes: agent === "hermes", agents: [agent], projectDirs: [...roots], agentRoots: discovery.roots.map((path) => ({ agent, path })), allowRootAliases: aliases.length > 0 });
14390
+ const inventory = inventoryNativeSkills(home, { includeVendor: true, guardHermes: agent === "hermes", agents: [agent], projectDirs: [...roots], agentRoots: discovery.roots.map((path) => ({ agent, path })), allowRootAliases: aliases.length > 0, disabledVendorPaths: agent === "codex" ? disabledCodexSkillPaths(codexConfig, aliases) : [] });
14162
14391
  const unexpected = inventory.filter((entry) => visible(entry) && !entry.bridge && !disabledVendorSkill(entry));
14163
14392
  if (unexpected.length) {
14164
14393
  const paths = unexpected.slice(0, 3).map((entry) => {
@@ -1,7 +1,11 @@
1
1
  export declare const CODEX_SKILL_CONFIG_SECTIONS: RegExp;
2
- /** The path editor supports ordinary array-of-table sections only. Removing
3
- * those sections must remove exactly the parsed path array, with all other
4
- * values unchanged. This also excludes header-like text inside user strings. */
2
+ /** Convert only Codex's native, single-line inline array representation into
3
+ * equivalent array-of-table sections. The replacement is accepted only when
4
+ * the complete parsed TOML value is deeply identical before and after. */
5
+ export declare function normalizeCodexInlinePathConfig(text: string): string;
6
+ /** Removing supported path sections must remove exactly the parsed skill path
7
+ * array while preserving every other TOML value. Native app-server inline
8
+ * arrays are first normalized by a targeted, semantically verified edit. */
5
9
  export declare function assertCodexPathConfigEditable(text: string): void;
6
10
  /** Preserve user TOML verbatim except for the supported bundled-skill control.
7
11
  * Bun's parser accepts some illegal table reopenings, so never append a table
@@ -86,6 +86,7 @@ export declare function inventoryNativeSkills(home?: string, options?: {
86
86
  discoveryInputs?: ReviewedDiscoveryInputs;
87
87
  allowRootAliases?: boolean;
88
88
  reviewedCacheAlias?: string;
89
+ disabledVendorPaths?: readonly string[];
89
90
  }): NativeSkillEntry[];
90
91
  /** Planning is read-only; credentials and unrelated settings never appear in CLI output. */
91
92
  export declare function planAgentIntegration(options: {
@@ -98,6 +99,7 @@ export declare function planAgentIntegration(options: {
98
99
  projectDir?: string;
99
100
  discoveryInputs?: ReviewedDiscoveryInputs;
100
101
  allowRootAliases?: boolean;
102
+ reviewedCacheAlias?: string;
101
103
  }): AgentIntegrationPlan;
102
104
  /** Plan an explicitly authorized Stop hook replacement without adopting drift.
103
105
  * The caller owns authorization of its exact Stop hook delta; Skills refuses
@@ -1,4 +1,4 @@
1
- export declare const SUPPORTED_CODEX_HOOK_VERSIONS: readonly ["codex-cli 0.153.0", "codex-cli 0.154.0", "codex-cli 0.155.0", "codex-cli 0.155.1", "codex-cli 0.156.1", "codex-cli 0.157.0", "codex-cli 0.157.1"];
1
+ export declare const SUPPORTED_CODEX_HOOK_VERSIONS: readonly ["codex-cli 0.153.0", "codex-cli 0.154.0", "codex-cli 0.155.0", "codex-cli 0.155.1", "codex-cli 0.156.1", "codex-cli 0.157.0", "codex-cli 0.157.1", "codex-cli 0.158.0"];
2
2
  export interface CodexHookRpc {
3
3
  version: string;
4
4
  processId?: number;