ui_guardrails 1.7.0 → 1.7.1
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 +4 -4
- data/README.md +1 -1
- data/lib/guardrails/hooks/config_file.rb +28 -2
- data/lib/guardrails/hooks/installer.rb +4 -1
- data/lib/guardrails/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 32e83a5c20961feae0830c519f4bf0b3363bcd4774d4644bab49053ce02c8cd5
|
|
4
|
+
data.tar.gz: 8fbaaa46298c2ea2805b2b291354d36cf521fd6f11f948290d62e2796bbafb24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 88fe2925e7787c6b0a63861d142f9d53e5e832395c7b22e7515400954f9a16f57dab73c2fa318b3df516ee5fa12af3e104604bd63125a08eb403eb3ed93f083d
|
|
7
|
+
data.tar.gz: 9ed0ec91a1310da006bf525c05163cec82e730c17838d22ba6e5c2ed2ab7607241541769dda5c60f9a7e2681b587bc5747d2116ddbef156e952bd6f079d8cbae
|
data/README.md
CHANGED
|
@@ -318,7 +318,7 @@ It reports only what the agent introduced. A template is compared with its versi
|
|
|
318
318
|
| Cursor | `.cursor/hooks.json` | `stop` and `sessionStart` only: Cursor's after-edit output doesn't reliably reach the model, so the stop check covers every changed template. Cursor also runs `.claude/settings.json` hooks; the hook recognises Cursor's input and doesn't run twice. |
|
|
319
319
|
| Gemini CLI | `.gemini/settings.json` | `AfterTool` (`write_file`, `replace`), `AfterAgent`, `SessionStart` |
|
|
320
320
|
|
|
321
|
-
The hook never breaks the agent's turn: if anything goes wrong it prints `{}`, explains on stderr, and exits 0. Other gems add to the same events with `Guardrails::Hooks.register(name, contributor)`, shipped at `lib/guardrails/hook_contributors/<name>.rb` so the hook finds them without booting the app.
|
|
321
|
+
The hook never breaks the agent's turn: if anything goes wrong it prints `{}`, explains on stderr, and exits 0. The installed command ends in `|| echo '{}'`, so the same holds when the hook can't start at all. That happens on a branch whose Gemfile doesn't have the gem, since the agent's config usually isn't tracked by git and outlives the branch. Running the install again replaces an earlier install's hooks instead of adding new ones beside them. Other gems add to the same events with `Guardrails::Hooks.register(name, contributor)`, shipped at `lib/guardrails/hook_contributors/<name>.rb` so the hook finds them without booting the app.
|
|
322
322
|
|
|
323
323
|
---
|
|
324
324
|
|
|
@@ -18,7 +18,8 @@ module Guardrails
|
|
|
18
18
|
|
|
19
19
|
# `entries` maps an event name to the list entries to add under
|
|
20
20
|
# `hooks.<event>` (each a Hash in the agent's own shape). An entry
|
|
21
|
-
# counts as present when one with the same command is there
|
|
21
|
+
# counts as present when one with the same command is there; an
|
|
22
|
+
# older form of the same Guardrails hook is replaced.
|
|
22
23
|
# `extra` merges top-level keys that must be set (Cursor's
|
|
23
24
|
# `version`). Returns true when the file changed.
|
|
24
25
|
def add(entries, extra: {})
|
|
@@ -32,7 +33,14 @@ module Guardrails
|
|
|
32
33
|
existing = (hooks[event] ||= [])
|
|
33
34
|
raise Error, "#{@path}: `hooks.#{event}` isn't a list" unless existing.is_a?(Array)
|
|
34
35
|
|
|
35
|
-
list.each
|
|
36
|
+
list.each do |entry|
|
|
37
|
+
wanted = command(entry)
|
|
38
|
+
next if commands(existing).include?(wanted)
|
|
39
|
+
|
|
40
|
+
identity = wanted.to_s[OURS]
|
|
41
|
+
remove(existing, identity) if identity
|
|
42
|
+
existing << entry
|
|
43
|
+
end
|
|
36
44
|
end
|
|
37
45
|
return false if JSON.generate(config) == before
|
|
38
46
|
|
|
@@ -43,6 +51,24 @@ module Guardrails
|
|
|
43
51
|
|
|
44
52
|
private
|
|
45
53
|
|
|
54
|
+
# An earlier install of the same hook, whatever its exact command:
|
|
55
|
+
# reinstalling replaces it rather than adding a second.
|
|
56
|
+
OURS = /guardrails-hook \w+ \w+/
|
|
57
|
+
|
|
58
|
+
# Takes out the hook with this identity and any group it leaves
|
|
59
|
+
# empty; the user's own hooks, in the same group or not, stay.
|
|
60
|
+
def remove(list, identity)
|
|
61
|
+
list.reject! do |entry|
|
|
62
|
+
next false unless entry.is_a?(Hash)
|
|
63
|
+
next true if entry["command"].to_s.include?(identity)
|
|
64
|
+
next false unless entry["hooks"].is_a?(Array)
|
|
65
|
+
|
|
66
|
+
before = entry["hooks"].size
|
|
67
|
+
entry["hooks"].reject! { |hook| hook.is_a?(Hash) && hook["command"].to_s.include?(identity) }
|
|
68
|
+
entry["hooks"].empty? && before.positive?
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
46
72
|
def read
|
|
47
73
|
return {} unless @path.file?
|
|
48
74
|
|
|
@@ -20,7 +20,10 @@ module Guardrails
|
|
|
20
20
|
def call
|
|
21
21
|
@adapters.map do |adapter|
|
|
22
22
|
path = @root.join(adapter.config_path)
|
|
23
|
-
|
|
23
|
+
# Falls back to `{}`, the answer every agent reads as "nothing to
|
|
24
|
+
# say", when the hook can't start at all: a branch without the
|
|
25
|
+
# gem in its Gemfile, or a missing project directory.
|
|
26
|
+
command = ->(event) { "(#{adapter.command_prefix}#{executable} #{adapter.name} #{event}) || echo '{}'" }
|
|
24
27
|
changed = ConfigFile.new(path).add(adapter.config_entries(command), extra: adapter.config_extra)
|
|
25
28
|
Change.new(agent: adapter.name, path: path.relative_path_from(@root).to_s, changed: changed)
|
|
26
29
|
end
|
data/lib/guardrails/version.rb
CHANGED