@gobing-ai/superskill 0.2.18 → 0.2.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +81 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -98521,7 +98521,7 @@ if (false) {}
98521
98521
  // package.json
98522
98522
  var package_default = {
98523
98523
  name: "@gobing-ai/superskill",
98524
- version: "0.2.18",
98524
+ version: "0.2.19",
98525
98525
  description: "A manager for multi-agent skill, slash command, subagent, hook, MCP and etc.",
98526
98526
  keywords: [
98527
98527
  "cli",
@@ -98823,7 +98823,7 @@ function registerHookRun(cmd, readInput) {
98823
98823
  init_src();
98824
98824
  init_dist();
98825
98825
  import {
98826
- copyFileSync as copyFileSync2,
98826
+ copyFileSync,
98827
98827
  existsSync as existsSync18,
98828
98828
  mkdirSync as mkdirSync12,
98829
98829
  readdirSync as readdirSync5,
@@ -98836,7 +98836,7 @@ import { homedir as homedir6 } from "os";
98836
98836
  import { join as join226 } from "path";
98837
98837
 
98838
98838
  // src/hooks.ts
98839
- import { copyFileSync, existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "fs";
98839
+ import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "fs";
98840
98840
  import { join as join223 } from "path";
98841
98841
  var CANONICAL_TO_PI_EVENT = {
98842
98842
  sessionStart: "session_start",
@@ -98888,6 +98888,38 @@ function readCanonicalHooks(rulesyncDir) {
98888
98888
  return null;
98889
98889
  }
98890
98890
  }
98891
+ function mergePiHooks(hooksPath, newHooks) {
98892
+ let existing = {};
98893
+ if (existsSync16(hooksPath)) {
98894
+ try {
98895
+ const raw = JSON.parse(readFileSync15(hooksPath, "utf-8"));
98896
+ if (raw && typeof raw.hooks === "object" && raw.hooks !== null) {
98897
+ existing = raw.hooks;
98898
+ }
98899
+ } catch {
98900
+ existing = {};
98901
+ }
98902
+ }
98903
+ const commandOf = (entry) => typeof entry === "string" ? entry : entry.command;
98904
+ const merged = {};
98905
+ const allEvents = new Set([...Object.keys(existing), ...Object.keys(newHooks)]);
98906
+ for (const event of allEvents) {
98907
+ const ex = existing[event] ?? [];
98908
+ const nx = newHooks[event] ?? [];
98909
+ const seen = new Set;
98910
+ const acc = [];
98911
+ for (const entry of [...ex, ...nx]) {
98912
+ const cmd = commandOf(entry);
98913
+ if (seen.has(cmd))
98914
+ continue;
98915
+ seen.add(cmd);
98916
+ acc.push(entry);
98917
+ }
98918
+ if (acc.length > 0)
98919
+ merged[event] = acc;
98920
+ }
98921
+ return merged;
98922
+ }
98891
98923
  function emitPiStyleHooks(rulesyncDir, outputRoot, targetDir, targetName, options2) {
98892
98924
  const config4 = readCanonicalHooks(rulesyncDir);
98893
98925
  if (!config4?.hooks) {
@@ -98912,7 +98944,8 @@ function emitPiStyleHooks(rulesyncDir, outputRoot, targetDir, targetName, option
98912
98944
  const hooksPath = join223(hooksDir, "hooks.json");
98913
98945
  if (!options2.dryRun) {
98914
98946
  mkdirSync10(hooksDir, { recursive: true });
98915
- writeFileSync9(hooksPath, `${JSON.stringify({ hooks: piHooks }, null, 2)}
98947
+ const merged = mergePiHooks(hooksPath, piHooks);
98948
+ writeFileSync9(hooksPath, `${JSON.stringify({ hooks: merged }, null, 2)}
98916
98949
  `);
98917
98950
  }
98918
98951
  return {
@@ -98923,6 +98956,43 @@ function emitPiStyleHooks(rulesyncDir, outputRoot, targetDir, targetName, option
98923
98956
  message: `${targetName}: ${hookCount} hook(s) emitted (rung b \u2014 @vahor/pi-hooks config; install with: pi install npm:@vahor/pi-hooks)`
98924
98957
  };
98925
98958
  }
98959
+ function mergeCanonicalHooks(hooksPath, newConfig) {
98960
+ let existingHooks = {};
98961
+ if (existsSync16(hooksPath)) {
98962
+ try {
98963
+ const raw = JSON.parse(readFileSync15(hooksPath, "utf-8"));
98964
+ if (raw && typeof raw.hooks === "object" && raw.hooks !== null) {
98965
+ existingHooks = raw.hooks;
98966
+ }
98967
+ } catch {
98968
+ existingHooks = {};
98969
+ }
98970
+ }
98971
+ const signatureOf = (def) => {
98972
+ const matcher = def.matcher ?? "*";
98973
+ const hooks = def.hooks;
98974
+ const commands = Array.isArray(hooks) && hooks.length > 0 ? hooks.filter((h2) => h2.type !== "command" || h2.command !== undefined).map((h2) => `${h2.type}:${h2.command ?? ""}:${h2.timeout ?? ""}`) : [`${def.type ?? ""}:${def.command ?? ""}:${def.timeout ?? ""}`];
98975
+ return `${matcher}|${commands.sort().join("||")}`;
98976
+ };
98977
+ const merged = {};
98978
+ const allEvents = new Set([...Object.keys(existingHooks), ...Object.keys(newConfig.hooks ?? {})]);
98979
+ for (const event of allEvents) {
98980
+ const ex = existingHooks[event] ?? [];
98981
+ const nx = newConfig.hooks?.[event] ?? [];
98982
+ const seen = new Set;
98983
+ const acc = [];
98984
+ for (const def of [...ex, ...nx]) {
98985
+ const sig = signatureOf(def);
98986
+ if (seen.has(sig))
98987
+ continue;
98988
+ seen.add(sig);
98989
+ acc.push(def);
98990
+ }
98991
+ if (acc.length > 0)
98992
+ merged[event] = acc;
98993
+ }
98994
+ return { hooks: merged };
98995
+ }
98926
98996
  function emitHermesHooks(rulesyncDir, outputRoot, options2) {
98927
98997
  const config4 = readCanonicalHooks(rulesyncDir);
98928
98998
  if (!config4?.hooks) {
@@ -98946,14 +99016,16 @@ function emitHermesHooks(rulesyncDir, outputRoot, options2) {
98946
99016
  const hooksPath = join223(hooksDir, "hooks.json");
98947
99017
  if (!options2.dryRun) {
98948
99018
  mkdirSync10(hooksDir, { recursive: true });
98949
- copyFileSync(join223(rulesyncDir, "hooks.json"), hooksPath);
99019
+ const merged = mergeCanonicalHooks(hooksPath, config4);
99020
+ writeFileSync9(hooksPath, `${JSON.stringify(merged, null, 2)}
99021
+ `);
98950
99022
  }
98951
99023
  return {
98952
99024
  target: "hermes",
98953
99025
  emitted: true,
98954
99026
  count: hookCount,
98955
99027
  path: hooksPath,
98956
- message: `hermes: ${hookCount} hook(s) copied (rung c \u2014 copy-step)`
99028
+ message: `hermes: ${hookCount} hook(s) merged (rung c \u2014 copy-step)`
98957
99029
  };
98958
99030
  }
98959
99031
 
@@ -99007,7 +99079,7 @@ function buildModuleContent(hook2) {
99007
99079
  const parts = hook2.command.split(/\s+/).map((p) => `'${p}'`).join(", ");
99008
99080
  const timeoutMs = hook2.timeout ? hook2.timeout * 1000 : undefined;
99009
99081
  const timeoutArg = timeoutMs ? `, timeout: ${timeoutMs}` : "";
99010
- const matcherGuard = hook2.matcher !== "*" && BLOCKABLE_OMP_EVENTS[hook2.ompEvent] === true ? ` if (event.toolName !== '${hook2.matcher}') return;
99082
+ const matcherGuard = hook2.matcher !== "*" && BLOCKABLE_OMP_EVENTS[hook2.ompEvent] === true ? ` if (!new RegExp(${JSON.stringify(hook2.matcher)}, 'i').test(event.toolName)) return;
99011
99083
  ` : "";
99012
99084
  const blockLogic = BLOCKABLE_OMP_EVENTS[hook2.ompEvent] === true ? ` if (result.status === 2) {
99013
99085
  ` + ` return { block: true, reason: String(result.stderr || 'Blocked by ${hook2.name}') };
@@ -99319,7 +99391,7 @@ function postInstallOmp(pluginRoot, installPath, hooksSourceDir, plugin, options
99319
99391
  const sourceManifest = join226(pluginRoot, "plugin.json");
99320
99392
  if (existsSync18(sourceManifest)) {
99321
99393
  mkdirSync12(manifestDir, { recursive: true });
99322
- copyFileSync2(sourceManifest, join226(manifestDir, "plugin.json"));
99394
+ copyFileSync(sourceManifest, join226(manifestDir, "plugin.json"));
99323
99395
  if (options2.verbose)
99324
99396
  echo(` OMP manifest: copied plugin.json \u2192 ${join226(manifestDir, "plugin.json")}`);
99325
99397
  }
@@ -99427,7 +99499,7 @@ function copyDirectory(source, destination, options2 = {}) {
99427
99499
  if (statSync7(sourcePath).isDirectory()) {
99428
99500
  copyDirectory(sourcePath, destinationPath, options2);
99429
99501
  } else {
99430
- copyFileSync2(sourcePath, destinationPath);
99502
+ copyFileSync(sourcePath, destinationPath);
99431
99503
  }
99432
99504
  }
99433
99505
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/superskill",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
4
4
  "description": "A manager for multi-agent skill, slash command, subagent, hook, MCP and etc.",
5
5
  "keywords": [
6
6
  "cli",