ask-skills 0.5.3 → 0.5.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c089659a27fb3e462fcf4646f9f5492854f353520f11fe999a7cf48fa11fe39
4
- data.tar.gz: 534b8f2e8a85d4ebcd603da0811c3b950e17d6f2ffceca7672c3988cb4a56e87
3
+ metadata.gz: c738f9a0a38e5b4cd6b21fb83d2870a099a740fd2b13dfed9c80cd07b7750e96
4
+ data.tar.gz: 4d7572316e077d1ca5d81b71c9cb6159e18411e0e730ee83491c6e7e3aea5569
5
5
  SHA512:
6
- metadata.gz: 1859bd5cd03315a118305b1446e0d562c9a4e3611894e07462e76f67ba2cede6e92f9ad09599e72cf955163a4d7b5413f6fafbc6c17c07df83d549ee397d57bb
7
- data.tar.gz: 5cbe3c7442cebebdc12410df4836ec99d7beb9379c31dcfc79790fd2914fb25a6bac19a556a00512fcdc1fe92875e92287213d911446457a8179825d1cb9a8d4
6
+ metadata.gz: 0be67d737827e139c109af737800bab4d76fca2488162a9327bbb04c304f0d76c6f6cc891b8f57752af0ce778c623db65e55aa9e3466a82fd830d73d103095fa
7
+ data.tar.gz: d2624c7c105319a4eaa9df7364f3fec95bd68440ada85960da0c3983bc99cee36a7f2029cc92b0744b7fea49cf2501a23e5237095a9c4150ea4cbca3af32e6de
@@ -36,15 +36,68 @@ module Ask
36
36
  source.load.each do |skill|
37
37
  next unless skill
38
38
  if @skills.key?(skill.name)
39
- # First-wins collision: log diagnostic but keep first
39
+ existing = @skills[skill.name]
40
+ if skill_equivalent?(existing, skill)
41
+ # Exact duplicate (e.g. local + installed gem copy) — skip silently
42
+ next
43
+ end
44
+ # Same gem identity (e.g. local sibling gem vs installed gem of
45
+ # the same name) — expected duplicate source, not a collision.
46
+ next if same_gem?(existing, skill)
47
+
40
48
  warn "[ask-skills] Collision: skill '#{skill.name}' already loaded from " \
41
- "#{@skills[skill.name].source}, skipping #{skill.source}"
49
+ "#{existing.source}, skipping #{skill.source}"
42
50
  else
43
51
  @skills[skill.name] = skill
44
52
  end
45
53
  end
46
54
  end
47
55
  end
56
+
57
+ # Two skills are equivalent when they share the same description and
58
+ # instructions (the two fields that matter for prompt entry and loading).
59
+ # Different sources (local vs gem) for the exact same content are
60
+ # silently deduplicated.
61
+ def skill_equivalent?(a, b)
62
+ a.description == b.description && a.instructions == b.instructions
63
+ end
64
+
65
+ # Two skills belong to the same gem when their source paths share a
66
+ # common ask-* gem directory (e.g. local sibling gem vs installed gem
67
+ # of the same name). Returns +nil+ when no gem name can be extracted.
68
+ def same_gem?(a, b)
69
+ a_name = extract_gem_name(a.source)
70
+ b_name = extract_gem_name(b.source)
71
+ return false if a_name.nil? || b_name.nil?
72
+
73
+ a_name == b_name
74
+ end
75
+
76
+ # Extract the gem directory name from a source path. Checks the
77
+ # immediate parent directory first, then walks up ancestors only if
78
+ # the parent is not an ask-* directory. This prevents false matches
79
+ # when an ask-* directory is nested inside another ask-* directory
80
+ # (e.g. +ask-x/ask-y/SKILL.md+ → +ask-y+, not +ask-x+).
81
+ # Strips version suffixes (e.g. +ask-skills-0.5.1+ → +ask-skills+).
82
+ def extract_gem_name(path)
83
+ return nil unless path
84
+ dir = File.dirname(path)
85
+ # Check immediate parent first — the most specific ask-* ancestor
86
+ parent = File.basename(dir)
87
+ if parent.match?(/\Aask-\w/)
88
+ return parent.sub(/-[\d.]+$/, "")
89
+ end
90
+ # Walk up ancestors until we find an ask-* directory
91
+ parent = File.dirname(dir)
92
+ while parent != File.dirname(parent)
93
+ component = File.basename(parent)
94
+ if component.match?(/\Aask-\w/)
95
+ return component.sub(/-[\d.]+$/, "")
96
+ end
97
+ parent = File.dirname(parent)
98
+ end
99
+ nil
100
+ end
48
101
  end
49
102
  end
50
103
  end
@@ -93,7 +93,7 @@ module Ask
93
93
  current_value = nil
94
94
 
95
95
  yaml_str.split("\n").each do |line|
96
- if (m = line.match(/\A(\w[\w_]*):\s*(.*)\z/))
96
+ if (m = line.match(/\A(\w*):\s*(.*)\z/))
97
97
  # Store previous key if any
98
98
  if current_key
99
99
  yaml[current_key] = process_value(current_value.strip)
@@ -1,5 +1,5 @@
1
1
  module Ask
2
2
  module Skills
3
- VERSION = "0.5.3"
3
+ VERSION = "0.5.4"
4
4
  end
5
5
  end
data/lib/ask/skills.rb CHANGED
@@ -68,7 +68,7 @@ module Ask
68
68
  current_value = nil
69
69
 
70
70
  yaml_str.split("\n").each do |line|
71
- if (m = line.match(/\A(\w[\w_]*):\s*(.*)\z/))
71
+ if (m = line.match(/\A(\w*):\s*(.*)\z/))
72
72
  if current_key
73
73
  yaml[current_key] = process_metadata_value(current_value.strip)
74
74
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-skills
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto