MingaAgent.ToolRouter (Minga v0.1.0)

Copy Markdown View Source

Routes file tool operations through ProjectView, buffer forks, and changesets.

Tools call this module instead of directly doing filesystem I/O. The routing decision tree for each file operation:

  1. Is there a ProjectView? YES: route through ProjectView so every tool sees workspace-local state.
  2. Is there an open buffer for this path AND a fork store is active? YES: route through Buffer.Fork (in-memory, instant, undo integration).
  3. Is there an active changeset? YES: route through Changeset overlay (filesystem-level isolation).
  4. Neither: fall through to direct I/O (returns :passthrough for writes).

Buffer.Fork handles files the user has open in a buffer. Changeset handles files that aren't open, or external tools that need a coherent filesystem view. A session can use both simultaneously.

This module is stateless. The fork store pid and changeset pid come from the caller (stored in session state, captured in tool closures).

Summary

Types

Changeset reference (nil when changeset is disabled).

Routing context passed by tool callbacks.

Fork store reference (nil when fork routing is disabled).

Functions

Returns true if any routing is active.

Returns environment variables for shell commands.

Returns environment variables for shell commands, or a tagged error if ProjectView is unavailable.

Builds a routing context from the fork store and changeset pids.

Builds a routing context with ProjectView as the first routing layer.

Deletes a file, routing through changeset if active.

Edits a file by find-and-replace, routing through fork or changeset.

Returns the filesystem path corresponding to path in the routed view.

Returns the filesystem path for search tools, or a tagged error if ProjectView is unavailable.

Returns true if a fork store is active and has forks.

Lists a directory through ProjectView when available.

Returns true when the context includes a ProjectView.

Reads a file, routing through fork or changeset if active.

Returns true if the context has any routing configured, even if it is currently dead.

Returns the working directory for shell commands.

Returns the working directory for shell commands, or a tagged error if ProjectView is unavailable.

Returns a short label for routed workspace output.

Writes a file, routing through fork or changeset if active.

Types

changeset()

@type changeset() :: pid() | nil

Changeset reference (nil when changeset is disabled).

context()

@type context() :: MingaAgent.ToolRouter.Context.t()

Routing context passed by tool callbacks.

fork_store()

@type fork_store() :: pid() | nil

Fork store reference (nil when fork routing is disabled).

Functions

active?(arg1)

@spec active?(context()) :: boolean()

Returns true if any routing is active.

command_env(context)

@spec command_env(context()) :: [{String.t(), String.t()}]

Returns environment variables for shell commands.

command_env_result(arg1)

@spec command_env_result(context()) ::
  {:ok, [{String.t(), String.t()}]} | {:error, term()}

Returns environment variables for shell commands, or a tagged error if ProjectView is unavailable.

context(fork_store, changeset)

@spec context(fork_store(), changeset()) :: context()

Builds a routing context from the fork store and changeset pids.

context(project_view, fork_store, changeset)

@spec context(MingaAgent.ProjectView.t() | nil, fork_store(), changeset()) ::
  context()

Builds a routing context with ProjectView as the first routing layer.

delete_file(arg1, path)

@spec delete_file(context(), String.t()) :: :ok | :passthrough | {:error, term()}

Deletes a file, routing through changeset if active.

Buffer forks don't support deletion (you can't delete an open buffer through a fork). Falls through to changeset or passthrough.

edit_file(ctx, path, old_text, new_text)

@spec edit_file(context(), String.t(), String.t(), String.t()) ::
  :ok | :passthrough | {:error, term()}

Edits a file by find-and-replace, routing through fork or changeset.

filesystem_path(context, path)

@spec filesystem_path(context(), String.t()) :: String.t()

Returns the filesystem path corresponding to path in the routed view.

filesystem_path_result(context, path)

@spec filesystem_path_result(context(), String.t()) ::
  {:ok, String.t()} | {:error, term()}

Returns the filesystem path for search tools, or a tagged error if ProjectView is unavailable.

has_forks?(context)

@spec has_forks?(context()) :: boolean()

Returns true if a fork store is active and has forks.

list_directory(context, path)

@spec list_directory(context(), String.t()) ::
  {:ok, [MingaAgent.ProjectView.Backend.directory_entry()]}
  | :passthrough
  | {:error, term()}

Lists a directory through ProjectView when available.

project_view?(context)

@spec project_view?(context()) :: boolean()

Returns true when the context includes a ProjectView.

read_file(ctx, path)

@spec read_file(context(), String.t()) :: {:ok, binary()} | {:error, term()}

Reads a file, routing through fork or changeset if active.

Forks take priority: if there's a fork for this path, read from it. Otherwise try the changeset. If neither, fall through to buffer/filesystem.

routing_configured?(arg1)

@spec routing_configured?(context()) :: boolean()

Returns true if the context has any routing configured, even if it is currently dead.

working_dir(arg1)

@spec working_dir(context()) :: String.t() | nil

Returns the working directory for shell commands.

working_dir_result(arg1)

@spec working_dir_result(context()) :: {:ok, String.t() | nil} | {:error, term()}

Returns the working directory for shell commands, or a tagged error if ProjectView is unavailable.

workspace_label(context)

@spec workspace_label(context()) :: String.t() | nil

Returns a short label for routed workspace output.

write_file(ctx, path, content)

@spec write_file(context(), String.t(), binary()) ::
  :ok | :passthrough | {:error, term()}

Writes a file, routing through fork or changeset if active.

If a buffer is open for this path and a fork store exists, creates a fork (lazily) and writes to it. Otherwise tries changeset. Returns :passthrough if neither is active.