Skip to content

Latest commit

 

History

History
104 lines (81 loc) · 10.1 KB

AGENTS.md

File metadata and controls

104 lines (81 loc) · 10.1 KB

Antigravity SDK for Java - Agent Guidelines

This file (AGENTS.md) provides context and instructions for AI agents working on this repository, outlining the project's purpose, structure, and our collaborative workflow.

🌟 What This Project Is About

The Antigravity SDK for Java is an unofficial, community-driven Java port of the Python-based Antigravity SDK. It bridges the gap for enterprise Java developers who want to build, configure, host, and execute powerful AI agents natively in Java. It aims for full feature parity with the official Python SDK, supporting streaming, tool calling, model context protocol (MCP), and multimodal inputs.

🏗️ How It Is Composed

This is a multi-module Maven project using Java 21:

  1. antigravity-sdk-parent: The root POM managing dependencies and plugin versions.
  2. antigravity-sdk-protocol: A generated artifact. It compiles the .proto files from the upstream Antigravity repository into Java classes using the protobuf-maven-plugin.
  3. antigravity-sdk-wrapper: The core SDK logic (~140KB).
    • The Go Harness: This SDK does not run an LLM directly. Instead, it wraps a pre-compiled native Go binary called localharness.
    • Hybrid Platform Resolution: PlatformResolver resolves the native binary in order:
      1. Local override via ANTIGRAVITY_HARNESS_PATH environment variable or antigravity.harness.path system property.
      2. Cached binary in ~/.antigravity/bin/<slice>/localharness (verified against .version stamp).
      3. Embedded classpath resource (if an offline classifier JAR from antigravity-sdk-harness is present).
      4. On-demand lazy download via HarnessDownloader (direct streaming from PyPI wheels, enabled by default, controllable via antigravity.harness.download=true|false).
    • Communication: The Java SDK communicates with the Go harness via standard input/output (for initialization) and WebSockets (for active turn streaming and chunk aggregation).
    • Data Modeling: Pure data-carrying objects (e.g., AgentResponse, InteractionRequest, AgentResponseChunk) are implemented as modern Java 21 record classes for ergonomics and immutability.
  4. antigravity-sdk-harness: Dedicated artifact packaging native Go binaries (~37-43MB per platform classifier, ~236MB for all) for air-gapped or offline enterprise deployments:
    • Classifiers: linux-x86_64, linux-aarch64, osx-aarch64, osx-x86_64, windows-x86_64, windows-aarch64, and all.
    • The 6 native binaries (~750MB uncompressed) exceed GitHub's 100MB limit and are gitignored. The script ./sync-harness.sh synchronizes binaries into antigravity-sdk-harness/src/main/resources/google/antigravity/bin/.

🤝 The Way We Work Together

This entire project was autonomously generated and implemented by me (the Antigravity agent) under the strict guidance of you (the human developer). Our pair-programming workflow operates as follows:

  1. Human Guidance: You provide high-level directions, architectural decisions, and code reviews. You guide the priority of features (like adding hooks, converting to records, or supporting MCP).
  2. Agent Execution: I proactively write the Java code, generate and update tests, build the project, and fix compilation errors.
  3. Proactive Refactoring: Whenever a class is purely carrying data, I should proactively suggest or use Java 21 record structures.
  4. Testing First: Before declaring a feature complete, I will run the test suite and ensure all tests pass (accounting for expected transient localharness network delays).
  5. Documentation & Skill Synchronization: Whenever the Antigravity Java SDK evolves (new features, API changes, hooks, policies, capabilities, etc.), agents MUST proactively update README.md and the official Agent Skill under skills/antigravity-sdk-java/ (SKILL.md and skills/antigravity-sdk-java/references/) to keep developer documentation and AI agent skill guidance synchronized with the codebase.

🛠️ Build & Commands

  • Java Version: Java 21. Agents must ensure they use Java 21 compatible syntax and standard library features.
  • Maven Wrapper: Always use the provided Maven wrapper (./mvnw). Do not rely on globally installed mvn or gradle.
  • Compilation: ./mvnw clean compile
  • Fast Unit Testing: ./mvnw test (Runs fast offline unit tests; @Tag("integration") is excluded by default)
  • Live Integration Testing: ./mvnw test -Pintegration-tests or ./mvnw test -Dgroups=integration
  • Code Formatting: ./mvnw spotless:apply

🎨 Coding Standards

  • No FQNs: Never use Fully Qualified Names (FQNs) directly in the code (e.g., java.util.List<String> list = ...). Always import the classes at the top of the file.
  • Code Formatting: The project uses the Maven Spotless plugin with the Eclipse formatter. Always run ./mvnw spotless:apply and ensure the code passes before committing.
  • License Headers: Spotless will automatically inject the Apache 2.0 license header. Do not manually add copyright headers.

🧪 Testing Guidelines & Strategy

  • Framework: We use JUnit 6 (JUnit Jupiter).
  • Test Categorization (@Tag):
    • Unit Tests (@Tag("unit")): Fast, offline tests evaluating configuration, policies, data structures, and SDK wrappers without invoking localharness or external APIs. These run by default during ./mvnw test.
    • Integration Tests (@Tag("integration")): Live network tests that launch the native localharness Go binary and communicate with remote model APIs. Excluded by default in ./mvnw test; run explicitly via ./mvnw test -Pintegration-tests or -Dgroups=integration.
  • Bounded Futures & Timeouts:
    • Never use unbounded .join(): Always use bounded calls like agent.chat(...).get(45, TimeUnit.SECONDS) or orTimeout(...) to prevent hanging test runs if localharness or the network stalls.
    • Per-Test Timeout: Annotate integration test classes or methods with JUnit 5 @Timeout (e.g., @Timeout(value = 60, unit = TimeUnit.SECONDS)).
  • Asynchronous Assertions: Because agent interactions happen asynchronously over WebSockets and CompletableFutures, never use Thread.sleep() for waiting on agent responses in tests. Always use Awaitility with a tight timeout (e.g., await().atMost(30, TimeUnit.SECONDS)).
  • Resilient Assertions: Avoid rigid string matching on non-deterministic LLM tool responses (e.g. strict lowercased JSON string prefixes). Check for key semantic contents instead to prevent unnecessary retries.

🔄 Upstream Synchronization

Keeping this SDK at feature parity with the upstream Antigravity project requires a rigorous six-step sync process whenever new features are released:

  1. Update the Go Harness Binaries:

    • Execute ./sync-harness.sh. This script scrapes the Python Package Index (PyPI), downloads the latest upstream wheels, extracts the native Go binaries for all supported platforms, and places them in src/main/resources/google/antigravity/bin/.
    • Keep the extracted Python package directory (or unpack to /tmp/antigravity_upstream/) to enable direct Python source diffing.
  2. Accurate Protocol Extraction (Never Guess Field Names):

    • The upstream wheel contains compiled Python descriptors (localharness_pb2.py and content_pb2.py), which embed the serialized FileDescriptorProto.
    • Rule: Never manually guess or hand-edit proto field names (e.g. naming a field complex_user_input instead of user_input). Go's localharness binary uses strict Protobuf unmarshalling and will immediately reject unknown JSON fields with failed to unmarshal: unknown field.
    • Extraction Command: Decompile the serialized descriptor directly from Python:
      import google.protobuf.descriptor_pb2 as d_pb2
      from google.antigravity.proto import localharness_pb2
      proto = d_pb2.FileDescriptorProto()
      localharness_pb2.DESCRIPTOR.CopyToProto(proto)
      print(proto)
    • Update antigravity-sdk-protocol/src/main/proto/localharness.proto to strictly match the extracted descriptor.
  3. Systematic Python SDK Source & Test Audit (Never Skip):

    • Wire descriptors only cover the Go harness contract; high-level developer ergonomics, tool sets, builder options, and policies live in the Python codebase.
    • Run a diff between the previous and new upstream Python source (google/antigravity/):
      • types.py: Check for new/deprecated enum values, updated tool categorization methods (BuiltinTools.deprecated(), minimal(), readOnly(), defaultTools()), and new data structures.
      • connections/ & connection_config.py: Check all builder options across LocalOpenAIAgentConfig, LiteRTAgentConfig, and local agent strategies for forwarded properties (budgets, continuation modes, policies).
      • hooks/policy.py: Check policy function signatures, callbacks (e.g., justification arguments), and decision evaluations.
      • *_test.py: Inspect newly added test cases in types_test.py, local_connection_test.py, policy_test.py, etc. Upstream tests are the authoritative specification for all new behaviors.
  4. Regenerate, Refactor & Create Parity Tests:

    • Recompile protocol and wrapper (./mvnw clean compile).
    • Update wrapper classes and builders to support new options, enums, records, and configs.
    • Create a dedicated unit test suite for the release (e.g. FeatureParity<version>Test.java) systematically verifying all audited diff items before running live tests.
  5. Verify Wire Compatibility & Local Smoke Testing:

    • Run fast unit tests: ./mvnw test
    • Run at least one live integration test against the newly extracted localharness binary (e.g., ./mvnw test -Pintegration-tests -Dtest=InteractiveAskQuestionTest) or run full integration tests (./mvnw test -Pintegration-tests) to verify that the native Go binary successfully unmarshals all InputEvent and HarnessConfig JSON messages over WebSockets.
  6. Update Skill & Documentation:

    • Update README.md and the official Agent Skill (skills/antigravity-sdk-java/SKILL.md and skills/antigravity-sdk-java/references/) with new features, configuration options, and code samples.