Documentation
¶
Index ¶
- Constants
- func Classify(event map[string]any) string
- func DigestLine(raw []byte) (line string, event map[string]any, err error)
- func ExtractLoopMarker(text string) (directive, label string, ok bool)
- func ExtractStatusMarker(text string) (phase, label string, ok bool)
- func Stream(in io.Reader, out io.Writer, opts Options) error
- type Options
Constants ¶
const ( TagMilestone = "MILESTONE" TagFinding = "FINDING" TagActivity = "ACTIVITY" )
Variables ¶
This section is empty.
Functions ¶
func Classify ¶ added in v0.6.0
Classify returns a tag (MILESTONE, FINDING, or ACTIVITY) for a parsed event. The event map is what DigestLine has already unmarshaled.
Rules (in priority order):
MILESTONE: session.end, permission.request, and tool.call / tool.call_update where kind=="commit" or kind=="task" with status=="completed", or where the title/command contains "git commit".
FINDING: agent.message_chunk, agent.thought_chunk, user.message_chunk where the content text contains a deliberate finding signal (confidence ≥60, explicit [finding] prefix, or multi-word phrase: "reviewer flagged", "correction needed", "failed test").
ACTIVITY: everything else.
func DigestLine ¶
DigestLine parses a single raw JSON line and returns the formatted plain-text line, the parsed event map, and any error.
When the JSON has no "event" field the line should be skipped: the returned string is empty and event is nil (no error). Callers that only need the string can ignore the map; callers that also need classification (e.g. streamLine) can pass the returned map directly to Classify without re-parsing the bytes.
func ExtractLoopMarker ¶ added in v0.9.0
func ExtractStatusMarker ¶ added in v0.7.2
ExtractStatusMarker scans text for the first [status: <phase>] or [status: <phase> | <label>] marker. Returns the normalised phase, trimmed label, and ok=true when a known phase is found. Unknown phase words are ignored (ok=false) to avoid spurious events from unrelated bracket text.
Known phases: thinking, working, waiting, done.
Types ¶
type Options ¶
type Options struct {
Follow bool
PollInterval time.Duration
Format string
// Classify, when true, prefixes each plain-format line with a tag:
// MILESTONE, FINDING, or ACTIVITY. For JSON format, a top-level
// "classify" field is injected into each emitted object.
Classify bool
// CursorPath, when non-empty, causes Stream to atomically rewrite the
// cursor file after processing. The caller is responsible for seeking the
// underlying reader to the offset recorded in the cursor file before
// calling Stream; CursorStartOffset must be set to that same offset so
// Stream can compute the absolute file position when writing the cursor.
//
// Design note: we keep Stream's signature as io.Reader (rather than
// *os.File) so tests can pass bytes.Buffer or strings.Reader without
// touching the filesystem. The caller in watch.go handles the actual
// os.File seek; we track bytes consumed here via a counting wrapper.
CursorPath string
CursorStartOffset int64
}