# Antigravity Trajectory Sidecar Parsing Mechanism: Extracting Full Transcripts in AgentsView

> Learn how the antigravity trajectory sidecar in AgentsView extracts full transcripts. Discover its defensive pipeline for high-fidelity data conversion and resource protection.

- Repository: [Kenn Software/agentsview](https://github.com/kenn-io/agentsview)
- Tags: internals
- Published: 2026-07-04

---

**The AgentsView parser extracts high-fidelity transcripts from [`.trajectory.json`](https://github.com/kenn-io/agentsview/blob/main/.trajectory.json) sidecars using a defensive, size-capped pipeline that converts daemon-written steps into structured messages while guarding against resource exhaustion.**

The `kenn-io/agentsview` repository implements a robust parsing pipeline for Antigravity CLI sessions. When the `agy-reader` daemon writes session data, it accompanies each `.db` or `.pb` file with a [`.trajectory.json`](https://github.com/kenn-io/agentsview/blob/main/.trajectory.json) sidecar containing detailed execution metadata. This article explains the **antigravity trajectory sidecar parsing mechanism** that transforms these JSON files into full transcripts suitable for analytics and UI rendering.

## File Discovery and Resource Protection

Before parsing begins, the system locates the sidecar file and enforces strict resource limits to prevent denial-of-service attacks.

### Path Resolution and Size Guarding

When processing a `.db` or `.pb` session file, the parser constructs the sidecar path by replacing the extension with [`.trajectory.json`](https://github.com/kenn-io/agentsview/blob/main/.trajectory.json). In [`internal/parser/antigravity_cli.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli.go), the code defines a hard-coded maximum size constant: `maxTrajectorySidecarBytes = 64 MiB`. This limit prevents the parser from attempting to load maliciously large JSON files that could exhaust memory.

### Stream Reading with Cap Enforcement

The file is opened and read through `io.LimitReader` (lines 24-33 of [`internal/parser/antigravity_cli.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli.go)). If the sidecar content exceeds the 64 MiB cap, the parser returns an error immediately and aborts processing. This defensive read ensures that oversized files never reach the JSON unmarshaler.

## JSON Unmarshaling and Schema Validation

Once the size check passes, the parser deserializes the sidecar content into a strongly-typed Go structure.

### Struct Mapping

The entire JSON payload is unmarshaled into the internal `agyTrajectory` struct, which mirrors the schema generated by the daemon. This struct includes fields such as `Steps` and `Metadata` that map directly to the daemon's output format (lines 34-38 of [`internal/parser/antigravity_cli.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli.go)).

### Error Handling

Any JSON parsing error aborts sidecar handling entirely. The parser treats the sidecar as **untrusted structured input** and falls back to lower-fidelity sources (such as the native DB decode or shell history) if the JSON is malformed. The parser never executes or echoes raw JSON content; it only deserializes into Go structs and discards unknown step types.

## Step-by-Step Transcript Conversion

The core parsing logic iterates over `traj.Steps` to reconstruct the conversation flow. Each step is dispatched based on its `step.Type` to generate `ParsedMessage` objects that preserve roles, content, timestamps, and tool-call metadata.

### Planner Response Handling

For steps of type `CORTEX_STEP_TYPE_PLANNER_RESPONSE`, the parser extracts tool calls, normalizes categories, and populates `ParsedToolCall` structs. If the planner's textual response is empty, the parser concatenates tool headers to form the assistant message content. This logic ensures that tool invocations remain visible in the transcript even when the assistant provides no additional commentary (lines 83-99 of [`internal/parser/antigravity_cli.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli.go)).

### Tool Execution and Synthetic Message Generation

Tool execution steps—including command-run, file-view, code-action, grep, directory-list, and error steps—capture raw output or error text. The parser marshals this data to JSON and stores it as pending `ParsedToolResult` objects.

When a new user or assistant turn begins, the parser emits a **synthetic empty-content user message** containing the pending tool results. This synthetic message is later filtered out by the sync engine but is essential for proper UI pairing, enabling the interface to render tool output inline with the conversation flow. Any remaining pending results are flushed into a final synthetic message at the end of parsing (lines 124-144 of [`internal/parser/antigravity_cli.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli.go)).

## Coverage Validation and Fallback Strategy

The parser implements intelligent selection logic in the higher-level `parseSessionWithStatus` routine (around line 140 of [`internal/parser/antigravity_cli.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli.go)). This function compares the sidecar transcript against the database decode to determine which source provides the most complete record.

### Selection Criteria

The sidecar transcript is preferred only when two conditions are met:
- The sidecar contains displayable messages
- The sidecar covers at least as many raw steps as the DB decode

### Retry Logic

If the sidecar parses successfully but does not fully cover the DB steps, the parser uses the DB transcript but sets the `NeedsRetry` status flag. This signals the sync engine to re-parse the session on a subsequent pass once the sidecar has caught up with the full execution trace.

## Implementation Example

The following Go code demonstrates how to invoke the trajectory parser and handle the results:

```go
// Example: parsing a trajectory sidecar for a given session file.
func exampleParseSidecar(sidecarPath string) (*ParsedSession, []ParsedMessage, []ParsedUsageEvent, error) {
    // The top-level parse function returns a struct with messages, raw step count,
    // and usage events extracted from the side-car.
    result, err := parseAntigravityCLITrajectory(sidecarPath)
    if err != nil {
        return nil, nil, nil, fmt.Errorf("failed to parse sidecar: %w", err)
    }

    // The caller can now store the messages and usage events in the DB.
    // result.messages holds the fully-fledged transcript.
    // result.usageEvents holds any token-usage information present in the side-car.
    return nil, result.messages, result.usageEvents, nil
}

// In the sync engine (simplified):
func (p *antigravityCLIProvider) parseSessionWithStatus(path, project, machine string) (*ParsedSession, []ParsedMessage, []ParsedUsageEvent, AntigravityCLIParseStatus, error) {
    sidecarPath := strings.TrimSuffix(path, ".db") + ".trajectory.json"
    sidecarRes, sidecarErr := parseAntigravityCLITrajectory(sidecarPath)

    // Prefer side-car when it provides displayable content and covers the DB.
    if sidecarErr == nil && hasDisplayableAntigravityCLITrajectoryMessage(sidecarRes.messages) && sidecarRes.rawSteps >= dbResult.rawStepCount {
        return nil, sidecarRes.messages, sidecarRes.usageEvents, AntigravityCLIParseStatus{}, nil
    }
    // …fallback handling omitted for brevity…
}

```

## Key Source Files

The parsing pipeline spans four primary files in the codebase:

- [`internal/parser/antigravity_cli.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli.go) – Contains the core sidecar reader (`parseAntigravityCLITrajectory`) and step-to-message conversion logic, including the 64 MiB size cap and synthetic message generation.
- [`internal/parser/antigravity_cli_provider.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli_provider.go) – Implements provider wiring, sidecar file discovery, and integration with the generic parser interface.
- [`internal/parser/antigravity_version.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_version.go) – Handles source-version fingerprinting for Antigravity sessions, determining when a sidecar is available for parsing.
- [`internal/parser/types.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/types.go) – Registers the `AgentAntigravityCLI` type and defines the parsing contracts used by the provider.

## Summary

- **Size Protection**: The parser enforces a 64 MiB limit on [`.trajectory.json`](https://github.com/kenn-io/agentsview/blob/main/.trajectory.json) files using `io.LimitReader` to prevent resource exhaustion.
- **Defensive Parsing**: JSON is unmarshaled into strictly typed structs; malformed sidecars trigger immediate fallback to DB sources.
- **Rich Transcript Generation**: The parser converts daemon steps into structured messages, handling planner responses and tool executions with full metadata preservation.
- **Synthetic Messages**: Tool results are bundled into synthetic empty-content user messages to maintain UI pairing, then filtered by the sync engine.
- **Intelligent Fallback**: The `parseSessionWithStatus` routine selects the sidecar only when it offers complete coverage, setting `NeedsRetry` for partial data.

## Frequently Asked Questions

### What is the maximum file size for trajectory sidecars?

The parser enforces a hard limit of **64 MiB** via the `maxTrajectorySidecarBytes` constant in [`internal/parser/antigravity_cli.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/antigravity_cli.go). Files exceeding this size are rejected before JSON parsing begins to protect against resource-exhaustion attacks.

### How does the parser handle tool execution steps?

Tool execution steps (such as command-run, file-view, and code-action) are converted to `ParsedToolResult` objects and accumulated in a temporary slice. When a new conversation turn begins, the parser emits a synthetic user message containing these results, ensuring tool outputs remain paired with their invocations in the UI timeline.

### What happens when the sidecar does not cover all database steps?

If the sidecar parses successfully but contains fewer raw steps than the database decode, the parser uses the DB transcript instead and sets the `NeedsRetry` flag in the status return. This allows the sync engine to automatically re-parse the session later when the sidecar has been fully written by the daemon.

### Why does the parser create empty-content synthetic messages?

Synthetic empty-content user messages serve as containers for `ParsedToolResult` payloads that need to be delivered between assistant tool calls and the next user input. These messages are essential for proper UI rendering of tool output inline with the conversation flow, even though they are filtered from the final display by the sync engine.