Documentation
¶
Overview ¶
Package hooksession owns the running session's resolved lifecycle-hook state: discovery, arming, and the /hooks listing text.
It is a leaf package deliberately: it imports only internal/config and internal/hooks, never internal/cli, internal/clichat, internal/agent, internal/coordinator, or internal/hub. That is what lets internal/uiadapter (which may not import any of those) reach the same session state and listing text the old CLI surface uses, without a seam indirection.
Index ¶
- func Configured() bool
- func Install(workspaceRoot string, staleBypass, quiet bool) (release func(), notices []string, err error)
- func RunStopForTurn(ctx context.Context, sessionID, turnID string) string
- func SetForTest(s *Session) (restore func())
- func SlashOutput(fields []string) string
- type Session
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Install ¶
func Install(workspaceRoot string, staleBypass, quiet bool) (release func(), notices []string, err error)
Install resolves this session's lifecycle hooks and publishes the result for /hooks and the dispatcher wiring. The returned function releases the handle at session end.
Notices (load warnings, the armed-hook summary, and the project-hook disclosure) are returned rather than printed, so this package stays a leaf: printing is the caller's job (internal/cli's wrapper calls cliagents.WarnHookLoad with them, matching the pre-migration behavior).
quiet (--quiet) suppresses the armed notice and the project-hook disclosure: the operator explicitly asked for quieter startup, and /hooks still lists every armed hook on demand. Genuine load warnings always print.
func RunStopForTurn ¶
RunStopForTurn fires Stop hooks for a completed ROOT turn and returns their output as an attributed continuation prompt.
Stop is pure observation: it has no denial channel at all, so a Stop hook can log a turn's cost and can never affect whether the turn ended.
This is internal/chat's single call site (see stop_hook.go there), reached from every surface (-p, --plain, line mode, TUI) because all four funnel through chat.Session.sendUserWithTurn, and fired once per root turn - a turn that began (sendPlain/sendAgent past beginPlainTurn/beginAgentTurn) fires Stop on every outcome (success, error, or a canceled ctx); a turn that never began (session switching or loading) fires nothing. PreToolUse and PostToolUse are unaffected: they run through the dispatcher's Policy, not through this seam.
workspaceRoot is not a parameter: it is the same directory Install resolved this session's hook argv[0] paths against (Session.workspaceRoot), so a caller that already knows its sessionID/turnID does not need to also thread the workspace root through every turn-completion path.
The context is the turn's own, deliberately not a detached one. A canceled turn therefore does not run its Stop hook, and the run is RECORDED rather than skipped silently - detaching would make Ctrl-C wait out the hook's timeout before the cancelled footer appeared.
func SetForTest ¶
func SetForTest(s *Session) (restore func())
SetForTest installs s as the current session and returns a restore func. Exported for cross-package tests (internal/cli, internal/clichat) that need to exercise a specific hook session without going through Install.
func SlashOutput ¶
SlashOutput is the surface-independent body of /hooks.
`/hooks trust <n>` is answered rather than rejected as an unknown argument. It was a real subcommand, it will be in muscle memory and in notes, and "unknown argument" would read as a bug in the listing rather than as a removed concept.
Types ¶
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is the running session's resolved lifecycle-hook state.
func Current ¶
func Current() *Session
Current returns the running session's hook state, or nil if none is installed. Every method on *Session is nil-safe, so callers may use the result directly without a nil check.
func Load ¶
Load discovers lifecycle hooks from both surfaces.
The user config at its fixed path comes first, then this workspace's own .mivia/mivia.toml. They ADD: a project's formatter and a user's global gate are two hooks, not competing answers, and ordering the user's first means a PreToolUse gate they wrote answers before a repository's does.
A project hook can therefore run code the operator did not write. What stands in for a confirmation is disclosure that cannot be missed - the startup notice, the [project] marker on every listed hook, and a transcript row per execution.
func (*Session) ArmedNotice ¶
ArmedNotice names every hook that will run this session.
It replaces the confirmation prompt, and it is not a lesser thing standing in for one: a prompt asks a question whose answer was already given by editing the config, while this states a fact the operator can act on. A session that executes programs on every tool call and says nothing about it is the actual hazard.
func (*Session) NoteRunWarnings ¶
NoteRunWarnings records bounded diagnostics from executed hooks.
func (*Session) RunnableGroups ¶
RunnableGroups returns the hook groups that may execute in this session.