Skip to content

feat(runtime): rebuild ACP execution as plugin adapters - #5224

Open
Sun-GLiang wants to merge 2 commits into
apache:mainfrom
Sun-GLiang:feat/antigravity-acp-pr2
Open

Sun-GLiang wants to merge 2 commits into
apache:mainfrom
Sun-GLiang:feat/antigravity-acp-pr2

Conversation

@Sun-GLiang

@Sun-GLiang Sun-GLiang commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR has been rebuilt from the latest main (ea990cab) after #5283 established the generic Plugin-backed Session executor architecture.

  • Add @maka/acp-executor-plugin, a shared ACP Runtime Plugin that exposes ctx.acp.register(ctx, adapter, config) to child Plugin Entries.
  • Add @maka/antigravity-acp-plugin as a thin Antigravity adapter containing only executable/helper validation, launch environment policy, and optional initial model configuration.
  • Route every ACP Agent through feat(runtime): add plugin-backed Session executors #5283's existing PluginExecutorService / PluginExecutorBackend; ACP is not a second backend or Session-routing authority.
  • Extend the generic executor boundary with hosted permission choices and durable text | file_diff tool results.
  • Retain one ACP process and ACP Session per Maka conversation, with cancellation, process-tree cleanup, workspace-contained file callbacks, tool/thought/text projection, and generic ACP config-option application.
  • Persist a conversation continuity marker. After a Host or Plugin restart, an existing external conversation becomes explicitly history-only instead of silently forking into a new ACP Session.

Refs #5103

Architecture

Runtime layers

flowchart LR
  Client["Desktop / CLI / API"]

  subgraph Maka["Maka generic execution authority"]
    Session["Session Manager<br/>executorId"]
    Backend["PluginExecutorBackend<br/>canonical event + interaction bridge"]
    Registry["PluginExecutorService<br/>scoped registry + generation binding"]
  end

  subgraph ACPPlugin["ACP Runtime Plugin"]
    AcpService["ctx.acp<br/>adapter registration"]
    AcpExecutor["AcpExecutor<br/>protocol + process + Session lifecycle"]
  end

  subgraph Adapters["External-Agent adapter plugins"]
    Antigravity["Antigravity adapter<br/>paths + env + model quirks"]
    Future["Future ACP adapter<br/>Cursor / other Agent"]
  end

  Agent["External ACP process"]
  Forms["Hosted Form authority"]
  Transcript["Canonical Session events"]

  Client -->|"create/send with executorId"| Session
  Session --> Backend
  Backend -->|"generation-pinned execute"| Registry
  Registry --> AcpExecutor

  AcpService -->|"wrap adapter as executor"| AcpExecutor
  Antigravity -->|"ctx.acp.register(ctx, adapter, config)"| AcpService
  Future -->|"ctx.acp.register(ctx, adapter, config)"| AcpService
  AcpExecutor <-->|"ACP over stdio"| Agent

  AcpExecutor -->|"PluginExecutorOutputEvent"| Backend
  Backend --> Transcript
  AcpExecutor -->|"requestPermission"| Backend
  Backend <--> Forms
Loading

The key boundary is the generic executor contract. Maka owns routing, binding, canonical persistence, and hosted interactions; the ACP Runtime Plugin owns ACP mechanics; each adapter owns only product-specific launch/configuration differences.

Setup-to-plugin activation

flowchart LR
  Settings["External Agent Settings"] -->|"persist executable"| Policy["RuntimePolicy"]
  Policy --> Coordinator["Builtin External-Agent Plugin Coordinator"]
  Bundles["release-shipped plugin.mjs bundles"] --> Coordinator
  Coordinator -->|"content-addressed install / replace / remove"| RuntimePkg["system package: acp-executor"]
  Coordinator -->|"configured child Entry"| AdapterPkg["system package: antigravity-acp"]
  RuntimePkg --> RuntimeEntry["isolated acp-runtime Entry"]
  RuntimeEntry --> AdapterEntry["antigravity-acp Entry<br/>executable config"]
  AdapterEntry --> Registry["PluginExecutorService inspection"]
Loading

RuntimePolicy remains the durable owner of setup facts. The coordinator creates replaceable derived Plugin packages in dependency order and compares canonical content digests before installation, so restart and repeated reconciliation do not churn Plugin generations. Clearing the setting removes the adapter first and then the shared runtime. Neither Plugin bundle receives RuntimePolicy authority.

Plugin composition and ownership

flowchart TB
  Profile["Profile Plugin root"]
  RuntimeEntry["acp-runtime Entry<br/>package: acp-executor"]
  Service["AcpRuntimeService<br/>provides ctx.acp"]
  AdapterEntry["antigravity-acp Entry<br/>inject: acp"]
  Adapter["AntigravityAcpAdapter"]
  Provider["registered PluginExecutorProvider"]

  Profile --> RuntimeEntry
  RuntimeEntry -->|"owns service lifetime"| Service
  RuntimeEntry -->|"parent Context"| AdapterEntry
  AdapterEntry -->|"inherits ctx.acp"| Service
  AdapterEntry --> Adapter
  Adapter -->|"register(ctx, adapter, config)"| Service
  Service -->|"ctx.executors.register"| Provider
Loading

The Host installs acp-executor as a system-managed package and contributes an isolated acp-runtime profile Entry. External-Agent Entries are mounted below it, so service availability and disposal follow normal Plugin Context/Fiber ownership. The adapter passes its consuming Context explicitly across independently bundled generations; executor registration remains scoped, transactional, generation-pinned, and retired by #5283's existing machinery.

One request lifecycle

sequenceDiagram
  participant User
  participant Session as Maka Session
  participant Backend as PluginExecutorBackend
  participant Service as PluginExecutorService
  participant ACP as ACP Runtime
  participant Agent as External ACP Agent

  User->>Session: send(turn, executorId)
  Session->>Backend: BackendSendInput
  Backend->>Service: execute(binding, request)
  Service->>ACP: execute(request, context)

  alt first prompt for this conversation
    ACP->>Agent: spawn + initialize
    ACP->>Agent: session/new(cwd)
    ACP->>Agent: setConfigOption (optional)
    ACP->>ACP: persist continuity marker
  end

  ACP->>Agent: session/prompt
  Agent-->>ACP: text / thought / tool updates
  ACP-->>Backend: generic output events
  Backend-->>Session: canonical SessionEvents

  opt Agent requests permission
    Agent->>ACP: session/requestPermission
    ACP->>Backend: context.requestPermission
    Backend->>User: Hosted Form
    User-->>Backend: selected / cancelled
    Backend-->>ACP: validated result
    ACP-->>Agent: ACP permission outcome
  end

  Agent-->>ACP: stopReason
  ACP-->>Service: completed / cancelled / failed
  Service-->>Backend: normalized terminal result
  Backend-->>Session: complete / abort / error
Loading

Cancellation flows in the reverse direction through the same chain: Session stop aborts the bound executor call, ACP sends session/cancel, waits for settlement, and force-terminates the process tree only when cooperative cleanup does not finish. Plugin disable/reload/uninstall uses the same retirement and drain path.

Responsibility boundary

Layer Owns Must not own
Maka Runtime executorId routing, scoped registration, generation binding, canonical events, Hosted Forms ACP Session ids, ACP processes, provider-specific models
ACP Runtime Plugin ACP SDK/stdio, process tree, per-conversation ACP Session, file callbacks, cancellation, common config and event projection Desktop selection state, Maka Session routing, Antigravity-specific environment policy
Agent adapter Plugin executor identity, executable/sidecars, arguments/environment, provider-specific config mapping ACP protocol loop, duplicated permission/file/tool plumbing
External Agent model execution and ACP protocol responses Maka persistence and Plugin lifecycle

The Antigravity adapter build is about 2.4 KB; the ACP SDK and shared lifecycle implementation live only in the runtime package. A future ACP provider implements the adapter contract instead of copying process, protocol, file, permission, cancellation, and event-projection code.

Removed from the previous implementation

The rebuild deliberately does not carry forward the old PR's:

  • Host-owned AcpAgentBackend and ACP backend registry;
  • backend: "acp" / externalAgentId Session and Storage branches;
  • external-Agent catalog and Session protocols;
  • renderer hot catalog cache and provider-specific task-entry state;
  • draft/prewarm ACP Session lease;
  • ACP-specific CLI transcript and model-picker forks;
  • WorkHub visual workaround and unrelated E2E coverage.

Those paths either duplicate #5283 or require a future generic executor configuration/selection capability. The installation and authentication foundation already merged in #5164 remains unchanged because it is still live mainline behavior.

Behavior and safety

  • ACP initialize, session/new, prompt, cancellation, and cleanup are shared across adapters.
  • ACP filesystem callbacks reject paths outside the Session workspace, including symlink escapes.
  • Required executables are resolved and checked before process launch.
  • Permission options cross a validated generic executor contract and settle through Maka's Hosted Form authority.
  • ACP diff content is preserved as canonical file_diff tool results; oversized diffs degrade to a bounded summary.
  • Plugin disable, reload, or uninstall aborts active work, drains executor calls, and terminates owned process trees.
  • Historical external conversations never silently continue with a newly created ACP Session after process continuity is lost.

Remaining PR 2 work

PR 2 remains one vertical PR. Work is tracked as four producer-to-consumer minimum sets inside this same PR:

  • Set A — setup facts → active Plugin executor: ship both production bundles, project the PR 1 executable into content-addressed system-managed packages/Entries, and verify real bundle install, idempotent restart/reconcile, config replacement, setting clear, package removal, and executor inspection.
  • Set B — provider catalog → Desktop choice → first ACP prompt: add generic readiness/catalog/configuration inspection (including unavailable/auth-required), Antigravity discovery, existing-menu integration, atomic Session executor/model persistence, and exact first-prompt application without preview Sessions.
  • Set C — ACP interactions → canonical conversation → ACP settlement: add Agent questions, actionable unsupported-input presentation, and ordered interaction/rendering regressions.
  • Set D — process continuity facts → safe task readiness: project history-only/process loss into generic Desktop readiness and repeat controlled-process plus official Antigravity acceptance.

A checklist group is complete only when its producer, boundary contract, real consumer, and acceptance test land together. Dynamic modes and catalog invalidation remain PR 4; restoring the same external Session remains PR 3.

Verification

Current head: 169b969df

Check Result
Workspace TypeScript typecheck Passed
Workspace build, including Desktop renderer Passed
Changed-file Biome checks Passed
Clean Runtime Host suite 1,938 passed, 12 skipped, 0 failed
ACP/Plugin/runtime-policy focused suite 80/80 passed
Desktop architecture suite 112/112 passed
Release/product/Desktop suite 72/72 passed
Production plugin.mjs install/restart/config-clear test Passed
Both Plugin builds and package-content checks Passed
git diff --check and staged ASF header guard Passed

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex contributed architecture analysis, implementation, tests, verification, documentation, and PR preparation. Independent human review remains required.

Checklist

  • Rebuilt on the latest main
  • Removed the superseded ACP-specific architecture
  • Tests cover lifecycle, continuity, cancellation, permission bridging, diff projection, and adapter registration
  • Lint, typecheck, builds, and affected suites pass locally

@Sun-GLiang
Sun-GLiang force-pushed the feat/antigravity-acp-pr2 branch from 9767546 to b278ff0 Compare September 14, 2026 14:09
@Sun-GLiang Sun-GLiang changed the title feat(runtime-host): add ACP connection ownership and sign-in state feat(runtime): rebuild ACP execution as plugin adapters Sep 14, 2026
@github-actions github-actions Bot added effort/XL Under 2500 readable lines and removed effort/XXL Over 2500 readable lines labels Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XL Under 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant