@gobing-ai/superskill 0.2.5 → 0.2.7

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 +290 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -40829,7 +40829,7 @@ var init_dist5 = __esm(() => {
40829
40829
  });
40830
40830
 
40831
40831
  // ../../packages/core/src/targets.ts
40832
- var TARGETS, TARGET_TO_RULESYNC, TARGET_SKILLS_RELDIR, TARGET_TO_AGENT_NAME;
40832
+ var TARGETS, TARGET_TO_RULESYNC, TARGET_TO_RULESYNC_HOOKS, TARGET_SKILLS_RELDIR, TARGET_TO_AGENT_NAME;
40833
40833
  var init_targets = __esm(() => {
40834
40834
  TARGETS = [
40835
40835
  "claude",
@@ -40848,6 +40848,12 @@ var init_targets = __esm(() => {
40848
40848
  "antigravity-cli": "codexcli",
40849
40849
  "antigravity-ide": "codexcli"
40850
40850
  };
40851
+ TARGET_TO_RULESYNC_HOOKS = {
40852
+ codex: "codexcli",
40853
+ opencode: "opencode",
40854
+ "antigravity-cli": "antigravity-cli",
40855
+ "antigravity-ide": "antigravity-ide"
40856
+ };
40851
40857
  TARGET_SKILLS_RELDIR = {
40852
40858
  codex: ".agents/skills",
40853
40859
  pi: ".agents/skills",
@@ -89666,9 +89672,10 @@ var init_dist9 = __esm(() => {
89666
89672
  // ../../packages/core/src/rulesync.ts
89667
89673
  import { homedir as homedir5 } from "os";
89668
89674
  async function runRulesync(targets, features, inputRoot, options2) {
89675
+ const targetMap = options2.targetMap ?? TARGET_TO_RULESYNC;
89669
89676
  const mappedTargets = [];
89670
89677
  for (const target of targets) {
89671
- const rt = TARGET_TO_RULESYNC[target];
89678
+ const rt = targetMap[target];
89672
89679
  if (rt)
89673
89680
  mappedTargets.push(rt);
89674
89681
  }
@@ -97508,6 +97515,271 @@ init_dist();
97508
97515
  import { homedir as homedir7 } from "os";
97509
97516
  import { join as join225 } from "path";
97510
97517
 
97518
+ // src/commands/hook-run.ts
97519
+ init_dist();
97520
+ import { spawnSync as spawnSync2 } from "child_process";
97521
+
97522
+ // ../../plugins/cc/scripts/anti-hallucination/ah_guard.ts
97523
+ var SOURCE_PATTERNS = [
97524
+ /\[Source:\s*[^\]]+\]/i,
97525
+ /Source:\s*\[?[^\n]+\]?/i,
97526
+ /Sources:\s*\n\s*-\s*\[?[^\n]+\]/i,
97527
+ /https?:\/\/[^\s)]+/i,
97528
+ /\*\*Source\*\*:\s*[^\n]+/i
97529
+ ];
97530
+ var CONFIDENCE_PATTERNS = [
97531
+ /Confidence:\s*(HIGH|MEDIUM|LOW)/i,
97532
+ /\*\*Confidence\*\*:\s*(HIGH|MEDIUM|LOW)/i,
97533
+ /### Confidence/i
97534
+ ];
97535
+ var TOOL_PATTERNS = [
97536
+ /ref_search_documentation/,
97537
+ /ref_read_url/,
97538
+ /searchCode/,
97539
+ /WebSearch/,
97540
+ /WebFetch/,
97541
+ /mcp__ref__ref_search_documentation/,
97542
+ /mcp__ref__ref_read_url/,
97543
+ /mcp__grep__searchCode/
97544
+ ];
97545
+ var RED_FLAG_PATTERNS = [
97546
+ /I (?:think|believe|recall) (?:that|the)?/gi,
97547
+ /(?:It|This) (?:should|might|may|could)/gi,
97548
+ /Probably|Likely|Possibly/gi,
97549
+ /(?:As far as|If I) (?:know|recall)/gi
97550
+ ];
97551
+ function buildStopOutput(result) {
97552
+ if (result.ok) {
97553
+ return JSON.stringify({
97554
+ hookSpecificOutput: { hookEventName: "Stop", additionalContext: result.reason }
97555
+ });
97556
+ }
97557
+ return JSON.stringify({
97558
+ decision: "block",
97559
+ reason: result.reason,
97560
+ hookSpecificOutput: { hookEventName: "Stop" }
97561
+ });
97562
+ }
97563
+ function extractLastAssistantMessage(context3) {
97564
+ const messages2 = context3.messages ?? [];
97565
+ for (let i2 = messages2.length - 1;i2 >= 0; i2--) {
97566
+ const message = messages2[i2];
97567
+ if (message?.role === "assistant") {
97568
+ const content = message.content;
97569
+ if (Array.isArray(content)) {
97570
+ const textParts = [];
97571
+ for (const part of content) {
97572
+ if (part.type === "text" && part.text) {
97573
+ textParts.push(part.text);
97574
+ }
97575
+ }
97576
+ return textParts.join(`
97577
+ `);
97578
+ }
97579
+ return String(content);
97580
+ }
97581
+ }
97582
+ const lastMsg = context3.last_message;
97583
+ if (lastMsg) {
97584
+ return String(lastMsg);
97585
+ }
97586
+ return;
97587
+ }
97588
+ function hasSourceCitations(text3) {
97589
+ if (!text3)
97590
+ return false;
97591
+ for (const pattern of SOURCE_PATTERNS) {
97592
+ if (pattern.test(text3)) {
97593
+ return true;
97594
+ }
97595
+ }
97596
+ return false;
97597
+ }
97598
+ function hasConfidenceLevel(text3) {
97599
+ if (!text3)
97600
+ return false;
97601
+ for (const pattern of CONFIDENCE_PATTERNS) {
97602
+ if (pattern.test(text3)) {
97603
+ return true;
97604
+ }
97605
+ }
97606
+ return false;
97607
+ }
97608
+ function hasToolUsageEvidence(text3) {
97609
+ if (!text3)
97610
+ return false;
97611
+ for (const pattern of TOOL_PATTERNS) {
97612
+ if (pattern.test(text3)) {
97613
+ return true;
97614
+ }
97615
+ }
97616
+ return false;
97617
+ }
97618
+ function hasRedFlags(text3) {
97619
+ if (!text3)
97620
+ return [];
97621
+ const foundFlags = [];
97622
+ for (const pattern of RED_FLAG_PATTERNS) {
97623
+ const matches = text3.match(pattern);
97624
+ if (matches) {
97625
+ foundFlags.push(...matches);
97626
+ }
97627
+ }
97628
+ return foundFlags;
97629
+ }
97630
+ function requiresExternalVerification(text3) {
97631
+ if (!text3)
97632
+ return false;
97633
+ const verificationKeywords = [
97634
+ "api",
97635
+ "library",
97636
+ "framework",
97637
+ "method",
97638
+ "function",
97639
+ "version",
97640
+ "documentation",
97641
+ "official",
97642
+ /recent\s+(?:change|update|release)/i,
97643
+ /\d+\.\d+(?:\.\d+)?/,
97644
+ /https?:\/\//
97645
+ ];
97646
+ const textLower = text3.toLowerCase();
97647
+ for (const keyword of verificationKeywords) {
97648
+ if (typeof keyword === "string") {
97649
+ if (textLower.includes(keyword)) {
97650
+ return true;
97651
+ }
97652
+ } else if (keyword.test(textLower)) {
97653
+ return true;
97654
+ }
97655
+ }
97656
+ return false;
97657
+ }
97658
+ function verifyAntiHallucinationProtocol(text3) {
97659
+ if (!text3 || text3.trim().length < 50) {
97660
+ return { ok: true, reason: "Task is complete" };
97661
+ }
97662
+ const needsVerification = requiresExternalVerification(text3);
97663
+ if (!needsVerification) {
97664
+ return { ok: true, reason: "Task is complete (internal discussion)" };
97665
+ }
97666
+ const hasSources = hasSourceCitations(text3);
97667
+ const hasConfidence = hasConfidenceLevel(text3);
97668
+ const hasTools = hasToolUsageEvidence(text3);
97669
+ const redFlags = hasRedFlags(text3);
97670
+ const issues = [];
97671
+ if (!hasSources) {
97672
+ issues.push("source citations for API/library claims");
97673
+ }
97674
+ if (!hasConfidence) {
97675
+ issues.push("confidence level (HIGH/MEDIUM/LOW)");
97676
+ }
97677
+ if (redFlags.length > 0 && !hasTools) {
97678
+ const uniqueFlags = Array.from(new Set(redFlags)).slice(0, 3);
97679
+ issues.push(`uncertainty phrases detected: ${uniqueFlags.join(", ")}`);
97680
+ }
97681
+ if (issues.length > 0) {
97682
+ const reason = `Add verification for: ${issues.join(", ")}`;
97683
+ return { ok: false, reason, issues };
97684
+ }
97685
+ return { ok: true, reason: "Task is complete" };
97686
+ }
97687
+ if (false) {}
97688
+
97689
+ // src/commands/hook-run.ts
97690
+ function preToolUseDecision(decision, reason) {
97691
+ const out = {
97692
+ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: decision }
97693
+ };
97694
+ if (reason !== undefined)
97695
+ out.systemMessage = reason;
97696
+ return { output: JSON.stringify(out), exitCode: 0 };
97697
+ }
97698
+ function resolveSpurTaskOwnership(filePath, cwd5) {
97699
+ const res = spawnSync2("spur", ["task", "resolve", filePath, "--strict", "--json"], {
97700
+ cwd: cwd5,
97701
+ encoding: "utf-8",
97702
+ timeout: 8000
97703
+ });
97704
+ if (res.error || typeof res.status !== "number")
97705
+ return "unknown";
97706
+ return res.status === 0 ? "owned" : "unowned";
97707
+ }
97708
+ function runSpTaskWriteGuard(env, stdinText, resolveTaskOwnership = resolveSpurTaskOwnership) {
97709
+ if (env.SPUR_WRITE_GUARD === "off")
97710
+ return preToolUseDecision("allow");
97711
+ let payload;
97712
+ try {
97713
+ payload = JSON.parse(stdinText);
97714
+ } catch {
97715
+ return preToolUseDecision("allow");
97716
+ }
97717
+ const toolName = payload.tool_name ?? "";
97718
+ if (toolName !== "Write" && toolName !== "Edit")
97719
+ return preToolUseDecision("allow");
97720
+ const filePath = payload.tool_input?.file_path ?? "";
97721
+ if (filePath === "")
97722
+ return preToolUseDecision("allow");
97723
+ const ownership = resolveTaskOwnership(filePath, env.CLAUDE_PROJECT_DIR ?? process.cwd());
97724
+ if (ownership === "owned") {
97725
+ return preToolUseDecision("deny", `${filePath} is a task file owned by the spur corpus. Edit it through the spur CLI ` + "(e.g. `spur task update <wbs> --section <name> --from-file <file>`), not a raw " + "Write/Edit. Set SPUR_WRITE_GUARD=off to bypass.");
97726
+ }
97727
+ return preToolUseDecision("allow");
97728
+ }
97729
+ var spTaskWriteGuard = {
97730
+ run: runSpTaskWriteGuard
97731
+ };
97732
+ var ccAntiHallucination = {
97733
+ run(env) {
97734
+ const argumentsJson = env.ARGUMENTS ?? "{}";
97735
+ const allowStop = (feedback, ok) => ({
97736
+ output: buildStopOutput({ ok, reason: feedback }),
97737
+ exitCode: ok ? 0 : 1
97738
+ });
97739
+ let context3;
97740
+ try {
97741
+ context3 = JSON.parse(argumentsJson);
97742
+ } catch {
97743
+ return allowStop("Task is complete (invalid context ignored)", true);
97744
+ }
97745
+ const content = extractLastAssistantMessage(context3);
97746
+ if (content === undefined)
97747
+ return allowStop("No content to verify", true);
97748
+ const result = verifyAntiHallucinationProtocol(content);
97749
+ return allowStop(result.reason, result.ok);
97750
+ }
97751
+ };
97752
+ var HOOK_RUNNERS = {
97753
+ "sp/task-write-guard": spTaskWriteGuard,
97754
+ "cc/anti-hallucination": ccAntiHallucination
97755
+ };
97756
+ function hookRun(plugin, hookId, env, stdinText) {
97757
+ const runner = HOOK_RUNNERS[`${plugin}/${hookId}`];
97758
+ if (!runner) {
97759
+ echoError(`Error: unknown hook '${plugin} ${hookId}'. Known hooks: ${Object.keys(HOOK_RUNNERS).join(", ")}`);
97760
+ return 2;
97761
+ }
97762
+ const result = runner.run(env, stdinText);
97763
+ echo(result.output);
97764
+ return result.exitCode;
97765
+ }
97766
+ function registerHookRun(cmd, readInput) {
97767
+ cmd.command("run <plugin> <hook-id>").description("Run a registered plugin hook runner (the runtime command installed hook configs call)").action((plugin, hookId) => {
97768
+ let stdinText = "";
97769
+ if (readInput) {
97770
+ stdinText = readInput();
97771
+ } else {
97772
+ try {
97773
+ stdinText = __require("fs").readFileSync(0, "utf-8");
97774
+ } catch {
97775
+ stdinText = "";
97776
+ }
97777
+ }
97778
+ const code = hookRun(plugin, hookId, process.env, stdinText);
97779
+ process.exit(code);
97780
+ });
97781
+ }
97782
+
97511
97783
  // src/commands/install.ts
97512
97784
  init_src();
97513
97785
  init_dist();
@@ -97687,7 +97959,7 @@ async function executeInstall(plugin, targets2, options2, dependencies = {}) {
97687
97959
  const targetInputRoot = prepareTargetRulesyncInput(outputDir, target, plugin);
97688
97960
  targetInputRoots.set(target, targetInputRoot);
97689
97961
  }
97690
- const rulesyncFeatures = ["skills", "hooks", ...mapResult.mcp ? ["mcp"] : []];
97962
+ const rulesyncFeatures = ["skills", ...mapResult.mcp ? ["mcp"] : []];
97691
97963
  const rulesyncTargets = targets2.filter((t) => t !== "claude" && t !== "hermes" && t !== "omp");
97692
97964
  if (targets2.includes("omp") && !targets2.includes("pi")) {
97693
97965
  if (!targetInputRoots.has("pi")) {
@@ -97726,6 +97998,20 @@ async function executeInstall(plugin, targets2, options2, dependencies = {}) {
97726
97998
  resultCounts.subagentsCount += result.subagentsCount;
97727
97999
  resultCounts.hooksCount += result.hooksCount;
97728
98000
  }
98001
+ if (mapResult.hooks) {
98002
+ for (const target of rulesyncTargets) {
98003
+ if (!TARGET_TO_RULESYNC_HOOKS[target])
98004
+ continue;
98005
+ const hookResult = await runRulesyncImpl([target], ["hooks"], targetInputRoots.get(target) ?? outputDir, {
98006
+ global: options2.global,
98007
+ dryRun: options2.dryRun,
98008
+ verbose: options2.verbose,
98009
+ outputRoot: options2.outputRoot,
98010
+ targetMap: TARGET_TO_RULESYNC_HOOKS
98011
+ });
98012
+ resultCounts.hooksCount += hookResult.hooksCount;
98013
+ }
98014
+ }
97729
98015
  if (options2.verbose) {
97730
98016
  echo(` Skills written: ${resultCounts.skillsCount}, Commands: ${resultCounts.commandsCount}, Subagents: ${resultCounts.subagentsCount}, Hooks: ${resultCounts.hooksCount}`);
97731
98017
  }
@@ -98005,6 +98291,7 @@ function registerHook(program2) {
98005
98291
  addTargetOption(cmd.command("emit <name>").description("Emit a hook definition to a single target agent (thin wrapper over the install hook path)")).option("--global", "Install to user-level global directory (default)", true).option("--dry-run", "Preview without writing files", false).action(async (name, opts) => {
98006
98292
  await runOperation(() => hookEmit({ name, ...opts }));
98007
98293
  });
98294
+ registerHookRun(cmd);
98008
98295
  }
98009
98296
 
98010
98297
  // src/commands/magent.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/superskill",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "A manager for multi-agent skill, slash command, subagent, hook, MCP and etc.",
5
5
  "keywords": [
6
6
  "cli",