Documentation
¶
Overview ¶
Package agent detects whether posh is being driven by an AI coding agent rather than a human, so callers (e.g. cmd/execute.go) can pick agent-friendly defaults such as JSON output instead of human-formatted prose.
Index ¶
- Constants
- func DetectFrom(getenv func(string) string) bool
- func Encode(v any) error
- func IsAgentMode() bool
- func Render(payload func() any, human func() error) error
- func SetDetected(v bool) func()
- func SetFlag(v bool)
- func Table(data pterm.TableData, opts ...TableOption) error
- func Tree(list pterm.LeveledList) error
- type TableJSON
- type TableOption
- type TreeJSON
- type TreeNode
Constants ¶
const Flag = "--agent"
Flag is the command-line flag that forces agent mode on, for harnesses that set none of the recognized environment variables.
It is exported so callers scanning argv by hand - see readline.ExtractFlags, needed where cobra's DisableFlagParsing stops flags being populated - do not restate the literal.
Variables ¶
This section is empty.
Functions ¶
func DetectFrom ¶
DetectFrom resolves agent mode using the given environment lookup. An explicit POSH_AGENT_MODE wins over harness detection in both directions. Exported so detection logic is testable without mutating the real process environment.
func Encode ¶
Encode writes v to stdout as a single JSON value followed by a newline.
Commands use this in agent mode to emit one machine-readable value instead of the human-formatted PTerm tables and trees they render otherwise. Results are emitted bare: a caller invoked a specific command and already knows what it asked for. Log lines written by pkg/log.AgentJSON keep a "type" field, which is what lets a consumer tell an interleaved log line from the result value.
Encode does not itself check agent mode - callers branch on IsAgentMode, and `posh agent catalog` uses it unconditionally.
HTML escaping is disabled to match pkg/log.AgentJSON: environment values and cache contents routinely contain characters like & and < that would otherwise be mangled into escape sequences.
func IsAgentMode ¶
func IsAgentMode() bool
IsAgentMode reports whether posh should behave as if driven by an agent.
func Render ¶
Render emits a command's result in whichever form the caller is expecting: the JSON payload in agent mode, the human-formatted output otherwise.
It exists so commands do not each carry their own `if agent.IsAgentMode()`. Both sides are closures, so only the branch actually taken does its work - building a payload or walking a cache is not paid for when the other form wins.
Payloads are emitted bare by Encode, without a type/schema_version envelope: a caller invoked a specific command and already knows what it asked for.
return agent.Render(
func() any { return CacheGet{Namespace: ns, Key: key, Value: value} },
func() error { c.l.Info(fmt.Sprintf("%v", value)); return nil },
)
func SetDetected ¶
func SetDetected(v bool) func()
SetDetected overrides the environment-based detection performed in init and returns a func restoring the previous value.
This exists for tests: inside an agent harness the real environment sets CLAUDECODE, so IsAgentMode reports true for the whole test binary and the human-formatted output path would be unreachable. Production code should let init do the detection and use POSH_AGENT_MODE to override it.
func SetFlag ¶
func SetFlag(v bool)
SetFlag records an explicit --agent flag, e.g. for harnesses that set none of the recognized environment variables.
func Table ¶
func Table(data pterm.TableData, opts ...TableOption) error
Table renders tabular data, emitting JSON in agent mode and a PTerm table otherwise.
Commands should prefer this over calling pterm.DefaultTable directly: PTerm writes human-formatted, colored text that an agent cannot parse, and this keeps both paths in one call rather than requiring every command to branch.
With WithHeader, rows are emitted as objects keyed by the header cells:
{"rows":[{"Name":"prod","Status":"ok"}]}
Without it, rows are emitted as positional arrays:
{"rows":[["prod","ok"]]}
Unlike the PTerm path, cell values are never wrapped or truncated to the terminal width, which would corrupt long values with embedded newlines.
func Tree ¶
func Tree(list pterm.LeveledList) error
Tree renders a leveled list, emitting nested JSON in agent mode and a PTerm tree otherwise.
Commands should prefer this over calling pterm.DefaultTree directly: PTerm draws box-drawing characters an agent cannot parse, and this keeps both paths in one call rather than requiring every command to branch.
The flat, level-based pterm.LeveledList is rebuilt into real nesting:
{"nodes":[{"text":"kubectl","children":[{"text":"clusters"}]}]}
Types ¶
type TableJSON ¶
type TableJSON struct {
Rows []any `json:"rows"`
}
TableJSON is the agent-mode representation of a table. Rows are either map[string]string (with a header) or []string (without).
type TableOption ¶
type TableOption func(*tableOptions)
TableOption configures Table.
func WithHeader ¶
func WithHeader() TableOption
WithHeader marks the first row of the data as a header row. In agent mode the header cells become the JSON object keys; without it rows are emitted as positional arrays.
type TreeJSON ¶
type TreeJSON struct {
Nodes []TreeNode `json:"nodes"`
}
TreeJSON is the agent-mode representation of a tree.
func TreeNodes ¶
func TreeNodes(list pterm.LeveledList) TreeJSON
TreeNodes converts a leveled list into its nested agent-mode representation.
It is exported for commands that need to embed a tree in a larger payload rather than emit one on its own; most callers want Tree instead.
Items whose level skips more than one step below their predecessor are attached to the nearest available parent, matching how PTerm renders them rather than rejecting input a command already considers valid.