Commit Graph
358 Commits
Author SHA1 Message Date
Jaana Dogan 233820befc make tasks immutable and revisit lifecycle management
Make Task manifests fully immutable once created, removing `UpdateTask`
in favor of `CreateTask` and driving lifecycle transitions (suspend,
resume, delete) through dedicated RPCs and event stream processing.

- Proto: Replace `UpdateTask` with `CreateTask` in AX service.
- Proto: Remove mutable `suspend` field from `TaskSpec` and reserve field 2.
- API / Server: Implement `CreateTask` with duplicate name rejection
  (`codes.AlreadyExists`). Update `SuspendTask`, `ResumeTask`, and `DeleteTask`
  to transition status phase and publish lifecycle events.
- Store: Remove redundant `SetTaskSuspended` and `MarkTaskDeleting` methods;
  standardize on `CreateTask`, `UpdateTaskStatus`, `DeleteTask`, and
  `PublishEvent`.
- Controller: Decouple spec reconciliation from task suspension; introduce
  `ReconcileSuspend` to handle checkpointing and pausing actors on Substrate.
- CLI: Update `ax apply` to submit tasks via `CreateTask`.
- Docs: Update design docs and specifications to reflect task immutability.
2026-09-24 04:03:32 -07:00
Alex Jones e6211f84a9 fix(controller): keep task templates stable across lifecycle changes (#390)
Exclude status and the suspend flag from embedded launch configuration so reconciliation reuses the existing template and golden snapshot.
2026-09-24 02:01:21 -07:00
JBD dc4f36cdba Restructure AX into a general-purpose orchestration layer for agentic tasks
AX is undergoing a significant redesign, moving away from a single CLI with
an embedded Python harness toward a general-purpose orchestration layer for
agentic tasks. The repository is reorganized around three binaries: ax-server
exposes a gRPC API for submitting Task manifests, ax-controller runs as a
horizontally scaled reconciler that consumes work from Redis Streams, and
ax-task-runner executes tasks inside sandboxed workers. Task state now lives
in Redis rather than Kubernetes CRDs so the system can handle millions of
short-lived tasks without straining etcd. The legacy Python harness, ATE
client, SQL event log, and skill examples are removed, and new design,
concepts, manifest, networking, runner, and sandbox docs plus Kubernetes
deploy manifests describe the new architecture.
2026-09-19 20:14:43 -07:00
JBD 20760f4e3d Remove redundant attached field and use cmd nil-check 2026-08-19 22:27:44 -07:00
JBD 34d81b78cf Enable sidecar PID tracking 2026-08-19 22:18:15 -07:00
Jaana Dogan 91567b2844 Remove skills.Available in favor of []skills.Group 2026-08-11 23:17:19 -07:00
Jaana Dogan 9faeb23bed Rename harnessConfig to agentConfig across the codebase for consistency 2026-08-11 23:00:48 -07:00
Jaana Dogan 2282424ebc Make the public facing ExecutionService more InteractionsService-like (#339)
We want AX to be compatible with the Interactions API protocol as much as possible. This PR aligns the proto with Steps and with the Interactions semantics. We will follow up with more changes to make it more compatible with Interactions while preserving a `conversation_id` based history model.

`ConversationService` is removed for now until we know what kind of data operations we want to provide for event log management.
2026-08-11 22:52:05 -07:00
Zhengbo Li f327e23b5b skills: add local directory source alongside the registry (#316)
Introduce a local skills source parallel to the Gemini Enterprise Skill
Registry integration. A local source points at a directory already on disk
(a parent dir holding <skill-id>/SKILL.md subfolders, the same layout as
examples/skills and a registry's target_dir); nothing is fetched and the
directory is used as-is.

- New mode-agnostic result shape (internal/skills: Available/Group/Skill) so
  both sources feed the same consumers without either depending on the other.
- internal/skills/local.Discover enumerates enabled local paths, treating
  immediate subfolders with a SKILL.md as skills (subfolder name = id). It is
  fail-safe like registry materialization: a missing/unreadable/empty path is
  logged and skipped, never blocking harness creation.
- config.SkillsConfig gains Local []LocalSkillsConfig (enabled + path) with
  validation; geminienterprise.Materialize now returns skills.Available.
- cliutil combines registry and local groups into one system-instruction
  pointer for the Antigravity Interactions harness. The Antigravity SDK
  harness (SKILLS_DIR-based) is left as a TODO.

Only the interactions harness is wired; tests cover discovery, fail-safe
degradation, config validation, and the examples/skills fixture.
2026-07-28 13:04:19 -07:00
Jaana Dogan 4474dff3cd refactor: move ate package from internal/k8s to internal/ to decouple from Kubernetes dependencies 2026-07-22 12:59:02 -07:00
Jaana Dogan 0f8d4c62ed refactor: remove unused history confirmation utility functions 2026-07-22 12:57:49 -07:00
Jaana Dogan 5ec51983e1 refactor: move antigravity configuration to top-level and rename HarnessesConfig to RegistryConfig 2026-07-22 12:19:30 -07:00
Jaana Dogan bab973e877 refactor: rename seq to step across protocol and internal controller logic 2026-07-22 12:13:19 -07:00
Jaana Dogan a0bfb5fb74 feat: add support for terminating existing orphan processes before starting the Python sidecar 2026-07-22 11:56:37 -07:00
Jaana Dogan 1abc003dca feat: prevent sidecar startup when ReadyFunc indicates the endpoint is already in use 2026-07-22 10:09:23 -07:00
Joyce Liu a34bbebf2d antigravity: remove _resolve_localhost /etc/hosts hack (#328)
google-antigravity 0.1.7's _connect_websocket retries both "localhost"
and "127.0.0.1" when dialing localharness (local_connection.py:993), so
the sidecar no longer needs to patch /etc/hosts for substrate/gVisor
environments where localhost may not resolve.

Ref #325

antigravity: guard conversation_id for safe save_dir use (#312)

harness_server uses the caller-supplied conversation_id directly as a
per-conversation storage directory name (save_dir = state_dir /
conversation_id) before the Antigravity harness ever sees it, so a value
like "../escape" could traverse outside state_dir. Reject an empty id or
one containing a path separator or a "." / ".." component at the boundary
in _run_turn, returning an INVALID_ARGUMENT end frame.

This is intentionally only a path-safety guard, not the id-format
contract. The Antigravity harness owns that: it validates the forwarded
cascade_id (length and character set) per cl/948016352. Keeping the
format rule in one place avoids the two layers drifting.

chore: remove stale docs, gitignore, and Makefile entries (#329)

- CONTRIBUTING.md: drop 'make run-remote' (no such Makefile target)
- .gitignore: remove orphaned entries (local/remote_agent, sandbox-router,
  tasklog, axepp, google-cloud-sdk, test-sandbox-config.yaml)
- Makefile: add missing deps, clean-logs to .PHONY

antigravity: remove vertex env-var override (superseded by AGY 0.1.7) (#331)

* antigravity: remove vertex env-var override (superseded by AGY 0.1.7)

google-antigravity 0.1.7 reads GOOGLE_GENAI_USE_VERTEXAI /
GOOGLE_GENAI_USE_ENTERPRISE + GOOGLE_CLOUD_{PROJECT,LOCATION} natively,
so the sidecar no longer needs _vertex_kwargs_from_env to thread them
into LocalAgentConfig.

- Delete _vertex_kwargs_from_env + VertexKwargs.
- _build_default_config: bare LocalAgentConfig(system_instructions=...).
- _has_credentials: read project/location from env (SDK hydrates them
  onto VertexEndpoint, not LocalAgentConfig).
- Update tests accordingly.

Requires the 0.1.7 bump. Credential resolution is startup-only and
does not touch the save_dir/state_dir resume path.

Ref #325

* antigravity: drop stale _has_credentials docstring note about vertex env override

Interactions: persist interactions harness with durable dir and resume from it (#327)

interactions: make WorkDir authoritative for run_command (#335)

The interactions harness executed run_command relative to the process's
ambient working directory, which is not reliably the agent's workspace: with
no Cwd argument the command ran wherever the process cwd happened to be, and a
model-supplied Cwd (including "/") was honored blindly. As a result tool calls
often ran from "/" instead of the configured workspace (#332).

Make the workspace directory authoritative in the executor rather than relying
on ambient process state:

- Add AntigravityInteractionsConfig.WorkDir (defaults from AX_HARNESS_WORKDIR).
- run_command now resolves its directory via resolveRunDir: no Cwd -> WorkDir;
  relative Cwd -> joined under WorkDir; absolute Cwd -> honored as-is. Empty
  WorkDir preserves the previous process-cwd behavior.
- Add WorkspaceSystemInstruction to orient the agent about its working
  directory so it emits workspace-relative paths, and wire it in cmd/ax.

Fixes #332

Remove the binary (#334)

* Remove the binary

* chore: add e2e directory to .gitignore

* refactor: migrate binary file check to a dedicated workflow file

* fix: restrict binary file check to added, copied, or modified files
2026-07-20 18:22:45 -07:00
Junjie Wang 6afbf90a8f Set workdir for interactions execution. (#324) 2026-07-16 13:25:39 -07:00
Junjie Wang 2db1833113 Handle default harness correctly. (#308) 2026-07-15 20:24:21 -07:00
zbl94 968348aea1 Honor view_file line range and cap result size (#303)
* Honor view_file line range and cap result size

execViewFile read the whole file and ignored the agent's StartLine/EndLine,
so viewing a large file returned its entire content as the tool result --
a ~900KB blob for a 3k-line CSV stalled the following turn.

Implement the Antigravity view_file contract (1-indexed inclusive line range
with slice-notation windowing) plus defensive caps:
- StartLine/EndLine window (neither=first N lines; start-only=next N forward;
  end-only=previous N backward; both=precise range, capped to N).
- viewFileMaxLines / viewFileMaxBytes caps so a large file can never blob.
- ContentOffset honored as the read position within the windowed content.

The result payload is just {"content": ...}; the view_file result schema is
defined server-side, so no extra fields are added.

Adds intArg/intArgOK helpers and tests for windowing, byte cap, offset read,
and range honoring.

* view_file: UTF-8-safe byte cap + pagination metadata

Address review feedback on the byte cap:

- applyByteWindow backs the cut off to the last complete UTF-8 rune so a
  multi-byte character straddling viewFileMaxBytes is never split (raw byte
  slicing could produce invalid UTF-8, corrupting the last char and JSON
  serialization).
- execViewFile returns the metadata the server needs to distinguish a
  complete read from a paginated/byte-truncated one: content, start_line/
  end_line (0-indexed inclusive served range), content_offset,
  line_range_bytes (total bytes of the line range pre-byte-cap), and
  num_lines/num_bytes. The server detects truncation via
  content_offset+len(content) < line_range_bytes and prompts the model to
  resume from that offset.

A paired server change reads these fields instead of hardcoding
start_line=0/end_line=last.

Adds tests for UTF-8 boundary capping, pagination metadata, and resume.
2026-07-15 10:34:14 -07:00
zbl94 37718e20bf Add Gemini Enterprise Skill Registry integration for local harnesses (#300)
Materialize agentskills.io skills from the Gemini Enterprise Skill Registry
(Vertex AI v1beta1) into on-disk folders before the harness starts, so the
built-in harnesses can use registry-hosted skills on the local `ax exec` /
`ax serve` path.

- internal/skills/geminienterprise: harness-agnostic package that reads
  config.SkillsConfig, drives the registry client (ListSkills / GetSkill /
  GetSkillRevision / skills:retrieve), safe-unzips payloads to
  <target_dir>/<skill-id>/, and reports what it wrote. First-wins on
  duplicate ids with a warning; fail-safe (a registry error never blocks
  harness startup).
- config: top-level `skills.registries[]` (harness-agnostic -- each actor
  runs a single harness that consumes the materialized folder). Per-registry
  selection (skills / query / all), required target_dir, and a validated
  "exactly one selection mode" rule. Also wires the interactions harness's
  system_instruction from ax.yaml.
- cliutil: materializes skills once, up front, at controller construction;
  for the interactions harness (no SKILLS_DIR concept) it appends a discovery
  pointer to the system instruction.

Scope: local path only; the substrate/pod path does not yet read ax.yaml.
Verified end-to-end against a live registry (by-id and by-query).
2026-07-14 17:40:31 -07:00
Joyce Liu 9873c87475 antigravity: stop exposing harness state_dir in ax.yaml (#304)
state_dir is an AGY SDK implementation detail (where trajectory /
resume-cursor storage lives), not something AX users should configure.
Remove the yaml surface for both built-in harnesses and derive the path
internally from config.AXAssetsDir().

- config: drop StateDir from AntigravityHarnessConfig and
  AntigravityInteractionsHarnessConfig.
- antigravity: add DefaultStateDir() -> ~/.ax/antigravity/conversations,
  mirroring antigravityinteractions.DefaultStateDir(). cliutil now passes
  this into antigravity.New instead of the yaml value.
- cliutil: interactions harness always uses DefaultStateDir(); drop the
  yaml read + fallback.

The internal APIs (antigravity.New's stateDir arg, the required
AntigravityInteractionsConfig.StateDir field, and the Python sidecar's
--state-dir default) are unchanged -- only the user-facing ax.yaml knob
is removed.

Addresses rakyll's follow-up on #292.
2026-07-14 13:28:49 -07:00
Junjie Wang 8eff724ca6 Interactions actor reads config from yaml. (#302) 2026-07-14 13:03:01 -07:00
Joyce Liu 1b58b0943e Antigravity sidecar state dir from config (#292)
* antigravity: plumb sidecar state_dir from ax.yaml

Sidecar's trajectory storage directory was hardcoded in Python. This
plumbs it through as a yaml config that users can override, matching
the pattern already used for the Interactions harness's state_dir.

Flow:
- ax.yaml: harnesses.antigravity.state_dir (optional; empty = default)
- config.go: AntigravityHarnessConfig.StateDir field (yaml surface only,
  no default logic on the Go side)
- cliutil.go: passes yaml value as-is (empty string when unset)
- antigravity Go client: appends --state-dir arg only when non-empty
- Python sidecar: argparse --state-dir with default
  ~/.ax/antigravity/conversations. Default is a transitional fallback
  for substrate mode (where ActorTemplate doesn't inject the flag yet).
  Removable once substrate can set the field via ActorTemplate.

Servicer's state_dir is required (no fallback) -- production path always
receives it from argparse; tests pass tmp_path.

Verified end-to-end with ax exec:
- No yaml state_dir  -> ~/.ax/antigravity/conversations/{conv_id}/
- yaml state_dir: X  -> X/{conv_id}/
- Different conversations remain isolated across both paths.

Closes part of the local-mode gap in issue #269 (harness_config
contract design); a follow-up will do the same for substrate via
ActorTemplate.

* antigravity: address PR review comments (P1/P2/P3)

- P1: two Python tests referenced tmp_path without declaring the fixture;
  add tmp_path to their signatures.
- P2: state_dir CLI arg was not tilde-expanded, so ~/.ax/... became a
  literal ~ dir. Add .expanduser().
- P3: no Go-side test asserted --state-dir forwarding. Extract
  buildSidecarArgs() as a small pure helper and add table test for the
  empty/non-empty cases, plus a yaml parse test for
  AntigravityHarnessConfig.StateDir.

* antigravity: inline sidecar args build instead of separate helper

Follow-up to review feedback: buildSidecarArgs was overkill for a 3-line
conditional. Move it back into New() inline. Also drops the associated
TestBuildSidecarArgs (the arg-forwarding rule is now covered only by
end-to-end verification).
2026-07-13 09:55:02 -07:00
Junjie Wang c48baf33a0 Update GOOGLE_CLOUD_PROJECT for interactions path. (#294) 2026-07-10 14:34:17 -07:00
Junjie Wang fea5d230db Run Antigravity Interactions as substrate actors (#287)
* Run antigravity interactions as actor.

* Add instructions for users.

* Remove a comment.

* Fix readme format.
2026-07-09 17:44:00 -07:00
zbl94 70a2581d49 Surface server error events in Antigravity Interactions harness (#288)
parseStreamedTurn only handled interaction.* and step.* SSE events; a
server-emitted "error" event fell through the switch and was silently
dropped. The turn then returned as completed-but-empty, which:

  - made a failure (e.g. INVALID_ARGUMENT for a malformed client tool
    result) look like a blank "no response" turn, and
  - persisted the failing interaction's id as a poisoned resume cursor.

Add an "error" case that returns a real error, plus a serverErrorMessage
helper that extracts message/status from the error payload. Now a
turn-level server failure aborts the turn with a descriptive error
instead of being hidden.

Adds tests for the error-event path and serverErrorMessage formatting.
2026-07-09 16:24:27 -07:00
zbl94 fef750f906 Harden Antigravity Interactions harness HTTP client (#285)
* Harden Antigravity Interactions harness HTTP client

Fix a substrate suspend/resume failure and tighten the config surface:

- Disable HTTP keep-alives on the harness's default client. On substrate the
  actor is suspended after a turn and resumed for the next (with a new routable
  IP), which leaves any pooled keep-alive connection stale; reusing it made the
  next turn's request fail. Opening a fresh connection per request avoids that
  at the cost of an extra handshake.
- Remove the public HTTPClient override from AntigravityInteractionsConfig.
  External callers don't configure the harness's transport, and exposing it
  risked silently reintroducing the keep-alive bug. New now always owns its
  (keep-alive-disabled) client; tests inject a fake transport via an unexported
  newWithHTTPClient seam.
- Reorder AntigravityInteractionsConfig fields to list required (Agent,
  StateDir) before optional, with clearer doc comments.

Build and package tests pass.

* Explain why the HTTP transport is cloned, not newly created

Address review feedback: document that cloning DefaultTransport (rather than a
bare &http.Transport{}) is intentional -- it inherits the production defaults
(env proxy, dial/TLS/handshake timeouts, HTTP/2) and only overrides keep-alives.
A fresh empty transport would silently drop those.
2026-07-09 14:08:05 -07:00
Jaana Dogan 7473132078 Setup ~/.ax/antigravity once until a new update arrives (#278)
* Consolidate .ax directory path resolution into a centralized config helper

* refactor: remove unused TargetDir field from SetupOptions in python sidecar tests

* test: update setup test to use HOME directory and verify .ax subdirectory extraction

* refactor: simplify directory path resolution and variable naming in python sidecar setup

* perf: skip redundant file copying and pip installations when dependencies are up to date

* fix: remove redundant check for non-existent requirements file in setup

* refactor: track file updates during extraction to skip unnecessary pip installs

* feat: add progress notification when installing Antigravity SDK

* fix: ensure site-packages directory exists before returning path in setup

* feat: add pypi simple index to pip install command for environment compatibility
2026-07-08 22:08:09 -07:00
Jaana Dogan 81c84f77b2 Embed python artifacts into ax (#276)
* Embed python artifacts into ax

And setup the AGY harness service at runtime.

* refactor: remove directory and file filtering logic from setup walk function

* refactor: rename installRequirements to install in python sidecar setup

* refactor: simplify Sidecar configuration by passing PYTHONPATH directly to Start method and removing unnecessary environment and binary options

* feat: configure pip install to use local site-packages and filter unwanted files during setup

* feat: support appending to PYTHONPATH and update Python setup path resolution

* refactor: remove redundant file filtering in sidecar setup directory traversal

* refactor: simplify python package installation and add PyPI index URL to pip command

* fix: remove extra index URL from pip install command

* refactor: remove Sidecar.Setup method and move asset extraction logic to external standalone function

* refactor: remove PythonPath configuration field from sidecar.Config in favor of direct global pythonPath usage

* test: remove integration test for antigravity sidecar auto-start logic

* fix: add pypi.org extra-index-url to python package installation command

* refactor: remove Stdin support from pythonsidecar configuration and cleanup redundant harness definitions
2026-07-08 19:28:18 -07:00
Junjie Wang 3ed25c7ec5 Antigravity interactions harness registry and config (#277) 2026-07-08 17:43:48 -07:00
JoyceLiu e1400ea634 Auto-start Antigravity Python sidecar from ax exec (#275)
Local mode (the default for ax exec) now forks the Antigravity Python
sidecar via the pythonsidecar package (introduced in #273) so users
don't need to launch the harness server out of band. Modeled after
cmd/ax/harness.go.

AntigravityHarness.New takes an autoStart bool:
- true  (cliutil, local mode): fork the sidecar, wait for TCPReady,
  and install a signal handler that stops the sidecar on
  ctrl-C / SIGTERM. Full lifecycle stays inside antigravity.go so
  callers don't need a registry -> controller -> antigravity
  teardown chain.
- false (e2e demo, unit tests against harnesstest.MockHarnessServer):
  pure gRPC-client constructor, no fork.

Close stops the forked sidecar; the signal-handler goroutine is the
primary caller today.

Tests:
- internal/harness/antigravity/antigravity_test.go covers both
  autoStart paths via TestNew_AutoStartTrue_StubServer_ForksSidecar
  (drives the real fork against a minimal stub Python module on
  PYTHONPATH) and TestNew_AutoStartFalse_NilSidecar.
- cmd/ax/internal/cliutil/cliutil_test.go's DefaultHarness test uses
  the same stub-Python trick to exercise the end-to-end wiring
  through NewControllerFromConfig.

e2e demo (internal/cmd/e2e/main.go) still uses autoStart=false; TODO
notes a companion autoStart=true demo as follow-up.
2026-07-08 12:37:59 -07:00
zbl94 e764d366a5 Serve the Antigravity Interactions harness over HarnessService (#274)
* Serve the Antigravity Interactions harness over HarnessService

Add a Go HarnessService server for the Antigravity Interactions harness so
it can run as a substrate actor, alongside the existing Python sidecar path.

- internal/harness/antigravityinteractions/server.go: Serve(...) stands up
  the gRPC HarnessService (plus gRPC health) and an HTTP /readyz endpoint
  reflecting this server's own serving state, with graceful shutdown on
  ctx-cancel or SIGINT/SIGTERM. Connect adapts the harness onto the wire
  contract: a start frame drives one turn (Start -> Queue -> Run), each agent
  message is streamed as a HarnessResponse{outputs} frame, and the stream
  terminates with exactly one HarnessResponse{end} (COMPLETED/FAILED/
  CANCELED); a mid-stream cancel frame cancels the run.
- cmd/ax/harness.go: add a thin runAntigravityInteractionsHarness(ctx,
  systemInstructions) entrypoint that builds the config and calls Serve; the
  dispatch layer decides when to invoke it.
- server_test.go: bufconn tests for the start->end contract and rejection of
  a non-start first frame.

* Persist resume cursors under .ax/cursors in the work dir

Place the Antigravity Interactions harness resume-cursor StateDir in a
dedicated ".ax/cursors" subdirectory under the actor working directory,
rather than the work dir root. This keeps AX internal state out of the
agent-visible workspace (so it isn't surfaced by list_dir and can't collide
with the agent's files) while staying within the snapshotted filesystem so
it survives snapshot/restore.

* Document why steering is not supported over Connect

Add a comment in the HarnessService Connect loop explaining that mid-run
steering is intentionally unsupported: the execution can accept steering via
Queue, but the HarnessRequest oneof only defines {start, cancel}, so there is
no wire frame to deliver input after start. Multi-turn conversation is
expressed as separate Connect executions that resume via the persisted cursor.

* Persist resume cursors under ~/.ax/cursors

Move the resume-cursor StateDir out of the agent's working directory to a
dedicated ~/.ax/cursors under the user's home directory. The working directory
is the agent's operating surface (it reads and edits files there, including
hidden ones), so keeping AX internal state separate avoids the agent seeing or
clobbering it. If the home directory cannot be resolved, the harness now fails
with an error rather than silently falling back to the current directory.
2026-07-08 09:42:27 -07:00
Jaana Dogan c507098025 Introduce pythonsidecar package (#273)
* Introduce pythonsidecar package

* chore: add Apache 2.0 license headers to pythonsidecar files

* chore: add development todo notes to sidecar configuration struct
2026-07-07 16:50:17 -07:00
Junjie Wang 948ca05b52 Serve /readyz from ax harness server. (#254)
* Serve readyz from ax harness.

* Surface the correct error message from server.
2026-07-06 18:04:28 -07:00
Jaana Dogan e39b1232b2 Move Harness implementations to their own packages (#243)
* Move Harness implementations to their own packages

Fixes #232.

* Shorten the constructor names
2026-07-06 14:00:57 -07:00
Jaana Dogan 72b51a4893 Rename ControllerService to ExecutionService (#242) 2026-07-06 10:30:46 -07:00
Jaana Dogan b8c87febf0 Add traces to the SQL event log implementation (#234) 2026-07-01 10:26:14 -07:00
zbl94 b0e97874a6 Add durable conversation resumability to the Antigravity Interactions harness (#180)
* Add durable conversation resumability to the Antigravity Interactions harness

Introduce a small durable key-value store and use it to persist each
conversation's interaction-chain cursor (the last interaction id), so a
conversation can resume after a process restart instead of starting a new chain.

- internal/storage: a minimal Store interface (Get/Put/Delete + ErrNotFound)
  with documented semantics (atomicity, read-after-write, not-found-vs-error,
  durability) and a single-writer concurrency model. Includes a filesystem
  implementation (FileStore) that writes atomically via temp-file + rename.
- harness: add AntigravityInteractionsConfig.StateStore; Start loads any
  persisted cursor and Run persists it after each successful turn, so a fresh
  Execution for the same conversation continues the existing interaction chain.
- harness: document the single-writer-per-conversation expectation on the
  Harness interface (the controller guarantees it), which is what makes the
  last-write-wins store correct.

Also includes related harness improvements:
- Retry HTTP 429 (rate limit) with exponential backoff + jitter, honoring
  Retry-After; only 429 is retried since it is rejected before any interaction
  is created.
- Terminology cleanup: the within-Run FC/FR loop is the "interaction loop"
  (continuation turns chained via previous_interaction_id), distinct from an
  AX-level resume.

* Scope resume-cursor persistence into the Antigravity Interactions harness

Address PR review feedback: instead of a repo-level internal/storage
key-value abstraction, keep resume-cursor persistence local to the
Antigravity Interactions harness.

- Remove the internal/storage package (Store interface + FileStore).
- Add a harness-local, file-based cursorStore (cursorstore.go) with
  load/save of the per-conversation resumeCursor. resumeCursor stays a
  struct so it can grow (e.g. partial function-call results for
  mid-tool-loop recovery) later.
- Replace Config.StateStore with Config.StateDir. StateDir is now
  required: NewAntigravityInteractionsHarness returns an error if it is
  empty, and the constructor now returns (*Harness, error).
- Add tests with a fake Interactions API (an http.RoundTripper) that
  records each request and returns a canned SSE stream, covering the
  resume-across-restart CUJ (a fresh harness over the same StateDir sends
  the persisted previous_interaction_id), same-harness resume, the
  required-StateDir error, and a cursorStore load/save round-trip.

* Clarify single-writer as a caller expectation, not a controller guarantee

Address PR review: the controller does not currently enforce one Execution
per conversation, so the StateDir doc comment shouldn't claim it does. Phrase
single-writer (last-write-wins, no CAS) as an expectation the caller/deployment
must satisfy -- e.g. sticky routing of a conversation id to one worker, or
resuming a worker from that conversation's snapshot.
2026-07-01 10:00:07 -07:00
Jaana Dogan ee1d8cfd8f Initial commit of the OpenTelemetry trace exposition (#226)
Refactor telemetry configuration and resolve deprecated GCP metadata calls:
- Replace deprecated `metadata.ProjectID()` and `metadata.OnGCE()` with context-aware versions.
- Update `telemetry.SetTraceProvider` to accept variadic `otlptracegrpc.Option`s and remove the hardcoded endpoint parameter.
- Add `telemetry.WithGCPCredentials()` helper to encapsulate GCP-specific credentials.
- Isolate GCP-specific server telemetry configuration into a new `serve_gcp.go` file.

Fix premature gRPC stream cancellation in the harness execution clients:
- Update the client receive loop to drain the stream until `io.EOF` after receiving the `HarnessEnd` frame, preventing `CANCELLED` errors in telemetry.
- Encapsulate the stream draining and message dispatching logic into a shared `drainStream` helper in a new `stream.go` file.
- Clean up unused `io` imports in `antigravity.go` and `substrate.go`.

Follow-up:
- End-to-end trace context propagation to HarnessService deployments
- End-to-end trace context propagation to Substrate calls
2026-06-30 22:47:56 -07:00
Junjie Wang 09beb2d12b Change bucket var name and bump substrate version. (#224)
* Change bucket env var and bump substrate version.

* Add TODO for atespace.
2026-06-29 17:20:14 -07:00
Jaana Dogan 1743290c6c Move Substrate package out of experimental (#214)
Agent Substrate is no longer experimental.
2026-06-29 10:19:28 -07:00
Jaana Dogan 9ce12ed12c Introduce version field to configuration with validation check (#218)
Fixes #217.
2026-06-29 00:04:24 -07:00
Jaana Dogan 78f4a8f229 Add structured Error in HarnessEnd (#215)
- Added Error message to proto
- Removed error_message
- Updated the autogenerated artifacts
2026-06-29 00:03:41 -07:00
Jaana Dogan 22153b43f6 Remove unused skills package (#209) 2026-06-27 04:27:38 -07:00
Jaana Dogan b6fe49a25d Relocate antigravity agent source files from the examples directory (#205)
* Relocate antigravity agent source files from the examples directory

Fixes #188.

* refactor: embed agent.py

* chore: update default antigravity harness address from localhost to 127.0.0.1

* refactor: remove unnecessary localhost resolution from harness server setup
2026-06-26 20:37:10 -07:00
Jaana Dogan 4a7f140d7c Move cmd/e2e to internal/cmd/e2e (#199)
Fixes #187.
2026-06-26 14:53:59 -07:00
Jaana Dogan 2abfec209d Remove dead code from the earlier controller (#196)
* Remove dead code from the earlier controller

Remove the agent package, AgentService related proto messages, and Gemini agents in favor of the new universal agent harness.

* feat: update proto definitions to use google.protobuf.Struct for harness_config and replace agent fields with harness fields in ExecRequest
2026-06-26 14:31:59 -07:00
Junjie Wang fa2a34588e Pass harness config through the incoming request (#193)
* Pass harness config from exec input.

* Update generated proto.

* Add a flag for inline config json.
2026-06-26 12:41:38 -07:00
Jaana Dogan 6d3a5f1798 Remove AgentService (#186) 2026-06-26 08:42:18 -07:00
Jaana Dogan 4aad1a6605 Consolidate controller and config packages by removing v2 suffixes (#179)
Also remove ununsed ExecutionEvent from proto.
2026-06-25 15:32:21 -07:00