@agentprojectcontext/apx 1.64.0 → 1.65.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/skills/apx/SKILL.md +2 -9
- package/skills/apx-mcp/SKILL.md +8 -5
- package/src/core/apc/scaffold.js +1 -1
- package/src/core/runtime-skills/apx-agency-agents/SKILL.md +1 -1
- package/src/core/runtime-skills/apx-voice/SKILL.md +41 -9
- package/src/core/runtimes/detect.js +21 -1
- package/src/host/daemon/runtimes/antigravity.js +153 -0
- package/src/host/daemon/runtimes/index.js +2 -0
- package/src/interfaces/cli/commands/runtime.js +1 -1
- package/src/interfaces/cli/index.js +3 -3
- package/src/interfaces/cli/postinstall.js +1 -1
- package/src/interfaces/mcp-server/index.js +1 -1
- package/src/interfaces/web/package-lock.json +30 -30
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ APX is opinionated about storage: the filesystem is the source of truth. Project
|
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
58
|
# 1 · Install
|
|
59
|
-
npm install -g apx
|
|
59
|
+
npm install -g @agentprojectcontext/apx
|
|
60
60
|
|
|
61
61
|
# 2 · Set up — interactive wizard (provider → model → channels → daemon)
|
|
62
62
|
apx setup
|
|
@@ -98,7 +98,7 @@ runtime. The session and memory land in `.apc/`.
|
|
|
98
98
|
## Installation
|
|
99
99
|
|
|
100
100
|
```bash
|
|
101
|
-
npm install -g apx
|
|
101
|
+
npm install -g @agentprojectcontext/apx
|
|
102
102
|
```
|
|
103
103
|
|
|
104
104
|
Requires Node.js 20+. The daemon starts automatically on first `apx` call.
|
package/package.json
CHANGED
package/skills/apx/SKILL.md
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apx
|
|
3
|
-
description:
|
|
4
|
-
APX CLI — local daemon that orchestrates agents, sessions, MCPs, and channels across CLIs.
|
|
5
|
-
Use `apx exec "prompt"` for the local super-agent, or `apx run <agent> --runtime <claude-code|codex|opencode|aider|cursor-agent|gemini-cli|qwen-code> "prompt"` to hand the task to another CLI.
|
|
6
|
-
Activate on: 'apx', 'apx exec', 'apx run', 'apx daemon', 'ask codex/claude/opencode/gemini to …', 'have <runtime> do …', 'delegate to another runtime', 'run this in <runtime>', 'route this task to <runtime>'.
|
|
3
|
+
description: Orchestrates agents, sessions, routines, and channels through the APX CLI and local daemon — run the super-agent locally or delegate a task to another coding CLI (Claude Code, Codex, OpenCode, Aider, Cursor, Gemini, Qwen). Triggers: 'apx', 'apx exec', 'apx run', 'apx daemon', 'apx routine', 'delegate to a runtime'.
|
|
7
4
|
homepage: https://github.com/agentprojectcontext/apx
|
|
8
5
|
---
|
|
9
6
|
|
|
@@ -21,7 +18,7 @@ This is the **engine-side** skill: a slim reference for runtimes invoked by APX.
|
|
|
21
18
|
- The user asks you to call APX from inside your session ("send a telegram via apx", "list apx sessions").
|
|
22
19
|
- You're inside an `.apc/` project and want to consult APX-managed state.
|
|
23
20
|
|
|
24
|
-
If you can do the task natively (you're an IDE/CLI with your own tools), prefer that. Only shell out to `apx` when the task is APX-specific.
|
|
21
|
+
If you can do the task natively (you're an IDE/CLI with your own tools), prefer that. Only shell out to `apx` when the task is APX-specific. For anything MCP-related, use the [[apx-mcp]] skill — it's the MCP entry point for agents.
|
|
25
22
|
|
|
26
23
|
---
|
|
27
24
|
|
|
@@ -53,10 +50,6 @@ apx project current # which project resolves from CWD
|
|
|
53
50
|
apx sessions list --engine <claude|codex|opencode> --project <name>
|
|
54
51
|
apx sessions list --dir <path>
|
|
55
52
|
|
|
56
|
-
# MCPs — see the apx-mcp skill for the full guide
|
|
57
|
-
apx mcp list
|
|
58
|
-
apx mcp run <name> <tool> '{"...":"..."}'
|
|
59
|
-
|
|
60
53
|
# Memory (curated, durable facts only)
|
|
61
54
|
apx memory <agent-slug>
|
|
62
55
|
apx memory <agent-slug> --append "<fact>"
|
package/skills/apx-mcp/SKILL.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apx-mcp
|
|
3
|
-
description:
|
|
3
|
+
description: Registers, lists, runs, debugs, and scopes MCP servers in APX — the MCP entry point for agents (shared/runtime/global scopes). In an .apc project, prefer APX-managed MCPs over a built-in client. Triggers: 'add MCP', 'apx mcp', 'list MCPs', 'run an MCP tool', 'MCP failing'.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# apx-mcp
|
|
7
7
|
|
|
8
|
-
APX exposes Model Context Protocol (MCP) servers to agents.
|
|
8
|
+
APX exposes Model Context Protocol (MCP) servers to agents. This is the MCP entry point: when you're in an `.apc/` project, prefer APX-managed MCPs over any built-in MCP client, because APX owns the project's scopes, secrets, and merge order. Run `apx mcp list` first to see what's already registered. (Outside an `.apc/` project, or when APX isn't installed, use your internal MCP.)
|
|
9
|
+
|
|
10
|
+
Three scopes, each in a different file with different rules:
|
|
9
11
|
|
|
10
12
|
| Scope | File | Committed? | Secrets OK? | When |
|
|
11
13
|
|---|---|---|---|---|
|
|
@@ -100,13 +102,14 @@ apx mcp remove github # if github lives in runtime, this errors with a
|
|
|
100
102
|
|
|
101
103
|
```bash
|
|
102
104
|
apx mcp check --project iacrmar # what scopes APX sees + which files exist
|
|
105
|
+
apx mcp tools <name> # list a server's tools (proves it spawned + initialized)
|
|
106
|
+
apx mcp tools <name> <tool> # one tool's input schema + a ready-to-run example
|
|
107
|
+
apx mcp logs <name> # spawn/init log + stderr tail for this server
|
|
103
108
|
apx mcp run <name> <tool> '{...}' # spawn the server and call a tool for real
|
|
104
109
|
apx log -f # tail unified log for spawn errors
|
|
105
110
|
```
|
|
106
111
|
|
|
107
|
-
A server that "doesn't show tools" usually means: the command failed to start (env vars missing, package not found), or the server crashed during initialize.
|
|
108
|
-
|
|
109
|
-
> `apx mcp tools <name>` is a placeholder stub (prints a "coming in v0.2" notice, lists nothing). To verify a server actually spawns, call a tool with `apx mcp run`.
|
|
112
|
+
A server that "doesn't show tools" usually means: the command failed to start (env vars missing, package not found), or the server crashed during initialize. `apx mcp logs <name>` has the spawn/init log and stderr tail — that's the fastest way to see why.
|
|
110
113
|
|
|
111
114
|
## Don't
|
|
112
115
|
|
package/src/core/apc/scaffold.js
CHANGED
|
@@ -194,7 +194,7 @@ export function installIdeSkills(root, targetIds = null) {
|
|
|
194
194
|
|
|
195
195
|
// Discover every bundled skill under skills/<slug>/SKILL.md. Used by
|
|
196
196
|
// installGlobalSkills() so a new skill added to the repo automatically lands
|
|
197
|
-
// on the user's machine after `npm install -g .` (or `npm update -g apx`)
|
|
197
|
+
// on the user's machine after `npm install -g .` (or `npm update -g @agentprojectcontext/apx`)
|
|
198
198
|
// without anyone having to touch this file.
|
|
199
199
|
//
|
|
200
200
|
// Excluded: directory names starting with "." (e.g. .DS_Store).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apx-agency-agents
|
|
3
|
-
description: "APX agent vault — reusable templates (
|
|
3
|
+
description: "APX agent vault — reusable templates (generic dev/marketing/ops/qa/support). Spawn a specialist, list, import into a project, create, or hide/restore a bundled default. Triggers: 'spawn agent', 'use Cody/Rocky/Tessa', 'list agents', 'agent vault', 'import agent', 'new agent'."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# apx-agency-agents — the APX agent vault
|
|
@@ -1,24 +1,46 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apx-voice
|
|
3
3
|
scope: optional
|
|
4
|
-
description: APX
|
|
4
|
+
description: Makes APX speak and configures text-to-speech — Piper (local), ElevenLabs/OpenAI/Gemini (cloud), or a custom OpenAI-compatible server (QVox/Qwen3-TTS), with per-engine emotion tags. Load when configuring a voice engine, adding a custom TTS server, enabling emotion tags, or fixing silent output.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# apx-voice
|
|
8
8
|
|
|
9
|
-
TTS facade in `core/voice/` with
|
|
9
|
+
TTS facade in `core/voice/` with the built-in engines below plus any number of custom OpenAI-compatible endpoints. STT lives separately in `core/voice/transcription.js` (Whisper). The "voice channel" combines both for mic→agent→speaker.
|
|
10
10
|
|
|
11
11
|
## Engines
|
|
12
12
|
|
|
13
13
|
| id | Local? | Needs key? | Notes |
|
|
14
14
|
|---|---|---|---|
|
|
15
|
-
| `piper`
|
|
16
|
-
| `elevenlabs`
|
|
17
|
-
| `openai`
|
|
18
|
-
| `gemini`
|
|
19
|
-
| `
|
|
15
|
+
| `piper` | yes | no | Local, offline. Requires `piper` CLI + `.onnx` model. es_AR-daniela-high recommended. |
|
|
16
|
+
| `elevenlabs` | no | yes | Excellent. Free tier 10k chars/mo. `eleven_multilingual_v2`. |
|
|
17
|
+
| `openai` | no | yes | Reuses `engines.openai.api_key`. `tts-1`. Set `base_url` to point it at a custom endpoint instead. |
|
|
18
|
+
| `gemini` | no | yes | Returns raw L16 PCM — APX wraps in WAV automatically. Supports emotion tags. |
|
|
19
|
+
| `custom:<slug>` | no | maybe | Any OpenAI-compatible TTS server (e.g. QVox / Qwen3-TTS). Config-only `base_url`, own key (often keyless). Supports emotion tags. |
|
|
20
|
+
| `mock` | yes | no | Silent WAV; placeholder for tests. |
|
|
20
21
|
|
|
21
|
-
`auto` probes: piper → elevenlabs → openai → gemini → mock.
|
|
22
|
+
`auto` probes: piper → elevenlabs → openai → gemini → mock (custom providers are never auto-selected — pick one explicitly).
|
|
23
|
+
|
|
24
|
+
## Custom OpenAI-compatible endpoints (QVox / Qwen3-TTS)
|
|
25
|
+
|
|
26
|
+
Point APX at a local or remote OpenAI-compatible `/v1/audio/speech` server without any hardcoding — it's pure config. Two shapes:
|
|
27
|
+
|
|
28
|
+
- `voice.tts.openai.base_url` — reuse the `openai` engine against a custom endpoint.
|
|
29
|
+
- `voice.tts.custom.<slug>` — a named custom provider, surfaces as engine id `custom:<slug>`, backed by the openai adapter.
|
|
30
|
+
|
|
31
|
+
When `base_url` is set, APX additionally forwards the non-OpenAI fields the server understands — `instruct` (base voice, from the style arg), `language`, `temperature` — and defaults the response format to `wav` (stock OpenAI stays `mp3`). A custom endpoint uses **only its own `api_key`** (often none) and never leaks `engines.openai.api_key` / `OPENAI_API_KEY`.
|
|
32
|
+
|
|
33
|
+
## Emotion tags (per-engine capability)
|
|
34
|
+
|
|
35
|
+
Some backends (QVox/Qwen3-TTS, Gemini) accept inline `[tag]` markers and switch speaking emotion per segment while keeping the base voice. This is a **generic per-engine toggle**, not hardcoded to any adapter:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
apx config set voice.tts.custom.qvox.emotions.enabled true
|
|
39
|
+
# optional: restrict the tag set (defaults to the canonical QVox set)
|
|
40
|
+
apx config set voice.tts.custom.qvox.emotions.tags '["happy","sad","excited","calm","whisper","laugh","neutral"]'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Default tags: `happy, sad, excited, angry, calm, whisper, shout, laugh, cry, narrator, neutral`. The voice-mode prompt learns the tag syntax **only when the engine that will actually speak has emotions enabled**. On any engine without tag support, stray `[tags]` are stripped from the displayed text and never read aloud (kept only for the speaking engine's audio).
|
|
22
44
|
|
|
23
45
|
## Concrete CLI calls
|
|
24
46
|
|
|
@@ -47,7 +69,17 @@ Playback uses system binaries (`afplay`, `paplay`, `aplay`, `play`, `ffplay`). I
|
|
|
47
69
|
"piper": { "bin": "piper", "model": "/Users/.../es_AR-daniela-high.onnx" },
|
|
48
70
|
"elevenlabs": { "api_key": "...", "model": "eleven_multilingual_v2", "voice_id": "..." },
|
|
49
71
|
"openai": { "api_key": "...", "model": "tts-1", "voice": "alloy", "format": "mp3" },
|
|
50
|
-
"gemini": { "api_key": "...", "model": "gemini-2.5-flash-preview-tts", "voice": "Aoede" }
|
|
72
|
+
"gemini": { "api_key": "...", "model": "gemini-2.5-flash-preview-tts", "voice": "Aoede", "emotions": { "enabled": true } },
|
|
73
|
+
"custom": {
|
|
74
|
+
"qvox": {
|
|
75
|
+
"label": "QVox local",
|
|
76
|
+
"base_url": "http://127.0.0.1:5111/v1",
|
|
77
|
+
"api_key": "",
|
|
78
|
+
"format": "wav",
|
|
79
|
+
"language": "es",
|
|
80
|
+
"emotions": { "enabled": true }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
51
83
|
}
|
|
52
84
|
}
|
|
53
85
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// We just probe the binary with `--version` (or equivalent) and don't fail if
|
|
3
3
|
// it isn't there — caller decides what to do with absence.
|
|
4
4
|
import { runProcess } from "#host/daemon/runtimes/_spawn.js";
|
|
5
|
+
import { resolveAntigravityCli } from "#host/daemon/runtimes/antigravity.js";
|
|
5
6
|
|
|
6
7
|
const PROBES = [
|
|
7
8
|
// Coding-agent CLIs (runtimes/)
|
|
@@ -12,6 +13,9 @@ const PROBES = [
|
|
|
12
13
|
{ id: "gemini-cli", binary: "gemini", args: ["--version"], category: "runtime" },
|
|
13
14
|
{ id: "cursor-agent",binary: "cursor-agent", args: ["--version"], category: "runtime" },
|
|
14
15
|
{ id: "qwen-code", binary: "qwen", args: ["--version"], category: "runtime" },
|
|
16
|
+
// Antigravity IDE ships its CLI inside the app bundle (not on PATH), so we
|
|
17
|
+
// resolve the absolute path rather than relying on the bare binary name.
|
|
18
|
+
{ id: "antigravity", binary: "antigravity-ide", args: ["--version"], category: "runtime", resolve: resolveAntigravityCli },
|
|
15
19
|
|
|
16
20
|
// Local LLM runners (engines/)
|
|
17
21
|
{ id: "ollama", binary: "ollama", args: ["--version"], category: "engine" },
|
|
@@ -36,8 +40,24 @@ export async function detectAll() {
|
|
|
36
40
|
async function probe(p) {
|
|
37
41
|
const start = Date.now();
|
|
38
42
|
try {
|
|
43
|
+
// Some runtimes (e.g. Antigravity) aren't on PATH — resolve an absolute
|
|
44
|
+
// path first; if the resolver finds nothing, report not-installed early.
|
|
45
|
+
let command = p.binary;
|
|
46
|
+
if (typeof p.resolve === "function") {
|
|
47
|
+
const resolved = p.resolve();
|
|
48
|
+
if (!resolved) {
|
|
49
|
+
return {
|
|
50
|
+
id: p.id,
|
|
51
|
+
binary: p.binary,
|
|
52
|
+
category: p.category,
|
|
53
|
+
installed: false,
|
|
54
|
+
reason: "not found",
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
command = resolved;
|
|
58
|
+
}
|
|
39
59
|
const r = await runProcess({
|
|
40
|
-
command
|
|
60
|
+
command,
|
|
41
61
|
args: p.args,
|
|
42
62
|
timeoutMs: 3000,
|
|
43
63
|
});
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// Google Antigravity runtime adapter.
|
|
2
|
+
//
|
|
3
|
+
// Antigravity ships in two shapes on a machine:
|
|
4
|
+
//
|
|
5
|
+
// 1. `agy` — a HEADLESS agent CLI (the one we want). It has a non-interactive
|
|
6
|
+
// print mode: agy -p "<prompt>" → prints the reply to stdout, so APX can
|
|
7
|
+
// capture the result like any other runtime. This is the preferred path.
|
|
8
|
+
//
|
|
9
|
+
// 2. `antigravity-ide` — the desktop IDE CLI (a VS Code fork). Its `chat`
|
|
10
|
+
// subcommand LAUNCHES THE GUI and shows the reply inside the editor
|
|
11
|
+
// window; it returns nothing on stdout. It cannot feed a result back to
|
|
12
|
+
// APX, so we only use it as a last-resort "launch the GUI" fallback and we
|
|
13
|
+
// say so explicitly.
|
|
14
|
+
//
|
|
15
|
+
// Neither binary is guaranteed to be on PATH: `agy` normally installs to
|
|
16
|
+
// ~/.local/bin; the IDE CLI lives inside the app bundle. We resolve both.
|
|
17
|
+
//
|
|
18
|
+
// Result flow: with `agy` we capture stdout directly. If only the IDE is
|
|
19
|
+
// present, the reply lives in the GUI and can only reach APX via the runtime
|
|
20
|
+
// bridge callback (the in-IDE agent running `apx session close <id> --result`).
|
|
21
|
+
|
|
22
|
+
import fs from "node:fs";
|
|
23
|
+
import os from "node:os";
|
|
24
|
+
import path from "node:path";
|
|
25
|
+
import { runProcess } from "./_spawn.js";
|
|
26
|
+
|
|
27
|
+
const IDE_BUNDLE_REL = "Contents/Resources/app/bin/antigravity-ide";
|
|
28
|
+
|
|
29
|
+
function whichSync(bin) {
|
|
30
|
+
const dirs = (process.env.PATH || "").split(path.delimiter);
|
|
31
|
+
for (const d of dirs) {
|
|
32
|
+
if (!d) continue;
|
|
33
|
+
const p = path.join(d, bin);
|
|
34
|
+
try {
|
|
35
|
+
fs.accessSync(p, fs.constants.X_OK);
|
|
36
|
+
return p;
|
|
37
|
+
} catch {}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function firstExisting(candidates) {
|
|
43
|
+
for (const c of candidates) {
|
|
44
|
+
try {
|
|
45
|
+
if (c && fs.existsSync(c)) return c;
|
|
46
|
+
} catch {}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// The headless `agy` CLI — the real runtime. Returns an absolute path or null.
|
|
52
|
+
export function resolveAgyCli() {
|
|
53
|
+
return (
|
|
54
|
+
whichSync("agy") ||
|
|
55
|
+
firstExisting([
|
|
56
|
+
path.join(os.homedir(), ".local", "bin", "agy"),
|
|
57
|
+
"/usr/local/bin/agy",
|
|
58
|
+
"/opt/homebrew/bin/agy",
|
|
59
|
+
])
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The desktop IDE CLI (GUI). Returns an absolute path or null.
|
|
64
|
+
export function resolveAntigravityIde() {
|
|
65
|
+
const home = os.homedir();
|
|
66
|
+
return (
|
|
67
|
+
whichSync("antigravity-ide") ||
|
|
68
|
+
firstExisting([
|
|
69
|
+
path.join("/Applications/Antigravity IDE.app", IDE_BUNDLE_REL),
|
|
70
|
+
path.join(home, "Applications", "Antigravity IDE.app", IDE_BUNDLE_REL),
|
|
71
|
+
"/usr/share/antigravity-ide/bin/antigravity-ide",
|
|
72
|
+
"/opt/Antigravity IDE/bin/antigravity-ide",
|
|
73
|
+
"/opt/antigravity-ide/bin/antigravity-ide",
|
|
74
|
+
path.join(home, ".local", "share", "antigravity-ide", "bin", "antigravity-ide"),
|
|
75
|
+
path.join(process.env.LOCALAPPDATA || "", "Programs", "Antigravity IDE", "bin", "antigravity-ide.cmd"),
|
|
76
|
+
])
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Used by env detection: Antigravity is "installed" if EITHER binary exists.
|
|
81
|
+
// We prefer `agy` (the headless CLI) since that's what makes it a usable
|
|
82
|
+
// runtime; fall back to the IDE path so detection still reports it as present.
|
|
83
|
+
export function resolveAntigravityCli() {
|
|
84
|
+
return resolveAgyCli() || resolveAntigravityIde();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
id: "antigravity",
|
|
89
|
+
binary: "agy",
|
|
90
|
+
versionFlag: "--version",
|
|
91
|
+
resolveBinary: resolveAntigravityCli,
|
|
92
|
+
|
|
93
|
+
async run({ system, prompt, cwd, env, timeoutMs }) {
|
|
94
|
+
const fullPrompt = system ? `${system}\n\n---\n\n${prompt}` : prompt;
|
|
95
|
+
|
|
96
|
+
// --- Preferred path: headless `agy` print mode (captures the reply) ---
|
|
97
|
+
const agy = resolveAgyCli();
|
|
98
|
+
if (agy) {
|
|
99
|
+
const args = ["--dangerously-skip-permissions"];
|
|
100
|
+
// Bound agy's own wait so it can't hang on the default 5-minute print
|
|
101
|
+
// timeout; leave a little headroom under our own process timeout.
|
|
102
|
+
if (timeoutMs) {
|
|
103
|
+
const secs = Math.max(30, Math.floor(timeoutMs / 1000) - 5);
|
|
104
|
+
args.push("--print-timeout", `${secs}s`);
|
|
105
|
+
}
|
|
106
|
+
args.push("-p", fullPrompt);
|
|
107
|
+
|
|
108
|
+
const r = await runProcess({ command: agy, args, cwd, env, timeoutMs });
|
|
109
|
+
const output = r.stdout.trim();
|
|
110
|
+
return {
|
|
111
|
+
exitCode: r.exitCode,
|
|
112
|
+
output:
|
|
113
|
+
output ||
|
|
114
|
+
"[antigravity] agy ran but returned no text. It may need `agy install` " +
|
|
115
|
+
"or an authenticated session — check `agy models`.",
|
|
116
|
+
stderr: r.stderr,
|
|
117
|
+
externalSessionPath: null,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// --- Fallback: only the desktop IDE is installed (GUI, no capture) ---
|
|
122
|
+
const ide = resolveAntigravityIde();
|
|
123
|
+
if (ide) {
|
|
124
|
+
const r = await runProcess({
|
|
125
|
+
command: ide,
|
|
126
|
+
args: ["chat", "--mode", "agent", "--reuse-window", fullPrompt],
|
|
127
|
+
cwd,
|
|
128
|
+
env,
|
|
129
|
+
timeoutMs,
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
exitCode: r.exitCode,
|
|
133
|
+
output:
|
|
134
|
+
r.stdout.trim() ||
|
|
135
|
+
"[antigravity] no headless `agy` CLI found — handed the prompt to the " +
|
|
136
|
+
"Antigravity IDE (GUI). The reply is shown in the editor, not returned " +
|
|
137
|
+
"to APX. Install the `agy` CLI for headless runs.",
|
|
138
|
+
stderr: r.stderr,
|
|
139
|
+
externalSessionPath: null,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// --- Nothing installed / enabled ---
|
|
144
|
+
return {
|
|
145
|
+
exitCode: -1,
|
|
146
|
+
output:
|
|
147
|
+
"[antigravity] not available: neither the `agy` headless CLI nor the " +
|
|
148
|
+
"Antigravity IDE was found. Install Antigravity and run `agy install`.",
|
|
149
|
+
stderr: "antigravity runtime unavailable (agy / antigravity-ide not found)",
|
|
150
|
+
externalSessionPath: null,
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
};
|
|
@@ -22,6 +22,7 @@ import aider from "./aider.js";
|
|
|
22
22
|
import cursorAgent from "./cursor-agent.js";
|
|
23
23
|
import geminiCli from "./gemini-cli.js";
|
|
24
24
|
import qwenCode from "./qwen-code.js";
|
|
25
|
+
import antigravity from "./antigravity.js";
|
|
25
26
|
|
|
26
27
|
const REGISTRY = {
|
|
27
28
|
"claude-code": claudeCode,
|
|
@@ -31,6 +32,7 @@ const REGISTRY = {
|
|
|
31
32
|
"cursor-agent": cursorAgent,
|
|
32
33
|
"gemini-cli": geminiCli,
|
|
33
34
|
"qwen-code": qwenCode,
|
|
35
|
+
antigravity,
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
export const RUNTIME_IDS = Object.keys(REGISTRY);
|
|
@@ -5,7 +5,7 @@ export async function cmdRun(args) {
|
|
|
5
5
|
const slug = args._[0];
|
|
6
6
|
if (!slug) throw new Error("apx run: usage: apx run <agent> --runtime <id> \"<prompt>\"");
|
|
7
7
|
const runtime = args.flags.runtime === true ? null : args.flags.runtime;
|
|
8
|
-
if (!runtime) throw new Error("apx run: --runtime required (claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code)");
|
|
8
|
+
if (!runtime) throw new Error("apx run: --runtime required (claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code | antigravity)");
|
|
9
9
|
|
|
10
10
|
let prompt = args._.slice(1).join(" ").trim();
|
|
11
11
|
if (!prompt || prompt === "-") {
|
|
@@ -1177,9 +1177,9 @@ const HELP_TOPICS = new Map(Object.entries({
|
|
|
1177
1177
|
run: topic({
|
|
1178
1178
|
title: "apx run",
|
|
1179
1179
|
summary: "Launch a full external runtime session for an agent.",
|
|
1180
|
-
usage: ["apx run <agent> --runtime <claude-code|codex|opencode|aider|cursor-agent|gemini-cli|qwen-code> \"<prompt>\" [--timeout <seconds>] [--project <name|id|path>]"],
|
|
1180
|
+
usage: ["apx run <agent> --runtime <claude-code|codex|opencode|aider|cursor-agent|gemini-cli|qwen-code|antigravity> \"<prompt>\" [--timeout <seconds>] [--project <name|id|path>]"],
|
|
1181
1181
|
options: [
|
|
1182
|
-
["--runtime <id>", "Runtime CLI to launch: claude-code, codex, opencode, aider, cursor-agent, gemini-cli, qwen-code."],
|
|
1182
|
+
["--runtime <id>", "Runtime CLI to launch: claude-code, codex, opencode, aider, cursor-agent, gemini-cli, qwen-code, antigravity."],
|
|
1183
1183
|
["--timeout <seconds>", "Runtime timeout."],
|
|
1184
1184
|
["--project <name|id|path>", "Pin command to a specific project."],
|
|
1185
1185
|
],
|
|
@@ -2102,7 +2102,7 @@ function buildHelp(version) {
|
|
|
2102
2102
|
|
|
2103
2103
|
hSec("Runtimes"),
|
|
2104
2104
|
hCmd("apx run <agent>", 36, "--runtime <id> \"prompt\" --timeout <s>"),
|
|
2105
|
-
` ${H.DI}runtimes: claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code${H.R}`,
|
|
2105
|
+
` ${H.DI}runtimes: claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code | antigravity${H.R}`,
|
|
2106
2106
|
hCmd("apx env detect", 36, "which agent CLIs are installed"),
|
|
2107
2107
|
|
|
2108
2108
|
hSec("Agent-to-Agent"),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Runs automatically after `npm install -g apx` and `npm update -g apx`.
|
|
2
|
+
// Runs automatically after `npm install -g @agentprojectcontext/apx` and `npm update -g @agentprojectcontext/apx`.
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import { refreshApcContextSkill } from "#core/apc/skill-sync.js";
|
|
5
5
|
import { installGlobalSkills } from "#core/apc/scaffold.js";
|
|
@@ -95,7 +95,7 @@ server.tool(
|
|
|
95
95
|
{
|
|
96
96
|
slug: z.string().describe("Agent slug"),
|
|
97
97
|
prompt: z.string().describe("Prompt / task for the agent"),
|
|
98
|
-
runtime: z.string().optional().describe("Runtime: claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code (default: claude-code)"),
|
|
98
|
+
runtime: z.string().optional().describe("Runtime: claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code | antigravity (default: claude-code)"),
|
|
99
99
|
},
|
|
100
100
|
async ({ slug, prompt, runtime }) => {
|
|
101
101
|
const proj = await resolveProject();
|
|
@@ -921,9 +921,9 @@
|
|
|
921
921
|
}
|
|
922
922
|
},
|
|
923
923
|
"node_modules/@radix-ui/primitive": {
|
|
924
|
-
"version": "1.1.
|
|
925
|
-
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.
|
|
926
|
-
"integrity": "sha512-
|
|
924
|
+
"version": "1.1.5",
|
|
925
|
+
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.5.tgz",
|
|
926
|
+
"integrity": "sha512-d86WIWFYNtGA0H/d8exstrTRTp7eWJYlYJbtNofxr/3ljupZYn6EFDG/Qgu/0Kc8v7yMUxySagqJsL1+PdYjWg==",
|
|
927
927
|
"license": "MIT"
|
|
928
928
|
},
|
|
929
929
|
"node_modules/@radix-ui/react-compose-refs": {
|
|
@@ -942,9 +942,9 @@
|
|
|
942
942
|
}
|
|
943
943
|
},
|
|
944
944
|
"node_modules/@radix-ui/react-context": {
|
|
945
|
-
"version": "1.
|
|
946
|
-
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.
|
|
947
|
-
"integrity": "sha512-
|
|
945
|
+
"version": "1.2.0",
|
|
946
|
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.0.tgz",
|
|
947
|
+
"integrity": "sha512-fOE+JtN9rygNZkCnHRBEP0TAvLldlhyOxMsbwFvTP4nAs+nBmfnna+o/Zski2wkmY1YMrFC0aSzsHoLY47iLrg==",
|
|
948
948
|
"license": "MIT",
|
|
949
949
|
"peerDependencies": {
|
|
950
950
|
"@types/react": "*",
|
|
@@ -957,20 +957,20 @@
|
|
|
957
957
|
}
|
|
958
958
|
},
|
|
959
959
|
"node_modules/@radix-ui/react-dialog": {
|
|
960
|
-
"version": "1.1.
|
|
961
|
-
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.
|
|
962
|
-
"integrity": "sha512
|
|
960
|
+
"version": "1.1.19",
|
|
961
|
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.19.tgz",
|
|
962
|
+
"integrity": "sha512-+HhbN2+YtkRgVirjZ2afMeutQRuGOrdkWR5+EFC58SJojGmtyNQwYzgi6tHBpOxvFHefMtPeHdgtjz0BOGxFQg==",
|
|
963
963
|
"license": "MIT",
|
|
964
964
|
"dependencies": {
|
|
965
|
-
"@radix-ui/primitive": "1.1.
|
|
965
|
+
"@radix-ui/primitive": "1.1.5",
|
|
966
966
|
"@radix-ui/react-compose-refs": "1.1.3",
|
|
967
|
-
"@radix-ui/react-context": "1.
|
|
968
|
-
"@radix-ui/react-dismissable-layer": "1.1.
|
|
967
|
+
"@radix-ui/react-context": "1.2.0",
|
|
968
|
+
"@radix-ui/react-dismissable-layer": "1.1.15",
|
|
969
969
|
"@radix-ui/react-focus-guards": "1.1.4",
|
|
970
|
-
"@radix-ui/react-focus-scope": "1.1.
|
|
970
|
+
"@radix-ui/react-focus-scope": "1.1.12",
|
|
971
971
|
"@radix-ui/react-id": "1.1.2",
|
|
972
972
|
"@radix-ui/react-portal": "1.1.13",
|
|
973
|
-
"@radix-ui/react-presence": "1.1.
|
|
973
|
+
"@radix-ui/react-presence": "1.1.7",
|
|
974
974
|
"@radix-ui/react-primitive": "2.1.7",
|
|
975
975
|
"@radix-ui/react-slot": "1.3.0",
|
|
976
976
|
"@radix-ui/react-use-controllable-state": "1.2.3",
|
|
@@ -993,12 +993,12 @@
|
|
|
993
993
|
}
|
|
994
994
|
},
|
|
995
995
|
"node_modules/@radix-ui/react-dismissable-layer": {
|
|
996
|
-
"version": "1.1.
|
|
997
|
-
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.
|
|
998
|
-
"integrity": "sha512-
|
|
996
|
+
"version": "1.1.15",
|
|
997
|
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.15.tgz",
|
|
998
|
+
"integrity": "sha512-b0XaRlzn2QKuo10XyNgi2DAJDf5XC9d1nD3FJcuvCjbR7+4Ad28zmZsLsqx+hvDEzMnRuZaZxZm9gYObV6RmRA==",
|
|
999
999
|
"license": "MIT",
|
|
1000
1000
|
"dependencies": {
|
|
1001
|
-
"@radix-ui/primitive": "1.1.
|
|
1001
|
+
"@radix-ui/primitive": "1.1.5",
|
|
1002
1002
|
"@radix-ui/react-compose-refs": "1.1.3",
|
|
1003
1003
|
"@radix-ui/react-primitive": "2.1.7",
|
|
1004
1004
|
"@radix-ui/react-use-callback-ref": "1.1.2",
|
|
@@ -1035,9 +1035,9 @@
|
|
|
1035
1035
|
}
|
|
1036
1036
|
},
|
|
1037
1037
|
"node_modules/@radix-ui/react-focus-scope": {
|
|
1038
|
-
"version": "1.1.
|
|
1039
|
-
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.
|
|
1040
|
-
"integrity": "sha512-
|
|
1038
|
+
"version": "1.1.12",
|
|
1039
|
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.12.tgz",
|
|
1040
|
+
"integrity": "sha512-jjk/lqTeNL0azUx5ZYzVrl4NgaDIrdzTNE4mABV9yBFI7FQqN7pIgzV1bTleUezP2QiTGA1BFTqY8MegDgWX9A==",
|
|
1041
1041
|
"license": "MIT",
|
|
1042
1042
|
"dependencies": {
|
|
1043
1043
|
"@radix-ui/react-compose-refs": "1.1.3",
|
|
@@ -1102,9 +1102,9 @@
|
|
|
1102
1102
|
}
|
|
1103
1103
|
},
|
|
1104
1104
|
"node_modules/@radix-ui/react-presence": {
|
|
1105
|
-
"version": "1.1.
|
|
1106
|
-
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.
|
|
1107
|
-
"integrity": "sha512-
|
|
1105
|
+
"version": "1.1.7",
|
|
1106
|
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.7.tgz",
|
|
1107
|
+
"integrity": "sha512-zBZ4QM5XG3JRanDmqXYf3MD6th4AFXFmgU6KNMFzUaV6F3uw9I5/zjMUvFriSEn5ewo1nxuibvyxJdmLlDcslA==",
|
|
1108
1108
|
"license": "MIT",
|
|
1109
1109
|
"dependencies": {
|
|
1110
1110
|
"@radix-ui/react-use-layout-effect": "1.1.2"
|
|
@@ -2218,9 +2218,9 @@
|
|
|
2218
2218
|
}
|
|
2219
2219
|
},
|
|
2220
2220
|
"node_modules/caniuse-lite": {
|
|
2221
|
-
"version": "1.0.
|
|
2222
|
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.
|
|
2223
|
-
"integrity": "sha512-
|
|
2221
|
+
"version": "1.0.30001803",
|
|
2222
|
+
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001803.tgz",
|
|
2223
|
+
"integrity": "sha512-g/uHREV2ZpK9qMalCsWaxmA6ol+DX8GYhuf3T40RKoP+oL7vhRJh8LNt73PCjpnR6l14FzfPrB5Yux4PKm2meg==",
|
|
2224
2224
|
"dev": true,
|
|
2225
2225
|
"funding": [
|
|
2226
2226
|
{
|
|
@@ -2580,9 +2580,9 @@
|
|
|
2580
2580
|
"license": "MIT"
|
|
2581
2581
|
},
|
|
2582
2582
|
"node_modules/electron-to-chromium": {
|
|
2583
|
-
"version": "1.5.
|
|
2584
|
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.
|
|
2585
|
-
"integrity": "sha512-
|
|
2583
|
+
"version": "1.5.388",
|
|
2584
|
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.388.tgz",
|
|
2585
|
+
"integrity": "sha512-Pl/aJaqOOxYxda3vcx1IKSJimwYXHDkEnGn0F+kG2EE68dDtx2uCinaS+Vih8Z91B9t8CSAbiF/HKyWcnXjhzw==",
|
|
2586
2586
|
"dev": true,
|
|
2587
2587
|
"license": "ISC"
|
|
2588
2588
|
},
|