Stream agent output through kelos-capture instead of writing to /tmp

Merged
KE
5mo ago
+292-181

What type of PR is this?

/kind bug

What this PR does / why we need it:

Every agent entrypoint used to tee the agent's JSON-lines stdout into
/tmp/agent-output.jsonl so that /kelos/kelos-capture could re-read it
after the agent exited and emit token usage between the
---KELOS_OUTPUTS_*--- markers. /tmp counts against the pod's
ephemeral-storage limit and the file was never rotated, so a verbose
run could fill the ephemeral budget and trigger node-pressure eviction
that silently failed user tasks.

This PR inlines the parser into the pipe. Each entrypoint now does:

<agent> "${ARGS[@]}" | /kelos/kelos-capture
AGENT_EXIT_CODE=${PIPESTATUS[0]}
exit $AGENT_EXIT_CODE

kelos-capture reads stdin line by line, forwards each line unchanged
to its own stdout (pod logs are byte-identical to today), and
accumulates per-agent counters in memory:

  • claude-code / gemini / cursor — keep only the most recent
    {"type":"result", ...} line.
  • codex / opencode — sum tokens across every turn.completed /
    step_finish event.

Memory cost is O(1) in the size of the stream, /tmp/agent-output.jsonl
is no longer created, and the controller's marker contract is
unchanged.

Which issue(s) this PR is related to:

Fixes #1187

Special notes for your reviewer:

  • ParseUsage(agentType, filePath) is replaced by
    StreamUsage(agentType, io.Reader, io.Writer).
  • The agent's exit code is still propagated via PIPESTATUS[0] — same
    pattern as before, just with kelos-capture on the right of the pipe
    instead of tee.
  • Unit tests in internal/capture now exercise the streaming path for
    all five agent types and verify every input line is forwarded
    unchanged.
  • docs/agent-image-interface.md updated to describe the pipe form.

Does this PR introduce a user-facing change?

Fix Task pod eviction from unbounded /tmp/agent-output.jsonl growth: agent stdout is now streamed through kelos-capture instead of being teed to disk, removing the ephemeral-storage pressure point.

Summary by cubic

Stream agent stdout through /kelos/kelos-capture instead of teeing to /tmp, removing the ephemeral-storage hotspot that caused task pod evictions. Pod logs remain identical to previous behavior and the ---KELOS_OUTPUTS_*--- contract is unchanged.

  • Bug Fixes

    • Removed /tmp/agent-output.jsonl writes to stop ephemeral-storage bloat and node-pressure evictions (fixes #1187).
    • Forwarding preserves bytes in order with no line-length cap, appends a final newline if missing, surfaces flush errors, and still emits usage at EOF.
  • Refactors

    • Replaced ParseUsage(...) with StreamUsage(agentType, io.Reader, io.Writer); /kelos-capture now streams stdin to stdout and accumulates usage in O(1) memory.
    • Updated entrypoints to <agent> "${ARGS[@]}" | /kelos/kelos-capture; agent exit code preserved via PIPESTATUS[0]. Tests cover large lines, newline-append, and flush-error paths; docs now prescribe the pipe pattern.