diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-02 13:38:06 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-02 13:38:06 +0200 |
| commit | 8a70afb354d0050f3f8e1142753284859036fa1c (patch) | |
| tree | 51bc468cb4505addef8f3a4ee8cb498e0c879bdc /internal/hexaiaction | |
| parent | 3bd295d60ecbb30852e8bcf672b1befd93eb9bff (diff) | |
codeaction: add Build/Resolve handler registries (task 410)
Diffstat (limited to 'internal/hexaiaction')
| -rw-r--r-- | internal/hexaiaction/run.go | 132 |
1 files changed, 115 insertions, 17 deletions
diff --git a/internal/hexaiaction/run.go b/internal/hexaiaction/run.go index bf355b0..ffd31f1 100644 --- a/internal/hexaiaction/run.go +++ b/internal/hexaiaction/run.go @@ -29,6 +29,35 @@ type configPathKey struct{} // to the executor. Cleared after use. var selectedCustom *appconfig.CustomAction +type actionPlan struct { + fallback string + run func(context.Context) (string, error) +} + +// CodeActionHandler builds a plan for an action and resolves it. +type CodeActionHandler interface { + Build(parts InputParts, cfg appconfig.App, client chatDoer, stderr io.Writer) (actionPlan, bool) + Resolve(ctx context.Context, plan actionPlan) (string, error) +} + +type codeActionHandler struct { + build func(parts InputParts, cfg appconfig.App, client chatDoer, stderr io.Writer) (actionPlan, bool) +} + +func (h codeActionHandler) Build(parts InputParts, cfg appconfig.App, client chatDoer, stderr io.Writer) (actionPlan, bool) { + if h.build == nil { + return actionPlan{}, false + } + return h.build(parts, cfg, client, stderr) +} + +func (h codeActionHandler) Resolve(ctx context.Context, plan actionPlan) (string, error) { + if plan.run == nil { + return plan.fallback, nil + } + return plan.run(ctx) +} + func Run(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer) error { logger := log.New(stderr, "hexai-tmux-action ", log.LstdFlags|log.Lmsgprefix) cfg := appconfig.LoadWithOptions(logger, appconfig.LoadOptions{ConfigPath: configPathFromContext(ctx)}) @@ -98,26 +127,95 @@ func configPathFromContext(ctx context.Context) string { } func executeAction(ctx context.Context, kind ActionKind, parts InputParts, cfg appconfig.App, client chatDoer, stderr io.Writer) (string, error) { - switch kind { - case ActionSkip: + handler, ok := codeActionHandlers()[kind] + if !ok { return parts.Selection, nil - case ActionRewrite: - return handleRewriteAction(ctx, parts, cfg, client, stderr) - case ActionDiagnostics: - return handleDiagnosticsAction(ctx, parts, cfg, client) - case ActionDocument: - return handleDocumentAction(ctx, parts, cfg, client) - case ActionGoTest: - return handleGoTestAction(ctx, parts, cfg, client) - case ActionSimplify: - return handleSimplifyAction(ctx, parts, cfg, client) - case ActionCustom: - return handleCustomAction(ctx, parts, cfg, client) - case ActionCustomPrompt: - return handleCustomPromptAction(ctx, parts, cfg, client, stderr) - default: + } + plan, ok := handler.Build(parts, cfg, client, stderr) + if !ok { return parts.Selection, nil } + return handler.Resolve(ctx, plan) +} + +func codeActionHandlers() map[ActionKind]CodeActionHandler { + return map[ActionKind]CodeActionHandler{ + ActionSkip: codeActionHandler{build: buildSkipPlan}, + ActionRewrite: codeActionHandler{build: buildRewritePlan}, + ActionDiagnostics: codeActionHandler{build: buildDiagnosticsPlan}, + ActionDocument: codeActionHandler{build: buildDocumentPlan}, + ActionGoTest: codeActionHandler{build: buildGoTestPlan}, + ActionSimplify: codeActionHandler{build: buildSimplifyPlan}, + ActionCustom: codeActionHandler{build: buildCustomPlan}, + ActionCustomPrompt: codeActionHandler{build: buildCustomPromptPlan}, + } +} + +func buildSkipPlan(parts InputParts, _ appconfig.App, _ chatDoer, _ io.Writer) (actionPlan, bool) { + return actionPlan{fallback: parts.Selection}, true +} + +func buildRewritePlan(parts InputParts, cfg appconfig.App, client chatDoer, stderr io.Writer) (actionPlan, bool) { + return actionPlan{ + fallback: parts.Selection, + run: func(ctx context.Context) (string, error) { + return handleRewriteAction(ctx, parts, cfg, client, stderr) + }, + }, true +} + +func buildDiagnosticsPlan(parts InputParts, cfg appconfig.App, client chatDoer, _ io.Writer) (actionPlan, bool) { + return actionPlan{ + fallback: parts.Selection, + run: func(ctx context.Context) (string, error) { + return handleDiagnosticsAction(ctx, parts, cfg, client) + }, + }, true +} + +func buildDocumentPlan(parts InputParts, cfg appconfig.App, client chatDoer, _ io.Writer) (actionPlan, bool) { + return actionPlan{ + fallback: parts.Selection, + run: func(ctx context.Context) (string, error) { + return handleDocumentAction(ctx, parts, cfg, client) + }, + }, true +} + +func buildGoTestPlan(parts InputParts, cfg appconfig.App, client chatDoer, _ io.Writer) (actionPlan, bool) { + return actionPlan{ + fallback: parts.Selection, + run: func(ctx context.Context) (string, error) { + return handleGoTestAction(ctx, parts, cfg, client) + }, + }, true +} + +func buildSimplifyPlan(parts InputParts, cfg appconfig.App, client chatDoer, _ io.Writer) (actionPlan, bool) { + return actionPlan{ + fallback: parts.Selection, + run: func(ctx context.Context) (string, error) { + return handleSimplifyAction(ctx, parts, cfg, client) + }, + }, true +} + +func buildCustomPlan(parts InputParts, cfg appconfig.App, client chatDoer, _ io.Writer) (actionPlan, bool) { + return actionPlan{ + fallback: parts.Selection, + run: func(ctx context.Context) (string, error) { + return handleCustomAction(ctx, parts, cfg, client) + }, + }, true +} + +func buildCustomPromptPlan(parts InputParts, cfg appconfig.App, client chatDoer, stderr io.Writer) (actionPlan, bool) { + return actionPlan{ + fallback: parts.Selection, + run: func(ctx context.Context) (string, error) { + return handleCustomPromptAction(ctx, parts, cfg, client, stderr) + }, + }, true } func handleRewriteAction(ctx context.Context, parts InputParts, cfg appconfig.App, client chatDoer, stderr io.Writer) (string, error) { |
