72 lines
3.2 KiB
Go
72 lines
3.2 KiB
Go
// actionTable dispatches applyAction's per-intent bodies. Each of the 7
|
|
// intents (fact, reminder, note, query, act, chat, system) has one handler
|
|
// here with the signature:
|
|
//
|
|
// func(h *reactiveHandler, ctx context.Context, dec router.Decision) string
|
|
//
|
|
// same contract as applyAction itself: "" means "let the Replier phrase the
|
|
// reply", a non-empty string OVERRIDES it. This is a straight extraction of
|
|
// applyAction's old switch cases (formerly ~300 lines in voice.go) — no
|
|
// reordering of side effects, no new abstractions inside a handler.
|
|
//
|
|
// What does NOT belong in this table, because it is not per-intent:
|
|
//
|
|
// - the dec.Clarify short-circuit ("" when the router's stage-3 fired) —
|
|
// stays in applyAction, before dispatch, since it applies to every
|
|
// intent identically.
|
|
// - the destructive-act confirm gate (park / resolveConfirm / confirmTTL)
|
|
// and the enabled-tool allowlist. Both live entirely inside
|
|
// actionAct/handleAct in actions_act.go, exactly where they lived in the old
|
|
// switch's IntentAct case — they are act-specific (a fact or a note
|
|
// can't be destructive), not shared across intents, so they do not need
|
|
// to move to a separate layer. The important invariant, preserved
|
|
// as-is: applyAction runs identically whether dec came from a fresh
|
|
// route or from a completed clarify answer (see finishClarified in
|
|
// clarify.go and its comment "filling in an argument never grants
|
|
// authority") — a handler must never special-case a clarify-completed
|
|
// decision to skip the confirm gate or the allowlist.
|
|
// - detectPattern and dialogue-session bookkeeping (rememberTurn,
|
|
// followUpMerge) run in the callers (runTurn,
|
|
// finishClarified), not per-intent, and are untouched by this slice.
|
|
//
|
|
// Each handler lives in actions_<intent>.go; the small ones (chat, system)
|
|
// and the table itself stay here.
|
|
//
|
|
// Adding an intent: write its handler in its own file, add one line to
|
|
// actionHandlers. Do not grow applyAction's switch back.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"github.com/kami/maven/internal/router"
|
|
)
|
|
|
|
// actionHandlers is the per-intent dispatch table used by applyAction.
|
|
var actionHandlers = map[router.Intent]func(*reactiveHandler, context.Context, router.Decision) string{
|
|
router.IntentFact: (*reactiveHandler).actionFact,
|
|
router.IntentReminder: (*reactiveHandler).actionReminder,
|
|
router.IntentAct: (*reactiveHandler).actionAct,
|
|
router.IntentChat: (*reactiveHandler).actionChat,
|
|
router.IntentSystem: (*reactiveHandler).actionSystem,
|
|
router.IntentNote: (*reactiveHandler).actionNote,
|
|
router.IntentQuery: (*reactiveHandler).actionQuery,
|
|
}
|
|
|
|
func (h *reactiveHandler) actionChat(ctx context.Context, dec router.Decision) string {
|
|
// Conversational: build history from dialogue session (prior user turns)
|
|
// and let the LLM respond from general knowledge + context.
|
|
history := h.chatHistory()
|
|
reply, err := h.phraser.PhraseChat(ctx, dec.Utterance, history)
|
|
if err != nil {
|
|
log.Printf("voice: chat: %v", err)
|
|
return "поговорили."
|
|
}
|
|
return reply
|
|
}
|
|
|
|
func (h *reactiveHandler) actionSystem(ctx context.Context, dec router.Decision) string {
|
|
return h.replySystem(ctx, dec)
|
|
}
|