Skip to content

feat(core): add antigravity support#355

Open
ddarkr wants to merge 8 commits intojunhoyeo:mainfrom
ddarkr:feat/antigravity-collector
Open

feat(core): add antigravity support#355
ddarkr wants to merge 8 commits intojunhoyeo:mainfrom
ddarkr:feat/antigravity-collector

Conversation

@ddarkr
Copy link
Copy Markdown
Contributor

@ddarkr ddarkr commented Mar 24, 2026

Summary

  • add tokscale antigravity status|sync|purge-cache so Antigravity usage can be collected from the local language server while the editor is running
  • store confirmed Antigravity usage as cached JSONL artifacts and keep tokscale-core focused on parsing local data instead of live RPC collection
  • preserve previously confirmed Antigravity artifacts when older sessions no longer appear in the live window
  • normalize Antigravity model aliases so reporting and pricing lookup use stable canonical model names

Test proof

  • cargo test — passed
  • cargo test -p tokscale-cli antigravity — passed
  • cargo test -p tokscale-core antigravity — passed
  • cargo run -p tokscale-cli -- antigravity status — verified sync-first UX
  • cargo run -p tokscale-cli -- antigravity sync — verified cache sync flow
  • cargo run -p tokscale-cli -- models --antigravity --json — verified parsed reporting path

Summary by cubic

Adds Antigravity support: tokscale antigravity syncs usage from the local language server into a cached JSONL store, and tokscale-core parses it with canonical model aliases for accurate pricing. Run tokscale antigravity sync while the editor is open; synced usage appears in local reports by default (optional --antigravity filter, TUI hotkey a).

  • New Features

    • New tokscale antigravity subcommands: status, sync, purge-cache.
    • Cache at ~/.config/tokscale/antigravity-cache/sessions/*.jsonl; manifest preserves prior confirmed artifacts.
    • Core wiring: added antigravity client (scans cached JSONL), parser, and pricing alias normalization for placeholders (e.g., model_placeholder_m26claude-opus-4-6).
    • Reporting/UI: included in default local parsing; optional --antigravity filter and TUI entry (hotkey a).
  • Bug Fixes

    • Skip broken trajectory RPC connections; parse chunked responses without truncation.
    • Cleanup hardening: persist the manifest before deletion, restrict cleanup to cache-relative session .jsonl paths, and remove stale legacy artifacts after sync.
    • Discovery fallbacks: tolerate missing lsof, probe declared RPC ports when port discovery returns nothing, and improve status/sync diagnostics.
    • Preserve numeric retry timestamps in exported metadata.

Written for commit 135ac58. Summary will update on new commits.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 24, 2026

@ddarkr is attempting to deploy a commit to the Inevitable Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/tokscale-cli/src/tui/data/mod.rs">

<violation number="1" location="crates/tokscale-cli/src/tui/data/mod.rs:1067">
P2: Pricing regression tests were weakened from exact expected costs to generic positive/finite checks, reducing ability to catch cost-calculation regressions.</violation>
</file>

<file name="crates/tokscale-cli/src/antigravity.rs">

<violation number="1" location="crates/tokscale-cli/src/antigravity.rs:373">
P1: Session artifact filenames are derived from a lossy sanitized session ID, allowing collisions between distinct session IDs and silent artifact overwrite.</violation>

<violation number="2" location="crates/tokscale-cli/src/antigravity.rs:710">
P2: Non-zero discovery command exits are silently treated as empty output, masking real detection failures.</violation>

<violation number="3" location="crates/tokscale-cli/src/antigravity.rs:727">
P1: Per-connection RPC failure in summary collection aborts the entire antigravity sync instead of skipping the bad connection.</violation>

<violation number="4" location="crates/tokscale-cli/src/antigravity.rs:1022">
P2: Chunked body parsing treats chunk-size parse failures as terminal zero-length chunks, which can prematurely truncate valid responses (e.g., with chunk extensions).</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d7c24c61f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +723 to +727
let response = rpc_request(
connection,
"GetAllCascadeTrajectories",
&serde_json::json!({}),
)?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Continue syncing when one RPC connection fails

list_trajectory_summaries currently propagates any single rpc_request error with ?, so tokscale antigravity sync aborts even if other detected language-server connections are healthy. This is user-visible when one editor instance exits or transiently fails between heartbeat probing and trajectory listing: one bad process prevents exporting sessions from all remaining processes. Treat per-connection RPC failures as best-effort (skip/log) to keep sync resilient.

Useful? React with 👍 / 👎.

Comment on lines +1171 to +1174
.get("createdAt")
.or_else(|| usage.get("timestamp"))
.and_then(Value::as_str)
.and_then(|text| chrono::DateTime::parse_from_rfc3339(text).ok())
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse numeric retry timestamps before writing artifacts

Timestamp extraction for retry usage only accepts RFC3339 strings via as_str, so numeric createdAt/timestamp fields become null in emitted JSONL rows. The antigravity parser later drops usage rows with non-positive timestamps, which silently undercounts tokens/cost whenever the RPC payload uses epoch numbers instead of strings. Add numeric timestamp handling here before falling back to created_at.

Useful? React with 👍 / 👎.

Skip broken trajectory RPC connections, make session artifact filenames collision-resistant, improve discovery diagnostics, and parse chunked responses without truncation. Restore the exact RooCode cost regression assertion to keep coverage strong.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/tokscale-cli/src/antigravity.rs">

<violation number="1" location="crates/tokscale-cli/src/antigravity.rs:373">
P2: Artifact filename migration introduces coexistence of legacy and new files, and downstream Antigravity ingestion scans `sessions/*.jsonl` directly, so both copies may be parsed.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12d2b21b96

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +622 to +625
let mut ports = parse_ports(&run_command(
"lsof",
&["-Pan", "-p", &pid_str, "-iTCP", "-sTCP:LISTEN"],
)?);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle missing lsof gracefully during sync

Connection discovery hard-fails when lsof is unavailable because find_listening_ports propagates run_command("lsof", ...) errors with ?. On systems where lsof is not installed (common in minimal Linux setups), tokscale antigravity status/sync will abort as soon as an Antigravity process candidate is found, so users cannot refresh cache data despite having a running editor. This should degrade to a warning and skip that process instead of failing the whole command.

Useful? React with 👍 / 👎.

Remove stale legacy session artifacts after sync, tolerate missing lsof during port discovery, and preserve numeric retry timestamps in exported metadata.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/tokscale-cli/src/antigravity.rs">

<violation number="1" location="crates/tokscale-cli/src/antigravity.rs:202">
P1: Stale artifacts are deleted before manifest persistence, so a save failure can leave the old manifest pointing to files that were already removed.</violation>

<violation number="2" location="crates/tokscale-cli/src/antigravity.rs:202">
P1: Sync cleanup deletes manifest-sourced artifact paths without constraining them to the cache root, enabling path traversal/absolute-path file deletion outside the antigravity cache.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20a5ac4f82

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +389 to +391
let artifact_path = cache_dir.join(relative_path);
if artifact_path.exists() {
fs::remove_file(&artifact_path)?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict artifact deletion to cache directory

delete_artifact_relative_path trusts artifact_path from the manifest and directly does cache_dir.join(relative_path) before remove_file. Because join accepts absolute paths and .. segments, a corrupted/edited manifest can cause sync cleanup to delete files outside ~/.config/tokscale/antigravity-cache (for example an absolute path or ../../...). This makes artifact cleanup unsafe against malformed local state and can lead to unintended data loss.

Useful? React with 👍 / 👎.

Comment on lines +509 to +510
let ports = find_listening_ports(candidate.pid)?;
for port in ports {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Probe declared RPC port when port scan returns nothing

Connection discovery only iterates ports returned by find_listening_ports, so candidates are dropped when lsof is unavailable/restricted or returns no rows. Fresh evidence in this commit: ProcessCandidate.declared_port is parsed from --extension_server_port but never used during probing, which means antigravity status/sync can still report zero connections even though the process advertises a usable RPC port.

Useful? React with 👍 / 👎.

Persist the manifest before deleting stale artifacts, restrict cleanup to cache-relative paths, and probe declared RPC ports when lsof discovery returns nothing.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/tokscale-cli/src/antigravity.rs">

<violation number="1" location="crates/tokscale-cli/src/antigravity.rs:413">
P2: `cleanup_stale_session_artifacts` deletes any relative path from the prior manifest as long as it’s under the cache root. The new `resolve_cache_relative_artifact_path` only blocks absolute/`..` components, so entries like `manifest.json` are considered valid and can delete arbitrary cache-root files (including the freshly saved manifest after the order change). Cleanup should restrict deletions to `sessions/*.jsonl` (or canonicalize and enforce the sessions dir) to avoid deleting non-artifacts.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1660f1be3f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

relative: ".config/tokscale/antigravity-cache/sessions",
pattern: "*.jsonl",
headless: false,
parse_local: false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Mark antigravity as parseable in local defaults

ClientId::Antigravity is registered with parse_local: false, but default local parse paths (e.g., parse_local_unified_messages and run_clients_command) build their source list from ClientId::iter().filter(|c| c.parse_local()). That means synced Antigravity cache files are omitted unless callers explicitly pass "antigravity", so default local workflows can silently miss this new client’s data. Make Antigravity parse-local (or explicitly include it in those defaults) so the new integration is visible without manual source overrides.

Useful? React with 👍 / 👎.

Limit stale artifact deletion to session jsonl files under the cache root and include Antigravity in default local parsing so synced sessions are visible without explicit source filters.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant