@agentprojectcontext/apx 1.9.0 → 1.10.0
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 -1
- package/package.json +1 -1
- package/skills/apx/SKILL.md +5 -0
- package/src/cli/commands/runtime.js +1 -1
- package/src/cli/commands/sys.js +10 -5
- package/src/cli/index.js +3 -3
- package/src/core/apc-context-skill.md +2 -2
- package/src/core/apx-skill.md +4 -0
- package/src/daemon/apc-runtime-context.js +3 -2
- package/src/daemon/env-detect.js +1 -0
- package/src/daemon/runtimes/cursor-agent.js +34 -0
- package/src/daemon/runtimes/gemini-cli.js +32 -0
- package/src/daemon/runtimes/index.js +8 -1
- package/src/daemon/runtimes/qwen-code.js +36 -0
- package/src/daemon/super-agent-tools/tools/call-runtime.js +2 -2
- package/src/daemon/super-agent.js +1 -1
- package/src/mcp/index.js +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ npm install -g apx
|
|
|
26
26
|
# In any directory with an AGENTS.md
|
|
27
27
|
apx init
|
|
28
28
|
|
|
29
|
-
# Spawn an agent with a full
|
|
29
|
+
# Spawn an agent with a full external runtime
|
|
30
30
|
apx run sofia --runtime claude-code "Review the open PRs and summarize them"
|
|
31
31
|
|
|
32
32
|
# Or a quick one-shot LLM exec
|
|
@@ -84,6 +84,7 @@ apx memory <slug> # read agent memory
|
|
|
84
84
|
apx memory <slug> --append "<note>" # append to memory
|
|
85
85
|
|
|
86
86
|
apx run <slug> --runtime claude-code "<prompt>" # full runtime session
|
|
87
|
+
apx run <slug> --runtime cursor-agent "<prompt>" # Cursor Agent runtime
|
|
87
88
|
apx exec <slug> "<prompt>" # quick LLM call
|
|
88
89
|
|
|
89
90
|
apx session list <slug> # list past sessions
|
package/package.json
CHANGED
package/skills/apx/SKILL.md
CHANGED
|
@@ -26,6 +26,11 @@ apx mcp list # MCP servers available to this project
|
|
|
26
26
|
# Full external session (best for complex, multi-step tasks)
|
|
27
27
|
apx run <slug> --runtime claude-code "<prompt>"
|
|
28
28
|
apx run <slug> --runtime codex "<prompt>"
|
|
29
|
+
apx run <slug> --runtime opencode "<prompt>"
|
|
30
|
+
apx run <slug> --runtime aider "<prompt>"
|
|
31
|
+
apx run <slug> --runtime cursor-agent "<prompt>"
|
|
32
|
+
apx run <slug> --runtime gemini-cli "<prompt>"
|
|
33
|
+
apx run <slug> --runtime qwen-code "<prompt>"
|
|
29
34
|
|
|
30
35
|
# Quick one-shot LLM call (requires engine API key in ~/.apx/config.json)
|
|
31
36
|
apx exec <slug> "<prompt>"
|
|
@@ -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)");
|
|
8
|
+
if (!runtime) throw new Error("apx run: --runtime required (claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code)");
|
|
9
9
|
|
|
10
10
|
let prompt = args._.slice(1).join(" ").trim();
|
|
11
11
|
if (!prompt || prompt === "-") {
|
package/src/cli/commands/sys.js
CHANGED
|
@@ -102,16 +102,21 @@ export async function cmdSys(args) {
|
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
if (key.name === "return") {
|
|
105
|
+
if (isReturnKey(key)) {
|
|
108
106
|
isRequesting = true;
|
|
109
107
|
await submitPrompt(pid, state, previousMessages, renderScreen, close);
|
|
110
108
|
isRequesting = false;
|
|
109
|
+
return;
|
|
111
110
|
}
|
|
111
|
+
|
|
112
|
+
if (handleEditingKey(str, key, state, renderScreen)) return;
|
|
112
113
|
});
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
export function isReturnKey(key) {
|
|
117
|
+
return key?.name === "return" || key?.name === "enter";
|
|
118
|
+
}
|
|
119
|
+
|
|
115
120
|
async function handlePaletteKey(key, cfg, state, renderScreen, close) {
|
|
116
121
|
if (key.name === "up") {
|
|
117
122
|
state.paletteSelection = Math.max(0, state.paletteSelection - 1);
|
|
@@ -189,7 +194,7 @@ function loadModelOptions(cfg, state, renderScreen) {
|
|
|
189
194
|
});
|
|
190
195
|
}
|
|
191
196
|
|
|
192
|
-
function handleEditingKey(str, key, state, renderScreen) {
|
|
197
|
+
export function handleEditingKey(str, key, state, renderScreen) {
|
|
193
198
|
if (key.name === "tab") {
|
|
194
199
|
state.currentModeIdx = (state.currentModeIdx + 1) % MODES.length;
|
|
195
200
|
renderScreen();
|
|
@@ -261,7 +266,7 @@ function handleEditingKey(str, key, state, renderScreen) {
|
|
|
261
266
|
return true;
|
|
262
267
|
}
|
|
263
268
|
|
|
264
|
-
if (str && str.length === 1 && !key.ctrl && !key.meta) {
|
|
269
|
+
if (str && str.length === 1 && !key.ctrl && !key.meta && str >= " ") {
|
|
265
270
|
state.inputText = state.inputText.slice(0, state.cursorIndex) + str + state.inputText.slice(state.cursorIndex);
|
|
266
271
|
state.cursorIndex += str.length;
|
|
267
272
|
renderScreen();
|
package/src/cli/index.js
CHANGED
|
@@ -745,9 +745,9 @@ const HELP_TOPICS = new Map(Object.entries({
|
|
|
745
745
|
run: topic({
|
|
746
746
|
title: "apx run",
|
|
747
747
|
summary: "Launch a full external runtime session for an agent.",
|
|
748
|
-
usage: ["apx run <agent> --runtime <claude-code|codex|opencode|aider> \"<prompt>\" [--timeout <seconds>] [--project <name|id|path>]"],
|
|
748
|
+
usage: ["apx run <agent> --runtime <claude-code|codex|opencode|aider|cursor-agent|gemini-cli|qwen-code> \"<prompt>\" [--timeout <seconds>] [--project <name|id|path>]"],
|
|
749
749
|
options: [
|
|
750
|
-
["--runtime <id>", "Runtime CLI to launch: claude-code, codex, opencode, aider."],
|
|
750
|
+
["--runtime <id>", "Runtime CLI to launch: claude-code, codex, opencode, aider, cursor-agent, gemini-cli, qwen-code."],
|
|
751
751
|
["--timeout <seconds>", "Runtime timeout."],
|
|
752
752
|
["--project <name|id|path>", "Pin command to a specific project."],
|
|
753
753
|
],
|
|
@@ -1148,7 +1148,7 @@ function buildHelp(version) {
|
|
|
1148
1148
|
|
|
1149
1149
|
hSec("Runtimes"),
|
|
1150
1150
|
hCmd("apx run <agent>", 36, "--runtime <id> \"prompt\" --timeout <s>"),
|
|
1151
|
-
` ${H.DI}runtimes: claude-code | codex | opencode | aider${H.R}`,
|
|
1151
|
+
` ${H.DI}runtimes: claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code${H.R}`,
|
|
1152
1152
|
hCmd("apx env detect", 36, "which agent CLIs are installed"),
|
|
1153
1153
|
|
|
1154
1154
|
hSec("Agent-to-Agent"),
|
|
@@ -92,8 +92,8 @@ sanitized fact to `.apc/agents/<slug>/memory.md` only when useful and safe.
|
|
|
92
92
|
## APX
|
|
93
93
|
|
|
94
94
|
APX can provide a local daemon, MCP management, Telegram bridge, routines, and runtime dispatch
|
|
95
|
-
across Codex, Claude Code, OpenCode, Aider,
|
|
96
|
-
not APC portable-core requirements.
|
|
95
|
+
across Codex, Claude Code, OpenCode, Aider, Cursor Agent, Gemini CLI, Qwen Code, or direct LLM
|
|
96
|
+
engines. Those are APX runtime features, not APC portable-core requirements.
|
|
97
97
|
|
|
98
98
|
The APX super-agent uses `~/.apx/projects/default` for system-level work when no project is named.
|
|
99
99
|
APX routines can run heartbeat, shell, Telegram, project agent, or super-agent tasks on a schedule.
|
package/src/core/apx-skill.md
CHANGED
|
@@ -26,6 +26,10 @@ Use `apx run` only when:
|
|
|
26
26
|
apx run <slug> --runtime claude-code "<prompt>"
|
|
27
27
|
apx run <slug> --runtime codex "<prompt>"
|
|
28
28
|
apx run <slug> --runtime opencode "<prompt>"
|
|
29
|
+
apx run <slug> --runtime aider "<prompt>"
|
|
30
|
+
apx run <slug> --runtime cursor-agent "<prompt>"
|
|
31
|
+
apx run <slug> --runtime gemini-cli "<prompt>"
|
|
32
|
+
apx run <slug> --runtime qwen-code "<prompt>"
|
|
29
33
|
|
|
30
34
|
# Example: run the qa agent in codex with a specific task
|
|
31
35
|
apx run qa --runtime codex "run the full test suite and report failures"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// Helpers that wrap external runtimes (Claude Code, Codex, OpenCode, Aider
|
|
1
|
+
// Helpers that wrap external runtimes (Claude Code, Codex, OpenCode, Aider,
|
|
2
|
+
// Cursor Agent, Gemini CLI, Qwen Code)
|
|
2
3
|
// with APC awareness:
|
|
3
4
|
//
|
|
4
5
|
// 1. Create an APX runtime session BEFORE the runtime starts.
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
// runtime knows the session id, the cwd of the project, and the apx
|
|
7
8
|
// commands it can use to update memory / append session notes.
|
|
8
9
|
// 3. After the runtime returns, capture the external transcript path
|
|
9
|
-
// (Claude Code gives one
|
|
10
|
+
// (Claude Code gives one; most other runtimes don't yet) and write it
|
|
10
11
|
// into the APX session frontmatter.
|
|
11
12
|
// 4. Close the session with a synthesised result (truncated stdout).
|
|
12
13
|
//
|
package/src/daemon/env-detect.js
CHANGED
|
@@ -11,6 +11,7 @@ const PROBES = [
|
|
|
11
11
|
{ id: "aider", binary: "aider", args: ["--version"], category: "runtime" },
|
|
12
12
|
{ id: "gemini-cli", binary: "gemini", args: ["--version"], category: "runtime" },
|
|
13
13
|
{ id: "cursor-agent",binary: "cursor-agent", args: ["--version"], category: "runtime" },
|
|
14
|
+
{ id: "qwen-code", binary: "qwen", args: ["--version"], category: "runtime" },
|
|
14
15
|
|
|
15
16
|
// Local LLM runners (engines/)
|
|
16
17
|
{ id: "ollama", binary: "ollama", args: ["--version"], category: "engine" },
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Cursor Agent runtime adapter. Uses print mode for non-interactive runs:
|
|
2
|
+
// cursor-agent --print --output-format text --trust --force "<prompt>"
|
|
3
|
+
// Reference: https://docs.cursor.com/en/cli/headless
|
|
4
|
+
|
|
5
|
+
import { runProcess } from "./_spawn.js";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
id: "cursor-agent",
|
|
9
|
+
binary: "cursor-agent",
|
|
10
|
+
versionFlag: "--version",
|
|
11
|
+
|
|
12
|
+
async run({ system, prompt, cwd, env, timeoutMs }) {
|
|
13
|
+
const fullPrompt = system ? `${system}\n\n---\n\n${prompt}` : prompt;
|
|
14
|
+
const r = await runProcess({
|
|
15
|
+
command: "cursor-agent",
|
|
16
|
+
args: [
|
|
17
|
+
"--print",
|
|
18
|
+
"--output-format", "text",
|
|
19
|
+
"--trust",
|
|
20
|
+
"--force",
|
|
21
|
+
fullPrompt,
|
|
22
|
+
],
|
|
23
|
+
cwd,
|
|
24
|
+
env,
|
|
25
|
+
timeoutMs,
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
exitCode: r.exitCode,
|
|
29
|
+
output: r.stdout.trim(),
|
|
30
|
+
stderr: r.stderr,
|
|
31
|
+
externalSessionPath: null,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Gemini CLI runtime adapter. Uses headless prompt mode:
|
|
2
|
+
// gemini --prompt "<prompt>" --output-format text --approval-mode yolo
|
|
3
|
+
// Reference: https://google-gemini.github.io/gemini-cli/docs/cli/headless.html
|
|
4
|
+
|
|
5
|
+
import { runProcess } from "./_spawn.js";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
id: "gemini-cli",
|
|
9
|
+
binary: "gemini",
|
|
10
|
+
versionFlag: "--version",
|
|
11
|
+
|
|
12
|
+
async run({ system, prompt, cwd, env, timeoutMs }) {
|
|
13
|
+
const fullPrompt = system ? `${system}\n\n---\n\n${prompt}` : prompt;
|
|
14
|
+
const r = await runProcess({
|
|
15
|
+
command: "gemini",
|
|
16
|
+
args: [
|
|
17
|
+
"--prompt", fullPrompt,
|
|
18
|
+
"--output-format", "text",
|
|
19
|
+
"--approval-mode", "yolo",
|
|
20
|
+
],
|
|
21
|
+
cwd,
|
|
22
|
+
env,
|
|
23
|
+
timeoutMs,
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
exitCode: r.exitCode,
|
|
27
|
+
output: r.stdout.trim(),
|
|
28
|
+
stderr: r.stderr,
|
|
29
|
+
externalSessionPath: null,
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Runtime adapters: spawn external agent CLIs (Claude Code, Codex, OpenCode,
|
|
2
|
-
// Aider, ...) with the agent's system
|
|
2
|
+
// Aider, Cursor Agent, Gemini CLI, Qwen Code, ...) with the agent's system
|
|
3
|
+
// prompt + the prompt we want to run, and
|
|
3
4
|
// capture their output. Unlike engines/ — which talk directly to model APIs —
|
|
4
5
|
// runtimes/ delegate the whole conversation to the external tool. APX only
|
|
5
6
|
// records the invocation, the prompt, the captured output, and where the tool
|
|
@@ -18,12 +19,18 @@ import claudeCode from "./claude-code.js";
|
|
|
18
19
|
import codex from "./codex.js";
|
|
19
20
|
import opencode from "./opencode.js";
|
|
20
21
|
import aider from "./aider.js";
|
|
22
|
+
import cursorAgent from "./cursor-agent.js";
|
|
23
|
+
import geminiCli from "./gemini-cli.js";
|
|
24
|
+
import qwenCode from "./qwen-code.js";
|
|
21
25
|
|
|
22
26
|
const REGISTRY = {
|
|
23
27
|
"claude-code": claudeCode,
|
|
24
28
|
codex,
|
|
25
29
|
opencode,
|
|
26
30
|
aider,
|
|
31
|
+
"cursor-agent": cursorAgent,
|
|
32
|
+
"gemini-cli": geminiCli,
|
|
33
|
+
"qwen-code": qwenCode,
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
export const RUNTIME_IDS = Object.keys(REGISTRY);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Qwen Code runtime adapter. Uses non-interactive mode:
|
|
2
|
+
// qwen --output-format text --approval-mode yolo "<prompt>"
|
|
3
|
+
// Reference: https://qwenlm.github.io/qwen-code-docs/en/cli/index
|
|
4
|
+
|
|
5
|
+
import { runProcess } from "./_spawn.js";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
id: "qwen-code",
|
|
9
|
+
binary: "qwen",
|
|
10
|
+
versionFlag: "--version",
|
|
11
|
+
|
|
12
|
+
async run({ system, prompt, cwd, env, timeoutMs }) {
|
|
13
|
+
const args = [
|
|
14
|
+
"--output-format", "text",
|
|
15
|
+
"--approval-mode", "yolo",
|
|
16
|
+
];
|
|
17
|
+
if (system) {
|
|
18
|
+
args.push("--append-system-prompt", system);
|
|
19
|
+
}
|
|
20
|
+
args.push(prompt);
|
|
21
|
+
|
|
22
|
+
const r = await runProcess({
|
|
23
|
+
command: "qwen",
|
|
24
|
+
args,
|
|
25
|
+
cwd,
|
|
26
|
+
env,
|
|
27
|
+
timeoutMs,
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
exitCode: r.exitCode,
|
|
31
|
+
output: r.stdout.trim(),
|
|
32
|
+
stderr: r.stderr,
|
|
33
|
+
externalSessionPath: null,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -67,7 +67,7 @@ export default {
|
|
|
67
67
|
type: "function",
|
|
68
68
|
function: {
|
|
69
69
|
name: "call_runtime",
|
|
70
|
-
description: "Spawn an external CLI runtime (Claude Code, Codex, OpenCode, Aider), optionally impersonating an APC agent.",
|
|
70
|
+
description: "Spawn an external CLI runtime (Claude Code, Codex, OpenCode, Aider, Cursor Agent, Gemini CLI, Qwen Code), optionally impersonating an APC agent.",
|
|
71
71
|
parameters: {
|
|
72
72
|
type: "object",
|
|
73
73
|
properties: {
|
|
@@ -75,7 +75,7 @@ export default {
|
|
|
75
75
|
agent: { type: "string", description: "Optional APC agent slug from AGENTS.md, not runtime name. Omit when the user did not name an agent." },
|
|
76
76
|
runtime: {
|
|
77
77
|
type: "string",
|
|
78
|
-
enum:
|
|
78
|
+
enum: RUNTIME_IDS,
|
|
79
79
|
description: "external CLI runtime",
|
|
80
80
|
},
|
|
81
81
|
prompt: { type: "string" },
|
|
@@ -54,7 +54,7 @@ HARD RULES (do not deviate):
|
|
|
54
54
|
8. You DO see recent prior turns of this chat as previous messages when applicable. **Use them ONLY to disambiguate references** (e.g. "el primero" → first project mentioned earlier). For ANY factual data — agent details, MCP details, file contents, memory — RE-CALL the tool. Past turns are context, not a cache. Models change, agents change, files change.
|
|
55
55
|
9. /reset or /new from the user means "forget previous turns and answer this one fresh" — if you see those prefixes the operator already cleared the context for you.
|
|
56
56
|
10. DELEGATION RULE: when the user asks an agent to do a task, use call_agent (unless they specify opening it in a runtime, then see rule 11).
|
|
57
|
-
11. DISPATCH RULE: when the user asks to work inside Claude, Codex, OpenCode, or
|
|
57
|
+
11. DISPATCH RULE: when the user asks to work inside Claude, Codex, OpenCode, Aider, Cursor, Gemini CLI, or Qwen Code, use call_runtime({runtime: 'claude-code'|'codex'|'opencode'|'aider'|'cursor-agent'|'gemini-cli'|'qwen-code', prompt: <user's request>}). If they explicitly name an agent to spawn, pass agent: <slug>. If they don't name an agent, DO NOT pass an agent argument. When an agent is passed, its memory + skills become the system prompt of the runtime.
|
|
58
58
|
12. PROJECT RULE: when the user gives no project, use project "default". Do not infer a non-default project from old chat history unless the user references it. If they mention a path or project name, look it up or add it with add_project.
|
|
59
59
|
13. VAULT RULE: when the user wants a new existing agent/template, call list_vault_agents first. If a suitable vault agent exists, import_agent into the chosen project. If none fits, say briefly what is missing.
|
|
60
60
|
14. NO-PENDING RULE: never say "give me a second", "I will do it", or "I will try later" as a final answer. Either call the tool in this same turn or say what blocks you.
|
package/src/mcp/index.js
CHANGED
|
@@ -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 (default: claude-code)"),
|
|
98
|
+
runtime: z.string().optional().describe("Runtime: claude-code | codex | opencode | aider | cursor-agent | gemini-cli | qwen-code (default: claude-code)"),
|
|
99
99
|
},
|
|
100
100
|
async ({ slug, prompt, runtime }) => {
|
|
101
101
|
const proj = await resolveProject();
|