Documentation
¶
Overview ¶
Package execsegment splits a Codex command script into its top-level segments and instruments them for per-segment tracking. The helper that runs inside the command shell and the router that displays it share this split, so their segment indices always agree.
Index ¶
Constants ¶
const ( Hello = "hello" Begin = "b" Output = "o" End = "e" Done = "d" // Lossy reports that the helper stopped reporting output to stay within // its bound; statuses continue. Lossy = "lossy" )
Message types.
const Guard = "MEKUGI_EXEC_TRACK"
Guard marks a shell that already decided whether to track its command, so nested Bash commands started by that command are never tracked.
const Protocol = 3
Protocol is the helper-to-router message version.
Variables ¶
This section is empty.
Functions ¶
func Hook ¶
Hook is Bash startup source, read from BASH_ENV, that tracks the command script Codex passed with -c. It decides before any segment runs: only when the helper plans the script and the router matches it to a live Codex command does the shell run the rewrite in place of the script and exit. Otherwise it returns and Bash runs the original script itself, so the command never runs twice.
Codex's own snapshot scripts, including the wrapper that re-executes the command shell, pass through without setting the guard: the snapshot would otherwise record it for every later command. Scripts without a list operator or newline are single commands and never start the helper.
func Rewrite ¶
Rewrite wraps each segment in hooks that report its start and exit status. Each wrapper runs in the current shell and returns the segment's status, so && and || chains, $?, and shell state behave as in the original. A hook passes a nonzero status on as the operand of an && list, where errexit ignores it: under set -e, only the segment's own command can end the shell.
func Tracker ¶
Tracker is the Bash source that runs a tracked script. The helper runs as a coprocess: the shell sends it segment boundaries and waits for each acknowledgment, so the helper has relayed a segment's output before the next segment starts. Output reaches Codex unchanged through the helper, which alone keeps the original descriptors. A terminal cannot be relayed without changing what programs detect, so terminal commands report status only.
The rewrite does not run from the startup file, whose errors differ from the script's: a fatal expansion error there would abandon the startup file and run the original script as well. A one-time DEBUG trap instead runs it in place of the script's first command, so error messages, line numbers, and fatal errors behave as in the original. Split accepts only scripts whose first command fires that trap before it has any effect.
Types ¶
type Message ¶
type Message struct {
Timing Timing `json:"timing,omitzero"`
Type string `json:"t"`
Version int `json:"v,omitzero"`
Thread string `json:"thread,omitempty"`
Script string `json:"script,omitempty"`
Segments []string `json:"segments,omitempty"`
Terminal bool `json:"tty,omitzero"`
Index int `json:"i,omitzero"`
Data string `json:"d,omitempty"`
Code *int `json:"c,omitempty"`
}
Message is one line of the helper's report. Hello opens a report and the router answers with Reply; the rest follow in the order the shell and its output produced them.
type Segment ¶
type Segment struct {
Start, End int // Script byte span, excluding terminators and heredoc bodies.
Source string // Display source, including any heredoc body.
}
Segment is one top-level command of a list: a statement, or an operand of a top-level && or || chain. Pipelines and compound commands stay whole.
func Split ¶
Split returns the script's segments when every segment can be tracked without changing the script's behavior. It reports false for single commands, for scripts whose first command runs before the shell's DEBUG trap can replace the script, and for scripts whose semantics depend on the shell state the instrumentation touches: job control, traps, top-level returns, process replacement, command tracing, and variables naming the current command.
type Timing ¶
type Timing struct {
Started time.Time `json:"started,omitzero"`
Ended time.Time `json:"ended,omitzero"`
ElapsedNS int64 `json:"elapsed_ns,omitzero"`
}
Timing records helper-observed command boundaries. ElapsedNS is measured with the helper's monotonic clock, independently of wall-clock adjustments.