diff options
| author | Paul Buetow <paul@buetow.org> | 2026-06-19 08:40:55 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-06-19 08:40:55 +0300 |
| commit | 42013b111a3dadd603b423a0bcc4bcbd02da2add (patch) | |
| tree | fd1c3dbdccc0298ee11961f115a14fe18a1be9c5 /internal/hexaiaction/action_handler.go | |
| parent | 8dbec6969ceff32662c41bd267210c34b90d8810 (diff) | |
Harden action handler registration for nk0
Diffstat (limited to 'internal/hexaiaction/action_handler.go')
| -rw-r--r-- | internal/hexaiaction/action_handler.go | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/internal/hexaiaction/action_handler.go b/internal/hexaiaction/action_handler.go index 8da90ea..c01edbd 100644 --- a/internal/hexaiaction/action_handler.go +++ b/internal/hexaiaction/action_handler.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "reflect" "sync" "codeberg.org/snonux/hexai/internal/appconfig" @@ -28,6 +29,9 @@ type CodeActionHandler = ActionHandler type actionHandlerFunc func(context.Context, actionRequest) (string, error) func (f actionHandlerFunc) Execute(ctx context.Context, req actionRequest) (string, error) { + if f == nil { + return "", fmt.Errorf("hexaiaction: nil action handler") + } return f(ctx, req) } @@ -44,7 +48,7 @@ func (r *actionHandlerRegistry) register(kind ActionKind, handler ActionHandler) if kind == "" { panic("hexaiaction: cannot register empty action kind") } - if handler == nil { + if isNilActionHandler(handler) { panic(fmt.Sprintf("hexaiaction: cannot register nil handler for %q", kind)) } @@ -56,6 +60,20 @@ func (r *actionHandlerRegistry) register(kind ActionKind, handler ActionHandler) r.handlers[kind] = handler } +func isNilActionHandler(handler ActionHandler) bool { + if handler == nil { + return true + } + + value := reflect.ValueOf(handler) + switch value.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice: + return value.IsNil() + default: + return false + } +} + func (r *actionHandlerRegistry) lookup(kind ActionKind) (ActionHandler, bool) { r.mu.RLock() defer r.mu.RUnlock() |
