From 42013b111a3dadd603b423a0bcc4bcbd02da2add Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Fri, 19 Jun 2026 08:40:55 +0300 Subject: Harden action handler registration for nk0 --- internal/hexaiaction/action_handler.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'internal/hexaiaction/action_handler.go') 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() -- cgit v1.2.3