agent-orchestrator/backend/internal/adapters/agent/goose/hooks.go

64 lines
2.4 KiB
Go

package goose
import (
"context"
"path/filepath"
"github.com/aoagents/agent-orchestrator/backend/internal/adapters/agent/hooksjson"
"github.com/aoagents/agent-orchestrator/backend/internal/ports"
)
const (
// Goose auto-discovers any plugin dir containing a hooks/hooks.json at
// startup; unlike Codex there is no separate feature flag to toggle, so
// installing the file is sufficient.
gooseHooksRootDirName = ".agents"
goosePluginsDirName = "plugins"
goosePluginName = "ao"
gooseHooksSubDirName = "hooks"
gooseHooksFileName = "hooks.json"
// gooseHookCommandPrefix identifies the hook commands AO owns, so install
// skips duplicates and uninstall recognizes AO entries by prefix.
gooseHookCommandPrefix = "ao hooks goose "
gooseHookTimeout = 30
)
// gooseManagedHooks is the source of truth for the hooks AO installs. Goose
// groups every hook under the nil matcher. Goose has no permission/approval
// lifecycle event yet, so AO installs only the session/prompt/stop signals.
var gooseManagedHooks = []hooksjson.HookSpec{
{Event: "SessionStart", Command: gooseHookCommandPrefix + "session-start"},
{Event: "UserPromptSubmit", Command: gooseHookCommandPrefix + "user-prompt-submit"},
{Event: "Stop", Command: gooseHookCommandPrefix + "stop"},
}
// gooseHooks manages AO's hooks in the workspace-local
// .agents/plugins/ao/hooks/hooks.json file.
var gooseHooks = hooksjson.Manager{
Label: "goose",
CommandPrefix: gooseHookCommandPrefix,
Timeout: gooseHookTimeout,
Path: gooseHooksPath,
Managed: gooseManagedHooks,
}
func gooseHooksPath(workspacePath string) string {
return filepath.Join(workspacePath, gooseHooksRootDirName, goosePluginsDirName, goosePluginName, gooseHooksSubDirName, gooseHooksFileName)
}
// GetAgentHooks installs AO's Goose hooks, preserving user-defined hooks.
func (p *Plugin) GetAgentHooks(ctx context.Context, cfg ports.WorkspaceHookConfig) error {
return gooseHooks.Install(ctx, cfg.WorkspacePath)
}
// UninstallHooks removes AO's Goose hooks, leaving user-defined hooks untouched.
func (p *Plugin) UninstallHooks(ctx context.Context, workspacePath string) error {
return gooseHooks.Uninstall(ctx, workspacePath)
}
// AreHooksInstalled reports whether any AO Goose hook is present.
func (p *Plugin) AreHooksInstalled(ctx context.Context, workspacePath string) (bool, error) {
return gooseHooks.AreInstalled(ctx, workspacePath)
}