summaryrefslogtreecommitdiff
path: root/internal/agentloop/tools.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/agentloop/tools.go')
-rw-r--r--internal/agentloop/tools.go14
1 files changed, 14 insertions, 0 deletions
diff --git a/internal/agentloop/tools.go b/internal/agentloop/tools.go
index e92a12f..fcb17a2 100644
--- a/internal/agentloop/tools.go
+++ b/internal/agentloop/tools.go
@@ -8,6 +8,7 @@ import (
"github.com/thepeterstone/claudomator/internal/agentchannel"
"github.com/thepeterstone/claudomator/internal/provider"
+ "github.com/thepeterstone/claudomator/internal/sandbox"
)
// agentToolSpecs returns the eight tools available to the loop: the four
@@ -193,6 +194,15 @@ func (l *Loop) dispatchTool(ctx context.Context, name, argsJSON string) (result
}
_ = json.Unmarshal([]byte(argsJSON), &a)
if writeErr := l.Sandbox.WriteFile(ctx, a.Path, a.Content); writeErr != nil {
+ // A guardrail rejection (sandbox.Guarded wrapping the real
+ // Sandbox) is not a fatal execution error: feed the reason back
+ // to the model as ordinary tool content so it can self-correct,
+ // instead of aborting the whole run the way a genuine sandbox
+ // failure (e.g. no working directory) does.
+ var rej *sandbox.RejectionError
+ if errors.As(writeErr, &rej) {
+ return rej.Error(), false, nil
+ }
return "", false, writeErr
}
return "Written.", false, nil
@@ -204,6 +214,10 @@ func (l *Loop) dispatchTool(ctx context.Context, name, argsJSON string) (result
_ = json.Unmarshal([]byte(argsJSON), &a)
out, errOut, exitCode, runErr := l.Sandbox.RunBash(ctx, a.Command)
if runErr != nil {
+ var rej *sandbox.RejectionError
+ if errors.As(runErr, &rej) {
+ return rej.Error(), false, nil
+ }
return "", false, runErr
}
return fmt.Sprintf("exit_code: %d\nstdout:\n%s\nstderr:\n%s", exitCode, out, errOut), false, nil