Packages

Extreme minimal AI assistant with persistent PTY, recursive sub-agents, and CLI-based MCP/browser integration (mcporter, agent-browser)

Retired package: Release invalid - Deprecated due to missing config files

Current section

Files

Jump to
eai config tools write_to_session.exs
Raw

config/tools/write_to_session.exs

defmodule Eai.Tool.WriteToSession do
@behaviour Eai.Tool
@right_sentinel Application.compile_env(:eai, [:sandbox, :sentinel_right])
@description """
Write raw bytes directly to a PTY session's stdin, bypassing the sentinel wrapper.
Use for interactive input (e.g. answering [Y/n] prompts) or for sending control characters.
Do NOT use for normal script execution — use execute_script for that.
Supported escape sequences (write them literally in the input string):
\\\\n newline
\\\\r carriage return
\\\\t tab
\\\\x03 Ctrl+C (interrupt running task)
\\\\x04 Ctrl+D (EOF)
\\\\x1a Ctrl+Z
**Example:** to interrupt a running task, send Ctrl+C then echo the right sentinel:
input: "\\\\x03\\\\necho #{@right_sentinel}\\\\n"
"""
@impl true
def schema do
%{
type: "function",
function: %{
name: "write_to_session",
description: @description,
parameters: %{
type: "object",
properties: %{
input: %{
type: "string",
description:
"String to write, using escape sequences for control chars (e.g. \"y\\\\n\", \"\\\\x03\\\\n\")."
},
pty_session_id: %{type: "string", description: "PTY session ID (default: 'default')."}
},
required: ["input"]
}
}
}
end
@impl true
def execute(args, pty_session_id, _chat_session_id) do
input = Map.get(args, "input", "")
target = Map.get(args, "pty_session_id", pty_session_id)
raw = unescape(input)
if Application.fetch_env!(:eai, :sandbox) |> Keyword.fetch!(:debug_pty_output) do
IO.puts(
"\n=== WRITE_TO_SESSION [#{target}] ===\ninput: #{inspect(input)}\nraw: #{inspect(raw)}\n=== END WRITE ==="
)
end
Eai.Naming.pool().write_raw(target, raw)
%{status: "ok", wrote: inspect(raw)}
|> Eai.Utils.sanitize_value()
|> Jason.encode!()
end
defp unescape(input) do
input
|> String.replace("\\n", "\n")
|> String.replace("\\r", "\r")
|> String.replace("\\t", "\t")
|> String.replace("\\x03", <<3>>)
|> String.replace("\\x04", <<4>>)
|> String.replace("\\x1a", <<26>>)
end
end