agent

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: MIT Imports: 48 Imported by: 0

Documentation

Overview

Path-validation helpers for the mutating filesystem tools (write_file, edit_file, mkdir, copy_file, move_file, delete_file). Three layers of defense:

  1. Cwd confinement — paths must resolve under the session's cwd, or under one of the user-provided AllowedPaths roots.
  2. Symlink rejection — symlinked write targets are refused unless the user explicitly opts in. Stops the "symlink to /etc/passwd" trick.
  3. Deny list — yottacode's own state directories (sessions, auto/, permissions.json, permissions.local.json) and git-internal paths are off-limits regardless of approval. Self-grants and memory injection don't go through the tool surface.

Reads run through a narrower validator (ValidateReadPath) gated by a targeted deny list of credential-bearing paths (DefaultDenyReadPaths). The agent legitimately reads dotfiles, USER.md, /etc/os-release, etc., so the read deny list is targeted — well-known credential locations only — instead of a blanket cwd-confinement. Reading credentials directly into the model's context (and from there into the upstream provider's logs) is a silent exfiltration vector via prompt injection; run_bash is the escape hatch for the rare case the user really wants the contents, because run_bash always prompts.

Index

Constants

View Source
const AgentToolName = "Agent"

AgentToolName is the schema-visible name of the subagent dispatch tool. Capital-A mirrors Claude Code's surface ("Agent"/"Task"). The name is referenced in several places (recursion guard, plan-mode gate exemption checks, TUI tool-card suppression) so it lives as a const here. Exported so consumers in internal/tui can compare against it without hardcoding the string.

View Source
const CommitSubjectMaxLen = 72

CommitSubjectMaxLen is the hard cap on a commit subject line. 72 is the de-facto standard (git's own --column wraps stay sane below it, most CI lint setups enforce ≤72). Exported because /commit's prompt references the same number, so any future bump moves both sides at once.

View Source
const ConsultAdvisorToolName = "consult_advisor"
View Source
const DefaultSystemPrompt = `` /* 22262-byte string literal not displayed */

DefaultSystemPrompt is the agent identity prompt sent to the model at the start of every session. It declares yottacode's tool surface and the action discipline the model should follow.

Both the TUI (`internal/tui/run.go`) and the non-interactive runner (`internal/oneshot/oneshot.go`) consume this single constant. Historically each kept its own copy of the string and the two drifted — the TUI gained guidance about choosing between edit_file / apply_diff / write_file (and a longer rule on read_many_files) that oneshot never got. One source of truth retires that drift class; a regression test in TestDefaultSystemPrompt_NamesEveryRegisteredTool keeps the tool list honest.

Memory injection (USER.md / YOTTACODE.md / memory tools) wraps this prompt downstream — see internal/memory/memory.go SystemPrompt for the "background — do not narrate" framing that gets layered on.

View Source
const DispatchPromptAddendum = `` /* 1989-byte string literal not displayed */
View Source
const DispatchToolName = "dispatch"

DispatchToolName is the schema-visible name of the batch fan-out tool.

View Source
const EnterPlanModeRefusalMessage = "user declined entering plan mode. " +
	"Continue in the current mode and do NOT call enter_plan_mode again this turn. " +
	"If they want plan mode later they can enter it themselves with /plan or Shift+Tab."

EnterPlanModeRefusalMessage is what the loop returns to the model when the user picks [N] at the enter-plan-mode card. Phrased firmly so the model continues in the CURRENT mode instead of re-requesting — the user saw the card and said no; re-calling would loop it.

View Source
const ExitPlanModeRefusalMessage = "User chose to keep planning. " +
	"END THIS TURN NOW with a brief one-sentence question asking what they'd like to change about the plan. " +
	"Do NOT call exit_plan_mode again in this turn. " +
	"Do NOT edit the plan file in this turn. " +
	"Do NOT call any other tools in this turn. " +
	"Wait for the user's next message before doing anything else. " +
	"After they respond with feedback, you may revise the plan file and call exit_plan_mode again on the following turn."

ExitPlanModeRefusalMessage is what the loop returns to the model when the user picks [K] / Keep planning at the plan-approval card. Phrased firmly so the model STOPS THE TURN and waits for user feedback. Without the firmness, models read "call exit_plan_mode again when ready" and immediately re-call without changing the plan — looping the approval card forever. The user pressed [K] because they have something to say; the model must yield the turn so they can say it.

View Source
const ExitPlanModeSavedForLaterMessage = "user approved the plan but is saving it for implementation later. " +
	"The plan file is preserved on disk; the user will resume via /plan list when ready. " +
	"END THIS TURN NOW. Do NOT call any more tools. Do NOT implement any part of the plan. " +
	"Do NOT suggest next steps. Reply with a one-sentence acknowledgement and stop."

ExitPlanModeSavedForLaterMessage is what the loop returns to the model when the user picks [L] / approve and implement later. The plan is good but the user isn't starting work now — they'll resume via /plan list or --plan-resume in a future session. The message is phrased firmly to make the model END THE TURN: no more tool calls, no implementation, no "next steps" prose. The user will re-initiate when they're ready.

View Source
const IntegrateToolName = "integrate"

IntegrateToolName is the schema-visible name of the branch-assembly tool.

View Source
const LoopIterationAddendum = `` /* 1162-byte string literal not displayed */

LoopIterationAddendum is the per-iteration system message prepended when the current turn is a /loop prose iteration (LoopConfig.LoopControl active). The single `%s` is filled with a one-line descriptor of the loop (cadence, bounded/unbounded). It gives the model the judgment to end the loop with the loop_control tool once the goal is met — without it the model runs the same prompt every interval forever, even when it has nothing new to do. Prepended to the per-iteration message slice only, so the persisted history stays clean (same approach as PlanModeAddendum).

View Source
const MaxBackgroundSubagents = 8

MaxBackgroundSubagents caps how many background subagents may be running concurrently per session. Hit the cap → the tool rejects the call with a recoverable error message the model can adapt around. 8 is a round number that matches what most users informally do — enough for genuine parallelism, low enough to keep API spend bounded if a model gets enthusiastic.

View Source
const MaxForegroundSubagents = 8

MaxForegroundSubagents caps how many foreground subagents may be running concurrently per session. Foreground spawns are no longer serialized (AgentTool.ParallelSafe returns true), so a parent that emits N Agent calls in one assistant message fans them out via the loop's parallel-batch path. The cap matches the background ceiling because the cost profile is the same: every concurrent child holds a goroutine, an iteration budget, and a slice of the parent's provider rate limit. The (N+1)th call returns a recoverable error the model can react to by waiting on the in-flight children before dispatching more.

View Source
const PRTitleMaxLen = 72

PRTitleMaxLen is the cap GH PR titles are validated against. GitHub itself allows ~256, but reviewer-friendly UIs (notification emails, Slack/Linear embeds, the PR list view) all start truncating in the 70-80 char range. Matching the commit-subject cap keeps both halves of the workflow visually consistent.

View Source
const PlanModeAddendum = `` /* 6290-byte string literal not displayed */

PlanModeAddendum is the per-iteration system message appended on top of DefaultSystemPrompt when LoopConfig.PlanMode is active. The single `%s` is filled with the current plan-file path. Mirrors Claude Code's plan-mode framing so the model recognizes the surface regardless of which agent it's running under.

Lives in the prompt module (not plan_mode.go) so the schema-vs-prompt regression test in prompt_test.go can assert plan-mode directives are reachable from the same package as the rest of the prompt copy.

View Source
const RepeatedToolFailureMarker = "repeated tool failure ("

RepeatedToolFailureMarker prefixes the guidance repeatedToolFailureMessage appends to a tool result once a failure repeats past the threshold. Exported so /usage (internal/tui) can retroactively count these events by scanning persisted tool-result content, without either package duplicating the literal or /usage needing its own separate tracking.

View Source
const SkillToolName = "Skill"

SkillToolName is the schema-visible name of the skill-invocation tool. Capital-S mirrors Claude Code's `Skill` surface. The name is referenced from the TUI / docs and slash-dispatch, so it lives as a const here.

Variables

This section is empty.

Functions

func BashSensitivePathHits added in v0.4.0

func BashSensitivePathHits(command, cwd string) []string

BashSensitivePathHits returns terse, deduped warnings for any segment of a run_bash command that references a credential/secret store (the DefaultDenyReadPaths) or a git hook. These are the sensitive targets the structured-file deny lists guard but run_bash does NOT — run_bash has no path confinement and no sandbox (see exec_tool.go), so the approval modal surfaces them here to keep `cat ~/.ssh/id_rsa` or `> .git/hooks/pre-commit` from rendering like ordinary commands. Empty when nothing sensitive is referenced; unresolved `$var` tokens are skipped (we only warn on a path we can name).

A recursive walk (`grep -r X ~`) flags an out-of-cwd store, but a walk of the project's own tree (`grep -r X .` reaching <cwd>/.env) is not flagged — mirroring the auto-mode gate: the concern is silently reaching OTHER credential stores, not the user's own project files.

func CheckpointFromContext added in v0.2.0

func CheckpointFromContext(ctx context.Context) (sessionID, cpID string)

CheckpointFromContext recovers the (sessionID, checkpointID) pair stored by WithCheckpoint. Returns empty strings when no checkpoint is bound — callers should treat that as "checkpointing disabled."

func DefaultDenyPaths

func DefaultDenyPaths(cwd string) []string

func DefaultDenyReadPaths

func DefaultDenyReadPaths(cwd string) []string

DefaultDenyReadPaths returns the hardcoded list of paths the agent's auto-execute read tools (read_file, read_many_files, grep) refuse to touch. Targeted at well-known credential stores; intentionally narrow so the model can still read dotfiles, /etc/os-release, USER.md, and other benign system files.

  • ~/.yottacode/.env — the agent's own provider keys. Reading this into context exfiltrates the active session's API key to the upstream provider on the next turn.
  • ~/.yottacode/auth/ — OAuth bearer + refresh tokens for the openai-auth provider. Same exfiltration risk as .env, plus the refresh token grants long-lived access. Whole directory denied so future per-provider auth files inherit the protection.
  • ~/.ssh/, ~/.gnupg/ — private key material.
  • ~/.aws/{credentials,config}, ~/.config/gcloud/ — cloud provider access.
  • ~/.netrc — HTTP basic-auth credentials.
  • ~/.config/gh/hosts.yml, ~/.config/hub — GitHub tokens.
  • ~/.docker/config.json — registry tokens.
  • ~/.kube/config — cluster credentials.
  • <cwd>/.env, <cwd>/.env.local — project secrets, the most common accidental-exfiltration target.

Power users who need the model to read one of these can bypass at the OS layer (cat the contents into a non-denied file first) or via run_bash, which prompts. Listing more paths is cheap; the cost is false-positive blocks on benign reads. Keep the list to files universally understood as secrets.

func IsAutoModeSafeBash added in v0.3.0

func IsAutoModeSafeBash(argsJSON string, cwd *CwdRef) bool

IsAutoModeSafeBash reports whether a run_bash invocation is safe to auto-approve without showing the modal — i.e., every segment uses a verb from autoModeSafeBashVerbs AND no segment carries a non-None risk classification (which would flag redirects, sudo, pipe-into-sh, etc. even when the leading verb itself is in the allowlist).

Returns false on bad JSON, empty commands, or any segment that fails either check. The loop's auto-mode bypass calls this AFTER confirming AutoMode is active and the tool is run_bash; on false, the call falls through to the normal approval modal so the user can still approve / [A]-always it.

func IsAutoModeSafetyFloor added in v0.2.0

func IsAutoModeSafetyFloor(toolName string) bool

IsAutoModeSafetyFloor returns true for tools whose approval prompt must NOT be skipped by auto mode. These are the calls that run arbitrary code (run_bash) or write permanent / hard-to-reverse history (git_commit, git_checkpoint, rollback). The user opted into auto mode to skip edit-by-edit approval friction — not to silently hand over shell access or amend git history.

To get true blanket auto-approval (including run_bash and commits), use yolo mode; that's the user-explicit "always approve" path.

func IsHardlineCommand added in v0.3.0

func IsHardlineCommand(cmd string) (bool, string)

IsHardlineCommand reports whether any segment of cmd matches the unconditional hardline blocklist, with a human-readable reason. The run_bash execution floor calls this to refuse catastrophic commands regardless of approval mode. Compound commands are split first so a hardline segment anywhere in a `a && b ; c` chain is caught.

func IsPlanFileWrite added in v0.2.0

func IsPlanFileWrite(name, argsJSON, planFile string) bool

IsPlanFileWrite reports whether this tool call is one of the mutating tools (write_file / edit_file / apply_diff) targeting the resolved plan file. The loop uses this to auto-approve those writes in plan mode — they're the model's only legitimate mutation surface while planning, so prompting on every edit is friction with no value (the gate already established the target is the plan file). False when planFile is empty, when the tool isn't a write tool, or when the target path differs from planFile.

func IsReadOnlyTool added in v0.4.0

func IsReadOnlyTool(name string) bool

IsReadOnlyTool reports whether a tool name is in the canonical read-only set — tools that cannot mutate the user's workspace or execute arbitrary commands. Used by the /usage efficiency section to distinguish verification- loop re-calls (same args after a mutation) from genuine idle duplicates.

func ParentDecisions added in v0.2.0

func ParentDecisions(ctx context.Context) <-chan Decision

ParentDecisions recovers the channel attached by WithParentDecisions, or nil when no parent loop is on the stack.

func ParentEvents added in v0.2.0

func ParentEvents(ctx context.Context) chan<- Event

ParentEvents recovers the channel attached by WithParentEvents, or nil when no parent loop is on the stack (tests, oneshot paths that haven't wired it in). Always check for nil before sending.

func PlanFilePath added in v0.2.0

func PlanFilePath(slug string) (string, error)

PlanFilePath resolves a slug to its absolute plan-file path. The returned path is what the gate compares writes against and what the system-prompt addendum tells the model to write to.

func PlanModeGate added in v0.2.0

func PlanModeGate(tool Tool, argsJSON, planFile string) (string, bool)

PlanModeGate is the read/write classifier the loop consults before every tool call when plan mode is active. Returns ("", false) when the call may proceed, or (errorString, true) when the call must be refused. The errorString is what the model sees as the tool result, so it's phrased as actionable guidance — the model can switch to a read-only or plan-file alternative on the next iteration.

Allowlist:

  • exit_plan_mode: the only way out of plan mode.
  • todo_write: progress tracking, no side effects.
  • write_file/edit_file/apply_diff: only when the target path equals planFile. Any other write target is blocked.
  • any tool whose RequiresApproval returns false: the implicit "read-only" classification (read_file, grep, glob, list_*, git_log_file, fetch_url, …). New read-only tools auto-classify.

The gate runs BEFORE Permissions.Evaluate so explicit deny rules still win in plan mode (Deny > plan-mode-allow > permissions > tool-policy).

func PlansDir added in v0.2.0

func PlansDir() (string, error)

PlansDir returns the directory plan files live under: $YOTTACODE_HOME/plans (when set) or ~/.yottacode/plans otherwise, via the shared ychome.Dir resolution. Does not create the directory — write_file's MkdirAll handles that lazily on first write.

func ReclaimEmptyDispatchWorktrees added in v0.3.0

func ReclaimEmptyDispatchWorktrees(ctx context.Context, tasks *subagents.Registry) int

ReclaimEmptyDispatchWorktrees sweeps every dispatch worktree recorded in the task registry and reclaims the ones that hold nothing (no commits beyond their dispatch base, clean tree). Called at session teardown, after CancelAll + the bounded drain: workers that unwound in time already reclaimed their own worktree (their dir is gone — stat-skipped here); the sweep catches workers that were still stuck mid-run when the session died. Worktrees with commits awaiting integrate or with unsaved work are kept, same as the per-worker rule. Best-effort: every error is "keep", never fatal. Returns how many worktrees were removed.

func ReclaimOrphanDispatchWorktrees added in v0.4.0

func ReclaimOrphanDispatchWorktrees(ctx context.Context, repoRoot string) int

ReclaimOrphanDispatchWorktrees sweeps the repo's dispatch worktrees on disk and reclaims the ones holding nothing, WITHOUT needing a registry record.

ReclaimEmptyDispatchWorktrees can only see worktrees the current session knows about — the ones it created, plus whatever the session import rehydrated. That misses the case the cleanup story most needs to cover: a session killed hard enough (SIGKILL, power loss, a crash before the session save) that its records never persisted, leaving worktrees no later session can attribute. Those used to accumulate forever. This walks `git worktree list` instead, so attribution comes from the branch name, not from memory.

An orphan has no recorded dispatch base, so it's derived as the merge-base of the repo's HEAD and the worker's branch — the point the branch diverged. Commits past it are the worker's output and mean "keep", exactly as a recorded base would. Everything else is the shared conservative rule in reclaimEmptyWorktree: both probes must affirmatively say empty, any git error means keep. Locked worktrees are skipped outright — a lock is an explicit "don't touch this". Scoped to repoRoot; other repos are not this session's business. Best-effort, never fatal. Returns how many were removed.

func RegisterCoreCwdTools added in v0.3.0

func RegisterCoreCwdTools(reg *Registry, cwd *CwdRef, deps CoreToolDeps)

RegisterCoreCwdTools registers the core working-directory-bound tools — file read/write/edit, directory + code search, git-read/stage/commit, checkpoints, and command execution — against the given CwdRef. Every tool resolves relative paths through cwd, so passing a fresh CwdRef (e.g. one pinned to a git worktree) yields a fully isolated toolset.

This is the shared core both the parent session (internal/tui/run.go, internal/oneshot/oneshot.go) and the dispatch worktree-child registry build on. It deliberately excludes session-scoped extras the parent registers separately — GitHub/PR/issue tools, memory, worktree-admin, the commit-workflow composites, web fetch/search, todo, plan-mode — and the Agent/dispatch/integrate delegation tools, none of which a leaf worker needs.

func SlugFromPrompt added in v0.2.0

func SlugFromPrompt(prompt, salt string) string

SlugFromPrompt converts a free-form prompt into a stable, filesystem- safe slug suitable for a plan filename. Format:

<kebab>-<16-hex-of-sha256(salt|prompt)>

The kebab portion caps at 60 characters so the suffixed filename stays well under common filesystem limits. Empty / all-punctuation input falls back to "untitled".

The hash suffix gives every plan a unique filename even when two prompts share the same opening words (e.g. "fix bug in foo" vs "fix bug in bar" both truncated to "fix-bug-in") and avoids the slug-collision class entirely. Salt is typically the session ID, so the same prompt typed in a different session lands on a different file.

func ToolPathsToSnapshot added in v0.2.0

func ToolPathsToSnapshot(t Tool, cwd, argsJSON string) []string

ToolPathsToSnapshot exposes the Mutator capability to callers in other packages (e.g. the agent loop's checkpoint hook) without forcing them to import nothing-vs-something interface assertions. Returns nil when the tool isn't a Mutator.

func Turn

func Turn(
	ctx context.Context,
	cfg LoopConfig,
	history *[]adapter.Message,
	events chan<- Event,
	decisions <-chan Decision,
) error

Turn drives one user-initiated round: it streams an assistant response (emitting Reasoning/Content tokens), dispatches any tool calls (with approval flow if required), feeds the results back, and loops until the assistant produces a tool-free reply or hits MaxIterations.

events is producer-only; Turn never closes it (caller owns lifecycle). decisions is consumer-only; Turn reads from it only after emitting an ApprovalNeeded event. Cancel ctx to abort cleanly.

history is mutated in place: user message is assumed already appended by the caller; Turn appends each assistant reply and tool result.

func ValidateReadPath

func ValidateReadPath(path string, deny []string) error

DefaultDenyPaths returns the hardcoded list of paths the agent's mutating filesystem tools must refuse to write to. Includes:

  • User-scope yottacode state under ~/.yottacode/ (sessions, memory/, projects/, auth/, index.sqlite, USER.md). The agent has supported pathways for the memory dirs (memory_save / memory_forget); the generic write_file / edit_file surface must not be a back door. USER.md is global preferences — the agent's project-scope view doesn't have enough signal to curate cross-project preferences. The home-anchored memory/ and projects/ trees are denied unconditionally; when $YOTTACODE_HOME redirects the memory tree off ~/.yottacode, that override root is denied too (so neither the active store nor an override-less session's store is writable via the tool surface).
  • Project-scope yottacode state under <cwd>/.yottacode/ (permissions.json, permissions.local.json). The permissions files are the user's policy surface — letting the model edit them via tools would let it self-grant approval. The /permissions slash command and the user's editor are the only legitimate write paths.
  • Git internals: .git/HEAD, .git/config, .git/index, .git/refs/, .git/packed-refs, .git/objects/. These define repo state; writes here should go through `git` commands, not direct filesystem manipulation. .git/hooks/ is deliberately NOT in the list — model authoring of hooks is a legitimate task.

YOTTACODE.md is deliberately NOT in the deny list. It's the project-scope context file the agent reads on every turn, and keeping it fresh requires writes — same role CLAUDE.md plays for Claude Code. The approval modal still gates every write, so the user sees each change before it lands.

Bypass is not possible via flags. Power users can edit these files themselves with their editor; the model just can't via tools. ValidateReadPath returns nil if the read of path is permitted under the given deny list, or a descriptive error. Targeted at silent exfiltration of credential-bearing files via read_file / read_many_files / grep — tools whose RequiresApproval is false. The user can still read these files via run_bash, which always prompts.

func ValidateWritePath

func ValidateWritePath(path string, opts WritePathOptions) error

ValidateWritePath returns nil if a write to path is permitted under the given options, or a descriptive error. Validation order matters: deny list checked first (so even a path inside cwd can be refused), then symlink check, then containment check against cwd / allowed roots.

func WithApprovalGate added in v0.3.0

func WithApprovalGate(ctx context.Context, gate *sync.Mutex) context.Context

WithApprovalGate attaches a mutex that serializes request→decision round-trips across tools running concurrently in one parallel batch. The parent's decisions channel and the TUI's single approval modal can each serve only one request at a time; without this lock two parallel workers reading decisions would misroute the user's answer (authorize the wrong call) or deadlock (one worker waits forever for a second decision the user never gives). A nil gate — the serial path, where there is no contention — is left unattached and locking becomes a no-op.

func WithCheckpoint added in v0.2.0

func WithCheckpoint(ctx context.Context, sessionID, cpID string) context.Context

WithCheckpoint binds a checkpoint id + session id to ctx. The TUI calls this immediately after checkpoints.Begin returns, before passing ctx into Turn. Returns ctx unchanged when either id is empty so callers don't need to special-case nil-checkpoint paths.

func WithParentDecisions added in v0.2.0

func WithParentDecisions(ctx context.Context, decisions <-chan Decision) context.Context

WithParentDecisions attaches the parent loop's decisions channel to ctx. Tools that don't need to forward approvals should ignore this seam — the channel is receive-only and may be nil.

func WithParentEvents added in v0.2.0

func WithParentEvents(ctx context.Context, events chan<- Event) context.Context

WithParentEvents attaches the parent loop's events channel to ctx so downstream Tool.Execute calls can pull it via ParentEvents(ctx). The channel is send-only; tools may push Subagent* / progress events onto it without coordinating with the loop.

Tools that don't need this seam should ignore the helper — the normal tool-result return value is still the primary output path.

Types

type AgentTool added in v0.2.0

type AgentTool struct {
	// Configs is the resolved set of agent definitions (builtin +
	// global + project). The Execute method looks up subagent_type
	// against this slice; it should remain stable across the session.
	Configs []subagents.AgentConfig

	// Tasks is the session-scoped task registry. Foreground runs add
	// + MarkDone within a single Execute; background runs add now and
	// MarkDone later from a detached goroutine.
	Tasks *subagents.Registry

	// Adapter is the streamer the child Turn calls into. Shared with
	// the parent — adapter calls are stateless per-request and
	// concurrency-safe by construction. This is the active session model
	// that a child inherits when nothing routes it elsewhere.
	Adapter Streamer

	// ImplementerAdapter is the fast coding model's streamer used for
	// cache-safe task routing. nil when routing is disabled. In auto mode,
	// delegated subagents default here; summarization also uses this role.
	ImplementerAdapter Streamer

	// ImplementerModel is recorded on task events so /subagents can show
	// which model handled a delegation. Empty when routing is off.
	ImplementerModel string

	// AdvisorAdapter is the reasoning/planning model's streamer. The main
	// session uses it at routed startup and in plan mode, while implementer
	// children can call consult_advisor for isolated help.
	AdvisorAdapter Streamer

	// AdvisorModel is the advisor model's name for task/tool display.
	AdvisorModel string

	// Fast*/Smart* are legacy aliases retained while TUI/oneshot call sites
	// migrate. Fast maps to implementer; smart maps to advisor.
	FastAdapter  Streamer
	FastModel    string
	SmartAdapter Streamer
	SmartModel   string

	// RouteAuto enables the heuristic that routes delegated subagents to
	// ImplementerAdapter. False in "manual" mode (only an explicit `model:`
	// frontmatter routes) and when routing is off.
	RouteAuto bool

	// ModelResolver resolves an agent's explicit `model:` frontmatter
	// to a streamer, or returns nil when the name matches no
	// configured model (the child then inherits Adapter). nil when
	// routing is disabled.
	ModelResolver func(model string) Streamer

	// ResolveWindow returns the context window (tokens) for a child
	// model, honoring the per-model override + default_window exactly
	// as the status bar does (contextwindow.EffectiveWindow). It is the
	// source of the child loop's compaction window: subagents run Turn
	// directly, so without this they have no context management and a
	// long run accumulates until the provider rejects it. The TUI and
	// oneshot both wire it; nil (tests) disables child compaction.
	ResolveWindow func(model string) int

	// ParentRegistry is the live tool set the parent session is using.
	// We clone it for the child, dropping the Agent tool itself plus
	// the plan-mode boundary tools (enter/exit_plan_mode), and
	// intersecting with the agent's `tools:` allowlist when one is
	// configured. The clone is a single-pass
	// snapshot — runtime changes to the parent registry don't
	// propagate into in-flight children, which keeps semantics easy
	// to reason about.
	ParentRegistry *Registry

	// Permissions is the parent's permission ruleset; children
	// inherit it unchanged. Per-config narrowing is a v2 extension.
	Permissions *permissions.Permissions

	// YoloMode is the process-wide yolo overlay. The pointer is
	// shared so a yolo session also applies to its subagents — the
	// user explicitly opted into unattended mutation, child runs
	// included.
	YoloMode *YoloModeState

	// PlanMode is the parent's plan-mode state. Pointer-shared so a
	// child run under a plan-mode parent inherits the restriction
	// transitively (no writes outside the plan file). When the
	// parent flips out of plan mode mid-conversation the next
	// subagent run automatically sees the new state. nil is safe —
	// runChild allocates a fresh inactive state in that case.
	PlanMode *PlanModeState

	// AutoMode is the parent's auto-mode state. Pointer-shared so a
	// child inherits parent's auto-mode (mutating tools auto-allow
	// except the safety floor, iteration cap multiplied 4×). nil is
	// safe — runChild allocates a fresh inactive state in that case.
	AutoMode *AutoModeState

	// Cwd is the working directory child tools resolve relative
	// paths against. Shared with the parent so an in-session cwd
	// swap (enter_worktree) flows to the spawned subagent.
	Cwd *CwdRef

	// TranscriptDir is the directory subagent transcripts get persisted
	// under, resolved at startup by the caller (TUI or oneshot wiring)
	// via subagents.TranscriptDirFor. It need NOT exist yet — openTranscript
	// MkdirAlls it lazily on the first dispatch, so a session that never
	// runs a subagent leaves no empty project-memory dir behind.
	TranscriptDir string

	// AllowBackground controls whether `run_in_background: true` is
	// honored. The TUI sets this true; oneshot leaves it false so the
	// non-interactive entry point returns a sensible error string the
	// model can recover from rather than silently detaching work that
	// nobody will see.
	AllowBackground bool

	// MaxSessionTokens caps the cumulative ESTIMATED tokens spent across
	// all subagent runs this session. A new spawn is rejected (with a
	// recoverable error the model relays) once the registry's
	// TotalTokensUsed reaches this ceiling — the session-wide backstop the
	// per-child iteration cap and the concurrency cap can't provide. 0
	// disables the budget (unbounded). Wired from
	// config.SubagentSessionTokenBudget by the TUI/oneshot setup.
	MaxSessionTokens int

	// SystemPromptSuffix is appended to the agent definition's body
	// when building the child's system prompt. Used to inject runtime
	// context the static config can't know (currently empty; reserved
	// for cwd / repo metadata if we decide to inject it).
	SystemPromptSuffix string
	// contains filtered or unexported fields
}

AgentTool dispatches typed-subagent invocations. One instance is registered per session — Execute spawns a child agent.Turn against a filtered registry and either blocks until the child completes (foreground) or detaches the child to a goroutine that updates the task registry on completion (background).

func (*AgentTool) AgentConfigs added in v0.2.0

func (t *AgentTool) AgentConfigs() []subagents.AgentConfig

Configs returns the resolved set of agent definitions (for the TUI's /subagents help / status rendering and for tests). The returned slice references the same memory; callers must not mutate.

func (*AgentTool) Description added in v0.2.0

func (t *AgentTool) Description() string

func (*AgentTool) Execute added in v0.2.0

func (t *AgentTool) Execute(ctx context.Context, argsJSON string) (string, error)

Execute is the parent-loop entry point. Parses args, validates the subagent_type, builds the child config + history, and either:

  • foreground: spawns the child Turn, drains its events through the translator inline, and returns the captured final reply as the tool result string the model sees;
  • background: launches the whole flow in a goroutine, returns a task-id handle immediately, and posts completion via the session-level callback when the child finishes.

func (*AgentTool) Name added in v0.2.0

func (t *AgentTool) Name() string

func (*AgentTool) ParallelSafe added in v0.2.0

func (t *AgentTool) ParallelSafe(string) bool

ParallelSafe returns true so several Agent calls from the same assistant message run concurrently — matching the user-visible pattern in other Claude-Code-style frontends where a parent spawns three Explore agents in one turn and they fan out at once. The loop's executeToolCallsParallel handles the fan-out; each child runs in its own goroutine with its own loop + provider call.

The cost the older sequential design avoided is real but manageable: N concurrent children share the parent's provider key, so a thundering herd can hit rate limits and burn iteration budget on dead-end investigations. Mitigations live elsewhere — MaxBackgroundSubagents caps background fan-out, and per-tool approval still gates write-y children. The model is generally conservative about how many it spawns at once (typically 2–4 Explores), so an explicit numeric cap on foreground concurrency would mostly punish the rare legitimate burst.

func (*AgentTool) PreviewCall added in v0.2.0

func (t *AgentTool) PreviewCall(argsJSON string) string

func (*AgentTool) RequiresApproval added in v0.2.0

func (t *AgentTool) RequiresApproval(string) bool

RequiresApproval is always false for the Agent tool itself — delegation is just compute. The child's own mutating tool calls still go through their normal approval flow (and v1 auto-denies any ApprovalNeeded inside the child since the child has no UI attached). The user retains control via the parent's permission rules.

func (*AgentTool) Schema added in v0.2.0

func (t *AgentTool) Schema() map[string]any

func (*AgentTool) SetBackgroundDoneCallback added in v0.2.0

func (t *AgentTool) SetBackgroundDoneCallback(fn func(SubagentBackgroundDone))

SetBackgroundDoneCallback installs the session-level handler that receives a SubagentBackgroundDone event when a detached child finishes. Safe to call after registration; safe to call with nil to clear.

type ApplyDiffTool

type ApplyDiffTool struct {
	Cwd       *CwdRef
	WriteOpts WritePathOptions
}

func (*ApplyDiffTool) Description

func (t *ApplyDiffTool) Description() string

func (*ApplyDiffTool) Execute

func (t *ApplyDiffTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ApplyDiffTool) Name

func (t *ApplyDiffTool) Name() string

func (*ApplyDiffTool) PathsToSnapshot added in v0.2.0

func (t *ApplyDiffTool) PathsToSnapshot(cwd, argsJSON string) []string

PathsToSnapshot reports every file the diff touches so /checkpoints can restore each pre-image. Uses the same ParseDiffPaths the tool already runs during validation, so the snapshot set matches the validation set by construction.

func (*ApplyDiffTool) PreviewCall

func (t *ApplyDiffTool) PreviewCall(argsJSON string) string

func (*ApplyDiffTool) RequiresApproval

func (t *ApplyDiffTool) RequiresApproval(string) bool

func (*ApplyDiffTool) Schema

func (t *ApplyDiffTool) Schema() map[string]any

type ApprovalAuto

type ApprovalAuto struct {
	ToolName string
	Preview  string
	Source   string
	// RuleSource identifies the permissions file that matched when Source is
	// "permissions" or "deny-rule". Empty for mode-based auto approvals.
	RuleSource string
}

ApprovalAuto is logged when the loop auto-approves (or auto-denies) a tool call without asking the user. Source identifies which gate fired: "permissions" (matched an allow rule), "deny-rule" (matched a deny rule, no execution), or "yolo-mode" (--yolo flag is set / /yolo toggle is on and no rule matched).

type ApprovalNeeded

type ApprovalNeeded struct {
	ToolName string
	Preview  string
	ArgsJSON string
}

ApprovalNeeded is the request half of an approval round-trip. The loop blocks on the decisions channel until the consumer replies. ArgsJSON is the raw tool args so the consumer can render richer previews — e.g. the TUI shows a colored diff for edit_file by parsing old_string/new_string.

type AssistantMessage

type AssistantMessage struct{ Message adapter.Message }

AssistantMessage fires once a streamed assistant response is finalized, just before its tool_calls (if any) are dispatched. Includes the same Message that gets appended to history; useful for consumers that want to react to a complete reply (e.g., TUI message-list rendering).

type AutoModeState added in v0.2.0

type AutoModeState struct {
	Active atomic.Bool
}

AutoModeState is the per-session, runtime-mutable auto-mode flag the loop reads on every tool dispatch. When active, mutating tools that would normally hit an approval modal auto-allow with Source=auto-mode — EXCEPT for the safety floor (run_bash, git_commit, git_checkpoint, rollback), which always prompt regardless of mode.

Mutually exclusive with plan mode at the TUI layer: entering one turns the other off. The loop-level gates don't enforce this on their own — they just observe whichever flag is set.

The pointer is shared between LoopConfig and the TUI Model so a flip from /auto, Shift+Tab, the plan-card [A] hotkey, or the --permission-mode auto startup flag takes effect on the next iteration with no reconstruction. atomic.Bool keeps that benign race detector-clean. There is deliberately no agent/tool-layer command that lets the model enable auto mode itself.

func (*AutoModeState) IsActive added in v0.2.0

func (a *AutoModeState) IsActive() bool

IsActive is a nil-safe check used by the loop.

type CheckpointInfo added in v0.2.0

type CheckpointInfo struct{ Message string }

CheckpointInfo carries a non-fatal status from the checkpoint subsystem — typically a snapshot failure for one file (permission denied, race with deletion) that should NOT abort the user's tool call. The TUI renders these dimly in the scrollback so the user knows the file won't be restorable from this checkpoint without confusing them about whether the tool itself failed.

type CheckpointWriter added in v0.2.0

type CheckpointWriter interface {
	SnapshotPath(sessionID, checkpointID, absPath string) error
}

CheckpointWriter is the slice of the checkpoint store the agent loop depends on. Defining it here keeps internal/checkpoint out of the agent's import surface and lets tests substitute a recording fake.

type CodeCyclesTool added in v0.4.0

type CodeCyclesTool struct{ Provider codemap.Provider }

func (*CodeCyclesTool) Description added in v0.4.0

func (t *CodeCyclesTool) Description() string

func (*CodeCyclesTool) Execute added in v0.4.0

func (t *CodeCyclesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeCyclesTool) Name added in v0.4.0

func (t *CodeCyclesTool) Name() string

func (*CodeCyclesTool) ParallelSafe added in v0.4.0

func (t *CodeCyclesTool) ParallelSafe(string) bool

func (*CodeCyclesTool) PreviewCall added in v0.4.0

func (t *CodeCyclesTool) PreviewCall(argsJSON string) string

func (*CodeCyclesTool) RequiresApproval added in v0.4.0

func (t *CodeCyclesTool) RequiresApproval(string) bool

func (*CodeCyclesTool) Schema added in v0.4.0

func (t *CodeCyclesTool) Schema() map[string]any

type CodeDependenciesTool added in v0.4.0

type CodeDependenciesTool struct{ Provider codemap.Provider }

func (*CodeDependenciesTool) Description added in v0.4.0

func (t *CodeDependenciesTool) Description() string

func (*CodeDependenciesTool) Execute added in v0.4.0

func (t *CodeDependenciesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeDependenciesTool) Name added in v0.4.0

func (t *CodeDependenciesTool) Name() string

func (*CodeDependenciesTool) ParallelSafe added in v0.4.0

func (t *CodeDependenciesTool) ParallelSafe(string) bool

func (*CodeDependenciesTool) PreviewCall added in v0.4.0

func (t *CodeDependenciesTool) PreviewCall(argsJSON string) string

func (*CodeDependenciesTool) RequiresApproval added in v0.4.0

func (t *CodeDependenciesTool) RequiresApproval(string) bool

func (*CodeDependenciesTool) Schema added in v0.4.0

func (t *CodeDependenciesTool) Schema() map[string]any

type CodeDependentsTool added in v0.4.0

type CodeDependentsTool struct{ Provider codemap.Provider }

func (*CodeDependentsTool) Description added in v0.4.0

func (t *CodeDependentsTool) Description() string

func (*CodeDependentsTool) Execute added in v0.4.0

func (t *CodeDependentsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeDependentsTool) Name added in v0.4.0

func (t *CodeDependentsTool) Name() string

func (*CodeDependentsTool) ParallelSafe added in v0.4.0

func (t *CodeDependentsTool) ParallelSafe(string) bool

func (*CodeDependentsTool) PreviewCall added in v0.4.0

func (t *CodeDependentsTool) PreviewCall(argsJSON string) string

func (*CodeDependentsTool) RequiresApproval added in v0.4.0

func (t *CodeDependentsTool) RequiresApproval(string) bool

func (*CodeDependentsTool) Schema added in v0.4.0

func (t *CodeDependentsTool) Schema() map[string]any

type CodeImpactTool added in v0.4.0

type CodeImpactTool struct{ Provider codemap.Provider }

func (*CodeImpactTool) Description added in v0.4.0

func (t *CodeImpactTool) Description() string

func (*CodeImpactTool) Execute added in v0.4.0

func (t *CodeImpactTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeImpactTool) Name added in v0.4.0

func (t *CodeImpactTool) Name() string

func (*CodeImpactTool) ParallelSafe added in v0.4.0

func (t *CodeImpactTool) ParallelSafe(string) bool

func (*CodeImpactTool) PreviewCall added in v0.4.0

func (t *CodeImpactTool) PreviewCall(argsJSON string) string

func (*CodeImpactTool) RequiresApproval added in v0.4.0

func (t *CodeImpactTool) RequiresApproval(string) bool

func (*CodeImpactTool) Schema added in v0.4.0

func (t *CodeImpactTool) Schema() map[string]any

type CodeMapDiagramTool added in v0.4.0

type CodeMapDiagramTool struct{ Provider codemap.Provider }

func (*CodeMapDiagramTool) Description added in v0.4.0

func (t *CodeMapDiagramTool) Description() string

func (*CodeMapDiagramTool) Execute added in v0.4.0

func (t *CodeMapDiagramTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeMapDiagramTool) Name added in v0.4.0

func (t *CodeMapDiagramTool) Name() string

func (*CodeMapDiagramTool) ParallelSafe added in v0.4.0

func (t *CodeMapDiagramTool) ParallelSafe(string) bool

func (*CodeMapDiagramTool) PreviewCall added in v0.4.0

func (t *CodeMapDiagramTool) PreviewCall(argsJSON string) string

func (*CodeMapDiagramTool) RequiresApproval added in v0.4.0

func (t *CodeMapDiagramTool) RequiresApproval(string) bool

func (*CodeMapDiagramTool) Schema added in v0.4.0

func (t *CodeMapDiagramTool) Schema() map[string]any

type CodeMapTool added in v0.4.0

type CodeMapTool struct{ Provider codemap.Provider }

CodeMapTool renders a bounded repository outline from the shared code index.

func (*CodeMapTool) Description added in v0.4.0

func (t *CodeMapTool) Description() string

func (*CodeMapTool) Execute added in v0.4.0

func (t *CodeMapTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeMapTool) Name added in v0.4.0

func (t *CodeMapTool) Name() string

func (*CodeMapTool) ParallelSafe added in v0.4.0

func (t *CodeMapTool) ParallelSafe(string) bool

func (*CodeMapTool) PreviewCall added in v0.4.0

func (t *CodeMapTool) PreviewCall(argsJSON string) string

func (*CodeMapTool) RequiresApproval added in v0.4.0

func (t *CodeMapTool) RequiresApproval(string) bool

func (*CodeMapTool) Schema added in v0.4.0

func (t *CodeMapTool) Schema() map[string]any

type CodeReviewContext added in v0.4.0

type CodeReviewContext struct {
	Effort         string
	CurrentBranch  string
	ResolvedBase   string
	BaseResolution string // "origin-head" | "fallback:<name>" | "unresolved"
	NotFoundBase   bool   // BaseResolution == "unresolved"
	EmptyRepo      bool   // repo has no commits yet (unborn HEAD) — a STOP flag, like NotFoundBase
	DiffSource     string // "branch-vs-base" | "working-tree"
	AheadCount     int
	AheadCountErr  bool // rev-list --count errored; AheadCount unreliable (0 may not mean "not ahead")
	FilesChanged   int
	Insertions     int
	Deletions      int
	DiffLines      int
	DiffEmpty      bool
	DiffErr        bool // a `git diff` call failed — distinct from a genuinely empty diff (must NOT read as "no changes")

	// MergeBase is the merge-base SHA of ResolvedBase and HEAD for the
	// branch-vs-base source (empty for working-tree, or when the two
	// histories share no common ancestor — see NoMergeBase). The diff is
	// built as MergeBase..HEAD (two-dot), identical to the three-dot
	// ResolvedBase...HEAD "Files changed" view, but resolving the
	// merge-base ourselves lets us (a) hand finders the exact base SHA so
	// they review the same range, and (b) detect the no-merge-base case
	// instead of letting three-dot's `fatal: no merge base` masquerade as
	// an empty diff.
	MergeBase   string
	NoMergeBase bool // ResolvedBase and HEAD share no common ancestor (orphan/grafted/unrelated history)
	// DiffBase is the left side of the two-dot range the snapshot was built
	// from — the ref finders must diff against (git_diff_files base=<DiffBase>,
	// head=HEAD) so their change set matches this snapshot exactly. MergeBase
	// for a normal branch, ResolvedBase when there is no merge-base, "HEAD"
	// for the working-tree source.
	DiffBase string

	ChangedFiles  string // name-status, capped
	ChangedCapped bool
	Diff          string // unified diff, capped to effortDiffCap(effort)
	DiffCap       int
	DiffCapped    bool
	// UntrackedFiles are new (untracked, non-ignored) files folded into the
	// working-tree review — `git diff HEAD` never shows them, so without this
	// a brand-new module would be invisible (and an untracked-only tree would
	// look empty). Empty for the branch-vs-base source.
	UntrackedFiles []string

	CommitLog     []string // "<short-sha> <subject>"; empty for working-tree source
	DetectedStyle string
}

CodeReviewContext is the typed snapshot the review tool returns. Same shape rationale as PRReviewContext: callers branch on the typed flags, and the rendered string is the model's view rather than the only access path.

func BuildCodeReviewContext added in v0.4.0

func BuildCodeReviewContext(ctx context.Context, cwd, effort string) (CodeReviewContext, error)

BuildCodeReviewContext is the deterministic core of code_review_context. It resolves the base (reusing resolveBaseBranch — the same logic pr_context uses), decides the diff source, and folds the result into typed STOP flags. A missing git binary or a non-repo cwd surfaces as the error from the first gitOutput call.

type CodeReviewContextTool added in v0.4.0

type CodeReviewContextTool struct {
	Cwd *CwdRef
}

CodeReviewContextTool gathers everything /code-review needs to fan out a multi-angle review of the local diff in one composite call: the resolved base, the changed-file list, the capped diff, the commit log, and detected commit style. Read-only, no approval modal. Counterpart to pr_review_context (which reviews an existing PR); this one reviews uncommitted/local work, so it needs no github.Interface.

func (*CodeReviewContextTool) Description added in v0.4.0

func (t *CodeReviewContextTool) Description() string

func (*CodeReviewContextTool) Execute added in v0.4.0

func (t *CodeReviewContextTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeReviewContextTool) Name added in v0.4.0

func (t *CodeReviewContextTool) Name() string

func (*CodeReviewContextTool) ParallelSafe added in v0.4.0

func (t *CodeReviewContextTool) ParallelSafe(string) bool

ParallelSafe: the tool only reads git state (no network, no mutation), so it can ride a parallel tool batch like the other read-only git context tools.

func (*CodeReviewContextTool) PreviewCall added in v0.4.0

func (t *CodeReviewContextTool) PreviewCall(argsJSON string) string

func (*CodeReviewContextTool) RequiresApproval added in v0.4.0

func (t *CodeReviewContextTool) RequiresApproval(string) bool

func (*CodeReviewContextTool) Schema added in v0.4.0

func (t *CodeReviewContextTool) Schema() map[string]any

type CodeStructureProjectionTool added in v0.4.0

type CodeStructureProjectionTool struct{ Provider codemap.Provider }

CodeStructureProjectionTool returns a compact context projection for agents.

func (*CodeStructureProjectionTool) Description added in v0.4.0

func (t *CodeStructureProjectionTool) Description() string

func (*CodeStructureProjectionTool) Execute added in v0.4.0

func (t *CodeStructureProjectionTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeStructureProjectionTool) Name added in v0.4.0

func (*CodeStructureProjectionTool) ParallelSafe added in v0.4.0

func (t *CodeStructureProjectionTool) ParallelSafe(string) bool

func (*CodeStructureProjectionTool) PreviewCall added in v0.4.0

func (t *CodeStructureProjectionTool) PreviewCall(string) string

func (*CodeStructureProjectionTool) RequiresApproval added in v0.4.0

func (t *CodeStructureProjectionTool) RequiresApproval(string) bool

func (*CodeStructureProjectionTool) Schema added in v0.4.0

func (t *CodeStructureProjectionTool) Schema() map[string]any

type CodeSymbolsTool added in v0.4.0

type CodeSymbolsTool struct{ Provider codemap.Provider }

CodeSymbolsTool returns symbols for one file or query from the code index.

func (*CodeSymbolsTool) Description added in v0.4.0

func (t *CodeSymbolsTool) Description() string

func (*CodeSymbolsTool) Execute added in v0.4.0

func (t *CodeSymbolsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CodeSymbolsTool) Name added in v0.4.0

func (t *CodeSymbolsTool) Name() string

func (*CodeSymbolsTool) ParallelSafe added in v0.4.0

func (t *CodeSymbolsTool) ParallelSafe(string) bool

func (*CodeSymbolsTool) PreviewCall added in v0.4.0

func (t *CodeSymbolsTool) PreviewCall(argsJSON string) string

func (*CodeSymbolsTool) RequiresApproval added in v0.4.0

func (t *CodeSymbolsTool) RequiresApproval(string) bool

func (*CodeSymbolsTool) Schema added in v0.4.0

func (t *CodeSymbolsTool) Schema() map[string]any

type CommandSegment

type CommandSegment struct {
	Text      string // the segment, trimmed
	Separator string // "" for first segment; "&&", "||", ";", "|" thereafter
	Risk      Risk
	Reason    string // human-readable why this is flagged, "" when RiskNone
}

CommandSegment is one piece of a (possibly) compound shell command, separated from the next segment by a logical operator or pipe. The separator that *precedes* this segment is recorded so the modal can label "and then" vs "or" vs "piped to" relationships.

func SplitCommand

func SplitCommand(cmd string) []CommandSegment

SplitCommand parses a shell command into segments separated by &&, ||, ;, and pipes. Quoted metacharacters (`"foo && bar"`) and escaped ones (`\&\&`) are ignored. Command substitutions ($(...) and `...`) are NOT recursively split; the whole substitution stays as part of its enclosing segment with a "contains substitution" caution flag if the substitution is non-trivial.

The output is suitable for display in the approval modal — not for execution semantics. We're trying to surface what a tired human might miss, not reproduce a real shell parser.

type CommitContext added in v0.3.0

type CommitContext struct {
	Branch         string
	StagedEmpty    bool
	StagedNameStat string
	StagedDiff     string
	StagedDiffCap  bool
	RecentSubjects []string
	BranchCommits  []string
	ProseDiff      string
	ProseDiffCap   bool
	Unstaged       []string
	Untracked      []string
	DetectedStyle  string // "conventional" | "ticket-prefix" | "plain"
}

CommitContext is the typed snapshot BuildCommitContext returns. Exported so the procedural /commit slash command can consume it directly (without a tool-call round trip) and the test suite can assert on each field rather than parsing the rendered string.

func BuildCommitContext added in v0.3.0

func BuildCommitContext(ctx context.Context, cwd string) (CommitContext, error)

BuildCommitContext is the deterministic core of git_commit_context. Returns a typed snapshot; the tool wrapper renders it to text for model consumption, and /commit calls it directly to drive a narrow synthesis prompt without a tool round trip.

type CommitResult added in v0.3.0

type CommitResult struct {
	Committed     bool
	SHA           string
	StagedEmpty   bool
	ValidationErr string
	HookError     string
	Unstaged      []string
	Untracked     []string
}

CommitResult is the typed envelope ApplyCommit returns. Rendering it to text is the tool's job; the procedural /commit slash command reads the struct directly for branching ("did the commit land? surface unstaged/untracked footer" vs "denied? quote it; bail").

func ApplyCommit added in v0.3.0

func ApplyCommit(ctx context.Context, cwd, message string) (CommitResult, error)

ApplyCommit is the deterministic core of git_commit_apply. Returns a typed CommitResult; the tool wrapper renders it for model consumption, and /commit's procedural path reads the struct directly. Errors return only on infrastructure failures (git binary missing, ctx canceled, fork failure); validation failures and hook rejections populate the result envelope so callers can branch without a stringy err = "..." check.

type CompactionConfig added in v0.3.0

type CompactionConfig struct {
	// Window is the model's context window in tokens. <=0 disables.
	Window int
	// Threshold is the fraction of Window at which compaction fires,
	// checked at the top of each iteration. <=0 disables.
	Threshold float64
	// TargetRatio is the share of Window retained verbatim as the recent
	// tail. <=0 uses defaultCompactionTargetRatio; callers should validate
	// user-configured values before building the LoopConfig.
	TargetRatio float64
	// Summarizer streams the one-shot summary call. nil falls back to
	// the loop's own Adapter (cache-safe routing can inject a cheaper
	// model here).
	Summarizer Streamer
	// SummarizerWindow is the context window (tokens) of the Summarizer
	// model. Under cache-safe routing the Summarizer is a cheaper model
	// that may have a SMALLER window than the loop's own model, so the
	// summary call's INPUT must be budgeted against whichever window is
	// smaller — otherwise a middle sized to the (larger) loop window
	// overflows the summarizer and the summary call fails, defeating
	// compaction. 0 means "same as Window" (the summarizer is the loop's
	// own adapter, so the windows match).
	SummarizerWindow int
	// PreCompact snapshots the exact pre-rewrite history. It is called
	// after compaction has proven it can change history but before the
	// replacement is installed. Snapshot failures are reported on the
	// ContextCompacted event and do not block compaction: provider-limit
	// recovery must still work on a full or unavailable disk.
	PreCompact func([]adapter.Message) (string, error)
}

CompactionConfig parameterizes in-loop compaction (LoopConfig.Compaction).

type ConsultAdvisorTool added in v0.4.0

type ConsultAdvisorTool struct {
	Advisor Streamer
	Model   string
	Timeout time.Duration
}

ConsultAdvisorTool lets an implementer subagent ask the configured advisor model for bounded design/debug guidance without recursively dispatching a child agent. The advisor call receives no tools, so it cannot mutate state or call back into consult_advisor.

func (*ConsultAdvisorTool) Description added in v0.4.0

func (t *ConsultAdvisorTool) Description() string

func (*ConsultAdvisorTool) Execute added in v0.4.0

func (t *ConsultAdvisorTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ConsultAdvisorTool) Name added in v0.4.0

func (t *ConsultAdvisorTool) Name() string

func (*ConsultAdvisorTool) PreviewCall added in v0.4.0

func (t *ConsultAdvisorTool) PreviewCall(string) string

func (*ConsultAdvisorTool) RequiresApproval added in v0.4.0

func (t *ConsultAdvisorTool) RequiresApproval(string) bool

func (*ConsultAdvisorTool) Schema added in v0.4.0

func (t *ConsultAdvisorTool) Schema() map[string]any

type ContentToken

type ContentToken struct{ Text string }

ContentToken carries one chunk of the assistant's actual reply. Render in normal style.

type ContextCompacted added in v0.3.0

type ContextCompacted struct {
	Before       int
	After        int
	Err          error
	SnapshotPath string
	SnapshotErr  error
	Forced       bool
}

ContextCompacted fires when the loop summarized its own older history in place to stay under the model's context window — the self-managed compaction that lets a long-running subagent keep working instead of overflowing the provider. Before/After are the estimated token counts of the history immediately before and after the rewrite. Err is set (with Before==After) when the summary call failed and history was left untouched — a best-effort skip, not a turn-ending error.

type ContextUsage added in v0.3.0

type ContextUsage struct {
	Tokens int
	Window int
}

ContextUsage reports a loop's current context size against its window, emitted at the top of each iteration. Subagent child loops (which set Compaction with a known window) emit it; the runner forwards it to the task registry so the live dock can render a per-subagent context-fill bar. The main TUI/oneshot loops don't set Compaction, so they don't emit it — their own status bar tracks context separately.

type CopyFileTool

type CopyFileTool struct {
	Cwd       *CwdRef
	WriteOpts WritePathOptions
	// DenyReadPaths gates the SOURCE against the credential read deny-list,
	// the same list read_file/read_many_files/grep use. copy_file is an
	// auto-approved read+write, so without this it would be a back door
	// around the read guard: copy ~/.ssh/id_rsa into a readable file, then
	// read that.
	DenyReadPaths []string
}

func (*CopyFileTool) Description

func (t *CopyFileTool) Description() string

func (*CopyFileTool) Execute

func (t *CopyFileTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CopyFileTool) Name

func (t *CopyFileTool) Name() string

func (*CopyFileTool) PathsToSnapshot added in v0.2.0

func (t *CopyFileTool) PathsToSnapshot(cwd, argsJSON string) []string

PathsToSnapshot reports only the destination — src is read-only here.

func (*CopyFileTool) PreviewCall

func (t *CopyFileTool) PreviewCall(argsJSON string) string

func (*CopyFileTool) RequiresApproval

func (t *CopyFileTool) RequiresApproval(string) bool

func (*CopyFileTool) Schema

func (t *CopyFileTool) Schema() map[string]any

type CoreToolDeps added in v0.3.0

type CoreToolDeps struct {
	// WriteOpts is the write-path policy for the mutating file tools. Its
	// Cwd field is overridden to match the cwd passed to
	// RegisterCoreCwdTools, so callers don't have to keep the two in sync.
	WriteOpts WritePathOptions

	// DenyReads is the credential-bearing read denylist (read_file,
	// read_many_files, grep). Typically DefaultDenyReadPaths(cwd).
	DenyReads []string

	// SupportsImages mirrors the adapter profile's image capability so
	// read_file can return image blocks when the model accepts them.
	SupportsImages bool

	// EnableLSP registers the experimental language-server-backed read-only
	// code-intelligence tools. The gate lives outside this helper so parent
	// sessions and dispatch workers expose the same surface once enabled.
	EnableLSP bool

	// LSPClientFactory lets tests inject a fake language-server client. Nil
	// uses the production stdio JSON-RPC client.
	LSPClientFactory lspClientFactory

	// LSPManager reuses initialized language-server processes across tool calls
	// for the parent session. Nil keeps the simple one-process-per-call path.
	LSPManager *lspci.Manager

	// LSPServers carries optional per-language server command overrides keyed by
	// stable language ID (go/typescript/python/rust).
	LSPServers map[string][]string

	// LSPDisabled lists language IDs whose server launch is disabled by config.
	LSPDisabled []string

	// CodeMapProvider exposes the optional experimental repository structure
	// index to read-only agent tools.
	CodeMapProvider codemap.Provider

	// EnableCodeMap registers the experimental read-only code-map tools.
	EnableCodeMap bool

	// EnableDocumentIngestion registers the experimental read_document
	// tool (bounded CSV/TSV/JSON/JSONL/XML/HTML extraction).
	EnableDocumentIngestion bool

	// EnableDocumentGeneration registers the experimental create_document
	// tool (xlsx generation via excelize; docx/pdf generation via pandoc,
	// routed through Sandbox).
	EnableDocumentGeneration bool

	// EnableSyntaxRanges registers offline parser-backed range-selection tools.
	// The actual edits still flow through anchored reads and edit_anchored.
	EnableSyntaxRanges bool

	// Sandbox is the command-execution backend for run_bash. Nil selects
	// HostSandbox (today's direct-on-host behavior) — see RunBashTool.sandbox.
	Sandbox Sandbox
}

CoreToolDeps carries the per-session settings the core cwd-bound tools need at construction. It is passed to RegisterCoreCwdTools so the same toolset can be built against different working directories — the parent session's cwd (TUI / oneshot) and a dispatch subagent's isolated worktree cwd — without duplicating the registration list.

type CreateDocumentTool added in v0.4.0

type CreateDocumentTool struct {
	Cwd       *CwdRef
	WriteOpts WritePathOptions

	// DenyReadPaths is the credential-path denylist for docx/pdf image
	// blocks (the only input read path this tool has — output_path is a
	// write). Mirrors MediaRenderTool.DenyReadPaths; typically
	// DefaultDenyReadPaths(cwd).
	DenyReadPaths []string

	// Sandbox is nil-safe: a nil Sandbox behaves exactly like HostSandbox,
	// mirroring RunBashTool.Sandbox. Only consulted for docx/pdf — xlsx and
	// pptx are native Go paths and never shell out.
	Sandbox Sandbox
}

CreateDocumentTool generates an xlsx, docx, pdf, or pptx file from structured content. xlsx and pptx are generated natively in Go; docx/pdf go through pandoc, routed through the same Sandbox seam RunBashTool uses — see roadmap/document-generation.md's "Sandbox integration".

Always requires approval: it writes a new file, same trust class as media_render/media_compose.

func (*CreateDocumentTool) Description added in v0.4.0

func (t *CreateDocumentTool) Description() string

func (*CreateDocumentTool) Execute added in v0.4.0

func (t *CreateDocumentTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*CreateDocumentTool) Name added in v0.4.0

func (t *CreateDocumentTool) Name() string

func (*CreateDocumentTool) PathsToSnapshot added in v0.4.0

func (t *CreateDocumentTool) PathsToSnapshot(cwd, argsJSON string) []string

func (*CreateDocumentTool) PreviewCall added in v0.4.0

func (t *CreateDocumentTool) PreviewCall(argsJSON string) string

func (*CreateDocumentTool) RequiresApproval added in v0.4.0

func (t *CreateDocumentTool) RequiresApproval(string) bool

func (*CreateDocumentTool) Schema added in v0.4.0

func (t *CreateDocumentTool) Schema() map[string]any

type CwdChanged added in v0.3.0

type CwdChanged struct {
	NewCwd string
}

CwdChanged fires when a tool (today: enter_worktree / exit_worktree) swapped the session's working directory mid-conversation. The TUI refreshes its status-line worktree chip and any cwd-derived display state; oneshot ignores it. Emitted by the loop right after the tool's ToolResult when LoopConfig.Cwd.Get() differs from the pre-call value.

type CwdRef added in v0.3.0

type CwdRef struct {
	// contains filtered or unexported fields
}

CwdRef is the shared working-directory holder a session's tools read through instead of stashing an immutable string at construction time. It exists so enter_worktree / exit_worktree can swap the session's working directory mid-conversation without rebuilding the tool registry.

All tools that previously held `Cwd string` now hold `CwdRef *CwdRef` and call CwdRef.Get() inside their Execute path. The same *CwdRef is shared across every tool at registration time (see tui/run.go and oneshot/oneshot.go), so one Set propagates to all of them on the next tool dispatch.

Backed by atomic.Pointer[string] so the race detector stays clean when (rarely) parallel-safe reads from concurrent tool dispatch land alongside a Set from enter_worktree. In normal use the loop runs tool calls sequentially within a turn — atomicity is belt-and-braces.

func NewCwdRef added in v0.3.0

func NewCwdRef(initial string) *CwdRef

NewCwdRef constructs a CwdRef holding the given initial value.

func (*CwdRef) Get added in v0.3.0

func (r *CwdRef) Get() string

Get returns the current cwd. Nil-safe: returns "" when r is nil (defensive — tests sometimes construct tools without one).

func (*CwdRef) Set added in v0.3.0

func (r *CwdRef) Set(v string)

Set replaces the current cwd. Subsequent Get calls (from any tool sharing this CwdRef) observe the new value.

type Decision

type Decision int

Decision is the verdict the consumer sends back when the loop emits an ApprovalNeeded event. AllowAlways writes a derived rule to the project-local .yottacode/permissions.local.json via the permissions.Permissions value passed in LoopConfig.

const (
	// Deny refuses this single call and reports "denied by user" to
	// the model so it can recover.
	Deny Decision = iota
	// AllowOnce permits this single call. No persistence.
	AllowOnce
	// AllowAlways permits this call and asks the loop to derive a
	// pattern from it (via permissions.DeriveAllowRule) and append it
	// to permissions.local.json so future matching calls are silent.
	// The TUI suppresses this option for cases where derivation isn't
	// safe (compound shell commands, dangerous verbs).
	AllowAlways
	// SaveForLater is the plan-mode-specific "[L] approve and
	// implement later" decision. The loop refuses the tool call (so
	// Execute never runs) but returns a firm "end this turn" message
	// to the model instead of the generic denial / refinement hint.
	// Only meaningful for exit_plan_mode; other tools should never
	// receive this value, and the loop falls back to generic-denial
	// semantics if they do.
	SaveForLater
	// PathAllowOnce is the inline path-trust elevation answer for
	// "[1] Allow once" — let this exact write proceed by adding the
	// file's path to the session-scoped allow list. Future writes to
	// other files outside cwd still prompt. Session-only, never
	// persisted to ~/.yottacode/trusted-roots.json.
	PathAllowOnce
	// PathTrustSession is the inline path-trust elevation answer for
	// "[2] Trust this directory for the session" — adds the file's
	// parent directory to the session-scoped allow list so every
	// future write under that directory also succeeds. Session-only.
	PathTrustSession
	// DenyAlways refuses this call (like Deny) AND asks the loop to
	// derive a block pattern from it (via permissions.DeriveDenyRule) and
	// append it to the deny[] list in permissions.local.json, so future
	// matching calls are refused without prompting. The mirror of
	// AllowAlways. Unlike AllowAlways it is offered even for dangerous or
	// compound commands — those are exactly the calls a user most wants to
	// block permanently. Scope is currently run_bash + git.
	DenyAlways
)

type DeleteFileTool

type DeleteFileTool struct {
	Cwd       *CwdRef
	WriteOpts WritePathOptions
}

func (*DeleteFileTool) Description

func (t *DeleteFileTool) Description() string

func (*DeleteFileTool) Execute

func (t *DeleteFileTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*DeleteFileTool) Name

func (t *DeleteFileTool) Name() string

func (*DeleteFileTool) PathsToSnapshot added in v0.2.0

func (t *DeleteFileTool) PathsToSnapshot(cwd, argsJSON string) []string

PathsToSnapshot reports the target so /checkpoints can recreate the deleted file on rewind.

func (*DeleteFileTool) PreviewCall

func (t *DeleteFileTool) PreviewCall(argsJSON string) string

func (*DeleteFileTool) RequiresApproval

func (t *DeleteFileTool) RequiresApproval(string) bool

func (*DeleteFileTool) Schema

func (t *DeleteFileTool) Schema() map[string]any

type DispatchTool added in v0.3.0

type DispatchTool struct {
	// Agent is the session's AgentTool. DispatchTool reuses its Configs,
	// Tasks registry, model routing, transcript dir, mode pointers, and
	// runChild. Required.
	Agent *AgentTool

	// SupportsImages mirrors the adapter profile so worktree children's
	// read_file can return image blocks.
	SupportsImages bool

	// SupportsBackground reports whether this session can host detached
	// background workers (true in the TUI, false in oneshot where there's
	// no long-running session to surface async completions). When false,
	// a background dispatch silently falls back to foreground/waiting mode.
	SupportsBackground bool

	// Enabled gates the tool behind the `dispatch` experimental feature.
	// When false, Execute returns a recoverable error string.
	Enabled bool

	// EnableSyntaxRanges lets dispatch workers use the same offline range-selection surface.
	EnableSyntaxRanges bool

	// EnableDocumentIngestion lets dispatch workers use the same
	// read_document tool surface as the parent session.
	EnableDocumentIngestion bool

	// EnableDocumentGeneration lets dispatch workers use the same
	// create_document tool surface as the parent session.
	EnableDocumentGeneration bool

	// EnableLSP lets dispatch workers expose the same LSP tool surface as the
	// parent session, while writes still flow through the worker's owned-file
	// WriteOpts.
	EnableLSP bool

	// LSPServers carries optional per-language server command overrides.
	LSPServers map[string][]string

	// LSPDisabled lists language IDs whose server launch is disabled by config.
	LSPDisabled []string

	// SandboxFactory, when non-nil, constructs a per-write-worker Sandbox
	// (a fresh podman container mounted at the worker's worktree) — the
	// same posture the parent session's own Sandbox uses, inherited by
	// default rather than gated by a separate dispatch-level flag. Nil
	// means dispatch write-workers run run_bash on the host, same as
	// today. Read-only workers never need this: they reuse the parent's
	// registry (and its Sandbox) via buildChildRegistry.
	SandboxFactory SandboxFactory
}

DispatchTool fans a batch of subtasks out to subagents that run concurrently. Write batches usually return immediately and continue in background worktrees; all-read batches wait and return their findings labeled together so the parent can assemble them. Write-capable subtasks each run in an isolated git worktree+branch (no shared-cwd clobbering); read-only subtasks share the parent cwd. The parent partitions work by declaring each write subtask's file scope; an overlap guard rejects colliding scopes so the branches merge cleanly via the integrate tool.

It reuses AgentTool for routing, transcripts, the task registry, and the child loop runner (runChild) — DispatchTool is the batch + worktree orchestration layer on top.

func (*DispatchTool) Description added in v0.3.0

func (t *DispatchTool) Description() string

func (*DispatchTool) Execute added in v0.3.0

func (t *DispatchTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*DispatchTool) Name added in v0.3.0

func (t *DispatchTool) Name() string

func (*DispatchTool) ParallelSafe added in v0.3.0

func (t *DispatchTool) ParallelSafe(string) bool

ParallelSafe is false: dispatch is a heavyweight orchestration call that itself fans out concurrent children. Running two dispatch calls at once would multiply worktree/branch churn and contend on the single approval modal with no benefit. The loop runs it on its own.

func (*DispatchTool) PreviewCall added in v0.3.0

func (t *DispatchTool) PreviewCall(argsJSON string) string

func (*DispatchTool) RequiresApproval added in v0.3.0

func (t *DispatchTool) RequiresApproval(string) bool

RequiresApproval is false for the dispatch call itself — it's orchestration. Each child's own mutating tool calls still flow through the normal approval path (forwarded to the parent modal for foreground children, serialized across the batch by the approval gate).

func (*DispatchTool) Schema added in v0.3.0

func (t *DispatchTool) Schema() map[string]any

type EditAnchoredTool added in v0.4.0

type EditAnchoredTool struct {
	Cwd        *CwdRef
	WriteOpts  WritePathOptions
	LSPManager *lspci.Manager
	LSPServers map[string][]string
}

func (*EditAnchoredTool) Description added in v0.4.0

func (t *EditAnchoredTool) Description() string

func (*EditAnchoredTool) Execute added in v0.4.0

func (t *EditAnchoredTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*EditAnchoredTool) Name added in v0.4.0

func (t *EditAnchoredTool) Name() string

func (*EditAnchoredTool) PathsToSnapshot added in v0.4.0

func (t *EditAnchoredTool) PathsToSnapshot(cwd, argsJSON string) []string

func (*EditAnchoredTool) PreviewCall added in v0.4.0

func (t *EditAnchoredTool) PreviewCall(argsJSON string) string

func (*EditAnchoredTool) RequiresApproval added in v0.4.0

func (t *EditAnchoredTool) RequiresApproval(string) bool

func (*EditAnchoredTool) Schema added in v0.4.0

func (t *EditAnchoredTool) Schema() map[string]any

type EditFileTool

type EditFileTool struct {
	Cwd        *CwdRef
	WriteOpts  WritePathOptions
	LSPManager *lspci.Manager
	LSPServers map[string][]string
}

EditFileTool performs a surgical replacement inside an existing file. Strictly better than write_file for code edits: it preserves the rest of the file and refuses to apply a non-unique match unless replace_all is set, which catches stale assumptions before they corrupt code.

func (*EditFileTool) Description

func (t *EditFileTool) Description() string

func (*EditFileTool) Execute

func (t *EditFileTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*EditFileTool) Name

func (t *EditFileTool) Name() string

func (*EditFileTool) PathsToSnapshot added in v0.2.0

func (t *EditFileTool) PathsToSnapshot(cwd, argsJSON string) []string

PathsToSnapshot reports the target file so /checkpoints can restore the pre-edit contents on rewind.

func (*EditFileTool) PreviewCall

func (t *EditFileTool) PreviewCall(argsJSON string) string

func (*EditFileTool) RequiresApproval

func (t *EditFileTool) RequiresApproval(string) bool

func (*EditFileTool) Schema

func (t *EditFileTool) Schema() map[string]any

type EnterPlanModeTool added in v0.3.0

type EnterPlanModeTool struct {
	// State is the session's shared plan-mode state, wired at
	// registration. Execute reads it on the approve path to report the
	// resolved plan file back to the model (the TUI fills it before
	// sending AllowOnce, so the channel receive orders the read).
	State *PlanModeState
}

EnterPlanModeTool is the model's request to switch the session into plan mode. Mirrors Claude Code's `EnterPlanMode`: when the user asks to plan first in natural language ("make a plan before coding", "drop into plan mode"), the model calls this instead of role-playing a mode it isn't in — without the tool, the model has no way to make the request real and tends to claim a mode change that never happened, with none of plan mode's read-only enforcement behind it.

The tool itself is intentionally minimal, the same shape as ExitPlanModeTool: RequiresApproval=true routes the call through the approval flow, the TUI renders a dedicated [Y]/[N] card for it, and on approve the TUI runs the same entry sequence as /plan (exit auto mode, flip the shared PlanModeState, derive the plan file from the turn's user message) BEFORE forwarding the decision. Execute therefore only runs once the mode is genuinely active.

The schema filter in streamIteration advertises this tool only while plan mode is OFF (inverse of exit_plan_mode), and executeToolCallImpl's boundary-tool guard ensures the call always prompts — yolo, auto mode, bypass, and permissions Allow rules never auto-approve it, because the approval IS the handshake that flips the TUI's state. Registered in the TUI build only: oneshot has no approval surface to host the handshake.

func (*EnterPlanModeTool) Description added in v0.3.0

func (t *EnterPlanModeTool) Description() string

func (*EnterPlanModeTool) Execute added in v0.3.0

func (t *EnterPlanModeTool) Execute(_ context.Context, _ string) (string, error)

Execute is only reached on the approve path — the TUI has already flipped the shared state and (when the turn carried a user message) resolved the plan file. Report both so the model can start writing the plan immediately; the per-iteration plan-mode addendum reinforces the rules from the next iteration on.

func (*EnterPlanModeTool) Name added in v0.3.0

func (t *EnterPlanModeTool) Name() string

func (*EnterPlanModeTool) PreviewCall added in v0.3.0

func (t *EnterPlanModeTool) PreviewCall(string) string

func (*EnterPlanModeTool) RequiresApproval added in v0.3.0

func (t *EnterPlanModeTool) RequiresApproval(string) bool

RequiresApproval is always true: entering plan mode mid-turn changes what every subsequent tool call is allowed to do, so the user confirms the transition. The loop's boundary-tool guard keeps this prompt alive even under yolo/auto/bypass.

func (*EnterPlanModeTool) Schema added in v0.3.0

func (t *EnterPlanModeTool) Schema() map[string]any

Schema is an empty object — like exit_plan_mode, the tool carries no arguments. The plan topic comes from the conversation itself: the TUI derives the plan-file slug from the turn's user message.

type EnterWorktreeTool added in v0.3.0

type EnterWorktreeTool struct {
	Cwd *CwdRef
	// Sandbox is nil when run_bash executes on the host (today's
	// default). Non-nil means a container-backed Sandbox (e.g.
	// PodmanSandbox) is active for this session — Execute then refuses:
	// the container only has the session's ORIGINAL cwd bind-mounted
	// (set once at session startup), so swapping CwdRef to a worktree
	// path would point every subsequent run_bash's `podman exec -w` at a
	// directory the container can't see, silently breaking it.
	Sandbox Sandbox
}

EnterWorktreeTool is the high-level "agent wants to work on this in isolation" entry point. It creates (or attaches to) a yottacode- managed worktree under <repo>/.yottacode/worktrees/<name>/ on branch worktree-<name>, copies the gitignored files listed in .worktreeinclude, and returns the new working directory.

v1 caveat: the session's cwd does NOT swap in-process. The agent is told the absolute path and is expected to use absolute paths (or `cd <path>` via run_bash) for subsequent operations. A fresh session in the worktree can be started with `yottacode --worktree <name>` (or via the worktree CLI subcommand), which sets cwd at process start. In-session cwd swap is v1.1 polish.

Always requires approval (auto-mode safety floor) because creating a worktree is a real side effect and the cwd-shift surprise warrants an explicit user click.

func (*EnterWorktreeTool) Description added in v0.3.0

func (t *EnterWorktreeTool) Description() string

func (*EnterWorktreeTool) Execute added in v0.3.0

func (t *EnterWorktreeTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*EnterWorktreeTool) Name added in v0.3.0

func (t *EnterWorktreeTool) Name() string

func (*EnterWorktreeTool) PreviewCall added in v0.3.0

func (t *EnterWorktreeTool) PreviewCall(argsJSON string) string

func (*EnterWorktreeTool) RequiresApproval added in v0.3.0

func (t *EnterWorktreeTool) RequiresApproval(string) bool

func (*EnterWorktreeTool) Schema added in v0.3.0

func (t *EnterWorktreeTool) Schema() map[string]any

type ErrPathOutsideWorkspace added in v0.3.0

type ErrPathOutsideWorkspace struct {
	Path         string
	Cwd          string
	AllowedRoots []string
}

ErrPathOutsideWorkspace is the structured error ValidateWritePath returns when a write target falls outside cwd and every --allow-paths root. Callers in the TUI (errors.As) catch this to render the inline path-trust elevation modal — Prompt 2 in yottacode-roadmap/folder-trust.md — and offer the user a choice between Allow-once / Trust-for-session / Reject.

The fields are the bits the modal needs to render a useful dialog: the absolute path the model wanted, the workspace it's outside of, and the existing allow-list so the user can see what's already trusted before deciding.

Error() returns a descriptive message the model sees on Reject: names the workspace boundary plus a recovery hint, so the model can switch to an in-workspace target or stop and ask the user to relaunch with --allow-paths. Mirrors Claude Code's per-tool deny semantics — informative, not prescriptive.

func (*ErrPathOutsideWorkspace) Error added in v0.3.0

func (e *ErrPathOutsideWorkspace) Error() string

type ErrorEvent

type ErrorEvent struct{ Err error }

ErrorEvent fires when the turn terminates because of an error (adapter failure, ctx cancel, etc.). The error is also returned by Turn.

type Event

type Event interface {
	// contains filtered or unexported methods
}

Event is the union of things the agent loop emits while a turn runs. Consumers (REPL today, TUI next, `yottacode run` after that) type-switch on the concrete value.

Channel ownership: the *caller* owns the events channel and is responsible for closing it; Turn never closes it. Use a buffered channel (~64) so the loop doesn't block when the consumer is briefly busy.

Approval flow: when a tool requires approval and policy doesn't pre-approve (a matching allow rule in permissions.json, or --yolo), the loop emits ApprovalNeeded and blocks on a receive from the decisions channel. The consumer must reply with a Decision or cancel ctx.

type ExitPlanModeTool added in v0.2.0

type ExitPlanModeTool struct{}

ExitPlanModeTool is the model's signal that planning is finished and the plan file is ready for user approval. Mirrors Claude Code's `ExitPlanMode` exactly: the tool takes no `plan` argument — the content is read from the plan file the model has been writing to all along. Single source of truth (the file on disk), lower token usage, and no ambiguity about whether the approval card shows the same thing as the file the model intends to execute.

The tool itself is intentionally minimal: RequiresApproval=true routes the call through the standard approval flow, the TUI reads the plan file from disk and renders a plan-specific approval card ([A]/[K] hotkeys) for `exit_plan_mode` rather than the generic preview, and on approve the TUI flips the shared PlanModeState.Active flag off before forwarding the decision. The loop's `deniedResultFor` is special-cased for this tool name so a [K] (Keep planning) returns refinement guidance to the model instead of the generic "denied by user".

Execute therefore only runs on the approve path and unconditionally returns the "approved" message. The TUI is responsible for the "file is missing/empty" guard — it auto-denies before showing the approval card.

func (*ExitPlanModeTool) Description added in v0.2.0

func (t *ExitPlanModeTool) Description() string

func (*ExitPlanModeTool) Execute added in v0.2.0

func (t *ExitPlanModeTool) Execute(_ context.Context, _ string) (string, error)

Execute is only reached on the approve path — the loop short-circuits on Deny in promptForApproval and never calls the tool. Before showing the approval card the TUI inspects the plan file and auto-denies if it's missing or empty, so by the time we're here the file existed and the user said yes. Return the "approved" string and the model continues.

func (*ExitPlanModeTool) Name added in v0.2.0

func (t *ExitPlanModeTool) Name() string

func (*ExitPlanModeTool) PreviewCall added in v0.2.0

func (t *ExitPlanModeTool) PreviewCall(string) string

func (*ExitPlanModeTool) RequiresApproval added in v0.2.0

func (t *ExitPlanModeTool) RequiresApproval(string) bool

RequiresApproval is always true: every exit_plan_mode call goes through the approval card so the user can see the proposed plan before yottacode regains write access.

func (*ExitPlanModeTool) Schema added in v0.2.0

func (t *ExitPlanModeTool) Schema() map[string]any

Schema is an empty object — exit_plan_mode takes no arguments. The model writes the plan to disk via write_file/edit_file first, then calls this tool to surface it for approval. Matches Claude Code's ExitPlanMode shape.

type ExitWorktreeTool added in v0.3.0

type ExitWorktreeTool struct {
	Cwd *CwdRef
}

ExitWorktreeTool leaves the named yottacode worktree, applying the cleanup rule. The session itself continues — this is symmetric to EnterWorktreeTool, which only created the worktree without swapping cwd. Cleanup behavior:

cleanup=auto (default): clean tree → remove; dirty tree → keep
                        with a "use cleanup=remove to discard"
                        hint in the result
cleanup=keep:           never remove
cleanup=remove:         force-remove (discards uncommitted /
                        untracked / unpushed work)

Always requires approval (auto-mode safety floor). The force-remove path is destructive and the user should see it.

func (*ExitWorktreeTool) Description added in v0.3.0

func (t *ExitWorktreeTool) Description() string

func (*ExitWorktreeTool) Execute added in v0.3.0

func (t *ExitWorktreeTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ExitWorktreeTool) Name added in v0.3.0

func (t *ExitWorktreeTool) Name() string

func (*ExitWorktreeTool) PreviewCall added in v0.3.0

func (t *ExitWorktreeTool) PreviewCall(argsJSON string) string

func (*ExitWorktreeTool) RequiresApproval added in v0.3.0

func (t *ExitWorktreeTool) RequiresApproval(string) bool

func (*ExitWorktreeTool) Schema added in v0.3.0

func (t *ExitWorktreeTool) Schema() map[string]any

type Fallback

type Fallback struct {
	From   string
	To     string
	Reason string
	Policy string
	// Agent names the context the fallback happened in — a subagent type
	// (e.g. "Explore") or "summarize" — so the TUI can distinguish a
	// delegated/summarization fallover from a main-thread one. Empty for
	// the main conversation.
	Agent string
}

Fallback fires when the multi-provider router falls through from one candidate to another after an early failure (an error before any tokens streamed). Carries enough metadata for the TUI to render a loud "↻ fallback: A → B (reason)" line — silent fallback is the failure mode the router design is built to avoid.

type FetchURLTool

type FetchURLTool struct {
	// Client overrides the HTTP client. nil (the production default) uses
	// the SSRF-guarded client; tests inject a permissive client to reach a
	// loopback httptest server.
	Client *http.Client
}

FetchURLTool retrieves a single URL over HTTP(S) and returns capped textual content. This is the local-network fallback for models that do not have provider-native web search.

func (*FetchURLTool) Description

func (t *FetchURLTool) Description() string

func (*FetchURLTool) Execute

func (t *FetchURLTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*FetchURLTool) Name

func (t *FetchURLTool) Name() string

func (*FetchURLTool) ParallelSafe

func (t *FetchURLTool) ParallelSafe(string) bool

func (*FetchURLTool) PreviewCall

func (t *FetchURLTool) PreviewCall(argsJSON string) string

func (*FetchURLTool) RequiresApproval

func (t *FetchURLTool) RequiresApproval(string) bool

func (*FetchURLTool) Schema

func (t *FetchURLTool) Schema() map[string]any

type GHIssueContextTool added in v0.3.0

type GHIssueContextTool struct{ Cwd *CwdRef }

GHIssueContextTool produces the read-only snapshot a caller needs to draft an issue title + body. Mirrors GHPRContextTool for issues.

func (*GHIssueContextTool) Description added in v0.3.0

func (t *GHIssueContextTool) Description() string

func (*GHIssueContextTool) Execute added in v0.3.0

func (t *GHIssueContextTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHIssueContextTool) Name added in v0.3.0

func (t *GHIssueContextTool) Name() string

func (*GHIssueContextTool) PreviewCall added in v0.3.0

func (t *GHIssueContextTool) PreviewCall(argsJSON string) string

func (*GHIssueContextTool) RequiresApproval added in v0.3.0

func (t *GHIssueContextTool) RequiresApproval(string) bool

func (*GHIssueContextTool) Schema added in v0.3.0

func (t *GHIssueContextTool) Schema() map[string]any

type GHIssueCreateTool added in v0.3.0

type GHIssueCreateTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GHIssueCreateTool is the typed mutator that opens the issue. Validates the title in Go *before* invoking github.Interface.CreateIssue; empty, multi-line, oversize, and trailing-period titles can't reach the network.

func (*GHIssueCreateTool) Description added in v0.3.0

func (t *GHIssueCreateTool) Description() string

func (*GHIssueCreateTool) Execute added in v0.3.0

func (t *GHIssueCreateTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHIssueCreateTool) Name added in v0.3.0

func (t *GHIssueCreateTool) Name() string

func (*GHIssueCreateTool) PreviewCall added in v0.3.0

func (t *GHIssueCreateTool) PreviewCall(argsJSON string) string

func (*GHIssueCreateTool) RequiresApproval added in v0.3.0

func (t *GHIssueCreateTool) RequiresApproval(string) bool

func (*GHIssueCreateTool) Schema added in v0.3.0

func (t *GHIssueCreateTool) Schema() map[string]any

type GHIssueListTool added in v0.3.0

type GHIssueListTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GHIssueListTool wraps Interface.ListOpenIssues. Returns lightweight summaries — number, title, author, URL, labels, assignees. Bodies are deliberately not included; the model follows up with issue_read on a specific issue when it needs more.

Read-only, no approval. Filters are AND-ed (e.g., labels=[bug] AND assignee=octocat returns only issues matching both).

func (*GHIssueListTool) Description added in v0.3.0

func (t *GHIssueListTool) Description() string

func (*GHIssueListTool) Execute added in v0.3.0

func (t *GHIssueListTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHIssueListTool) Name added in v0.3.0

func (t *GHIssueListTool) Name() string

func (*GHIssueListTool) PreviewCall added in v0.3.0

func (t *GHIssueListTool) PreviewCall(argsJSON string) string

func (*GHIssueListTool) RequiresApproval added in v0.3.0

func (t *GHIssueListTool) RequiresApproval(string) bool

func (*GHIssueListTool) Schema added in v0.3.0

func (t *GHIssueListTool) Schema() map[string]any

type GHIssueReadTool added in v0.3.0

type GHIssueReadTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GHIssueReadTool wraps Interface.ReadIssue. Single API call (plus one comment fetch when MaxComments != -1). The /git-implement-issue slash command calls this as its first step; ad-hoc model use is the cheap default for any "what does issue 42 say" question.

Read-only, no approval modal. Single API surface, so cheaper than pr_review_context — there's no checks/diff equivalent to bundle in for issues.

func (*GHIssueReadTool) Description added in v0.3.0

func (t *GHIssueReadTool) Description() string

func (*GHIssueReadTool) Execute added in v0.3.0

func (t *GHIssueReadTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHIssueReadTool) Name added in v0.3.0

func (t *GHIssueReadTool) Name() string

func (*GHIssueReadTool) PreviewCall added in v0.3.0

func (t *GHIssueReadTool) PreviewCall(argsJSON string) string

func (*GHIssueReadTool) RequiresApproval added in v0.3.0

func (t *GHIssueReadTool) RequiresApproval(string) bool

func (*GHIssueReadTool) Schema added in v0.3.0

func (t *GHIssueReadTool) Schema() map[string]any

type GHPRAddCommentTool added in v0.3.0

type GHPRAddCommentTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GHPRAddCommentTool posts a top-level conversation comment on a PR. Approval-gated — every comment goes through the modal so the user reads the body before it lands publicly on GitHub.

Companion to pr_create / pr_update for the write surface. Validates body length in Go before dialing the Interface so runaway template output can't reach the network.

func (*GHPRAddCommentTool) Description added in v0.3.0

func (t *GHPRAddCommentTool) Description() string

func (*GHPRAddCommentTool) Execute added in v0.3.0

func (t *GHPRAddCommentTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHPRAddCommentTool) Name added in v0.3.0

func (t *GHPRAddCommentTool) Name() string

func (*GHPRAddCommentTool) PreviewCall added in v0.3.0

func (t *GHPRAddCommentTool) PreviewCall(argsJSON string) string

func (*GHPRAddCommentTool) RequiresApproval added in v0.3.0

func (t *GHPRAddCommentTool) RequiresApproval(string) bool

func (*GHPRAddCommentTool) Schema added in v0.3.0

func (t *GHPRAddCommentTool) Schema() map[string]any

type GHPRContextTool added in v0.3.0

type GHPRContextTool struct{ Cwd *CwdRef }

GHPRContextTool produces the read-only snapshot a caller needs to draft a PR title + body and decide whether to push or fall through to draft-only. Replaces the multi-step bash heredoc the legacy /git:create-pr directive used as its first tool call.

func (*GHPRContextTool) Description added in v0.3.0

func (t *GHPRContextTool) Description() string

func (*GHPRContextTool) Execute added in v0.3.0

func (t *GHPRContextTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHPRContextTool) Name added in v0.3.0

func (t *GHPRContextTool) Name() string

func (*GHPRContextTool) PreviewCall added in v0.3.0

func (t *GHPRContextTool) PreviewCall(argsJSON string) string

func (*GHPRContextTool) RequiresApproval added in v0.3.0

func (t *GHPRContextTool) RequiresApproval(string) bool

func (*GHPRContextTool) Schema added in v0.3.0

func (t *GHPRContextTool) Schema() map[string]any

type GHPRCreateTool added in v0.3.0

type GHPRCreateTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GHPRCreateTool is the typed mutator that opens the PR. Validates title length and required fields in Go *before* invoking github.Interface.CreatePR; oversize titles, missing bodies, and blank bases can't reach the network. Hooks back into the github.Interface so v0.5.0's typed go-github client replaces the shell-out without touching this file.

func (*GHPRCreateTool) Description added in v0.3.0

func (t *GHPRCreateTool) Description() string

func (*GHPRCreateTool) Execute added in v0.3.0

func (t *GHPRCreateTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHPRCreateTool) Name added in v0.3.0

func (t *GHPRCreateTool) Name() string

func (*GHPRCreateTool) PreviewCall added in v0.3.0

func (t *GHPRCreateTool) PreviewCall(argsJSON string) string

func (*GHPRCreateTool) RequiresApproval added in v0.3.0

func (t *GHPRCreateTool) RequiresApproval(string) bool

func (*GHPRCreateTool) Schema added in v0.3.0

func (t *GHPRCreateTool) Schema() map[string]any

type GHPRReadTool added in v0.3.0

type GHPRReadTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GHPRReadTool is the cheap counterpart to GHPRReviewContextTool — a single ReadPR call returning just the PR metadata (no diff, no checks). Exists so the model has a body-only read path that doesn't pull megabytes of diff + every check-run when the task is "fetch the PR description" or "what's the title of #29".

Read-only, no approval modal, single API call. The cheap default for any PR-metadata question; pr_review_context stays the right choice when the model also needs the diff or check status.

func (*GHPRReadTool) Description added in v0.3.0

func (t *GHPRReadTool) Description() string

func (*GHPRReadTool) Execute added in v0.3.0

func (t *GHPRReadTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHPRReadTool) Name added in v0.3.0

func (t *GHPRReadTool) Name() string

func (*GHPRReadTool) PreviewCall added in v0.3.0

func (t *GHPRReadTool) PreviewCall(argsJSON string) string

func (*GHPRReadTool) RequiresApproval added in v0.3.0

func (t *GHPRReadTool) RequiresApproval(string) bool

func (*GHPRReadTool) Schema added in v0.3.0

func (t *GHPRReadTool) Schema() map[string]any

type GHPRReviewContextTool added in v0.3.0

type GHPRReviewContextTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GHPRReviewContextTool fetches everything /git-review-pr needs in one composite call: PR metadata, full diff (capped), and the status check rollup. Counterpart to pr_context (which gathers local pre-PR state); this one talks to an existing PR via the github.Interface.

Read-only — no approval modal — but does touch the network and so is NOT marked parallel-safe. The fetch fans out to three Interface calls (ReadPR + ListPRChecks + ReadPRDiff). When the caller only needs PR metadata (title, body, state, labels), the cheaper pr_read tool is the right choice — see its Description for the selection rule.

func (*GHPRReviewContextTool) Description added in v0.3.0

func (t *GHPRReviewContextTool) Description() string

func (*GHPRReviewContextTool) Execute added in v0.3.0

func (t *GHPRReviewContextTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHPRReviewContextTool) Name added in v0.3.0

func (t *GHPRReviewContextTool) Name() string

func (*GHPRReviewContextTool) PreviewCall added in v0.3.0

func (t *GHPRReviewContextTool) PreviewCall(argsJSON string) string

func (*GHPRReviewContextTool) RequiresApproval added in v0.3.0

func (t *GHPRReviewContextTool) RequiresApproval(string) bool

func (*GHPRReviewContextTool) Schema added in v0.3.0

func (t *GHPRReviewContextTool) Schema() map[string]any

type GHPRUpdateTool added in v0.3.0

type GHPRUpdateTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GHPRUpdateTool is the typed mutator that rewrites an existing PR's title and body. Paired with /git-update-pr for the "follow-up commits made the original description stale" workflow. Title validation reuses validatePRTitle (same rules as create-pr: ≤72 chars, no trailing period, single line); body must be non-empty because an empty body would clobber the existing description, which is almost never intended.

Other PR-level edits (labels, base, reviewers, draft toggle) are intentionally out of scope. When a concrete workflow asks for them, they grow Interface.UpdatePR's request type rather than spawning a new tool.

func (*GHPRUpdateTool) Description added in v0.3.0

func (t *GHPRUpdateTool) Description() string

func (*GHPRUpdateTool) Execute added in v0.3.0

func (t *GHPRUpdateTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GHPRUpdateTool) Name added in v0.3.0

func (t *GHPRUpdateTool) Name() string

func (*GHPRUpdateTool) PreviewCall added in v0.3.0

func (t *GHPRUpdateTool) PreviewCall(argsJSON string) string

func (*GHPRUpdateTool) RequiresApproval added in v0.3.0

func (t *GHPRUpdateTool) RequiresApproval(string) bool

func (*GHPRUpdateTool) Schema added in v0.3.0

func (t *GHPRUpdateTool) Schema() map[string]any

type GetSubagentResultTool added in v0.2.0

type GetSubagentResultTool struct {
	// Tasks is the session-scoped subagent task registry. The same
	// pointer the AgentTool uses to record spawns; pointer-shared
	// so we observe live-updated state.
	Tasks *subagents.Registry
}

GetSubagentResultTool retrieves a previously-dispatched subagent's state and final reply from the session task registry. The intended flow:

  1. Parent calls Agent(...) with run_in_background:true → tool returns a task id handle immediately.
  2. Parent's turn ends; user keeps working; child runs to completion in a goroutine.
  3. Some turns later, when the user asks about the subagent's findings, the parent calls get_subagent_result(task_id=<id>) and the final reply lands as a normal tool result that flows back into the parent's adapter context.

Without this tool, background subagents are fire-and-forget: the transcript lives on disk and in the registry, but the parent's model has no programmatic way to pull a completed result back into the conversation. The pairing with run_in_background is what makes background runs actually useful.

Read-only and ParallelSafe — safe to call repeatedly, safe to call alongside other read-only tools in the same model turn.

func (*GetSubagentResultTool) Description added in v0.2.0

func (t *GetSubagentResultTool) Description() string

func (*GetSubagentResultTool) Execute added in v0.2.0

func (t *GetSubagentResultTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GetSubagentResultTool) Name added in v0.2.0

func (t *GetSubagentResultTool) Name() string

func (*GetSubagentResultTool) ParallelSafe added in v0.2.0

func (t *GetSubagentResultTool) ParallelSafe(string) bool

ParallelSafe lets the model fetch several subagent results in one turn — useful for "summarize all the background investigations I started" workflows.

func (*GetSubagentResultTool) PreviewCall added in v0.2.0

func (t *GetSubagentResultTool) PreviewCall(argsJSON string) string

func (*GetSubagentResultTool) RequiresApproval added in v0.2.0

func (t *GetSubagentResultTool) RequiresApproval(string) bool

RequiresApproval is false: the tool only reads from the in-memory task registry and produces a string — no disk mutation, no network calls, no shell. Safe to auto-execute on every call.

func (*GetSubagentResultTool) Schema added in v0.2.0

func (t *GetSubagentResultTool) Schema() map[string]any

type GitBlameLinesTool

type GitBlameLinesTool struct{ Cwd *CwdRef }

func (*GitBlameLinesTool) Description

func (t *GitBlameLinesTool) Description() string

func (*GitBlameLinesTool) Execute

func (t *GitBlameLinesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitBlameLinesTool) Name

func (t *GitBlameLinesTool) Name() string

func (*GitBlameLinesTool) ParallelSafe

func (t *GitBlameLinesTool) ParallelSafe(string) bool

func (*GitBlameLinesTool) PreviewCall

func (t *GitBlameLinesTool) PreviewCall(argsJSON string) string

func (*GitBlameLinesTool) RequiresApproval

func (t *GitBlameLinesTool) RequiresApproval(string) bool

func (*GitBlameLinesTool) Schema

func (t *GitBlameLinesTool) Schema() map[string]any

type GitBranchAheadBehindTool added in v0.3.0

type GitBranchAheadBehindTool struct{ Cwd *CwdRef }

func (*GitBranchAheadBehindTool) Description added in v0.3.0

func (t *GitBranchAheadBehindTool) Description() string

func (*GitBranchAheadBehindTool) Execute added in v0.3.0

func (t *GitBranchAheadBehindTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitBranchAheadBehindTool) Name added in v0.3.0

func (t *GitBranchAheadBehindTool) Name() string

func (*GitBranchAheadBehindTool) ParallelSafe added in v0.3.0

func (t *GitBranchAheadBehindTool) ParallelSafe(string) bool

func (*GitBranchAheadBehindTool) PreviewCall added in v0.3.0

func (t *GitBranchAheadBehindTool) PreviewCall(argsJSON string) string

func (*GitBranchAheadBehindTool) RequiresApproval added in v0.3.0

func (t *GitBranchAheadBehindTool) RequiresApproval(string) bool

func (*GitBranchAheadBehindTool) Schema added in v0.3.0

func (t *GitBranchAheadBehindTool) Schema() map[string]any

type GitBranchDiffTool added in v0.3.0

type GitBranchDiffTool struct{ Cwd *CwdRef }

func (*GitBranchDiffTool) Description added in v0.3.0

func (t *GitBranchDiffTool) Description() string

func (*GitBranchDiffTool) Execute added in v0.3.0

func (t *GitBranchDiffTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitBranchDiffTool) Name added in v0.3.0

func (t *GitBranchDiffTool) Name() string

func (*GitBranchDiffTool) ParallelSafe added in v0.3.0

func (t *GitBranchDiffTool) ParallelSafe(string) bool

func (*GitBranchDiffTool) PreviewCall added in v0.3.0

func (t *GitBranchDiffTool) PreviewCall(argsJSON string) string

func (*GitBranchDiffTool) RequiresApproval added in v0.3.0

func (t *GitBranchDiffTool) RequiresApproval(string) bool

func (*GitBranchDiffTool) Schema added in v0.3.0

func (t *GitBranchDiffTool) Schema() map[string]any

type GitBranchStatusTool

type GitBranchStatusTool struct{ Cwd *CwdRef }

func (*GitBranchStatusTool) Description

func (t *GitBranchStatusTool) Description() string

func (*GitBranchStatusTool) Execute

func (t *GitBranchStatusTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitBranchStatusTool) Name

func (t *GitBranchStatusTool) Name() string

func (*GitBranchStatusTool) ParallelSafe

func (t *GitBranchStatusTool) ParallelSafe(string) bool

func (*GitBranchStatusTool) PreviewCall

func (t *GitBranchStatusTool) PreviewCall(string) string

func (*GitBranchStatusTool) RequiresApproval

func (t *GitBranchStatusTool) RequiresApproval(string) bool

func (*GitBranchStatusTool) Schema

func (t *GitBranchStatusTool) Schema() map[string]any

type GitCheckpointTool

type GitCheckpointTool struct{ Cwd *CwdRef }

func (*GitCheckpointTool) Description

func (t *GitCheckpointTool) Description() string

func (*GitCheckpointTool) Execute

func (t *GitCheckpointTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitCheckpointTool) Name

func (t *GitCheckpointTool) Name() string

func (*GitCheckpointTool) PreviewCall

func (t *GitCheckpointTool) PreviewCall(argsJSON string) string

func (*GitCheckpointTool) RequiresApproval

func (t *GitCheckpointTool) RequiresApproval(string) bool

func (*GitCheckpointTool) Schema

func (t *GitCheckpointTool) Schema() map[string]any

type GitCommitAmendTool added in v0.3.0

type GitCommitAmendTool struct{ Cwd *CwdRef }

func (*GitCommitAmendTool) Description added in v0.3.0

func (t *GitCommitAmendTool) Description() string

func (*GitCommitAmendTool) Execute added in v0.3.0

func (t *GitCommitAmendTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitCommitAmendTool) Name added in v0.3.0

func (t *GitCommitAmendTool) Name() string

func (*GitCommitAmendTool) PreviewCall added in v0.3.0

func (t *GitCommitAmendTool) PreviewCall(argsJSON string) string

func (*GitCommitAmendTool) RequiresApproval added in v0.3.0

func (t *GitCommitAmendTool) RequiresApproval(string) bool

func (*GitCommitAmendTool) Schema added in v0.3.0

func (t *GitCommitAmendTool) Schema() map[string]any

type GitCommitApplyTool added in v0.3.0

type GitCommitApplyTool struct{ Cwd *CwdRef }

GitCommitApplyTool lands a one-line commit message produced by the model (or a procedural caller). The validation contract is the hard guarantee — empty staging, oversize subject, trailing period, and trailing newlines that would extend into a body all fail deterministically *before* invoking git. That's the reliability fix the legacy markdown directive could only ask for in prose.

On hook failure the result envelope reports hook_error verbatim without auto-retry or auto-amend — the legacy directive's "hard prohibitions" become an unreachable code path rather than a model discipline ask.

func (*GitCommitApplyTool) Description added in v0.3.0

func (t *GitCommitApplyTool) Description() string

func (*GitCommitApplyTool) Execute added in v0.3.0

func (t *GitCommitApplyTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitCommitApplyTool) Name added in v0.3.0

func (t *GitCommitApplyTool) Name() string

func (*GitCommitApplyTool) PreviewCall added in v0.3.0

func (t *GitCommitApplyTool) PreviewCall(argsJSON string) string

func (*GitCommitApplyTool) RequiresApproval added in v0.3.0

func (t *GitCommitApplyTool) RequiresApproval(string) bool

func (*GitCommitApplyTool) Schema added in v0.3.0

func (t *GitCommitApplyTool) Schema() map[string]any

type GitCommitContextTool added in v0.3.0

type GitCommitContextTool struct{ Cwd *CwdRef }

GitCommitContextTool gathers the read-only snapshot a caller needs to draft a commit message: what's staged, what style the repo uses, what's untracked. Replaces the bash heredoc the legacy /git:commit-message directive ran as its first tool call.

func (*GitCommitContextTool) Description added in v0.3.0

func (t *GitCommitContextTool) Description() string

func (*GitCommitContextTool) Execute added in v0.3.0

func (t *GitCommitContextTool) Execute(ctx context.Context, _ string) (string, error)

func (*GitCommitContextTool) Name added in v0.3.0

func (t *GitCommitContextTool) Name() string

func (*GitCommitContextTool) ParallelSafe added in v0.3.0

func (t *GitCommitContextTool) ParallelSafe(string) bool

func (*GitCommitContextTool) PreviewCall added in v0.3.0

func (t *GitCommitContextTool) PreviewCall(string) string

func (*GitCommitContextTool) RequiresApproval added in v0.3.0

func (t *GitCommitContextTool) RequiresApproval(string) bool

func (*GitCommitContextTool) Schema added in v0.3.0

func (t *GitCommitContextTool) Schema() map[string]any

type GitCommitFixupTool added in v0.3.0

type GitCommitFixupTool struct{ Cwd *CwdRef }

func (*GitCommitFixupTool) Description added in v0.3.0

func (t *GitCommitFixupTool) Description() string

func (*GitCommitFixupTool) Execute added in v0.3.0

func (t *GitCommitFixupTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitCommitFixupTool) Name added in v0.3.0

func (t *GitCommitFixupTool) Name() string

func (*GitCommitFixupTool) PreviewCall added in v0.3.0

func (t *GitCommitFixupTool) PreviewCall(argsJSON string) string

func (*GitCommitFixupTool) RequiresApproval added in v0.3.0

func (t *GitCommitFixupTool) RequiresApproval(string) bool

func (*GitCommitFixupTool) Schema added in v0.3.0

func (t *GitCommitFixupTool) Schema() map[string]any

type GitCommitTool

type GitCommitTool struct{ Cwd *CwdRef }

func (*GitCommitTool) Description

func (t *GitCommitTool) Description() string

func (*GitCommitTool) Execute

func (t *GitCommitTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitCommitTool) Name

func (t *GitCommitTool) Name() string

func (*GitCommitTool) PreviewCall

func (t *GitCommitTool) PreviewCall(argsJSON string) string

func (*GitCommitTool) RequiresApproval

func (t *GitCommitTool) RequiresApproval(string) bool

func (*GitCommitTool) Schema

func (t *GitCommitTool) Schema() map[string]any

type GitCommitsBetweenTool added in v0.3.0

type GitCommitsBetweenTool struct{ Cwd *CwdRef }

func (*GitCommitsBetweenTool) Description added in v0.3.0

func (t *GitCommitsBetweenTool) Description() string

func (*GitCommitsBetweenTool) Execute added in v0.3.0

func (t *GitCommitsBetweenTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitCommitsBetweenTool) Name added in v0.3.0

func (t *GitCommitsBetweenTool) Name() string

func (*GitCommitsBetweenTool) ParallelSafe added in v0.3.0

func (t *GitCommitsBetweenTool) ParallelSafe(string) bool

func (*GitCommitsBetweenTool) PreviewCall added in v0.3.0

func (t *GitCommitsBetweenTool) PreviewCall(argsJSON string) string

func (*GitCommitsBetweenTool) RequiresApproval added in v0.3.0

func (t *GitCommitsBetweenTool) RequiresApproval(string) bool

func (*GitCommitsBetweenTool) Schema added in v0.3.0

func (t *GitCommitsBetweenTool) Schema() map[string]any

type GitCreateBranchTool added in v0.3.0

type GitCreateBranchTool struct {
	Cwd        *CwdRef
	LSPManager *lspci.Manager
}

func (*GitCreateBranchTool) Description added in v0.3.0

func (t *GitCreateBranchTool) Description() string

func (*GitCreateBranchTool) Execute added in v0.3.0

func (t *GitCreateBranchTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitCreateBranchTool) Name added in v0.3.0

func (t *GitCreateBranchTool) Name() string

func (*GitCreateBranchTool) PreviewCall added in v0.3.0

func (t *GitCreateBranchTool) PreviewCall(argsJSON string) string

func (*GitCreateBranchTool) RequiresApproval added in v0.3.0

func (t *GitCreateBranchTool) RequiresApproval(string) bool

func (*GitCreateBranchTool) Schema added in v0.3.0

func (t *GitCreateBranchTool) Schema() map[string]any

type GitDiffFilesTool

type GitDiffFilesTool struct{ Cwd *CwdRef }

func (*GitDiffFilesTool) Description

func (t *GitDiffFilesTool) Description() string

func (*GitDiffFilesTool) Execute

func (t *GitDiffFilesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitDiffFilesTool) Name

func (t *GitDiffFilesTool) Name() string

func (*GitDiffFilesTool) ParallelSafe

func (t *GitDiffFilesTool) ParallelSafe(string) bool

func (*GitDiffFilesTool) PreviewCall

func (t *GitDiffFilesTool) PreviewCall(argsJSON string) string

func (*GitDiffFilesTool) RequiresApproval

func (t *GitDiffFilesTool) RequiresApproval(string) bool

func (*GitDiffFilesTool) Schema

func (t *GitDiffFilesTool) Schema() map[string]any

type GitDiffStagedTool added in v0.3.0

type GitDiffStagedTool struct{ Cwd *CwdRef }

func (*GitDiffStagedTool) Description added in v0.3.0

func (t *GitDiffStagedTool) Description() string

func (*GitDiffStagedTool) Execute added in v0.3.0

func (t *GitDiffStagedTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitDiffStagedTool) Name added in v0.3.0

func (t *GitDiffStagedTool) Name() string

func (*GitDiffStagedTool) ParallelSafe added in v0.3.0

func (t *GitDiffStagedTool) ParallelSafe(string) bool

func (*GitDiffStagedTool) PreviewCall added in v0.3.0

func (t *GitDiffStagedTool) PreviewCall(string) string

func (*GitDiffStagedTool) RequiresApproval added in v0.3.0

func (t *GitDiffStagedTool) RequiresApproval(string) bool

func (*GitDiffStagedTool) Schema added in v0.3.0

func (t *GitDiffStagedTool) Schema() map[string]any

type GitDiffStatTool added in v0.3.0

type GitDiffStatTool struct{ Cwd *CwdRef }

func (*GitDiffStatTool) Description added in v0.3.0

func (t *GitDiffStatTool) Description() string

func (*GitDiffStatTool) Execute added in v0.3.0

func (t *GitDiffStatTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitDiffStatTool) Name added in v0.3.0

func (t *GitDiffStatTool) Name() string

func (*GitDiffStatTool) ParallelSafe added in v0.3.0

func (t *GitDiffStatTool) ParallelSafe(string) bool

func (*GitDiffStatTool) PreviewCall added in v0.3.0

func (t *GitDiffStatTool) PreviewCall(argsJSON string) string

func (*GitDiffStatTool) RequiresApproval added in v0.3.0

func (t *GitDiffStatTool) RequiresApproval(string) bool

func (*GitDiffStatTool) Schema added in v0.3.0

func (t *GitDiffStatTool) Schema() map[string]any

type GitDiffUnstagedTool added in v0.3.0

type GitDiffUnstagedTool struct{ Cwd *CwdRef }

func (*GitDiffUnstagedTool) Description added in v0.3.0

func (t *GitDiffUnstagedTool) Description() string

func (*GitDiffUnstagedTool) Execute added in v0.3.0

func (t *GitDiffUnstagedTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitDiffUnstagedTool) Name added in v0.3.0

func (t *GitDiffUnstagedTool) Name() string

func (*GitDiffUnstagedTool) ParallelSafe added in v0.3.0

func (t *GitDiffUnstagedTool) ParallelSafe(string) bool

func (*GitDiffUnstagedTool) PreviewCall added in v0.3.0

func (t *GitDiffUnstagedTool) PreviewCall(string) string

func (*GitDiffUnstagedTool) RequiresApproval added in v0.3.0

func (t *GitDiffUnstagedTool) RequiresApproval(string) bool

func (*GitDiffUnstagedTool) Schema added in v0.3.0

func (t *GitDiffUnstagedTool) Schema() map[string]any

type GitLogFileTool

type GitLogFileTool struct{ Cwd *CwdRef }

func (*GitLogFileTool) Description

func (t *GitLogFileTool) Description() string

func (*GitLogFileTool) Execute

func (t *GitLogFileTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitLogFileTool) Name

func (t *GitLogFileTool) Name() string

func (*GitLogFileTool) ParallelSafe

func (t *GitLogFileTool) ParallelSafe(string) bool

func (*GitLogFileTool) PreviewCall

func (t *GitLogFileTool) PreviewCall(argsJSON string) string

func (*GitLogFileTool) RequiresApproval

func (t *GitLogFileTool) RequiresApproval(string) bool

func (*GitLogFileTool) Schema

func (t *GitLogFileTool) Schema() map[string]any

type GitMergeBaseTool

type GitMergeBaseTool struct{ Cwd *CwdRef }

func (*GitMergeBaseTool) Description

func (t *GitMergeBaseTool) Description() string

func (*GitMergeBaseTool) Execute

func (t *GitMergeBaseTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitMergeBaseTool) Name

func (t *GitMergeBaseTool) Name() string

func (*GitMergeBaseTool) ParallelSafe

func (t *GitMergeBaseTool) ParallelSafe(string) bool

func (*GitMergeBaseTool) PreviewCall

func (t *GitMergeBaseTool) PreviewCall(argsJSON string) string

func (*GitMergeBaseTool) RequiresApproval

func (t *GitMergeBaseTool) RequiresApproval(string) bool

func (*GitMergeBaseTool) Schema

func (t *GitMergeBaseTool) Schema() map[string]any

type GitPushTool added in v0.3.0

type GitPushTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

GitPushTool runs `git push` for the current branch and (best effort) looks up the PR for the pushed branch via the typed github.Interface so /git-push can surface a "PR updated" footer when a PR exists. GH is optional — if nil, the PR lookup is skipped silently.

func (*GitPushTool) Description added in v0.3.0

func (t *GitPushTool) Description() string

func (*GitPushTool) Execute added in v0.3.0

func (t *GitPushTool) Execute(ctx context.Context, _ string) (string, error)

func (*GitPushTool) Name added in v0.3.0

func (t *GitPushTool) Name() string

func (*GitPushTool) PreviewCall added in v0.3.0

func (t *GitPushTool) PreviewCall(string) string

func (*GitPushTool) RequiresApproval added in v0.3.0

func (t *GitPushTool) RequiresApproval(string) bool

func (*GitPushTool) Schema added in v0.3.0

func (t *GitPushTool) Schema() map[string]any

type GitShowFileAtRevTool

type GitShowFileAtRevTool struct{ Cwd *CwdRef }

func (*GitShowFileAtRevTool) Description

func (t *GitShowFileAtRevTool) Description() string

func (*GitShowFileAtRevTool) Execute

func (t *GitShowFileAtRevTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitShowFileAtRevTool) Name

func (t *GitShowFileAtRevTool) Name() string

func (*GitShowFileAtRevTool) ParallelSafe

func (t *GitShowFileAtRevTool) ParallelSafe(string) bool

func (*GitShowFileAtRevTool) PreviewCall

func (t *GitShowFileAtRevTool) PreviewCall(argsJSON string) string

func (*GitShowFileAtRevTool) RequiresApproval

func (t *GitShowFileAtRevTool) RequiresApproval(string) bool

func (*GitShowFileAtRevTool) Schema

func (t *GitShowFileAtRevTool) Schema() map[string]any

type GitStageFilesTool

type GitStageFilesTool struct{ Cwd *CwdRef }

func (*GitStageFilesTool) Description

func (t *GitStageFilesTool) Description() string

func (*GitStageFilesTool) Execute

func (t *GitStageFilesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitStageFilesTool) Name

func (t *GitStageFilesTool) Name() string

func (*GitStageFilesTool) PreviewCall

func (t *GitStageFilesTool) PreviewCall(argsJSON string) string

func (*GitStageFilesTool) RequiresApproval

func (t *GitStageFilesTool) RequiresApproval(string) bool

func (*GitStageFilesTool) Schema

func (t *GitStageFilesTool) Schema() map[string]any

type GitTool

type GitTool struct {
	Cwd        *CwdRef
	LSPManager *lspci.Manager
}

GitTool is the unified entrypoint for every git command. The model passes argv-style tokens (no shell), and approval policy is decided by inspecting the first arg.

func (*GitTool) Description

func (t *GitTool) Description() string

func (*GitTool) Execute

func (t *GitTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitTool) Name

func (t *GitTool) Name() string

func (*GitTool) PreviewCall

func (t *GitTool) PreviewCall(argsJSON string) string

func (*GitTool) RequiresApproval

func (t *GitTool) RequiresApproval(argsJSON string) bool

func (*GitTool) Schema

func (t *GitTool) Schema() map[string]any

type GitUnstageFilesTool

type GitUnstageFilesTool struct{ Cwd *CwdRef }

func (*GitUnstageFilesTool) Description

func (t *GitUnstageFilesTool) Description() string

func (*GitUnstageFilesTool) Execute

func (t *GitUnstageFilesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitUnstageFilesTool) Name

func (t *GitUnstageFilesTool) Name() string

func (*GitUnstageFilesTool) PreviewCall

func (t *GitUnstageFilesTool) PreviewCall(argsJSON string) string

func (*GitUnstageFilesTool) RequiresApproval

func (t *GitUnstageFilesTool) RequiresApproval(string) bool

func (*GitUnstageFilesTool) Schema

func (t *GitUnstageFilesTool) Schema() map[string]any

type GitWorktreeAddTool added in v0.3.0

type GitWorktreeAddTool struct{ Cwd *CwdRef }

GitWorktreeAddTool adds a new worktree.

func (*GitWorktreeAddTool) Description added in v0.3.0

func (t *GitWorktreeAddTool) Description() string

func (*GitWorktreeAddTool) Execute added in v0.3.0

func (t *GitWorktreeAddTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitWorktreeAddTool) Name added in v0.3.0

func (t *GitWorktreeAddTool) Name() string

func (*GitWorktreeAddTool) ParallelSafe added in v0.3.0

func (t *GitWorktreeAddTool) ParallelSafe(string) bool

func (*GitWorktreeAddTool) PreviewCall added in v0.3.0

func (t *GitWorktreeAddTool) PreviewCall(argsJSON string) string

func (*GitWorktreeAddTool) RequiresApproval added in v0.3.0

func (t *GitWorktreeAddTool) RequiresApproval(string) bool

func (*GitWorktreeAddTool) Schema added in v0.3.0

func (t *GitWorktreeAddTool) Schema() map[string]any

type GitWorktreeListTool added in v0.3.0

type GitWorktreeListTool struct{ Cwd *CwdRef }

GitWorktreeListTool lists all worktrees for the current repository.

func (*GitWorktreeListTool) Description added in v0.3.0

func (t *GitWorktreeListTool) Description() string

func (*GitWorktreeListTool) Execute added in v0.3.0

func (t *GitWorktreeListTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitWorktreeListTool) Name added in v0.3.0

func (t *GitWorktreeListTool) Name() string

func (*GitWorktreeListTool) ParallelSafe added in v0.3.0

func (t *GitWorktreeListTool) ParallelSafe(string) bool

func (*GitWorktreeListTool) PreviewCall added in v0.3.0

func (t *GitWorktreeListTool) PreviewCall(string) string

func (*GitWorktreeListTool) RequiresApproval added in v0.3.0

func (t *GitWorktreeListTool) RequiresApproval(string) bool

func (*GitWorktreeListTool) Schema added in v0.3.0

func (t *GitWorktreeListTool) Schema() map[string]any

type GitWorktreeLockTool added in v0.3.0

type GitWorktreeLockTool struct{ Cwd *CwdRef }

GitWorktreeLockTool locks a worktree.

func (*GitWorktreeLockTool) Description added in v0.3.0

func (t *GitWorktreeLockTool) Description() string

func (*GitWorktreeLockTool) Execute added in v0.3.0

func (t *GitWorktreeLockTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitWorktreeLockTool) Name added in v0.3.0

func (t *GitWorktreeLockTool) Name() string

func (*GitWorktreeLockTool) ParallelSafe added in v0.3.0

func (t *GitWorktreeLockTool) ParallelSafe(string) bool

func (*GitWorktreeLockTool) PreviewCall added in v0.3.0

func (t *GitWorktreeLockTool) PreviewCall(argsJSON string) string

func (*GitWorktreeLockTool) RequiresApproval added in v0.3.0

func (t *GitWorktreeLockTool) RequiresApproval(string) bool

func (*GitWorktreeLockTool) Schema added in v0.3.0

func (t *GitWorktreeLockTool) Schema() map[string]any

type GitWorktreePruneTool added in v0.3.0

type GitWorktreePruneTool struct{ Cwd *CwdRef }

GitWorktreePruneTool prunes stale worktree data.

func (*GitWorktreePruneTool) Description added in v0.3.0

func (t *GitWorktreePruneTool) Description() string

func (*GitWorktreePruneTool) Execute added in v0.3.0

func (t *GitWorktreePruneTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitWorktreePruneTool) Name added in v0.3.0

func (t *GitWorktreePruneTool) Name() string

func (*GitWorktreePruneTool) ParallelSafe added in v0.3.0

func (t *GitWorktreePruneTool) ParallelSafe(string) bool

func (*GitWorktreePruneTool) PreviewCall added in v0.3.0

func (t *GitWorktreePruneTool) PreviewCall(string) string

func (*GitWorktreePruneTool) RequiresApproval added in v0.3.0

func (t *GitWorktreePruneTool) RequiresApproval(string) bool

func (*GitWorktreePruneTool) Schema added in v0.3.0

func (t *GitWorktreePruneTool) Schema() map[string]any

type GitWorktreeRemoveTool added in v0.3.0

type GitWorktreeRemoveTool struct{ Cwd *CwdRef }

GitWorktreeRemoveTool removes a worktree.

func (*GitWorktreeRemoveTool) Description added in v0.3.0

func (t *GitWorktreeRemoveTool) Description() string

func (*GitWorktreeRemoveTool) Execute added in v0.3.0

func (t *GitWorktreeRemoveTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitWorktreeRemoveTool) Name added in v0.3.0

func (t *GitWorktreeRemoveTool) Name() string

func (*GitWorktreeRemoveTool) ParallelSafe added in v0.3.0

func (t *GitWorktreeRemoveTool) ParallelSafe(string) bool

func (*GitWorktreeRemoveTool) PreviewCall added in v0.3.0

func (t *GitWorktreeRemoveTool) PreviewCall(argsJSON string) string

func (*GitWorktreeRemoveTool) RequiresApproval added in v0.3.0

func (t *GitWorktreeRemoveTool) RequiresApproval(string) bool

func (*GitWorktreeRemoveTool) Schema added in v0.3.0

func (t *GitWorktreeRemoveTool) Schema() map[string]any

type GitWorktreeUnlockTool added in v0.3.0

type GitWorktreeUnlockTool struct{ Cwd *CwdRef }

GitWorktreeUnlockTool unlocks a worktree.

func (*GitWorktreeUnlockTool) Description added in v0.3.0

func (t *GitWorktreeUnlockTool) Description() string

func (*GitWorktreeUnlockTool) Execute added in v0.3.0

func (t *GitWorktreeUnlockTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GitWorktreeUnlockTool) Name added in v0.3.0

func (t *GitWorktreeUnlockTool) Name() string

func (*GitWorktreeUnlockTool) ParallelSafe added in v0.3.0

func (t *GitWorktreeUnlockTool) ParallelSafe(string) bool

func (*GitWorktreeUnlockTool) PreviewCall added in v0.3.0

func (t *GitWorktreeUnlockTool) PreviewCall(argsJSON string) string

func (*GitWorktreeUnlockTool) RequiresApproval added in v0.3.0

func (t *GitWorktreeUnlockTool) RequiresApproval(string) bool

func (*GitWorktreeUnlockTool) Schema added in v0.3.0

func (t *GitWorktreeUnlockTool) Schema() map[string]any

type GlobTool

type GlobTool struct {
	Cwd *CwdRef
}

GlobTool finds files matching a doublestar pattern (e.g., "**/*.go").

func (*GlobTool) Description

func (t *GlobTool) Description() string

func (*GlobTool) Execute

func (t *GlobTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GlobTool) Name

func (t *GlobTool) Name() string

func (*GlobTool) ParallelSafe

func (t *GlobTool) ParallelSafe(string) bool

func (*GlobTool) PreviewCall

func (t *GlobTool) PreviewCall(argsJSON string) string

func (*GlobTool) RequiresApproval

func (t *GlobTool) RequiresApproval(string) bool

func (*GlobTool) Schema

func (t *GlobTool) Schema() map[string]any

type GrepTool

type GrepTool struct {
	Cwd           *CwdRef
	DenyReadPaths []string
}

GrepTool searches files for a pattern. Uses ripgrep if available, otherwise falls back to GNU grep. Args are passed via argv (no /bin/sh) so the model can't inject shell metacharacters. When the user supplies an explicit path, it's validated against DenyReadPaths so a targeted grep can't extract secrets line-by-line.

func (*GrepTool) Description

func (t *GrepTool) Description() string

func (*GrepTool) Execute

func (t *GrepTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*GrepTool) Name

func (t *GrepTool) Name() string

func (*GrepTool) ParallelSafe

func (t *GrepTool) ParallelSafe(string) bool

func (*GrepTool) PreviewCall

func (t *GrepTool) PreviewCall(argsJSON string) string

func (*GrepTool) RequiresApproval

func (t *GrepTool) RequiresApproval(string) bool

func (*GrepTool) Schema

func (t *GrepTool) Schema() map[string]any

type HostSandbox added in v0.4.0

type HostSandbox struct{}

HostSandbox runs commands directly on the host via /bin/sh -c — today's only behavior, reproduced verbatim so wrapping RunBashTool's exec.Command construction behind the Sandbox interface changes nothing when no other Sandbox is configured. The zero value of RunBashTool.Sandbox behaves identically to HostSandbox (see RunBashTool.sandbox).

func (HostSandbox) Close added in v0.4.0

func (HostSandbox) Close() error

func (HostSandbox) Command added in v0.4.0

func (HostSandbox) Command(ctx context.Context, command, cwd string) *exec.Cmd

func (HostSandbox) Label added in v0.4.0

func (HostSandbox) Label() string

type IntegrateTool added in v0.3.0

type IntegrateTool struct {
	// Cwd is the session working dir, used to resolve the repo root.
	Cwd *CwdRef
	// Enabled gates the tool behind the `dispatch` experimental feature
	// (integrate and dispatch ship together). When false, Execute returns
	// a recoverable error string.
	Enabled bool
}

IntegrateTool merges dispatch task branches into a single integration branch — the one branch a PR is opened from. It runs in a dedicated integration worktree so the user's working tree is never touched, merges each branch in order, and on a conflict stops with the conflicted files reported so the parent (or user) can resolve them and resume.

Re-entrant: pass the same integration_branch back to continue after resolving a conflict or to add more branches.

func (*IntegrateTool) Description added in v0.3.0

func (t *IntegrateTool) Description() string

func (*IntegrateTool) Execute added in v0.3.0

func (t *IntegrateTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*IntegrateTool) Name added in v0.3.0

func (t *IntegrateTool) Name() string

func (*IntegrateTool) ParallelSafe added in v0.3.0

func (t *IntegrateTool) ParallelSafe(string) bool

func (*IntegrateTool) PreviewCall added in v0.3.0

func (t *IntegrateTool) PreviewCall(argsJSON string) string

func (*IntegrateTool) RequiresApproval added in v0.3.0

func (t *IntegrateTool) RequiresApproval(string) bool

func (*IntegrateTool) Schema added in v0.3.0

func (t *IntegrateTool) Schema() map[string]any
type IssueContactLink struct {
	Name  string `yaml:"name"`
	URL   string `yaml:"url"`
	About string `yaml:"about"`
}

IssueContactLink mirrors GitHub chooser contact links. These are not issue-creation targets, but surfacing them keeps `/git-create-issue` from trying to turn docs, discussions, or security reports into public issues.

type IssueContext added in v0.3.0

type IssueContext struct {
	Owner                string
	Repo                 string
	GhAvailable          bool
	IssueTemplate        string
	IssueTemplatePath    string   // relative to cwd
	IssueTemplateChoices []string // all issue template names when the template dir offers several
	IssueTemplates       []IssueTemplate
	ContactLinks         []IssueContactLink
	BlankIssuesEnabled   bool
}

IssueContext is the typed snapshot BuildIssueContext returns.

func BuildIssueContext added in v0.3.0

func BuildIssueContext(ctx context.Context, cwd string) (IssueContext, error)

BuildIssueContext is the deterministic core of issue_context. Owner/repo come from the cwd's origin remote, GhAvailable reports whether the GitHub auth token chain resolves (same signal BuildPRContext exposes — the /git-create-issue directive branches to draft-only on gh_available=false), and the template fields carry a repo-local issue template when one exists.

type IssueCreateResult added in v0.3.0

type IssueCreateResult struct {
	Created           bool
	URL               string
	Number            int
	ValidationErr     string
	GitHubUnavailable bool
	GitHubError       string
}

IssueCreateResult is the typed envelope CreateIssue returns. Same shape rationale as PRCreateResult: callers branch on typed fields, not stringy err checks. Reason discriminates the failure mode so the procedural /create-issue handles each branch differently (validation → re-prompt; github_unavailable → fall through to draft-only; github_error → surface verbatim and stop).

func CreateIssue added in v0.3.0

CreateIssue is the deterministic core of issue_create. Validates title *before* dialing the Interface, so an oversize title never reaches the network. Returns a typed IssueCreateResult; the tool wrapper renders it for model consumption, /create-issue reads it directly.

The Interface returns ErrGitHubUnavailable when the local environment can't make the call; we surface that as GitHubUnavailable=true so the caller can fall through to draft-only instead of treating it as an opaque error.

type IssueListContext added in v0.3.0

type IssueListContext struct {
	GitHubUnavailable bool
	FetchErr          string

	Filter github.ListIssuesRequest
	Issues []github.IssueSummary
}

IssueListContext is the typed snapshot issue_list returns. GitHubUnavailable + FetchErr follow the same state-flag pattern as the other read tools. Empty Issues with no flags means "no open issues match" — a valid result, not an error.

func BuildIssueListContext added in v0.3.0

func BuildIssueListContext(ctx context.Context, client github.Interface, req github.ListIssuesRequest) IssueListContext

BuildIssueListContext is the deterministic core of issue_list. Folds typed errors into the snapshot's flags so callers branch on flags rather than err strings.

type IssueReadContext added in v0.3.0

type IssueReadContext struct {
	Number            int
	NotFound          bool
	GitHubUnavailable bool
	FetchErr          string

	Issue github.IssueDetails
}

IssueReadContext is the typed snapshot issue_read returns. State flags follow the same pattern as PR snapshots (NotFound, GitHubUnavailable, FetchErr) so callers branch on flags before reading the issue body.

func BuildIssueReadContext added in v0.3.0

func BuildIssueReadContext(ctx context.Context, client github.Interface, number, maxComments int) IssueReadContext

BuildIssueReadContext is the deterministic core of issue_read. Wraps one ReadIssue call; folds typed errors into the snapshot. Doesn't return an error itself — every failure shape is captured in the snapshot so callers can branch on flags.

type IssueTemplate added in v0.3.1

type IssueTemplate struct {
	Name        string
	Description string
	Path        string
	Kind        string
	TitlePrefix string
	Labels      []string
	Assignees   []string
	Content     string
}

IssueTemplate is a normalized issue-creation target discovered from `.github/ISSUE_TEMPLATE`. Markdown templates keep their fillable body; YAML issue forms are rendered into an equivalent Markdown body because GitHub's public issue API creates normal issue bodies, not form submissions.

type IterCap

type IterCap struct{ Max int }

IterCap fires when the loop hits MaxIterations without a final assistant reply. The turn ends after this event.

type IterationContinue

type IterationContinue struct {
	Number    int
	Reason    string
	ToolCalls int
}

IterationContinue explains why the loop is going around again after an iteration completes.

type IterationStart

type IterationStart struct {
	Number int
	Max    int
}

IterationStart fires when a new model->tools->model loop iteration begins. Number is 1-based.

type LSPApplyWorkspaceEditTool added in v0.4.0

type LSPApplyWorkspaceEditTool struct {
	WriteOpts WritePathOptions
	// contains filtered or unexported fields
}

LSPApplyWorkspaceEditTool applies a previously previewed WorkspaceEdit through yottacode's own write-path validator and checkpoint snapshot flow.

func (*LSPApplyWorkspaceEditTool) Description added in v0.4.0

func (t *LSPApplyWorkspaceEditTool) Description() string

func (*LSPApplyWorkspaceEditTool) Execute added in v0.4.0

func (t *LSPApplyWorkspaceEditTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPApplyWorkspaceEditTool) Name added in v0.4.0

func (*LSPApplyWorkspaceEditTool) PathsToSnapshot added in v0.4.0

func (t *LSPApplyWorkspaceEditTool) PathsToSnapshot(cwd, argsJSON string) []string

func (*LSPApplyWorkspaceEditTool) PreviewCall added in v0.4.0

func (t *LSPApplyWorkspaceEditTool) PreviewCall(argsJSON string) string

func (*LSPApplyWorkspaceEditTool) RequiresApproval added in v0.4.0

func (t *LSPApplyWorkspaceEditTool) RequiresApproval(string) bool

func (*LSPApplyWorkspaceEditTool) Schema added in v0.4.0

func (t *LSPApplyWorkspaceEditTool) Schema() map[string]any

type LSPCallHierarchyTool added in v0.4.0

type LSPCallHierarchyTool struct {
	// contains filtered or unexported fields
}

LSPCallHierarchyTool returns incoming/outgoing calls for a source position.

func (*LSPCallHierarchyTool) Description added in v0.4.0

func (t *LSPCallHierarchyTool) Description() string

func (*LSPCallHierarchyTool) Execute added in v0.4.0

func (t *LSPCallHierarchyTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPCallHierarchyTool) Name added in v0.4.0

func (t *LSPCallHierarchyTool) Name() string

func (*LSPCallHierarchyTool) ParallelSafe added in v0.4.0

func (t *LSPCallHierarchyTool) ParallelSafe(string) bool

func (*LSPCallHierarchyTool) PreviewCall added in v0.4.0

func (t *LSPCallHierarchyTool) PreviewCall(argsJSON string) string

func (*LSPCallHierarchyTool) RequiresApproval added in v0.4.0

func (t *LSPCallHierarchyTool) RequiresApproval(string) bool

func (*LSPCallHierarchyTool) Schema added in v0.4.0

func (t *LSPCallHierarchyTool) Schema() map[string]any

type LSPChangedFilesDiagnosticsTool added in v0.4.0

type LSPChangedFilesDiagnosticsTool struct {
	// contains filtered or unexported fields
}

LSPChangedFilesDiagnosticsTool checks diagnostics for changed supported source files. It gives the agent one semantic post-edit check instead of requiring a separate lsp_diagnostics call for every touched file.

func (*LSPChangedFilesDiagnosticsTool) Description added in v0.4.0

func (t *LSPChangedFilesDiagnosticsTool) Description() string

func (*LSPChangedFilesDiagnosticsTool) Execute added in v0.4.0

func (t *LSPChangedFilesDiagnosticsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPChangedFilesDiagnosticsTool) Name added in v0.4.0

func (*LSPChangedFilesDiagnosticsTool) ParallelSafe added in v0.4.0

func (t *LSPChangedFilesDiagnosticsTool) ParallelSafe(string) bool

func (*LSPChangedFilesDiagnosticsTool) PreviewCall added in v0.4.0

func (*LSPChangedFilesDiagnosticsTool) RequiresApproval added in v0.4.0

func (t *LSPChangedFilesDiagnosticsTool) RequiresApproval(string) bool

func (*LSPChangedFilesDiagnosticsTool) Schema added in v0.4.0

func (t *LSPChangedFilesDiagnosticsTool) Schema() map[string]any

type LSPCodeActionPreviewTool added in v0.4.0

type LSPCodeActionPreviewTool struct {
	// contains filtered or unexported fields
}

LSPCodeActionPreviewTool resolves one code action into a WorkspaceEdit preview without applying it. The separate apply tool keeps all writes approval-gated.

func (*LSPCodeActionPreviewTool) Description added in v0.4.0

func (t *LSPCodeActionPreviewTool) Description() string

func (*LSPCodeActionPreviewTool) Execute added in v0.4.0

func (t *LSPCodeActionPreviewTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPCodeActionPreviewTool) Name added in v0.4.0

func (t *LSPCodeActionPreviewTool) Name() string

func (*LSPCodeActionPreviewTool) ParallelSafe added in v0.4.0

func (t *LSPCodeActionPreviewTool) ParallelSafe(string) bool

func (*LSPCodeActionPreviewTool) PreviewCall added in v0.4.0

func (t *LSPCodeActionPreviewTool) PreviewCall(argsJSON string) string

func (*LSPCodeActionPreviewTool) RequiresApproval added in v0.4.0

func (t *LSPCodeActionPreviewTool) RequiresApproval(string) bool

func (*LSPCodeActionPreviewTool) Schema added in v0.4.0

func (t *LSPCodeActionPreviewTool) Schema() map[string]any

type LSPCodeActionsTool added in v0.4.0

type LSPCodeActionsTool struct {
	// contains filtered or unexported fields
}

LSPCodeActionsTool lists available code actions without applying them.

func (*LSPCodeActionsTool) Description added in v0.4.0

func (t *LSPCodeActionsTool) Description() string

func (*LSPCodeActionsTool) Execute added in v0.4.0

func (t *LSPCodeActionsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPCodeActionsTool) Name added in v0.4.0

func (t *LSPCodeActionsTool) Name() string

func (*LSPCodeActionsTool) ParallelSafe added in v0.4.0

func (t *LSPCodeActionsTool) ParallelSafe(string) bool

func (*LSPCodeActionsTool) PreviewCall added in v0.4.0

func (t *LSPCodeActionsTool) PreviewCall(argsJSON string) string

func (*LSPCodeActionsTool) RequiresApproval added in v0.4.0

func (t *LSPCodeActionsTool) RequiresApproval(string) bool

func (*LSPCodeActionsTool) Schema added in v0.4.0

func (t *LSPCodeActionsTool) Schema() map[string]any

type LSPDefinitionTool added in v0.4.0

type LSPDefinitionTool struct {
	// contains filtered or unexported fields
}

LSPDefinitionTool returns definition locations for a source position.

func (*LSPDefinitionTool) Description added in v0.4.0

func (t *LSPDefinitionTool) Description() string

func (*LSPDefinitionTool) Execute added in v0.4.0

func (t *LSPDefinitionTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPDefinitionTool) Name added in v0.4.0

func (t *LSPDefinitionTool) Name() string

func (*LSPDefinitionTool) ParallelSafe added in v0.4.0

func (t *LSPDefinitionTool) ParallelSafe(string) bool

func (*LSPDefinitionTool) PreviewCall added in v0.4.0

func (t *LSPDefinitionTool) PreviewCall(argsJSON string) string

func (*LSPDefinitionTool) RequiresApproval added in v0.4.0

func (t *LSPDefinitionTool) RequiresApproval(string) bool

func (*LSPDefinitionTool) Schema added in v0.4.0

func (t *LSPDefinitionTool) Schema() map[string]any

type LSPDiagnosticsTool added in v0.4.0

type LSPDiagnosticsTool struct {
	// contains filtered or unexported fields
}

LSPDiagnosticsTool returns language-server diagnostics for one source file.

func (*LSPDiagnosticsTool) Description added in v0.4.0

func (t *LSPDiagnosticsTool) Description() string

func (*LSPDiagnosticsTool) Execute added in v0.4.0

func (t *LSPDiagnosticsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPDiagnosticsTool) Name added in v0.4.0

func (t *LSPDiagnosticsTool) Name() string

func (*LSPDiagnosticsTool) ParallelSafe added in v0.4.0

func (t *LSPDiagnosticsTool) ParallelSafe(string) bool

func (*LSPDiagnosticsTool) PreviewCall added in v0.4.0

func (t *LSPDiagnosticsTool) PreviewCall(argsJSON string) string

func (*LSPDiagnosticsTool) RequiresApproval added in v0.4.0

func (t *LSPDiagnosticsTool) RequiresApproval(string) bool

func (*LSPDiagnosticsTool) Schema added in v0.4.0

func (t *LSPDiagnosticsTool) Schema() map[string]any

type LSPDocumentHighlightsTool added in v0.4.0

type LSPDocumentHighlightsTool struct {
	// contains filtered or unexported fields
}

LSPDocumentHighlightsTool returns current-file symbol occurrences for a position. It is intentionally narrower than references so agents can inspect local reads/writes without pulling workspace-wide results into context.

func (*LSPDocumentHighlightsTool) Description added in v0.4.0

func (t *LSPDocumentHighlightsTool) Description() string

func (*LSPDocumentHighlightsTool) Execute added in v0.4.0

func (t *LSPDocumentHighlightsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPDocumentHighlightsTool) Name added in v0.4.0

func (*LSPDocumentHighlightsTool) ParallelSafe added in v0.4.0

func (t *LSPDocumentHighlightsTool) ParallelSafe(string) bool

func (*LSPDocumentHighlightsTool) PreviewCall added in v0.4.0

func (t *LSPDocumentHighlightsTool) PreviewCall(argsJSON string) string

func (*LSPDocumentHighlightsTool) RequiresApproval added in v0.4.0

func (t *LSPDocumentHighlightsTool) RequiresApproval(string) bool

func (*LSPDocumentHighlightsTool) Schema added in v0.4.0

func (t *LSPDocumentHighlightsTool) Schema() map[string]any

type LSPDocumentSymbolsTool added in v0.4.0

type LSPDocumentSymbolsTool struct {
	// contains filtered or unexported fields
}

LSPDocumentSymbolsTool returns the structural symbols declared in one file.

func (*LSPDocumentSymbolsTool) Description added in v0.4.0

func (t *LSPDocumentSymbolsTool) Description() string

func (*LSPDocumentSymbolsTool) Execute added in v0.4.0

func (t *LSPDocumentSymbolsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPDocumentSymbolsTool) Name added in v0.4.0

func (t *LSPDocumentSymbolsTool) Name() string

func (*LSPDocumentSymbolsTool) ParallelSafe added in v0.4.0

func (t *LSPDocumentSymbolsTool) ParallelSafe(string) bool

func (*LSPDocumentSymbolsTool) PreviewCall added in v0.4.0

func (t *LSPDocumentSymbolsTool) PreviewCall(argsJSON string) string

func (*LSPDocumentSymbolsTool) RequiresApproval added in v0.4.0

func (t *LSPDocumentSymbolsTool) RequiresApproval(string) bool

func (*LSPDocumentSymbolsTool) Schema added in v0.4.0

func (t *LSPDocumentSymbolsTool) Schema() map[string]any

type LSPFormatPreviewTool added in v0.4.0

type LSPFormatPreviewTool struct {
	// contains filtered or unexported fields
}

LSPFormatPreviewTool asks for formatting edits without applying them.

func (*LSPFormatPreviewTool) Description added in v0.4.0

func (t *LSPFormatPreviewTool) Description() string

func (*LSPFormatPreviewTool) Execute added in v0.4.0

func (t *LSPFormatPreviewTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPFormatPreviewTool) Name added in v0.4.0

func (t *LSPFormatPreviewTool) Name() string

func (*LSPFormatPreviewTool) ParallelSafe added in v0.4.0

func (t *LSPFormatPreviewTool) ParallelSafe(string) bool

func (*LSPFormatPreviewTool) PreviewCall added in v0.4.0

func (t *LSPFormatPreviewTool) PreviewCall(argsJSON string) string

func (*LSPFormatPreviewTool) RequiresApproval added in v0.4.0

func (t *LSPFormatPreviewTool) RequiresApproval(string) bool

func (*LSPFormatPreviewTool) Schema added in v0.4.0

func (t *LSPFormatPreviewTool) Schema() map[string]any

type LSPHoverTool added in v0.4.0

type LSPHoverTool struct {
	// contains filtered or unexported fields
}

LSPHoverTool returns hover/type information for a source position.

func (*LSPHoverTool) Description added in v0.4.0

func (t *LSPHoverTool) Description() string

func (*LSPHoverTool) Execute added in v0.4.0

func (t *LSPHoverTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPHoverTool) Name added in v0.4.0

func (t *LSPHoverTool) Name() string

func (*LSPHoverTool) ParallelSafe added in v0.4.0

func (t *LSPHoverTool) ParallelSafe(string) bool

func (*LSPHoverTool) PreviewCall added in v0.4.0

func (t *LSPHoverTool) PreviewCall(argsJSON string) string

func (*LSPHoverTool) RequiresApproval added in v0.4.0

func (t *LSPHoverTool) RequiresApproval(string) bool

func (*LSPHoverTool) Schema added in v0.4.0

func (t *LSPHoverTool) Schema() map[string]any

type LSPImpactTool added in v0.4.0

type LSPImpactTool struct {
	CodeMapProvider codemap.Provider
	// contains filtered or unexported fields
}

LSPImpactTool combines several semantic queries into one compact blast-radius report. It is agent-facing rather than raw-LSP-facing: callers get hover, definitions, references, calls, diagnostics, and optional Code Map import impact without spending a tool round on each primitive.

func (*LSPImpactTool) Description added in v0.4.0

func (t *LSPImpactTool) Description() string

func (*LSPImpactTool) Execute added in v0.4.0

func (t *LSPImpactTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPImpactTool) Name added in v0.4.0

func (t *LSPImpactTool) Name() string

func (*LSPImpactTool) ParallelSafe added in v0.4.0

func (t *LSPImpactTool) ParallelSafe(string) bool

lsp_impact holds one LSP client across multiple sequential JSON-RPC requests, so the scheduler should not run it concurrently with other LSP work.

func (*LSPImpactTool) PreviewCall added in v0.4.0

func (t *LSPImpactTool) PreviewCall(argsJSON string) string

func (*LSPImpactTool) RequiresApproval added in v0.4.0

func (t *LSPImpactTool) RequiresApproval(string) bool

func (*LSPImpactTool) Schema added in v0.4.0

func (t *LSPImpactTool) Schema() map[string]any

type LSPImplementationTool added in v0.4.0

type LSPImplementationTool struct {
	// contains filtered or unexported fields
}

LSPImplementationTool returns implementation locations for a source position.

func (*LSPImplementationTool) Description added in v0.4.0

func (t *LSPImplementationTool) Description() string

func (*LSPImplementationTool) Execute added in v0.4.0

func (t *LSPImplementationTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPImplementationTool) Name added in v0.4.0

func (t *LSPImplementationTool) Name() string

func (*LSPImplementationTool) ParallelSafe added in v0.4.0

func (t *LSPImplementationTool) ParallelSafe(string) bool

func (*LSPImplementationTool) PreviewCall added in v0.4.0

func (t *LSPImplementationTool) PreviewCall(argsJSON string) string

func (*LSPImplementationTool) RequiresApproval added in v0.4.0

func (t *LSPImplementationTool) RequiresApproval(string) bool

func (*LSPImplementationTool) Schema added in v0.4.0

func (t *LSPImplementationTool) Schema() map[string]any

type LSPReferencesTool added in v0.4.0

type LSPReferencesTool struct {
	// contains filtered or unexported fields
}

LSPReferencesTool returns reference locations for a source position.

func (*LSPReferencesTool) Description added in v0.4.0

func (t *LSPReferencesTool) Description() string

func (*LSPReferencesTool) Execute added in v0.4.0

func (t *LSPReferencesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPReferencesTool) Name added in v0.4.0

func (t *LSPReferencesTool) Name() string

func (*LSPReferencesTool) ParallelSafe added in v0.4.0

func (t *LSPReferencesTool) ParallelSafe(string) bool

func (*LSPReferencesTool) PreviewCall added in v0.4.0

func (t *LSPReferencesTool) PreviewCall(argsJSON string) string

func (*LSPReferencesTool) RequiresApproval added in v0.4.0

func (t *LSPReferencesTool) RequiresApproval(string) bool

func (*LSPReferencesTool) Schema added in v0.4.0

func (t *LSPReferencesTool) Schema() map[string]any

type LSPRenamePreviewTool added in v0.4.0

type LSPRenamePreviewTool struct {
	// contains filtered or unexported fields
}

LSPRenamePreviewTool asks the language server for a semantic rename plan and prints the normalized WorkspaceEdit JSON. It intentionally does not mutate; applying the edit is a separate approval-gated tool call.

func (*LSPRenamePreviewTool) Description added in v0.4.0

func (t *LSPRenamePreviewTool) Description() string

func (*LSPRenamePreviewTool) Execute added in v0.4.0

func (t *LSPRenamePreviewTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPRenamePreviewTool) Name added in v0.4.0

func (t *LSPRenamePreviewTool) Name() string

func (*LSPRenamePreviewTool) ParallelSafe added in v0.4.0

func (t *LSPRenamePreviewTool) ParallelSafe(string) bool

func (*LSPRenamePreviewTool) PreviewCall added in v0.4.0

func (t *LSPRenamePreviewTool) PreviewCall(argsJSON string) string

func (*LSPRenamePreviewTool) RequiresApproval added in v0.4.0

func (t *LSPRenamePreviewTool) RequiresApproval(string) bool

func (*LSPRenamePreviewTool) Schema added in v0.4.0

func (t *LSPRenamePreviewTool) Schema() map[string]any

type LSPSelectionRangesTool added in v0.4.0

type LSPSelectionRangesTool struct {
	// contains filtered or unexported fields
}

LSPSelectionRangesTool returns the nested syntax ranges around a position. Agents can use the smallest-to-largest chain to choose a safe expression, block, or function-sized context window before editing.

func (*LSPSelectionRangesTool) Description added in v0.4.0

func (t *LSPSelectionRangesTool) Description() string

func (*LSPSelectionRangesTool) Execute added in v0.4.0

func (t *LSPSelectionRangesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPSelectionRangesTool) Name added in v0.4.0

func (t *LSPSelectionRangesTool) Name() string

func (*LSPSelectionRangesTool) ParallelSafe added in v0.4.0

func (t *LSPSelectionRangesTool) ParallelSafe(string) bool

func (*LSPSelectionRangesTool) PreviewCall added in v0.4.0

func (t *LSPSelectionRangesTool) PreviewCall(argsJSON string) string

func (*LSPSelectionRangesTool) RequiresApproval added in v0.4.0

func (t *LSPSelectionRangesTool) RequiresApproval(string) bool

func (*LSPSelectionRangesTool) Schema added in v0.4.0

func (t *LSPSelectionRangesTool) Schema() map[string]any

type LSPSignatureHelpTool added in v0.4.0

type LSPSignatureHelpTool struct {
	// contains filtered or unexported fields
}

LSPSignatureHelpTool returns callable signatures for a source position.

func (*LSPSignatureHelpTool) Description added in v0.4.0

func (t *LSPSignatureHelpTool) Description() string

func (*LSPSignatureHelpTool) Execute added in v0.4.0

func (t *LSPSignatureHelpTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPSignatureHelpTool) Name added in v0.4.0

func (t *LSPSignatureHelpTool) Name() string

func (*LSPSignatureHelpTool) ParallelSafe added in v0.4.0

func (t *LSPSignatureHelpTool) ParallelSafe(string) bool

func (*LSPSignatureHelpTool) PreviewCall added in v0.4.0

func (t *LSPSignatureHelpTool) PreviewCall(argsJSON string) string

func (*LSPSignatureHelpTool) RequiresApproval added in v0.4.0

func (t *LSPSignatureHelpTool) RequiresApproval(string) bool

func (*LSPSignatureHelpTool) Schema added in v0.4.0

func (t *LSPSignatureHelpTool) Schema() map[string]any

type LSPStatusTool added in v0.4.0

type LSPStatusTool struct {
	// contains filtered or unexported fields
}

LSPStatusTool reports language-server readiness for the current workspace.

func (*LSPStatusTool) Description added in v0.4.0

func (t *LSPStatusTool) Description() string

func (*LSPStatusTool) Execute added in v0.4.0

func (t *LSPStatusTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPStatusTool) Name added in v0.4.0

func (t *LSPStatusTool) Name() string

func (*LSPStatusTool) ParallelSafe added in v0.4.0

func (t *LSPStatusTool) ParallelSafe(string) bool

func (*LSPStatusTool) PreviewCall added in v0.4.0

func (t *LSPStatusTool) PreviewCall(argsJSON string) string

func (*LSPStatusTool) RequiresApproval added in v0.4.0

func (t *LSPStatusTool) RequiresApproval(string) bool

func (*LSPStatusTool) Schema added in v0.4.0

func (t *LSPStatusTool) Schema() map[string]any

type LSPSymbolsTool added in v0.4.0

type LSPSymbolsTool struct {
	// contains filtered or unexported fields
}

LSPSymbolsTool searches workspace symbols through the resolved server.

func (*LSPSymbolsTool) Description added in v0.4.0

func (t *LSPSymbolsTool) Description() string

func (*LSPSymbolsTool) Execute added in v0.4.0

func (t *LSPSymbolsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPSymbolsTool) Name added in v0.4.0

func (t *LSPSymbolsTool) Name() string

func (*LSPSymbolsTool) ParallelSafe added in v0.4.0

func (t *LSPSymbolsTool) ParallelSafe(string) bool

func (*LSPSymbolsTool) PreviewCall added in v0.4.0

func (t *LSPSymbolsTool) PreviewCall(argsJSON string) string

func (*LSPSymbolsTool) RequiresApproval added in v0.4.0

func (t *LSPSymbolsTool) RequiresApproval(string) bool

func (*LSPSymbolsTool) Schema added in v0.4.0

func (t *LSPSymbolsTool) Schema() map[string]any

type LSPTypeDefinitionTool added in v0.4.0

type LSPTypeDefinitionTool struct {
	// contains filtered or unexported fields
}

LSPTypeDefinitionTool returns type definition locations for a source position.

func (*LSPTypeDefinitionTool) Description added in v0.4.0

func (t *LSPTypeDefinitionTool) Description() string

func (*LSPTypeDefinitionTool) Execute added in v0.4.0

func (t *LSPTypeDefinitionTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*LSPTypeDefinitionTool) Name added in v0.4.0

func (t *LSPTypeDefinitionTool) Name() string

func (*LSPTypeDefinitionTool) ParallelSafe added in v0.4.0

func (t *LSPTypeDefinitionTool) ParallelSafe(string) bool

func (*LSPTypeDefinitionTool) PreviewCall added in v0.4.0

func (t *LSPTypeDefinitionTool) PreviewCall(argsJSON string) string

func (*LSPTypeDefinitionTool) RequiresApproval added in v0.4.0

func (t *LSPTypeDefinitionTool) RequiresApproval(string) bool

func (*LSPTypeDefinitionTool) Schema added in v0.4.0

func (t *LSPTypeDefinitionTool) Schema() map[string]any

type ListDirTool

type ListDirTool struct {
	Cwd *CwdRef
}

ListDirTool returns the immediate children of a directory.

func (*ListDirTool) Description

func (t *ListDirTool) Description() string

func (*ListDirTool) Execute

func (t *ListDirTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ListDirTool) Name

func (t *ListDirTool) Name() string

func (*ListDirTool) ParallelSafe

func (t *ListDirTool) ParallelSafe(string) bool

func (*ListDirTool) PreviewCall

func (t *ListDirTool) PreviewCall(argsJSON string) string

func (*ListDirTool) RequiresApproval

func (t *ListDirTool) RequiresApproval(string) bool

func (*ListDirTool) Schema

func (t *ListDirTool) Schema() map[string]any

type ListGitChangedFilesTool

type ListGitChangedFilesTool struct{ Cwd *CwdRef }

func (*ListGitChangedFilesTool) Description

func (t *ListGitChangedFilesTool) Description() string

func (*ListGitChangedFilesTool) Execute

func (t *ListGitChangedFilesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ListGitChangedFilesTool) Name

func (t *ListGitChangedFilesTool) Name() string

func (*ListGitChangedFilesTool) ParallelSafe

func (t *ListGitChangedFilesTool) ParallelSafe(string) bool

func (*ListGitChangedFilesTool) PreviewCall

func (t *ListGitChangedFilesTool) PreviewCall(argsJSON string) string

func (*ListGitChangedFilesTool) RequiresApproval

func (t *ListGitChangedFilesTool) RequiresApproval(string) bool

func (*ListGitChangedFilesTool) Schema

func (t *ListGitChangedFilesTool) Schema() map[string]any

type ListProjectStructureTool

type ListProjectStructureTool struct {
	Cwd *CwdRef
}

ListProjectStructureTool returns a bounded tree view of files and directories with sizes and last-modified timestamps. Designed as the "survey first" tool: the model can scan structure once and choose what to read with read_many_files instead of reading exploratorily.

func (*ListProjectStructureTool) Description

func (t *ListProjectStructureTool) Description() string

func (*ListProjectStructureTool) Execute

func (t *ListProjectStructureTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ListProjectStructureTool) Name

func (t *ListProjectStructureTool) Name() string

func (*ListProjectStructureTool) ParallelSafe

func (t *ListProjectStructureTool) ParallelSafe(string) bool

func (*ListProjectStructureTool) PreviewCall

func (t *ListProjectStructureTool) PreviewCall(argsJSON string) string

func (*ListProjectStructureTool) RequiresApproval

func (t *ListProjectStructureTool) RequiresApproval(string) bool

func (*ListProjectStructureTool) Schema

func (t *ListProjectStructureTool) Schema() map[string]any

type LoopConfig

type LoopConfig struct {
	Adapter  Streamer
	Registry *Registry
	// Permissions gates every tool call against project-local rules
	// loaded from .yottacode/permissions.json (committable) and
	// .yottacode/permissions.local.json (gitignored). Optional: nil
	// disables rule matching and falls through to the tool's own
	// RequiresApproval policy.
	Permissions *permissions.Permissions
	// BypassPermissions is the internal name for the user-facing
	// --yolo flag.
	// Skip every approval prompt, run silently. DANGEROUS —
	// model-emitted commands execute without a human in the loop.
	// Explicit `deny` rules in permissions.json still refuse the call
	// (bypass is "skip prompts," not "ignore my policy"). Use only
	// in trusted CI / scripted contexts.
	BypassPermissions bool
	Cwd               *CwdRef
	MaxIterations     int
	// PlanMode is the shared plan-mode flag the TUI flips via /plan or
	// Shift+Tab. nil disables plan mode entirely (oneshot; tests). When
	// set and Active, the loop prepends a plan-mode addendum to the
	// system prompt on every request and gates mutating tools through
	// PlanModeGate before approval evaluation. Pointer-shared so a TUI
	// flip takes effect on the next iteration with no reconfiguration.
	PlanMode *PlanModeState

	// LoopControl is the shared signal for the /loop self-stop tool. When set
	// and IsActive (the current turn is a /loop prose iteration), the loop
	// advertises the loop_control tool so the model can end its own loop once
	// the loop's stated goal is met. nil disables the tool entirely (oneshot;
	// subagents; tests). Pointer-shared with the TUI, which sets the per-turn
	// active flag and consumes a stop request at turn end.
	LoopControl *LoopControlState

	// AutoMode is the shared auto-mode flag the TUI flips via
	// Shift+Tab, the plan-card [A] hotkey, or the --permission-mode
	// auto startup flag. When active, the loop auto-approves
	// non-safety-floor tool calls (no modal) so the model can
	// implement a multi-step plan without per-edit friction.
	// run_bash and git mutations remain in the safety floor — see
	// IsAutoModeSafetyFloor.
	AutoMode *AutoModeState

	// YoloMode is the unrestricted toggle — auto-approves ALL tool
	// calls including the safety floor, and raises the iteration cap to
	// a generous but finite budget (see yoloIterationCap) so a runaway
	// model still terminates instead of looping forever. Explicit Deny
	// rules in permissions.json still win. Intended for unattended
	// long-running implementations where the user has decided no further
	// oversight is needed. Mutually exclusive with AutoMode and PlanMode
	// at the TUI layer.
	YoloMode *YoloModeState

	// FixedIterationCap pins the effective iteration budget to
	// MaxIterations exactly, bypassing the auto-mode 4× multiplier and
	// the yolo expansion. Subagents set this: a child inherits the
	// parent's AutoMode/YoloMode pointers so its *approval* behavior
	// matches the parent (writes don't block under auto, etc.), but its
	// iteration budget must stay bounded — the user opted into "let the
	// parent run unattended," not "let the parent spawn child loops with
	// 4×/unbounded budgets." Without this the shared mode pointers leak
	// the multiplier into children (see childIterationCap). Default
	// false: top-level loops keep the mode-scaled budget.
	FixedIterationCap bool

	// BackgroundApprovalPolicy, when non-nil, is the deterministic approval
	// policy for an unattended background child. It runs before yolo / auto /
	// permissions Allow can auto-approve a tool, so background workers cannot
	// inherit the parent's broad approval modes by accident. The policy returns
	// (decision, note, handled). handled=false means "not a background-gated
	// tool; continue with the normal approval chain". handled=true with Deny
	// returns note as the tool result; handled=true with AllowOnce emits an
	// ApprovalAuto event using note as the Source and executes the tool.
	//
	// Dispatch supplies a scoped policy that allows worktree-confined file
	// writes and run_tests while denying shell/git/network mutations. Standalone
	// background Agent runs use a conservative policy that denies every tool
	// requiring approval, keeping GA background delegation read-only by default.
	BackgroundApprovalPolicy func(tool Tool, argsJSON string) (Decision, string, bool)

	// Checkpoints, when non-nil, receives pre-image snapshot
	// requests for every Mutator tool call. nil disables checkpoint
	// capture entirely — oneshot and tests pass nil. The TUI builds
	// a *checkpoint.Store and attaches it; see internal/tui/run.go.
	// Implementations must be safe under concurrent SnapshotPath
	// calls within a turn.
	Checkpoints CheckpointWriter

	// UserMessages, when non-nil, is checked (non-blocking) after
	// each tool round completes. If a message is pending, it's
	// appended to history as a RoleUser message and the loop
	// continues — the next streamIteration sees the user's input
	// alongside the tool results. This lets the TUI inject
	// additive instructions ("also check the tests") without
	// cancelling the active turn.
	UserMessages <-chan string

	// HistoryLock, when non-nil, serializes this loop's mutations and
	// snapshots of the history slice against concurrent reads on another
	// goroutine. The TUI sets it to the session's lock: its bubbletea
	// Update goroutine reads m.sess.Messages (live token estimate,
	// /context, system-prompt edits) while this loop appends to the same
	// slice on its own goroutine — without it that's a data race that can
	// torn-read or, on an append-triggered reallocation, crash. nil
	// (oneshot, subagents, tests) means the history is owned by a single
	// goroutine and needs no locking. The lock is only ever held across
	// in-memory slice work — never across a network or channel op — so it
	// cannot stall the turn.
	HistoryLock *sync.Mutex

	// Compaction, when non-nil, enables in-loop history compaction:
	// once the running history approaches Window, the loop summarizes
	// its older middle messages in place and continues with a compacted
	// history. This is the ONLY context management a subagent has — it
	// runs Turn directly rather than through the TUI's turn-boundary
	// summarizer, so without this a long subagent accumulates until the
	// provider rejects the request. nil disables it; the TUI and oneshot
	// leave it unset and manage context at their own boundaries.
	Compaction *CompactionConfig
}

LoopConfig is the value-typed configuration for one or more agent turns. Channels are passed separately to Turn so the same config can drive a streaming session across many turns without rewiring.

type LoopControlState added in v0.4.0

type LoopControlState struct {
	// contains filtered or unexported fields
}

LoopControlState is the shared signal between a /loop prose iteration's agent turn and the TUI that schedules it. The TUI sets turnActive before firing a loop's prose turn and clears it when the turn ends; streamIteration reads IsActive to decide whether to advertise the loop_control tool. The tool sets stop when the model asks to end the loop, and the TUI consumes it at turn end to disarm the owning loop.

All fields are atomic: the TUI's Update goroutine writes turnActive and reads stop/reason while the agent goroutine reads turnActive and writes stop/reason. The pointer is shared between LoopConfig and the TUI Model (and the tool), so the gate and the stop request need no reconstruction — the same pattern PlanModeState uses.

func (*LoopControlState) ConsumeStop added in v0.4.0

func (s *LoopControlState) ConsumeStop() (bool, string)

ConsumeStop reports whether the model asked to stop this turn's loop, resetting the flag so it fires at most once. The returned reason is the model's stated justification (may be empty). Nil-safe.

func (*LoopControlState) Context added in v0.4.0

func (s *LoopControlState) Context() string

Context returns the loop descriptor set by SetContext, or "" if none. Nil-safe.

func (*LoopControlState) IsActive added in v0.4.0

func (s *LoopControlState) IsActive() bool

IsActive reports whether the current turn is a /loop prose iteration. Nil-safe — oneshot, subagents, and tests leave LoopControl unset, which reads as "not a loop turn" and hides the tool.

func (*LoopControlState) SetContext added in v0.4.0

func (s *LoopControlState) SetContext(c string)

SetContext records the one-line loop descriptor injected into the per-iteration addendum (cadence, bounded/unbounded). Set by the TUI just before a loop's prose turn starts. Nil-safe.

func (*LoopControlState) SetTurnActive added in v0.4.0

func (s *LoopControlState) SetTurnActive(active bool)

SetTurnActive marks (or unmarks) the current turn as a /loop iteration. On unmark it also clears any unconsumed stop so a request can never leak from one turn into the next. Nil-safe.

type LoopControlTool added in v0.4.0

type LoopControlTool struct {
	State *LoopControlState
}

LoopControlTool lets a /loop prose iteration end its own loop once the agent judges the loop's goal met — e.g. `/loop 2m check CI and stop when green`. It is advertised ONLY while a /loop prose iteration owns the turn (see the loop_control gate in iterationToolFilter); in any other turn it is hidden, so the model cannot stop a loop that isn't running. Stopping takes effect after the current turn finishes: the TUI disarms the loop so it does not re-fire.

func (*LoopControlTool) Description added in v0.4.0

func (t *LoopControlTool) Description() string

func (*LoopControlTool) Execute added in v0.4.0

func (t *LoopControlTool) Execute(_ context.Context, argsJSON string) (string, error)

func (*LoopControlTool) Name added in v0.4.0

func (t *LoopControlTool) Name() string

func (*LoopControlTool) PreviewCall added in v0.4.0

func (t *LoopControlTool) PreviewCall(argsJSON string) string

func (*LoopControlTool) RequiresApproval added in v0.4.0

func (t *LoopControlTool) RequiresApproval(string) bool

RequiresApproval is false: a loop ending itself on the model's judgment is the whole point — gating it behind a modal would defeat hands-off polling.

func (*LoopControlTool) Schema added in v0.4.0

func (t *LoopControlTool) Schema() map[string]any

Schema: a single required "action" (only "stop" today) plus an optional human-facing "reason". Kept tiny so the model reaches for it decisively.

type MCPTool added in v0.3.0

type MCPTool struct {
	// Server is the MCPServer.Name from config. Stable across the
	// session.
	Server string

	// ToolName is the server-side tool name (no namespace prefix).
	ToolName string

	// Desc is the human-readable description the server advertised.
	Desc string

	// InputSchema is the JSON Schema the server advertised, passed
	// through to the model verbatim.
	InputSchema map[string]any

	// ReadOnly mirrors the server's annotations.readOnlyHint. When
	// true, the tool auto-executes without the approval modal.
	ReadOnly bool

	// Client is the live MCP client used to invoke the tool. Held
	// here directly (not looked up by Server name each call) so a
	// /mcp restart of the server replaces the registered tools'
	// Client field via re-registration, not silent indirection.
	Client mcp.Client
}

MCPTool adapts one tool exposed by an MCP server to the agent.Tool interface, so MCP tools register into the same Registry as native tools and flow through the same approval / permissions / dispatch pipeline. Constructed once per (server, tool) pair at session start by the manager in internal/tui/run.go.

Naming: the public Name() is the namespaced form `mcp/<Server>/<ToolName>`. The unprefixed ToolName is what gets sent over the wire to the server's tools/call. The agent loop, model, and permission rules only ever see the namespaced form — there's no collision risk with native tool names (which never contain a slash).

Approval: defaults to required. The server's `annotations.readOnlyHint` hint, when set, flips ReadOnly=true and the bridge stops asking. Users can elevate further per-tool via `Tool(mcp/<server>/<tool>)` permission rules — same syntax as native tools.

Mutator: MCPTool does NOT implement Mutator. MCP tools mutate state outside yottacode's file model (databases, external APIs, filesystem-via-server), so /checkpoints can't snapshot them — same rationale as run_bash. Document this in docs/mcp.md.

func (*MCPTool) Description added in v0.3.0

func (t *MCPTool) Description() string

Description is the server-supplied hint shown to the model.

func (*MCPTool) Execute added in v0.3.0

func (t *MCPTool) Execute(ctx context.Context, argsJSON string) (string, error)

Execute calls the underlying MCP tool and translates the result back into the agent's (string, error) shape.

Result envelope mapping:

  • Transport-level failures (subprocess crash, ctx cancellation, malformed argsJSON) surface as a Go error.
  • Server-side tool errors (CallToolResult.isError = true) surface as a Go error too, with the server's text content as the message — so the agent loop's existing tool_result-with-is_error path fires and the model sees the failure and self-corrects.
  • Success returns the joined text content as the tool result.

func (*MCPTool) Name added in v0.3.0

func (t *MCPTool) Name() string

Name returns the namespaced tool name: `mcp/<Server>/<ToolName>`. Used by the agent loop, model adapter, and permission rules.

func (*MCPTool) PreviewCall added in v0.3.0

func (t *MCPTool) PreviewCall(argsJSON string) string

PreviewCall renders a single-line summary for the approval modal / tool-card header. Format: `MCP <server>/<tool> { ... }`. Long argument blobs are truncated.

func (*MCPTool) RequiresApproval added in v0.3.0

func (t *MCPTool) RequiresApproval(string) bool

RequiresApproval gates the approval modal. The default is "ask"; only an explicit readOnlyHint=true on the server side flips this off. Users can elevate further with permission rules.

Note: argsJSON is unused — MCP tools don't carry per-call policy in v1 (no subcommand-style branching the way the unified git tool does). Subagents may add finer-grained policy in v1.1+.

func (*MCPTool) Schema added in v0.3.0

func (t *MCPTool) Schema() map[string]any

Schema returns the server-supplied JSON Schema for the tool's arguments. The agent loop hands it to the model unchanged.

type MediaAnalyzeTool added in v0.4.0

type MediaAnalyzeTool struct {
	Cwd           *CwdRef
	DenyReadPaths []string
}

MediaAnalyzeTool runs one public analysis surface over separate internal detectors. Audio-backed demos use silence detection; silent terminal demos use visual freeze/idle detection; auto mode picks the useful detectors from the file's streams.

func (*MediaAnalyzeTool) Description added in v0.4.0

func (t *MediaAnalyzeTool) Description() string

func (*MediaAnalyzeTool) Execute added in v0.4.0

func (t *MediaAnalyzeTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*MediaAnalyzeTool) Name added in v0.4.0

func (t *MediaAnalyzeTool) Name() string

func (*MediaAnalyzeTool) ParallelSafe added in v0.4.0

func (t *MediaAnalyzeTool) ParallelSafe(string) bool

func (*MediaAnalyzeTool) PreviewCall added in v0.4.0

func (t *MediaAnalyzeTool) PreviewCall(argsJSON string) string

func (*MediaAnalyzeTool) RequiresApproval added in v0.4.0

func (t *MediaAnalyzeTool) RequiresApproval(string) bool

func (*MediaAnalyzeTool) Schema added in v0.4.0

func (t *MediaAnalyzeTool) Schema() map[string]any

type MediaComposeTool added in v0.4.0

type MediaComposeTool struct {
	Cwd           *CwdRef
	DenyReadPaths []string
	WriteOpts     WritePathOptions
}

MediaComposeTool assembles an approved storyboard into one draft MP4. It is intentionally a local composition primitive: the model still plans the story, but ffmpeg does deterministic rendering from title cards, stills, real clips, simple motion, branded overlays, and conservative fades.

func (*MediaComposeTool) Description added in v0.4.0

func (t *MediaComposeTool) Description() string

func (*MediaComposeTool) Execute added in v0.4.0

func (t *MediaComposeTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*MediaComposeTool) Name added in v0.4.0

func (t *MediaComposeTool) Name() string

func (*MediaComposeTool) PathsToSnapshot added in v0.4.0

func (t *MediaComposeTool) PathsToSnapshot(cwd, argsJSON string) []string

func (*MediaComposeTool) PreviewCall added in v0.4.0

func (t *MediaComposeTool) PreviewCall(argsJSON string) string

func (*MediaComposeTool) RequiresApproval added in v0.4.0

func (t *MediaComposeTool) RequiresApproval(string) bool

func (*MediaComposeTool) Schema added in v0.4.0

func (t *MediaComposeTool) Schema() map[string]any

type MediaProbeTool added in v0.4.0

type MediaProbeTool struct {
	Cwd           *CwdRef
	DenyReadPaths []string
}

MediaProbeTool inspects a media file through ffprobe without sending the media bytes to the model. The result is a compact metadata snapshot the agent can use to plan edits and pick output profiles.

func (*MediaProbeTool) Description added in v0.4.0

func (t *MediaProbeTool) Description() string

func (*MediaProbeTool) Execute added in v0.4.0

func (t *MediaProbeTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*MediaProbeTool) Name added in v0.4.0

func (t *MediaProbeTool) Name() string

func (*MediaProbeTool) ParallelSafe added in v0.4.0

func (t *MediaProbeTool) ParallelSafe(string) bool

func (*MediaProbeTool) PreviewCall added in v0.4.0

func (t *MediaProbeTool) PreviewCall(argsJSON string) string

func (*MediaProbeTool) RequiresApproval added in v0.4.0

func (t *MediaProbeTool) RequiresApproval(string) bool

func (*MediaProbeTool) Schema added in v0.4.0

func (t *MediaProbeTool) Schema() map[string]any

type MediaRenderTool added in v0.4.0

type MediaRenderTool struct {
	Cwd           *CwdRef
	DenyReadPaths []string
	WriteOpts     WritePathOptions
}

MediaRenderTool renders approved edit ranges into platform-specific outputs. It shells out to ffmpeg with argv-only construction; no filter text is ever interpreted by a shell.

func (*MediaRenderTool) Description added in v0.4.0

func (t *MediaRenderTool) Description() string

func (*MediaRenderTool) Execute added in v0.4.0

func (t *MediaRenderTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*MediaRenderTool) Name added in v0.4.0

func (t *MediaRenderTool) Name() string

func (*MediaRenderTool) PathsToSnapshot added in v0.4.0

func (t *MediaRenderTool) PathsToSnapshot(cwd, argsJSON string) []string

func (*MediaRenderTool) PreviewCall added in v0.4.0

func (t *MediaRenderTool) PreviewCall(argsJSON string) string

func (*MediaRenderTool) RequiresApproval added in v0.4.0

func (t *MediaRenderTool) RequiresApproval(string) bool

func (*MediaRenderTool) Schema added in v0.4.0

func (t *MediaRenderTool) Schema() map[string]any

type MemoryArchivePruneTool added in v0.4.0

type MemoryArchivePruneTool struct {
	Cwd *CwdRef
}

MemoryArchivePruneTool inventories or prunes archived prior memory versions. Dry runs are read-only; actual deletion is approval-gated and constrained to files discovered under memory .archive directories.

func (*MemoryArchivePruneTool) Description added in v0.4.0

func (t *MemoryArchivePruneTool) Description() string

func (*MemoryArchivePruneTool) Execute added in v0.4.0

func (t *MemoryArchivePruneTool) Execute(_ context.Context, argsJSON string) (string, error)

func (*MemoryArchivePruneTool) Name added in v0.4.0

func (t *MemoryArchivePruneTool) Name() string

func (*MemoryArchivePruneTool) ParallelSafe added in v0.4.0

func (t *MemoryArchivePruneTool) ParallelSafe(argsJSON string) bool

func (*MemoryArchivePruneTool) PreviewCall added in v0.4.0

func (t *MemoryArchivePruneTool) PreviewCall(argsJSON string) string

func (*MemoryArchivePruneTool) RequiresApproval added in v0.4.0

func (t *MemoryArchivePruneTool) RequiresApproval(argsJSON string) bool

func (*MemoryArchivePruneTool) Schema added in v0.4.0

func (t *MemoryArchivePruneTool) Schema() map[string]any

type MemoryAuditTool added in v0.4.0

type MemoryAuditTool struct {
	Cwd *CwdRef
}

MemoryAuditTool lets the agent inspect memory-store hygiene before doing a curation pass. It is intentionally read-only: the agent must explicitly use memory_get, memory_save, and memory_forget for each consolidation decision so memory changes stay reviewable in the transcript.

func (*MemoryAuditTool) Description added in v0.4.0

func (t *MemoryAuditTool) Description() string

func (*MemoryAuditTool) Execute added in v0.4.0

func (t *MemoryAuditTool) Execute(_ context.Context, argsJSON string) (string, error)

func (*MemoryAuditTool) Name added in v0.4.0

func (t *MemoryAuditTool) Name() string

func (*MemoryAuditTool) ParallelSafe added in v0.4.0

func (t *MemoryAuditTool) ParallelSafe(string) bool

func (*MemoryAuditTool) PreviewCall added in v0.4.0

func (t *MemoryAuditTool) PreviewCall(argsJSON string) string

func (*MemoryAuditTool) RequiresApproval added in v0.4.0

func (t *MemoryAuditTool) RequiresApproval(string) bool

func (*MemoryAuditTool) Schema added in v0.4.0

func (t *MemoryAuditTool) Schema() map[string]any

type MemoryCurateApplyTool added in v0.4.0

type MemoryCurateApplyTool struct {
	Cwd *CwdRef
}

MemoryCurateApplyTool performs narrow, approval-gated memory curation actions that are safe to apply mechanically after memory_audit has surfaced them. It deliberately avoids subjective rewrites or merges: those still need the agent to read, propose, and save explicit final content.

func (*MemoryCurateApplyTool) Description added in v0.4.0

func (t *MemoryCurateApplyTool) Description() string

func (*MemoryCurateApplyTool) Execute added in v0.4.0

func (t *MemoryCurateApplyTool) Execute(_ context.Context, argsJSON string) (string, error)

func (*MemoryCurateApplyTool) Name added in v0.4.0

func (t *MemoryCurateApplyTool) Name() string

func (*MemoryCurateApplyTool) ParallelSafe added in v0.4.0

func (t *MemoryCurateApplyTool) ParallelSafe(string) bool

func (*MemoryCurateApplyTool) PreviewCall added in v0.4.0

func (t *MemoryCurateApplyTool) PreviewCall(argsJSON string) string

func (*MemoryCurateApplyTool) RequiresApproval added in v0.4.0

func (t *MemoryCurateApplyTool) RequiresApproval(string) bool

func (*MemoryCurateApplyTool) Schema added in v0.4.0

func (t *MemoryCurateApplyTool) Schema() map[string]any

type MemoryForgetTool

type MemoryForgetTool struct {
	Cwd *CwdRef
}

MemoryForgetTool deletes a memory file and regenerates the scope's MEMORY.md index. Errors cleanly when the named memory does not exist — the agent can use that signal to learn the right names.

func (*MemoryForgetTool) Description

func (t *MemoryForgetTool) Description() string

func (*MemoryForgetTool) Execute

func (t *MemoryForgetTool) Execute(_ context.Context, argsJSON string) (string, error)

func (*MemoryForgetTool) Name

func (t *MemoryForgetTool) Name() string

func (*MemoryForgetTool) ParallelSafe

func (t *MemoryForgetTool) ParallelSafe(string) bool

func (*MemoryForgetTool) PreviewCall

func (t *MemoryForgetTool) PreviewCall(argsJSON string) string

func (*MemoryForgetTool) RequiresApproval

func (t *MemoryForgetTool) RequiresApproval(string) bool

func (*MemoryForgetTool) Schema

func (t *MemoryForgetTool) Schema() map[string]any

type MemoryGetTool added in v0.3.0

type MemoryGetTool struct {
	Cwd *CwdRef
}

MemoryGetTool returns the full, untruncated contents of one saved memory (frontmatter + body). memory_search only exposes a 300-char preview, so without this the agent has no way to see a memory's full body before memory_save overwrites the whole file — a blind read-modify-write that silently drops the unseen tail. This is the READ half of an agent-performed update; the model still decides what (if anything) to write back, so it stays within the agent-owned memory model.

func (*MemoryGetTool) Description added in v0.3.0

func (t *MemoryGetTool) Description() string

func (*MemoryGetTool) Execute added in v0.3.0

func (t *MemoryGetTool) Execute(_ context.Context, argsJSON string) (string, error)

func (*MemoryGetTool) Name added in v0.3.0

func (t *MemoryGetTool) Name() string

func (*MemoryGetTool) ParallelSafe added in v0.3.0

func (t *MemoryGetTool) ParallelSafe(string) bool

func (*MemoryGetTool) PreviewCall added in v0.3.0

func (t *MemoryGetTool) PreviewCall(argsJSON string) string

func (*MemoryGetTool) RequiresApproval added in v0.3.0

func (t *MemoryGetTool) RequiresApproval(string) bool

func (*MemoryGetTool) Schema added in v0.3.0

func (t *MemoryGetTool) Schema() map[string]any

type MemorySaveTool

type MemorySaveTool struct {
	Cwd      *CwdRef
	Embedder *memory.EmbedClient
	Source   memory.Source
}

MemorySaveTool persists a typed memory file under either the user-scope (~/.yottacode/memory/user/) or project-scope (~/.yottacode/memory/projects/<slug>/) directory and refreshes the MEMORY.md index for that scope. Replaces the post-turn extractor — the agent now decides in-band when something is worth remembering.

When Embedder is set, a vector sidecar (.vec) is generated alongside the memory file for semantic retrieval.

func (*MemorySaveTool) Description

func (t *MemorySaveTool) Description() string

func (*MemorySaveTool) Execute

func (t *MemorySaveTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*MemorySaveTool) Name

func (t *MemorySaveTool) Name() string

func (*MemorySaveTool) ParallelSafe

func (t *MemorySaveTool) ParallelSafe(string) bool

func (*MemorySaveTool) PreviewCall

func (t *MemorySaveTool) PreviewCall(argsJSON string) string

func (*MemorySaveTool) RequiresApproval

func (t *MemorySaveTool) RequiresApproval(string) bool

func (*MemorySaveTool) Schema

func (t *MemorySaveTool) Schema() map[string]any

type MemorySearchTool added in v0.3.0

type MemorySearchTool struct {
	Cwd      *CwdRef
	Embedder *memory.EmbedClient
	// Strategy is the configured retrieval strategy (keyword | bm25 |
	// semantic | auto). Empty falls back to "auto" so the tool keeps
	// working when constructed without config wired. Threaded so search
	// ranks the same way injection does instead of always forcing auto.
	Strategy string
	// SemanticWeight is retrieval.semantic_weight. When unset by old tests or
	// ad-hoc construction, Execute falls back to the config default so semantic
	// search is not accidentally pure BM25.
	SemanticWeight float64
	// SemanticWeightConfigured distinguishes an explicit 0.0 semantic weight
	// from the zero value of an unwired tool.
	SemanticWeightConfigured bool
}

MemorySearchTool lets the agent introspect its own memory store. It searches across both user and project scopes, returning ranked results with scores. The agent uses this to check whether a memory already exists before saving, to find related memories when reasoning about a topic, or to verify that a remembered fact is still current.

func (*MemorySearchTool) Description added in v0.3.0

func (t *MemorySearchTool) Description() string

func (*MemorySearchTool) Execute added in v0.3.0

func (t *MemorySearchTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*MemorySearchTool) Name added in v0.3.0

func (t *MemorySearchTool) Name() string

func (*MemorySearchTool) ParallelSafe added in v0.3.0

func (t *MemorySearchTool) ParallelSafe(string) bool

func (*MemorySearchTool) PreviewCall added in v0.3.0

func (t *MemorySearchTool) PreviewCall(argsJSON string) string

func (*MemorySearchTool) RequiresApproval added in v0.3.0

func (t *MemorySearchTool) RequiresApproval(string) bool

func (*MemorySearchTool) Schema added in v0.3.0

func (t *MemorySearchTool) Schema() map[string]any

type MkdirTool

type MkdirTool struct {
	Cwd       *CwdRef
	WriteOpts WritePathOptions
}

func (*MkdirTool) Description

func (t *MkdirTool) Description() string

func (*MkdirTool) Execute

func (t *MkdirTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*MkdirTool) Name

func (t *MkdirTool) Name() string

func (*MkdirTool) PreviewCall

func (t *MkdirTool) PreviewCall(argsJSON string) string

func (*MkdirTool) RequiresApproval

func (t *MkdirTool) RequiresApproval(string) bool

func (*MkdirTool) Schema

func (t *MkdirTool) Schema() map[string]any

type MoveFileTool

type MoveFileTool struct {
	Cwd       *CwdRef
	WriteOpts WritePathOptions
}

func (*MoveFileTool) Description

func (t *MoveFileTool) Description() string

func (*MoveFileTool) Execute

func (t *MoveFileTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*MoveFileTool) Name

func (t *MoveFileTool) Name() string

func (*MoveFileTool) PathsToSnapshot added in v0.2.0

func (t *MoveFileTool) PathsToSnapshot(cwd, argsJSON string) []string

PathsToSnapshot reports both src (so we can recreate it on rewind) and dst (so we can remove the moved-to file on rewind).

func (*MoveFileTool) PreviewCall

func (t *MoveFileTool) PreviewCall(argsJSON string) string

func (*MoveFileTool) RequiresApproval

func (t *MoveFileTool) RequiresApproval(string) bool

func (*MoveFileTool) Schema

func (t *MoveFileTool) Schema() map[string]any

type MultimodalResult added in v0.3.0

type MultimodalResult struct {
	Content string
	Images  []adapter.ImageBlock
}

MultimodalResult carries the output of a multimodal tool execution — text content plus optional image blocks.

type MultimodalTool added in v0.3.0

type MultimodalTool interface {
	ExecuteMultimodal(ctx context.Context, argsJSON string) (MultimodalResult, error)
}

MultimodalTool is an optional interface for tools that can produce image content alongside text output. The agent loop prefers ExecuteMultimodal over Execute when both are available; images are attached to the tool-result message so the model can see them.

type Mutator added in v0.2.0

type Mutator interface {
	PathsToSnapshot(cwd, argsJSON string) []string
}

Mutator is the optional capability marker for tools that modify files on disk. The checkpoint subsystem queries this before tool.Execute to capture pre-images so /checkpoints can restore. PathsToSnapshot returns absolute paths the tool intends to touch, derived from argsJSON. Returning extra paths is harmless (snapshots are content-addressed and dedup); returning too few breaks restore.

Tools that mutate files via opaque side effects (e.g. run_bash) do NOT implement this — those mutations are intentionally untracked, mirroring Claude Code /rewind. Surface the limitation in user-facing docs / picker footer.

type PRAddCommentResult added in v0.3.0

type PRAddCommentResult struct {
	Posted            bool
	URL               string
	ID                int64
	ValidationErr     string
	GitHubUnavailable bool
	NotFound          bool
	GitHubError       string
}

PRAddCommentResult is the typed envelope AddPRComment returns through the tool wrapper. Reason discriminates the failure mode — same pattern as PRCreateResult / PRUpdateResult so the model brief and slash commands can branch on typed flags rather than stringy error checks.

func AddPRComment added in v0.3.0

AddPRComment is the deterministic core of pr_add_comment. Validates body length and presence in Go before dialing the Interface; folds typed errors (ErrPRNotFound, ErrGitHubUnavailable) into the typed result envelope so callers branch on flags rather than err strings.

type PRCheckLogsTool added in v0.4.0

type PRCheckLogsTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

PRCheckLogsTool fetches failed GitHub Actions job logs for a PR without shelling out to `gh run view --log-failed | tail`. It is read-only, but intentionally bounded so failed logs cannot flood the model context.

func (*PRCheckLogsTool) Description added in v0.4.0

func (t *PRCheckLogsTool) Description() string

func (*PRCheckLogsTool) Execute added in v0.4.0

func (t *PRCheckLogsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*PRCheckLogsTool) Name added in v0.4.0

func (t *PRCheckLogsTool) Name() string

func (*PRCheckLogsTool) PreviewCall added in v0.4.0

func (t *PRCheckLogsTool) PreviewCall(argsJSON string) string

func (*PRCheckLogsTool) RequiresApproval added in v0.4.0

func (t *PRCheckLogsTool) RequiresApproval(string) bool

func (*PRCheckLogsTool) Schema added in v0.4.0

func (t *PRCheckLogsTool) Schema() map[string]any

type PRContext added in v0.3.0

type PRContext struct {
	ResolvedBase      string
	BaseResolution    string // "explicit" | "origin-head" | "fallback:<name>" | "unresolved"
	CurrentBranch     string
	BaseEqualsCurrent bool
	AheadCount        int
	AheadCountErr     string
	DiffStat          string
	DiffStatCapped    bool
	CommitLog         []string // each entry: "<short-sha> <subject>"
	PushedToOrigin    bool
	GhAvailable       bool
	PRTemplate        string
	PRTemplatePath    string // relative to cwd
	PRTemplateCapped  bool
}

PRContext is the typed snapshot BuildPRContext returns. Same rationale as CommitContext: structured fields the procedural /create-pr can consume directly without a tool-call round trip, and a typed shape tests can assert against rather than parsing the rendered string.

func BuildPRContext added in v0.3.0

func BuildPRContext(ctx context.Context, cwd, explicitBase string) (PRContext, error)

BuildPRContext is the deterministic core of pr_context. Returns a typed snapshot the tool wrapper renders to text, and the procedural /create-pr reads directly. Errors return only on infrastructure failures (git binary missing, etc.); informational gaps (ahead-count not computable because base doesn't exist locally, no PR template found) populate fields rather than failing.

type PRCreateResult added in v0.3.0

type PRCreateResult struct {
	Created           bool
	URL               string
	Number            int
	ValidationErr     string
	GitHubUnavailable bool
	GitHubError       string
}

PRCreateResult is the typed envelope CreatePR returns. Same shape rationale as CommitResult: callers branch on typed fields, not stringy err checks. Reason discriminates the failure mode so the procedural /create-pr handles each branch differently (validation → re-prompt; github_unavailable → fall through to draft-only; github_error → surface verbatim and stop).

func CreatePR added in v0.3.0

CreatePR is the deterministic core of pr_create. Validates title and required fields *before* dialing the Interface, so an oversize title or empty body never reaches the network. Returns a typed PRCreateResult; the tool wrapper renders it for model consumption, /create-pr reads it directly.

The Interface returns ErrGitHubUnavailable when the local environment can't make the call; we surface that as GitHubUnavailable=true so the caller can fall through to draft-only instead of treating it as an opaque error.

type PRReadContext added in v0.3.0

type PRReadContext struct {
	Ref               string
	NotFound          bool
	GitHubUnavailable bool
	FetchErr          string

	PR github.PRDetails
}

PRReadContext is the typed snapshot pr_read returns. Same state-flag pattern as PRReviewContext (NotFound / GitHubUnavailable / FetchErr) so the model branches on typed flags before reading the metadata. PR is zero-valued when the read failed.

func BuildPRReadContext added in v0.3.0

func BuildPRReadContext(ctx context.Context, client github.Interface, ref string) PRReadContext

BuildPRReadContext is the deterministic core of pr_read. Wraps a single Interface.ReadPR call and folds the typed errors into the snapshot's flags. Doesn't return an error itself — every failure shape is captured in the snapshot so callers can branch on flags rather than err strings.

type PRReadinessContextTool added in v0.4.0

type PRReadinessContextTool struct{ Cwd *CwdRef }

PRReadinessContextTool gathers a cheap local readiness snapshot before a PR.

func (*PRReadinessContextTool) Description added in v0.4.0

func (t *PRReadinessContextTool) Description() string

func (*PRReadinessContextTool) Execute added in v0.4.0

func (t *PRReadinessContextTool) Execute(ctx context.Context, _ string) (string, error)

func (*PRReadinessContextTool) Name added in v0.4.0

func (t *PRReadinessContextTool) Name() string

func (*PRReadinessContextTool) ParallelSafe added in v0.4.0

func (t *PRReadinessContextTool) ParallelSafe(string) bool

func (*PRReadinessContextTool) PreviewCall added in v0.4.0

func (t *PRReadinessContextTool) PreviewCall(string) string

func (*PRReadinessContextTool) RequiresApproval added in v0.4.0

func (t *PRReadinessContextTool) RequiresApproval(string) bool

func (*PRReadinessContextTool) Schema added in v0.4.0

func (t *PRReadinessContextTool) Schema() map[string]any

type PRRerunChecksTool added in v0.4.0

type PRRerunChecksTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

PRRerunChecksTool re-runs failed GitHub Actions jobs for a PR. It is approval-required because it mutates remote CI state and can consume CI minutes.

func (*PRRerunChecksTool) Description added in v0.4.0

func (t *PRRerunChecksTool) Description() string

func (*PRRerunChecksTool) Execute added in v0.4.0

func (t *PRRerunChecksTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*PRRerunChecksTool) Name added in v0.4.0

func (t *PRRerunChecksTool) Name() string

func (*PRRerunChecksTool) PreviewCall added in v0.4.0

func (t *PRRerunChecksTool) PreviewCall(argsJSON string) string

func (*PRRerunChecksTool) RequiresApproval added in v0.4.0

func (t *PRRerunChecksTool) RequiresApproval(string) bool

func (*PRRerunChecksTool) Schema added in v0.4.0

func (t *PRRerunChecksTool) Schema() map[string]any

type PRReviewContext added in v0.3.0

type PRReviewContext struct {
	Ref               string
	NotFound          bool   // true when gh couldn't resolve the ref
	GitHubUnavailable bool   // true when gh is missing / unauthed
	FetchErr          string // any other Interface error, surfaced verbatim

	PR            github.PRDetails
	Checks        []github.CheckRun
	Diff          string
	DiffCapped    bool
	FailingChecks []string
}

PRReviewContext is the typed snapshot the review tool returns. Same shape rationale as CommitContext / PRContext: callers branch on typed fields, and the rendered string is for the model's consumption rather than the only access path.

func BuildPRReviewContext added in v0.3.0

func BuildPRReviewContext(ctx context.Context, client github.Interface, ref string) (PRReviewContext, error)

BuildPRReviewContext is the deterministic core of pr_review_context. Fans out the three Interface calls (ReadPR, ListPRChecks, ReadPRDiff), folds the typed errors into the snapshot's NotFound / GitHubUnavailable flags so the caller can branch without parsing err strings, and computes the FailingChecks list for the slash command to surface at the top of the review.

type PRUpdateResult added in v0.3.0

type PRUpdateResult struct {
	Updated           bool
	URL               string
	Number            int
	ValidationErr     string
	GitHubUnavailable bool
	NotFound          bool
	GitHubError       string
}

PRUpdateResult is the typed envelope UpdatePR returns. Same shape rationale as PRCreateResult: callers branch on typed fields. Reason discriminates the failure mode so the procedural /git-update-pr handles each branch differently.

func UpdatePR added in v0.3.0

UpdatePR is the deterministic core of pr_update. Validates title and body *before* dialing the Interface, so oversize titles and empty bodies never reach the network. Returns a typed PRUpdateResult; the tool wrapper renders it for model consumption.

The Interface's ErrPRNotFound and ErrGitHubUnavailable get folded into typed envelope fields so callers branch on flags rather than err strings.

type PRWatchChecksSnapshot added in v0.4.0

type PRWatchChecksSnapshot struct {
	Ref                string
	NotFound           bool
	GitHubUnavailable  bool
	TimedOut           bool
	AllSuccess         bool
	Failed             bool
	FetchErr           string
	FailedLogsFetchErr string
	PR                 github.PRDetails
	Checks             []github.CheckRun
	FailingChecks      []string
	FailedLogs         github.FailedWorkflowLogsResult
}

func WatchPRChecks added in v0.4.0

func WatchPRChecks(ctx context.Context, client github.Interface, opts PRWatchOptions) (PRWatchChecksSnapshot, error)

type PRWatchChecksTool added in v0.4.0

type PRWatchChecksTool struct {
	Cwd *CwdRef
	GH  github.Interface
}

PRWatchChecksTool waits for a PR's checks to reach a useful terminal state. It replaces shell pipelines such as `gh run watch ...; gh run view --log-failed | tail` with a bounded, read-only typed GitHub workflow.

func (*PRWatchChecksTool) Description added in v0.4.0

func (t *PRWatchChecksTool) Description() string

func (*PRWatchChecksTool) Execute added in v0.4.0

func (t *PRWatchChecksTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*PRWatchChecksTool) Name added in v0.4.0

func (t *PRWatchChecksTool) Name() string

func (*PRWatchChecksTool) PreviewCall added in v0.4.0

func (t *PRWatchChecksTool) PreviewCall(argsJSON string) string

func (*PRWatchChecksTool) RequiresApproval added in v0.4.0

func (t *PRWatchChecksTool) RequiresApproval(string) bool

func (*PRWatchChecksTool) Schema added in v0.4.0

func (t *PRWatchChecksTool) Schema() map[string]any

type PRWatchOptions added in v0.4.0

type PRWatchOptions struct {
	Ref          string
	Timeout      time.Duration
	PollInterval time.Duration
	LogTailLines int
}

type ParallelSafeTool

type ParallelSafeTool interface {
	ParallelSafe(argsJSON string) bool
}

ParallelSafeTool is an optional capability marker for tools that can run concurrently with other read-only tool calls from the same assistant message. Keep this narrow and explicit: a false negative only costs some latency, but a false positive can create hard-to-debug races.

type PatchFailureKind added in v0.4.0

type PatchFailureKind string
const (
	PatchFailureUnknown   PatchFailureKind = "unknown"
	PatchFailureMalformed PatchFailureKind = "malformed"
	PatchFailureStale     PatchFailureKind = "stale"
)

func ClassifyPatchFailure added in v0.4.0

func ClassifyPatchFailure(output string) PatchFailureKind

ClassifyPatchFailure gives all user-facing surfaces the same patch-error vocabulary. The apply_diff tool and TUI cards both see either preflight errors or git-apply stderr; keeping the classifier here prevents their malformed/stale wording from drifting as new git diagnostics are observed.

type PathTrustElevationNeeded added in v0.3.0

type PathTrustElevationNeeded struct {
	ToolName     string
	Path         string
	Cwd          string
	AllowedRoots []string
	ArgsJSON     string
}

PathTrustElevationNeeded fires when a mutating tool's ValidateWritePath rejects a target as outside the workspace (Cwd + AllowedPaths). The TUI catches this via its existing decisions channel and renders the inline path-trust elevation modal — see yottacode-roadmap/folder-trust.md "Prompt 2."

The loop blocks on the decisions channel exactly like ApprovalNeeded. Expected replies:

  • PathAllowOnce: consumer added Path to the session allow list; loop re-runs Execute once.
  • PathTrustSession: consumer added filepath.Dir(Path) to the session allow list; loop re-runs Execute once.
  • Deny: loop surfaces the structured error to the model as the tool result (Claude-style per-tool deny: descriptive + with a recovery hint).

Cwd and AllowedRoots are echoed so the modal can render the existing trust state next to the new request without re-walking LoopConfig.

type PlanEntry added in v0.2.0

type PlanEntry struct {
	Slug     string
	Path     string
	Modified time.Time
	Size     int64
}

PlanEntry describes one plan file on disk for the picker + CLI resume flow. Slug is the basename without the `.md` suffix (matches the format SlugFromPrompt produces).

func ListPlans added in v0.2.0

func ListPlans() ([]PlanEntry, error)

ListPlans enumerates plan files under PlansDir() and returns them sorted by modified-time descending (newest first). Missing directory returns (nil, nil) — a fresh install has no plans yet and that's not an error.

func MatchPlan added in v0.2.0

func MatchPlan(plans []PlanEntry, query string) *PlanEntry

MatchPlan returns the first plan whose slug contains the query (case-insensitive substring match). Plans must already be sorted newest-first — typical usage is ListPlans → MatchPlan, so the most recent match wins on ties. Returns nil when nothing matches; the caller renders the list to help the user pick a real slug.

type PlanModeState added in v0.2.0

type PlanModeState struct {
	Active   atomic.Bool
	PlanFile string
}

PlanModeState is the per-session, runtime-mutable plan-mode flag the loop reads on every tool dispatch and prompt assembly. The TUI flips `Active` from the main goroutine via /plan or Shift+Tab while the agent goroutine reads it inside executeToolCall and streamIteration — atomic.Bool keeps that benign race detector-clean.

The pointer is shared between LoopConfig and the TUI Model, so a flip in cmd_plan.go takes effect on the very next iteration with no reconstruction or message rewriting. PlanFile is set when entering plan mode (from `/plan <topic>` arg or the first user message) and kept stable for the lifetime of the active plan. Until it's set, writes to the plan file are blocked — the gate compares against PlanFile and an empty string never matches a real path.

func (*PlanModeState) IsActive added in v0.2.0

func (p *PlanModeState) IsActive() bool

IsActive is a nil-safe check used by the loop.

type PlanStore added in v0.2.0

type PlanStore struct {
	// contains filtered or unexported fields
}

PlanStore is the session-scoped owner of the current todo list. The TodoWriteTool replaces the list wholesale on each call; the agent loop reads the snapshot to emit a TodoUpdate event; the TUI renders from that event; session save/load copies the slice in/out for cross-session persistence.

func NewPlanStore added in v0.2.0

func NewPlanStore() *PlanStore

func (*PlanStore) Replace added in v0.2.0

func (p *PlanStore) Replace(items []Todo)

Replace overwrites the list with the given items. The caller is responsible for validation (TodoWriteTool.Execute does it before reaching here).

func (*PlanStore) Snapshot added in v0.2.0

func (p *PlanStore) Snapshot() []Todo

Snapshot returns a copy of the current todo list. Safe for the caller to retain — the returned slice does not alias the store's internal state.

type ProviderToolCall

type ProviderToolCall struct {
	ToolName string
	Phase    string
	Detail   string
}

ProviderToolCall carries a provider-native tool lifecycle update emitted by the adapter stream itself, e.g. OpenAI/xAI web search or code interpreter.

type PushResult added in v0.3.0

type PushResult struct {
	Pushed      bool
	Branch      string
	SetUpstream bool   // true when the push added -u origin HEAD
	GitOutput   string // verbatim stdout+stderr from git, capped
	GitError    string // populated when git exited non-zero
	Detached    bool   // true when HEAD is detached (no branch)
	PRURL       string // best-effort: populated when a PR exists for the branch
	PRNumber    int    // populated alongside PRURL
}

PushResult is the typed envelope the tool returns. Same shape rationale as CommitResult / PRCreateResult: callers branch on typed fields rather than parsing err strings. Reason discriminates the failure mode so the slash directive can route each branch to the right surface.

func PushBranch added in v0.3.0

func PushBranch(ctx context.Context, cwd string, client github.Interface) (PushResult, error)

PushBranch is the deterministic core of git_push. Returns a typed PushResult; errors return only on infrastructure failures (git binary missing, etc.). Detached-HEAD, missing remote, and authentication failures populate the envelope.

The PR lookup is best-effort: a missing PR or an unreachable github.Interface leaves PRURL empty and never blocks the push result. The push itself is the load-bearing piece.

type ReadDocumentTool added in v0.4.0

type ReadDocumentTool struct {
	Cwd           *CwdRef
	DenyReadPaths []string

	// Registry is the format dispatch table. Nil uses the production
	// registry (CSV/TSV/JSON/JSONL/XML/HTML, plus PDF when Sandbox lets
	// pdftotext/pdfinfo run); tests can inject a fake.
	Registry *documents.Registry

	// Sandbox is nil-safe: a nil Sandbox behaves exactly like HostSandbox,
	// mirroring RunBashTool.Sandbox and CreateDocumentTool.Sandbox. Only
	// consulted for PDF and docx's optional pandoc tier — every other
	// format (and docx's own native fallback) is pure Go and never
	// shells out.
	Sandbox Sandbox
}

ReadDocumentTool extracts bounded, provenance-labeled text from CSV, TSV, JSON, JSONL, XML, and HTML files — a structured alternative to read_file for these formats. Where read_file returns a raw cat -n dump (which shears a CSV field's embedded newline into a bogus extra row, and dumps HTML/XML markup noise verbatim), read_document parses the format properly and returns a structure summary plus a bounded, row/record-aligned preview.

Read-only, no approval — same trust posture as read_file. Path validation and the credential-path denylist happen here, at the agent-tool boundary; internal/documents itself is a pure content library with no notion of cwd or trust.

func (*ReadDocumentTool) Description added in v0.4.0

func (t *ReadDocumentTool) Description() string

func (*ReadDocumentTool) Execute added in v0.4.0

func (t *ReadDocumentTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ReadDocumentTool) Name added in v0.4.0

func (t *ReadDocumentTool) Name() string

func (*ReadDocumentTool) ParallelSafe added in v0.4.0

func (t *ReadDocumentTool) ParallelSafe(string) bool

func (*ReadDocumentTool) PreviewCall added in v0.4.0

func (t *ReadDocumentTool) PreviewCall(argsJSON string) string

func (*ReadDocumentTool) RequiresApproval added in v0.4.0

func (t *ReadDocumentTool) RequiresApproval(string) bool

func (*ReadDocumentTool) Schema added in v0.4.0

func (t *ReadDocumentTool) Schema() map[string]any

type ReadFileTool

type ReadFileTool struct {
	Cwd            *CwdRef
	DenyReadPaths  []string
	SupportsImages bool
}

ReadFileTool lets the model fetch local file contents. Read-only, no approval. DenyReadPaths blocks a small set of credential-bearing locations (see DefaultDenyReadPaths) so prompt injection can't silently exfiltrate keys; everything else is fair game.

func (*ReadFileTool) Description

func (t *ReadFileTool) Description() string

func (*ReadFileTool) Execute

func (t *ReadFileTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ReadFileTool) ExecuteMultimodal added in v0.3.0

func (t *ReadFileTool) ExecuteMultimodal(ctx context.Context, argsJSON string) (MultimodalResult, error)

func (*ReadFileTool) Name

func (t *ReadFileTool) Name() string

func (*ReadFileTool) ParallelSafe

func (t *ReadFileTool) ParallelSafe(string) bool

func (*ReadFileTool) PreviewCall

func (t *ReadFileTool) PreviewCall(argsJSON string) string

func (*ReadFileTool) RequiresApproval

func (t *ReadFileTool) RequiresApproval(string) bool

func (*ReadFileTool) Schema

func (t *ReadFileTool) Schema() map[string]any

type ReadManyFilesTool

type ReadManyFilesTool struct {
	Cwd           *CwdRef
	DenyReadPaths []string
}

func (*ReadManyFilesTool) Description

func (t *ReadManyFilesTool) Description() string

func (*ReadManyFilesTool) Execute

func (t *ReadManyFilesTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*ReadManyFilesTool) Name

func (t *ReadManyFilesTool) Name() string

func (*ReadManyFilesTool) ParallelSafe

func (t *ReadManyFilesTool) ParallelSafe(string) bool

func (*ReadManyFilesTool) PreviewCall

func (t *ReadManyFilesTool) PreviewCall(argsJSON string) string

func (*ReadManyFilesTool) RequiresApproval

func (t *ReadManyFilesTool) RequiresApproval(string) bool

func (*ReadManyFilesTool) Schema

func (t *ReadManyFilesTool) Schema() map[string]any

type ReasoningToken

type ReasoningToken struct{ Text string }

ReasoningToken carries one chunk of "thinking" output from a reasoning model (Qwen 3, DeepSeek R1). Render dimmed.

type RecallHit added in v0.3.0

type RecallHit struct {
	SessionID   string
	SessionName string
	Model       string
	Created     time.Time
	Role        string
	Snippet     string
}

RecallHit mirrors recall.Hit without importing the recall package (which would create an import cycle via session → agent).

type RecallSearcher added in v0.3.0

type RecallSearcher interface {
	Search(query string, limit int) ([]RecallHit, error)
}

RecallSearcher is the interface the session_recall tool needs from the recall index. Satisfied by *recall.Index — wired in run.go via a thin adapter so the agent package stays cycle-free.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry owns the set of tools exposed to a given agent run.

Concurrency: the agent loop's goroutine calls Get to dispatch each tool invocation while the TUI goroutine may concurrently mutate the set (the /mcp restart path calls Deregister followed by Register on the fresh client's tool catalog). A concurrent map read+write is a Go runtime panic — not just inconsistent state — so every entry point takes the mutex. Lock granularity is the whole map: the expected mid-session mutation rate is so low (slash commands, not per-turn) that fine-grained locking would only add complexity for no measurable win.

func NewRegistry

func NewRegistry() *Registry

func (*Registry) AsAdapterTools

func (r *Registry) AsAdapterTools() []adapter.Tool

AsAdapterTools converts the registry into the schema shape the adapter advertises to the model. Equivalent to AsAdapterToolsFiltered(nil) — every registered tool is exposed.

func (*Registry) AsAdapterToolsFiltered added in v0.2.0

func (r *Registry) AsAdapterToolsFiltered(filter func(name string) bool) []adapter.Tool

AsAdapterToolsFiltered is the gated variant: when filter is non-nil and returns false for a tool name, that tool is omitted from the advertised schema. Used by the loop to hide `exit_plan_mode` outside of plan mode — without the filter the model could synthesize the call out of context and confuse the user with an approval card for a plan that doesn't exist. Pure read-side filter; the registry's own map is unchanged so Get() still resolves the tool when (legitimately) called.

func (*Registry) Deregister added in v0.3.0

func (r *Registry) Deregister(name string) bool

Deregister removes a tool by name. Returns true when a tool was actually removed, false when no such name was registered. Used by the MCP /mcp restart path to drop stale tools before re-registering the post-restart generation — without it, tools that disappear after a server restart would linger in the registry and surface as "missing client" errors on first invocation.

Safe to call mid-session: tools currently executing aren't affected (they hold their own receiver), only future Get() lookups miss the removed name.

func (*Registry) Get

func (r *Registry) Get(name string) (Tool, bool)

func (*Registry) Names added in v0.2.0

func (r *Registry) Names() map[string]bool

Names returns the set of registered tool names. Useful for callers that need to validate references (e.g. subagent allowlists) without caring about the Tool values themselves.

func (*Registry) Register

func (r *Registry) Register(t Tool)

func (*Registry) Tools added in v0.2.0

func (r *Registry) Tools() []Tool

Tools returns every registered Tool. The order is non-deterministic (map iteration). Subagent registry construction uses this to clone the parent's toolset while applying an allowlist filter — see internal/agent/agent_tool.go. Read-only on the registry: callers must not mutate the returned tools.

type Risk

type Risk int

Risk classifies how dangerous a command segment looks at a glance. Used by the approval modal to color-code parts of a compound command so users can see destructive segments without parsing the whole line.

const (
	RiskNone Risk = iota
	RiskCaution
	RiskDestructive
)

func AssessRisk

func AssessRisk(segment string) (Risk, string)

AssessRisk classifies a single segment. Returns RiskNone for boring commands; RiskCaution for things worth a glance; RiskDestructive for patterns that almost always end in tears if mistakenly approved. The reason string is human-readable for display next to the segment.

func (Risk) String

func (r Risk) String() string

type RollbackTool

type RollbackTool struct {
	Cwd        *CwdRef
	LSPManager *lspci.Manager
}

func (*RollbackTool) Description

func (t *RollbackTool) Description() string

func (*RollbackTool) Execute

func (t *RollbackTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*RollbackTool) Name

func (t *RollbackTool) Name() string

func (*RollbackTool) PreviewCall

func (t *RollbackTool) PreviewCall(argsJSON string) string

func (*RollbackTool) RequiresApproval

func (t *RollbackTool) RequiresApproval(string) bool

func (*RollbackTool) Schema

func (t *RollbackTool) Schema() map[string]any

type RunBashTool

type RunBashTool struct {
	Cwd *CwdRef
	// Sandbox is nil-safe: a nil Sandbox behaves exactly like HostSandbox,
	// so every call site that doesn't set it keeps today's behavior.
	Sandbox Sandbox
}

RunBashTool runs a shell command in cwd via /bin/sh -c. Always requires approval. Command execution routes through Sandbox — nil selects HostSandbox (today's direct-on-host behavior); a config/experimental-flag gated PodmanSandbox (internal/sandbox) provides real isolation.

func (*RunBashTool) Description

func (t *RunBashTool) Description() string

func (*RunBashTool) Execute

func (t *RunBashTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*RunBashTool) Name

func (t *RunBashTool) Name() string

func (*RunBashTool) PreviewCall

func (t *RunBashTool) PreviewCall(argsJSON string) string

func (*RunBashTool) RequiresApproval

func (t *RunBashTool) RequiresApproval(string) bool

func (*RunBashTool) Schema

func (t *RunBashTool) Schema() map[string]any

type RunTestsTool

type RunTestsTool struct{ Cwd *CwdRef }

func (*RunTestsTool) Description

func (t *RunTestsTool) Description() string

func (*RunTestsTool) Execute

func (t *RunTestsTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*RunTestsTool) Name

func (t *RunTestsTool) Name() string

func (*RunTestsTool) PreviewCall

func (t *RunTestsTool) PreviewCall(argsJSON string) string

func (*RunTestsTool) RequiresApproval

func (t *RunTestsTool) RequiresApproval(string) bool

func (*RunTestsTool) Schema

func (t *RunTestsTool) Schema() map[string]any

type Sandbox added in v0.4.0

type Sandbox interface {
	// Command returns the *exec.Cmd that will run `command` (a shell
	// command line interpreted by /bin/sh -c) with working directory cwd.
	// Callers set Stdout/Stderr and call Run/Start themselves.
	Command(ctx context.Context, command, cwd string) *exec.Cmd

	// Label identifies the backend for scrollback annotation. Contract a
	// new implementation must follow for the tag to actually render:
	//   - HostSandbox{}.Label() ("[no sandbox]") is the one value
	//     RunBashTool.PreviewCall treats as "don't prepend anything" —
	//     don't reuse it for a real backend, or its tag silently vanishes.
	//   - Every other label must be the exact form "[name]" — a leading
	//     "[", the name, trailing "]", NO trailing space (PreviewCall adds
	//     the separating space itself: `sb.Label() + " " + preview`).
	//     PreviewCall's output is then what the TUI's toolHeader
	//     (tool_card.go) recovers the tag from, by scanning for a leading
	//     "[...] " rather than through a structured field — a label
	//     outside this shape degrades safely (the tag is silently dropped
	//     from the card header) but never renders. See
	//     tool_card_test.go's TestToolHeader_RunBashCarriesSandboxTag.
	Label() string

	// Close tears down any backing resources (e.g. a session container).
	// Called once at session/worker teardown.
	Close() error
}

Sandbox is the command-execution seam RunBashTool routes every command through. Constructed once per session (or once per dispatch write-worker) and shared across every tool call built from that cwd — never rebuilt per call, so a container-backed implementation can stay session-scoped (podman exec per command, not podman run --rm per command).

The hardline blocklist (IsHardlineCommand) is checked by RunBashTool BEFORE Command is ever called, and stays that way regardless of which Sandbox is active — it is not part of this seam.

type SandboxFactory added in v0.4.0

type SandboxFactory func(ctx context.Context, wtDir, taskID string) (Sandbox, error)

SandboxFactory constructs a fresh, worker-scoped Sandbox for a dispatch write-worker's isolated git worktree. wtDir is the worker's worktree root (its mount point, if the returned Sandbox is container-backed); taskID identifies the worker for container naming/logging.

type SessionRecallTool added in v0.3.0

type SessionRecallTool struct {
	Searcher RecallSearcher
}

SessionRecallTool lets the agent search across past sessions via the FTS5 index. The agent uses this to pull in context from prior conversations — "I think we discussed authentication before" — or to check whether an issue was already resolved in a previous session, without the user having to invoke /recall manually.

func (*SessionRecallTool) Description added in v0.3.0

func (t *SessionRecallTool) Description() string

func (*SessionRecallTool) Execute added in v0.3.0

func (t *SessionRecallTool) Execute(_ context.Context, argsJSON string) (string, error)

func (*SessionRecallTool) Name added in v0.3.0

func (t *SessionRecallTool) Name() string

func (*SessionRecallTool) ParallelSafe added in v0.3.0

func (t *SessionRecallTool) ParallelSafe(string) bool

func (*SessionRecallTool) PreviewCall added in v0.3.0

func (t *SessionRecallTool) PreviewCall(argsJSON string) string

func (*SessionRecallTool) RequiresApproval added in v0.3.0

func (t *SessionRecallTool) RequiresApproval(string) bool

func (*SessionRecallTool) Schema added in v0.3.0

func (t *SessionRecallTool) Schema() map[string]any

type SkillTool added in v0.3.0

type SkillTool struct {

	// All is the full resolved set loaded at session start (built-in +
	// user + project). Reassigned only by SetAll (install/uninstall
	// reload). The TUI's /skills picker uses this as the universe to
	// render rows against. Read it through the SetAll lock when on a
	// goroutine other than the one that owns the field.
	All []skills.Skill
	// contains filtered or unexported fields
}

SkillTool is the model-facing entry point for the Agent Skills surface. The LLM picks a skill by name from the description-matched list it sees in the system prompt, calls `Skill(skill="<name>")`, and receives the skill's full body as the tool result. The model then continues the turn with the skill's guidance loaded.

Skills are loaded once at session start (built-in + user + project, project shadows user shadows built-in) and the slice is stable for the session. A `/skills` reload command is a v1.1 follow-up.

func (*SkillTool) Active added in v0.3.0

func (t *SkillTool) Active() []skills.Skill

Active returns the subset of All currently enabled, in input order. Used by callers that need to recompute prompt sections or slash dispatch around the active set.

func (*SkillTool) Description added in v0.3.0

func (t *SkillTool) Description() string

Description lists every skill's name + description so the model can pick by keyword match. Spec calls this the "metadata" tier of progressive disclosure — small, always loaded; bodies stay out until activation.

func (*SkillTool) Disable added in v0.4.0

func (t *SkillTool) Disable(name string)

Disable marks the named skill as not exposed without disturbing the rest of the enablement set. If the tool is still in the nil "all enabled" state, it first materializes every current skill except name as explicitly enabled so the disable survives future prompt recomposition.

func (*SkillTool) Enable added in v0.3.0

func (t *SkillTool) Enable(name string)

Enable marks the named skill as exposed without disturbing the rest of the enablement set. Used by install paths so a just-installed skill is immediately visible — installing something strongly implies "I want to use this," and forcing a second trip through the picker for a checkbox was its own usability bug.

func (*SkillTool) Execute added in v0.3.0

func (t *SkillTool) Execute(_ context.Context, argsJSON string) (string, error)

Execute returns the named skill's body so the model can fold it into the next iteration. An unknown skill name returns a recoverable error string the model can react to (suggest a near match, ask the user, or give up) — same pattern AgentTool uses for unknown subagent_type.

func (*SkillTool) IsEnabled added in v0.3.0

func (t *SkillTool) IsEnabled(name string) bool

IsEnabled reports whether the named skill is currently exposed. A nil enablement map means everything is enabled (the default).

func (*SkillTool) Name added in v0.3.0

func (t *SkillTool) Name() string

func (*SkillTool) ParallelSafe added in v0.3.0

func (t *SkillTool) ParallelSafe(string) bool

ParallelSafe so a model can grab multiple complementary skills in one assistant message (e.g. `diagnose` + `verification-before-completion` for a bug fix). Each call is a pure read of an embedded string; concurrent calls have no shared mutable state.

func (*SkillTool) PreviewCall added in v0.3.0

func (t *SkillTool) PreviewCall(argsJSON string) string

func (*SkillTool) RequiresApproval added in v0.3.0

func (t *SkillTool) RequiresApproval(string) bool

RequiresApproval is always false — loading a playbook into the model's context is just text injection. Any mutating action the skill's body recommends still flows through the *underlying* tool's own approval gate (run_bash, write_file, etc.).

func (*SkillTool) Schema added in v0.3.0

func (t *SkillTool) Schema() map[string]any

func (*SkillTool) SetAll added in v0.3.0

func (t *SkillTool) SetAll(all []skills.Skill)

SetAll replaces the resolved skill universe under the write lock. The install/uninstall reload path calls this from the TUI goroutine while the agent goroutine may be reading All via Active(); a direct field write would race that read.

func (*SkillTool) SetEnabled added in v0.3.0

func (t *SkillTool) SetEnabled(names map[string]bool)

SetEnabled installs the per-session enablement set. Passing nil resets to "all enabled". Names that aren't in All are ignored. The SkillTool's Description() reads through this filter so the model only sees the active skills on each turn.

type StreamProgress

type StreamProgress struct{}

StreamProgress is a heartbeat for adapter-side stream activity that has no visible text — currently emitted by the OpenAI Responses adapter on each `function_call_arguments.delta`. The TUI uses this to keep the live "tok/s" indicator moving on turns that produce only a tool call (no reasoning summary, no body text) so the row doesn't sit at "0.0 tok/s" the whole time.

type Streamer

type Streamer interface {
	ChatStream(ctx context.Context, messages []adapter.Message, tools []adapter.Tool) <-chan adapter.StreamEvent
}

Streamer is the slice of the adapter the loop actually depends on. Defining it here (instead of pulling in the concrete *adapter.Adapter) lets tests substitute a scripted implementation without standing up an HTTP server.

type SubagentBackgroundDone added in v0.2.0

type SubagentBackgroundDone struct {
	TaskID     string
	AgentType  string
	Result     string
	Errored    bool
	Duration   time.Duration
	TokensUsed int
	ToolCalls  int    // child's tool-call count, for inline stats rendering
	Model      string // model the child ran on when task-routed; "" = inherited the parent's model
	// NotifyOnDone mirrors the spawning Agent call's notify_on_done: when
	// true the TUI wakes the model with this result (starts a turn that
	// injects it) instead of only painting the completion banner.
	NotifyOnDone bool
	// Branch / BatchID are populated for dispatch background workers.
	Branch  string
	BatchID string
	// Committed / CommitSHA / CommitErr report what the worker left on its
	// branch — so the async banner doesn't imply integrate-ready work when
	// the branch is empty or the commit was rejected. Committed is true when
	// CommitSHA is set (base..branch has commits). CommitErr carries a
	// one-line reason when a write worker produced no committable branch
	// (hook/lint rejection, staging failure, or an errored worker that left
	// uncommitted work in its worktree). All empty for read-only workers.
	Committed bool
	CommitSHA string
	CommitErr string
	// Reclaimed is true when the worker's worktree+branch were removed at
	// the end of its run because they held nothing (no commits beyond the
	// dispatch base, clean tree) — so the banner can explain why the named
	// branch no longer exists.
	Reclaimed bool
}

SubagentBackgroundDone fires asynchronously when a background subagent completes after the parent turn has already ended. The TUI surfaces this as a card on the next idle redraw / via /subagents list. Oneshot rejects background invocations entirely so this event is unreachable from non-interactive contexts.

type SubagentDone added in v0.2.0

type SubagentDone struct {
	TaskID     string
	AgentType  string
	Result     string
	Errored    bool
	Duration   time.Duration
	TokensUsed int
	ToolCalls  int    // child's tool-call count, for inline stats rendering
	Model      string // model the child ran on when task-routed; "" = inherited the parent's model
	// Branch / BatchID mirror SubagentStart for dispatch worktree-subtasks.
	Branch  string
	BatchID string
}

SubagentDone fires when a foreground subagent completes. The Result is the child's final assistant message — that same string is also returned synchronously from the Agent tool's Execute, so the parent's model receives it as a normal tool result. SubagentDone is for the UI side of the picture: it lets the TUI close the "subagent running" card and oneshot print a final status line.

type SubagentProgress added in v0.2.0

type SubagentProgress struct {
	TaskID    string
	AgentType string
	Activity  string
}

SubagentProgress is the parent-visible activity stream for a running subagent — typically "Explore: read_file internal/foo.go" or "Plan: grep TODO". The child's raw ContentToken/ReasoningToken events are deliberately NOT forwarded; only high-level tool-level activity reaches the parent, which keeps the parent's UI uncluttered AND keeps the child's reasoning out of the parent's adapter context.

type SubagentStart added in v0.2.0

type SubagentStart struct {
	TaskID         string
	AgentType      string
	Prompt         string
	Background     bool
	TranscriptPath string
	// Branch / BatchID are populated for dispatch worktree-subtasks: the
	// git branch the child commits to, and the id grouping a dispatch
	// batch's children. Empty for standalone Agent dispatches.
	Branch  string
	BatchID string
}

SubagentStart fires when the Agent tool begins a child Turn. The parent's TUI/oneshot renders this as a short header so the user can see that delegation is happening; the child's transcript file at TranscriptPath captures everything that happens inside the child.

type SyntaxRangeTool added in v0.4.0

type SyntaxRangeTool struct {
	Cwd           *CwdRef
	DenyReadPaths []string
}

SyntaxRangeTool exposes parser-backed enclosing ranges without starting a language server. Agents use the returned anchor_read hints to re-read the chosen range with anchors before applying edit_anchored.

func (*SyntaxRangeTool) Description added in v0.4.0

func (t *SyntaxRangeTool) Description() string

func (*SyntaxRangeTool) Execute added in v0.4.0

func (t *SyntaxRangeTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*SyntaxRangeTool) Name added in v0.4.0

func (t *SyntaxRangeTool) Name() string

func (*SyntaxRangeTool) ParallelSafe added in v0.4.0

func (t *SyntaxRangeTool) ParallelSafe(string) bool

func (*SyntaxRangeTool) PreviewCall added in v0.4.0

func (t *SyntaxRangeTool) PreviewCall(argsJSON string) string

func (*SyntaxRangeTool) RequiresApproval added in v0.4.0

func (t *SyntaxRangeTool) RequiresApproval(string) bool

func (*SyntaxRangeTool) Schema added in v0.4.0

func (t *SyntaxRangeTool) Schema() map[string]any

type Todo added in v0.2.0

type Todo struct {
	Content string     `json:"content"`
	Status  TodoStatus `json:"status"`
}

Todo is one item in the agent's working plan. Content is the human-readable description; Status is one of the lifecycle values above. There is intentionally no stable ID — the model passes the full list every call, so identity is positional and renames are indistinguishable from delete+add (matching Claude's shape).

type TodoStatus added in v0.2.0

type TodoStatus string

TodoStatus is the lifecycle state of a single todo item. The three core values mirror Claude Code's TodoWrite contract so the model has a familiar schema target. skipped is yottacode-specific: it lets the agent explicitly abandon obsolete plan items instead of leaving them pending.

const (
	TodoPending    TodoStatus = "pending"
	TodoInProgress TodoStatus = "in_progress"
	TodoCompleted  TodoStatus = "completed"
	TodoSkipped    TodoStatus = "skipped"
)

type TodoUpdate added in v0.2.0

type TodoUpdate struct{ Todos []Todo }

TodoUpdate fires after a tool implementing the planAware interface (TodoWriteTool today) finishes, carrying the new full snapshot of the working plan. The TUI renders this as a scrollback card showing the current list with status markers; oneshot prints a one-liner on stderr. The slice is a copy — consumers may retain it.

type TodoWriteTool added in v0.2.0

type TodoWriteTool struct {
	Store *PlanStore
}

TodoWriteTool is the yottacode analogue of Claude Code's TodoWrite: a model-callable tool that replaces the working plan on every call, with one item allowed to be `in_progress` at a time. Rendering and persistence happen one layer out — this tool just owns the validated write into the PlanStore. The loop notices the write via the planAware interface (see loop.go) and emits a TodoUpdate event for the TUI.

func (*TodoWriteTool) Description added in v0.2.0

func (t *TodoWriteTool) Description() string

func (*TodoWriteTool) Execute added in v0.2.0

func (t *TodoWriteTool) Execute(_ context.Context, argsJSON string) (string, error)

func (*TodoWriteTool) Name added in v0.2.0

func (t *TodoWriteTool) Name() string

func (*TodoWriteTool) PlanStore added in v0.2.0

func (t *TodoWriteTool) PlanStore() *PlanStore

PlanStore exposes the underlying store so the agent loop can snapshot the list after this tool runs and emit a TodoUpdate event. Satisfies the unexported planAware interface in loop.go.

func (*TodoWriteTool) PreviewCall added in v0.2.0

func (t *TodoWriteTool) PreviewCall(argsJSON string) string

func (*TodoWriteTool) RequiresApproval added in v0.2.0

func (t *TodoWriteTool) RequiresApproval(string) bool

RequiresApproval is always false: this tool has no filesystem, network, or external side effects — it's purely a visibility primitive that updates a per-session in-memory list. Matches Claude Code's TodoWrite posture exactly: real safety comes from the per-mutation prompts on edit_file, write_file, run_bash, etc., not from gating the plan itself.

func (*TodoWriteTool) Schema added in v0.2.0

func (t *TodoWriteTool) Schema() map[string]any

type Tool

type Tool interface {
	Name() string
	Description() string
	Schema() map[string]any
	RequiresApproval(argsJSON string) bool
	PreviewCall(argsJSON string) string
	Execute(ctx context.Context, argsJSON string) (string, error)
}

Tool is one capability the agent can invoke. Execute receives the raw JSON arguments the model emitted; tools parse them internally so the registry stays schema-agnostic.

RequiresApproval takes the argsJSON because some tools (e.g. the unified git tool) decide policy based on the specific subcommand: `git status` auto-executes, `git push --force` prompts. Tools that don't care about args may ignore the parameter.

type ToolResult

type ToolResult struct {
	ToolName string
	Output   string
	Errored  bool
}

ToolResult fires after the tool finishes. Output is the string the model will see; Errored signals whether it was a tool-level error vs. success.

type ToolStart

type ToolStart struct {
	ToolName string
	Preview  string
	ArgsJSON string
}

ToolStart fires immediately before a tool's Execute is called (after any approval flow has resolved). The consumer can render this as a status line. ArgsJSON carries the raw tool-call arguments so consumers can do structured rendering (e.g., the TUI's edit_file diff card) without parsing the human-friendly Preview string.

type TurnDone

type TurnDone struct{}

TurnDone fires when the turn completes cleanly (no more tool calls, no error, not at iter cap). The consumer can re-enable input.

type TurnInterrupted added in v0.2.0

type TurnInterrupted struct {
	// PartialContent is the assistant text that streamed before the
	// cancel, already appended to history. Carried in the event so the
	// TUI can render a one-line snippet without re-walking history.
	PartialContent string
	// OrphanedCalls counts tool_use entries in the just-cancelled batch
	// that received synthetic results (i.e. were never actually run or
	// did not produce real output). Zero when the cancel landed mid-
	// stream before any tool call started.
	OrphanedCalls int
	// Explicit reports whether the user intentionally stopped the turn. False
	// covers non-fatal internal cancellation paths where consumers should stay quiet.
	Explicit bool
}

TurnInterrupted fires when the turn ended via user-initiated context cancellation (Esc/Ctrl+C or an explicit turn-canceling command mid-turn) rather than an error or a clean finish. By the time this event lands, the loop has already preserved history correctness: any tokens that streamed before the cancel are appended as a content-only assistant message, and any in-flight or pending tool_calls in the current batch get synthetic "interrupted by user" tool_result entries so no tool_use is left orphaned for the next request. Consumers should render this as a calm marker, not an error — the turn was cut on purpose.

type UserMessageAppended added in v0.3.0

type UserMessageAppended struct{ Content string }

UserMessageAppended fires when a user message queued via UserMessages is injected into history between tool rounds. The TUI renders a "[delivered]" receipt so the user knows the model will see it on the next iteration.

type WebSearchTool added in v0.3.0

type WebSearchTool struct{}

WebSearchTool provides web search for models whose provider lacks a native web_search built-in (Ollama, NVIDIA NIM, OpenAI-compatible endpoints, etc.). Queries DuckDuckGo's HTML endpoint and returns parsed results.

func (*WebSearchTool) Description added in v0.3.0

func (t *WebSearchTool) Description() string

func (*WebSearchTool) Execute added in v0.3.0

func (t *WebSearchTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*WebSearchTool) Name added in v0.3.0

func (t *WebSearchTool) Name() string

func (*WebSearchTool) ParallelSafe added in v0.3.0

func (t *WebSearchTool) ParallelSafe(string) bool

func (*WebSearchTool) PreviewCall added in v0.3.0

func (t *WebSearchTool) PreviewCall(argsJSON string) string

func (*WebSearchTool) RequiresApproval added in v0.3.0

func (t *WebSearchTool) RequiresApproval(string) bool

func (*WebSearchTool) Schema added in v0.3.0

func (t *WebSearchTool) Schema() map[string]any

type WorktreeStatusTool added in v0.3.0

type WorktreeStatusTool struct {
	Cwd *CwdRef
}

WorktreeStatusTool reports the clean/dirty state of a yottacode- managed worktree without entering it. Useful when the agent has multiple worktrees in flight and wants to decide which one to resume work in, or whether a sibling is safe to remove.

Read-only and parallel-safe — never modifies anything.

func (*WorktreeStatusTool) Description added in v0.3.0

func (t *WorktreeStatusTool) Description() string

func (*WorktreeStatusTool) Execute added in v0.3.0

func (t *WorktreeStatusTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*WorktreeStatusTool) Name added in v0.3.0

func (t *WorktreeStatusTool) Name() string

func (*WorktreeStatusTool) ParallelSafe added in v0.3.0

func (t *WorktreeStatusTool) ParallelSafe(string) bool

func (*WorktreeStatusTool) PreviewCall added in v0.3.0

func (t *WorktreeStatusTool) PreviewCall(argsJSON string) string

func (*WorktreeStatusTool) RequiresApproval added in v0.3.0

func (t *WorktreeStatusTool) RequiresApproval(string) bool

func (*WorktreeStatusTool) Schema added in v0.3.0

func (t *WorktreeStatusTool) Schema() map[string]any

type WriteFileTool

type WriteFileTool struct {
	Cwd        *CwdRef
	WriteOpts  WritePathOptions
	LSPManager *lspci.Manager
	LSPServers map[string][]string
}

WriteFileTool creates or overwrites a file. Always needs approval; the WriteOpts validator pre-rejects out-of-cwd, symlinked, or deny-listed paths *before* the approval modal opens, so the model can't trick a distracted user into approving a misleading path.

func (*WriteFileTool) Description

func (t *WriteFileTool) Description() string

func (*WriteFileTool) Execute

func (t *WriteFileTool) Execute(ctx context.Context, argsJSON string) (string, error)

func (*WriteFileTool) Name

func (t *WriteFileTool) Name() string

func (*WriteFileTool) PathsToSnapshot added in v0.2.0

func (t *WriteFileTool) PathsToSnapshot(cwd, argsJSON string) []string

PathsToSnapshot reports the destination path so /checkpoints can restore the pre-write contents (or remove the file if it didn't exist before this turn).

func (*WriteFileTool) PreviewCall

func (t *WriteFileTool) PreviewCall(argsJSON string) string

func (*WriteFileTool) RequiresApproval

func (t *WriteFileTool) RequiresApproval(string) bool

func (*WriteFileTool) Schema

func (t *WriteFileTool) Schema() map[string]any

type WritePathOptions

type WritePathOptions struct {
	// Cwd is the primary allowed root, queried at validate time so an
	// in-session cwd swap (enter_worktree) flows through to the write
	// validator without rebuilding WriteOpts. Required. Shared pointer
	// across all mutating tools registered for one session, same as
	// each tool's own t.Cwd.
	Cwd *CwdRef

	// AllowedPaths is the list of additional roots a user has opted into
	// via --allow-paths or YOTTACODE_ALLOW_PATHS. Each entry is treated
	// as an absolute root the model is allowed to write under.
	AllowedPaths []string

	// DenyExact is a list of absolute paths (or path prefixes) the model
	// must never write to. Populated from DefaultDenyPaths(cwd) at
	// registration time. Always wins, even if a path otherwise matches
	// Cwd or AllowedPaths.
	DenyExact []string

	// AllowSymlinks lets the validator follow symlinks on write paths.
	// Default false — symlinks are a known exfil vector.
	AllowSymlinks bool

	// OwnedPaths optionally narrows writes to the file/directory set a dispatch
	// worker owns. Paths may be absolute or relative to Cwd. When non-empty, a
	// write must pass the normal workspace/deny-list checks AND land inside one
	// of these owned paths. This turns dispatch's "partition by files" contract
	// from a prompt instruction into an enforcement boundary. Directory-style
	// ownership is explicit: list an existing directory or a path ending in a
	// path separator; otherwise an owned path is treated as one file.
	OwnedPaths []string

	// PlanModeAllowedFile is the absolute path of the single plan file
	// the agent is permitted to write to while plan mode is active.
	// When non-empty, ValidateWritePath short-circuits to nil for an
	// exact match (after symlink rejection still applies). Empty when
	// plan mode is off — the regular Cwd / AllowedPaths / DenyExact
	// stack is the only authority. The TUI mutates this field on the
	// registered *WriteFileTool / *EditFileTool / *ApplyDiffTool when
	// /plan toggles, and zeroes it on exit.
	PlanModeAllowedFile string
}

WritePathOptions configures the validator for a single tool. Build it once per session in run.go and share across every mutating tool.

type YoloModeState added in v0.2.0

type YoloModeState struct {
	Active atomic.Bool
}

YoloModeState is the per-session "no questions asked" flag. When active, the loop auto-approves every tool call WITHOUT the safety floor that auto mode keeps (run_bash, git_commit, git_checkpoint, rollback all auto-allow silently), and raises the iteration cap to a large but FINITE bound (see yoloIterationCap — not literally uncapped). Explicit Deny rules in permissions.json still win — yolo is "skip prompts," not "ignore my policy."

Orthogonal OVERLAY, not a mode: it sits on top of whichever mode (auto, plan, or none) is active and does NOT turn the others off. The loop's approval switch checks the yolo case ahead of the auto and plan cases, so it dominates while active; exiting it hands the gate back to whatever mode was underneath.

NOT in the Shift+Tab mode cycle. Entered by launching with --yolo or by the /yolo slash command mid-session (cmdYolo), and /yolo also exits it — the deliberate escape hatch the flag alone doesn't give. In the TUI this is the SOLE representation of the bypass; the separate LoopConfig.BypassPermissions bool is used only on the non-TUI oneshot/CI path, which never constructs a YoloModeState.

func (*YoloModeState) IsActive added in v0.2.0

func (y *YoloModeState) IsActive() bool

IsActive is a nil-safe check used by the loop.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL