P1 (part 1): move skilltools core -> tool/ (clean, verbatim)
executus CI / test (push) Successful in 36s
executus CI / test (push) Successful in 36s
The tool registry core (registry, permission model, Invocation, gated-tool wrapper, ssrf guard, hmac, encryption, argcoerce, helpers, rootrun, session_tools, webhook_rate_limit) had zero mort coupling — it imports only majordomo/llm + x/crypto/hkdf — so it moves verbatim with a package rename (skilltools -> tool). All same-package tests came along and pass; the SSRF, gated-wrapper, encryption and output-pattern invariants are re-anchored here. majordomo re-enters the module graph (now pinned to the latest, incl. the front-loaded-output fix). model/ + llmmeta + structured follow next. Docs: CLAUDE.md now requires README/examples to stay in sync with changes in the same commit; CI skips docs/example-only pushes via paths-ignore. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package tool
|
||||
|
||||
import "fmt"
|
||||
|
||||
// CheckGate returns an error if the invocation context's SkillName does
|
||||
// not match the tool's gate. Tools should call this at the top of their
|
||||
// handler when their Permission has a non-empty SkillNameGate.
|
||||
//
|
||||
// Why: the gate is enforced per-call (not per-build) because the same
|
||||
// Tool may be referenced by multiple skills, only one of which is
|
||||
// gate-eligible. Build cannot know in advance which skill will call it
|
||||
// — that's per-Invocation.
|
||||
//
|
||||
// What: returns nil if no gate, or the names match. Returns an error
|
||||
// suitable for surfacing to the LLM as the tool's failure result.
|
||||
func CheckGate(inv Invocation) error {
|
||||
if inv.gate == "" {
|
||||
return nil
|
||||
}
|
||||
if inv.currentSkill == inv.gate {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("tool %q is restricted to the %q skill", inv.toolName, inv.gate)
|
||||
}
|
||||
|
||||
// EmitAudit forwards a tool's call+result to the audit hook, if one is
|
||||
// wired. Tools should call this once per Execute, after the underlying
|
||||
// work has completed (regardless of error). Pass the original args
|
||||
// JSON, the result string, and any error.
|
||||
//
|
||||
// Why: keeping the audit emission inside the tool ensures the captured
|
||||
// args are exactly what the tool ran with (after coercion / defaults),
|
||||
// not the raw LLM JSON which can drift.
|
||||
func EmitAudit(inv Invocation, args, result string, err error) {
|
||||
if inv.audit == nil {
|
||||
return
|
||||
}
|
||||
inv.audit(AuditCall{
|
||||
Tool: inv.toolName,
|
||||
Args: args,
|
||||
Result: result,
|
||||
Err: err,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user