@agentprojectcontext/apx 1.31.2 → 1.32.2
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/package.json +6 -1
- package/skills/apc-context/SKILL.md +5 -2
- package/skills/apx/SKILL.md +3 -3
- package/skills/apx-agency-agents/SKILL.md +5 -5
- package/skills/apx-agent/SKILL.md +7 -7
- package/skills/apx-mcp/SKILL.md +6 -4
- package/skills/apx-mcp-builder/SKILL.md +4 -7
- package/skills/apx-project/SKILL.md +4 -5
- package/skills/apx-routine/SKILL.md +14 -12
- package/skills/apx-runtime/SKILL.md +5 -3
- package/skills/apx-sessions/SKILL.md +5 -5
- package/skills/apx-skill-builder/SKILL.md +10 -6
- package/skills/apx-task/SKILL.md +8 -8
- package/skills/apx-telegram/SKILL.md +23 -7
- package/skills/apx-voice/SKILL.md +8 -6
- package/src/core/{agent-system.js → agent/build-agent-system.js} +10 -12
- package/src/core/agent/constants.js +5 -0
- package/src/core/agent/index.js +0 -2
- package/src/core/{agent-memory.js → agent/memory.js} +2 -2
- package/src/core/agent/model-router.js +21 -43
- package/src/core/agent/prompt-builder.js +17 -63
- package/src/core/agent/prompts/action-discipline.md +17 -0
- package/src/core/agent/prompts/channels/code.md +8 -12
- package/src/core/agent/prompts/channels/desktop.md +6 -4
- package/src/core/agent/prompts/channels/routine.md +10 -1
- package/src/core/agent/prompts/channels/telegram.md +5 -0
- package/src/core/agent/prompts/channels/web_code.md +20 -0
- package/src/core/agent/prompts/modes/voice.md +2 -2
- package/src/core/agent/prompts/super-agent-base.md +2 -2
- package/src/core/agent/run-agent.js +66 -36
- package/src/core/agent/runtime-bridge.js +42 -0
- package/src/core/agent/self-memory.js +19 -9
- package/src/core/agent/skills/catalog.js +65 -0
- package/src/core/agent/skills/index.js +6 -0
- package/src/{host/daemon/skills-loader.js → core/agent/skills/loader.js} +3 -3
- package/src/core/agent/skills/rag.js +91 -0
- package/src/core/agent/skills/trigger.js +71 -0
- package/src/{host/daemon → core/agent}/super-agent.js +5 -5
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/add-project.js +3 -4
- package/src/core/agent/tools/handlers/ask-questions.js +115 -0
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-agent.js +2 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-mcp.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-runtime.js +10 -11
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/create-task.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/discover-tools.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/edit-file.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/import-agent.js +4 -5
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-agents.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-skills.js +7 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-tasks.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-vault-agents.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/load-skill.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-agent-memory.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-self-memory.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/remember.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/run-shell.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-messages.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-sessions.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/send-telegram.js +0 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/set-identity.js +1 -3
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/set-permission-mode.js +1 -3
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/tail-messages.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/transcribe-audio.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/write-file.js +1 -2
- package/src/core/agent/tools/helpers.js +74 -0
- package/src/{host/daemon/super-agent-tools → core/agent/tools}/registry-bridge.js +3 -3
- package/src/{host/daemon/super-agent-tools/index.js → core/agent/tools/registry.js} +31 -32
- package/src/core/apc/agents-vault.js +37 -0
- package/src/core/{scaffold.js → apc/scaffold.js} +4 -5
- package/src/core/{config.js → config/index.js} +21 -27
- package/src/core/config/paths.js +32 -0
- package/src/core/constants/actors.js +8 -0
- package/src/core/constants/channels.js +19 -0
- package/src/core/constants/index.js +5 -0
- package/src/core/constants/permissions.js +17 -0
- package/src/core/constants/roles.js +9 -0
- package/src/core/engines/_streaming.js +63 -0
- package/src/core/engines/anthropic.js +11 -22
- package/src/core/engines/ollama.js +7 -16
- package/src/core/identity/index.js +8 -0
- package/src/core/{identity.js → identity/self.js} +5 -5
- package/src/core/{telegram-identity.js → identity/telegram.js} +1 -1
- package/src/core/logging.js +1 -1
- package/src/core/mascot.js +1 -1
- package/src/core/memory/active-threads.js +10 -10
- package/src/core/memory/broker.js +9 -9
- package/src/core/memory/compactor.js +2 -2
- package/src/core/memory/index.js +2 -2
- package/src/core/memory/indexer.js +1 -1
- package/src/core/{code-sessions-store.js → stores/code-sessions.js} +3 -7
- package/src/core/{messages-store.js → stores/messages.js} +6 -4
- package/src/core/stores/routine-memory.js +71 -0
- package/src/core/{routines-store.js → stores/routines.js} +1 -3
- package/src/core/stores/runtime-sessions.js +99 -0
- package/src/core/{tasks-store.js → stores/tasks.js} +3 -8
- package/src/core/update-check.js +1 -1
- package/src/core/util/ids.js +14 -0
- package/src/core/util/index.js +2 -0
- package/src/core/util/text-similarity.js +52 -0
- package/src/core/util/time.js +9 -0
- package/src/core/voice/tts.js +1 -1
- package/src/host/daemon/api/admin-config.js +4 -3
- package/src/host/daemon/api/admin.js +1 -1
- package/src/host/daemon/api/agents.js +4 -25
- package/src/host/daemon/api/artifacts.js +118 -1
- package/src/host/daemon/api/code.js +60 -16
- package/src/host/daemon/api/confirm.js +1 -1
- package/src/host/daemon/api/connections.js +2 -2
- package/src/host/daemon/api/conversations.js +2 -2
- package/src/host/daemon/api/deck.js +1 -1
- package/src/host/daemon/api/desktop.js +1 -1
- package/src/host/daemon/api/embeddings.js +4 -4
- package/src/host/daemon/api/engines.js +2 -2
- package/src/host/daemon/api/exec.js +3 -3
- package/src/host/daemon/api/identity.js +1 -1
- package/src/host/daemon/api/mcps.js +1 -1
- package/src/host/daemon/api/messages.js +1 -1
- package/src/host/daemon/api/runtimes.js +9 -8
- package/src/host/daemon/api/sessions-search.js +1 -1
- package/src/host/daemon/api/sessions.js +2 -2
- package/src/host/daemon/api/shared.js +5 -4
- package/src/host/daemon/api/skills.js +30 -0
- package/src/host/daemon/api/super-agent.js +29 -9
- package/src/host/daemon/api/tasks.js +2 -2
- package/src/host/daemon/api/telegram.js +1 -1
- package/src/host/daemon/api/tools.js +6 -6
- package/src/host/daemon/api/tts.js +2 -2
- package/src/host/daemon/api/voice.js +14 -12
- package/src/host/daemon/api.js +2 -0
- package/src/host/daemon/compact.js +1 -1
- package/src/host/daemon/db.js +4 -4
- package/src/host/daemon/desktop-ws.js +1 -1
- package/src/host/daemon/index.js +4 -4
- package/src/host/daemon/plugins/{desktop.js → desktop/index.js} +45 -6
- package/src/host/daemon/plugins/index.js +2 -2
- package/src/host/daemon/plugins/telegram/ask.js +309 -0
- package/src/host/daemon/plugins/{telegram.js → telegram/index.js} +390 -191
- package/src/host/daemon/plugins/telegram/media.js +162 -0
- package/src/host/daemon/projects-helpers.js +54 -0
- package/src/host/daemon/routines.js +28 -12
- package/src/host/daemon/smoke.js +2 -2
- package/src/host/daemon/token-store.js +1 -1
- package/src/host/daemon/transcription.js +2 -2
- package/src/host/daemon/wakeup.js +2 -2
- package/src/interfaces/cli/commands/agent.js +3 -3
- package/src/interfaces/cli/commands/artifact.js +99 -0
- package/src/interfaces/cli/commands/command.js +1 -1
- package/src/interfaces/cli/commands/config.js +3 -2
- package/src/interfaces/cli/commands/desktop.js +1 -1
- package/src/interfaces/cli/commands/exec.js +2 -1
- package/src/interfaces/cli/commands/identity.js +2 -2
- package/src/interfaces/cli/commands/init.js +1 -1
- package/src/interfaces/cli/commands/mcp.js +1 -1
- package/src/interfaces/cli/commands/memory.js +2 -2
- package/src/interfaces/cli/commands/model.js +16 -6
- package/src/interfaces/cli/commands/project.js +1 -1
- package/src/interfaces/cli/commands/routine.js +58 -0
- package/src/interfaces/cli/commands/search.js +1 -1
- package/src/interfaces/cli/commands/session.js +4 -4
- package/src/interfaces/cli/commands/setup.js +4 -3
- package/src/interfaces/cli/commands/skills.js +25 -4
- package/src/interfaces/cli/commands/status.js +1 -1
- package/src/interfaces/cli/commands/sys.js +11 -4
- package/src/interfaces/cli/commands/update.js +1 -1
- package/src/interfaces/cli/index.js +8 -4
- package/src/interfaces/cli/postinstall.js +2 -2
- package/src/interfaces/cli/terminal-chat/renderer.js +22 -2
- package/src/interfaces/mcp-server/index.js +1 -1
- package/src/interfaces/tui/component/prompt/index.tsx +3 -1
- package/src/interfaces/tui/context/sdk-apx.tsx +47 -7
- package/src/interfaces/tui/context/sync-apx.tsx +20 -2
- package/src/interfaces/tui/context/sync.tsx +2 -1
- package/src/interfaces/tui/routes/session/index.tsx +151 -136
- package/src/interfaces/tui/routes/session/sidebar-apx.tsx +37 -15
- package/src/interfaces/tui/run.ts +2 -0
- package/src/interfaces/web/dist/assets/index-34U_Mp1M.css +1 -0
- package/src/interfaces/web/dist/assets/index-BkybwwRn.js +570 -0
- package/src/interfaces/web/dist/assets/index-BkybwwRn.js.map +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/package-lock.json +9 -9
- package/src/interfaces/web/src/App.tsx +51 -32
- package/src/interfaces/web/src/components/RobyBubble.tsx +12 -6
- package/src/interfaces/web/src/components/UiSelect.tsx +1 -1
- package/src/interfaces/web/src/components/chat/AskQuestionsCard.tsx +72 -0
- package/src/interfaces/web/src/components/chat/InlineAskPanel.tsx +399 -0
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +16 -3
- package/src/interfaces/web/src/components/chat/MessageList.tsx +2 -1
- package/src/interfaces/web/src/components/chat/SkillPicker.tsx +77 -0
- package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +230 -0
- package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +1 -1
- package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +40 -17
- package/src/interfaces/web/src/components/common/TabLayout.tsx +9 -5
- package/src/interfaces/web/src/components/common/TabNav.tsx +3 -3
- package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +4 -2
- package/src/interfaces/web/src/hooks/useChat.ts +47 -2
- package/src/interfaces/web/src/hooks/useNavCollapseCtx.tsx +59 -0
- package/src/interfaces/web/src/hooks/usePersonaName.ts +11 -0
- package/src/interfaces/web/src/i18n/en.ts +27 -7
- package/src/interfaces/web/src/i18n/es.ts +27 -7
- package/src/interfaces/web/src/lib/api/artifacts.ts +47 -0
- package/src/interfaces/web/src/lib/api/skills.ts +25 -0
- package/src/interfaces/web/src/lib/api.ts +2 -0
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +41 -20
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +5 -18
- package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +1 -8
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +39 -40
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +27 -9
- package/src/skills/apc-context/SKILL.md +159 -0
- package/src/core/agent/ghost-guard.js +0 -24
- package/src/core/agent/prompts/channels/terminal.md +0 -16
- package/src/host/daemon/apc-runtime-context.js +0 -124
- package/src/host/daemon/super-agent-tools/helpers.js +0 -124
- package/src/host/daemon/super-agent-tools/tools/ask-questions.js +0 -32
- package/src/host/daemon/tool-call-parser.js +0 -2
- package/src/interfaces/web/dist/assets/index-BDUsA6L6.css +0 -1
- package/src/interfaces/web/dist/assets/index-BV615I9p.js +0 -548
- package/src/interfaces/web/dist/assets/index-BV615I9p.js.map +0 -1
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-files.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-mcps.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-projects.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-file.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-files.js +0 -0
- /package/src/core/agent/{pseudo-tools.js → tools/pseudo-tools.js} +0 -0
- /package/src/core/agent/{tool-call-parser.js → tools/tool-call-parser.js} +0 -0
- /package/src/core/{parser.js → apc/parser.js} +0 -0
- /package/src/core/{apc-skill-sync.js → apc/skill-sync.js} +0 -0
- /package/src/core/{artifacts-store.js → stores/artifacts.js} +0 -0
- /package/src/{host/daemon → core/stores}/engine-sessions.js +0 -0
- /package/src/core/{session-store.js → stores/sessions.js} +0 -0
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
1
2
|
import { http } from "../http.js";
|
|
2
3
|
import { resolveProjectId } from "./project.js";
|
|
4
|
+
import { listRoutines } from "#core/stores/routines.js";
|
|
5
|
+
import { projectStorageRoot } from "#core/config/index.js";
|
|
6
|
+
import {
|
|
7
|
+
routineMemoryPath,
|
|
8
|
+
readRoutineMemory,
|
|
9
|
+
appendRoutineMemory,
|
|
10
|
+
ensureRoutineMemory,
|
|
11
|
+
} from "#core/stores/routine-memory.js";
|
|
3
12
|
|
|
4
13
|
function parseSpec(args) {
|
|
5
14
|
// Build spec from --spec '<json>' or from --K=V pairs
|
|
@@ -120,6 +129,55 @@ export async function cmdRoutineRun(args) {
|
|
|
120
129
|
console.log(JSON.stringify(r, null, 2));
|
|
121
130
|
}
|
|
122
131
|
|
|
132
|
+
// Resolve a routine by name OR id to its { id, name, storagePath } so the
|
|
133
|
+
// memory subcommand accepts either argument transparently.
|
|
134
|
+
async function resolveRoutineRef(pid, refRaw) {
|
|
135
|
+
const ref = String(refRaw || "").trim();
|
|
136
|
+
if (!ref) throw new Error("missing <name|id>");
|
|
137
|
+
const projects = await http.get("/projects");
|
|
138
|
+
const project = projects.find((p) => String(p.id) === String(pid));
|
|
139
|
+
if (!project) throw new Error(`project #${pid} not found`);
|
|
140
|
+
const storagePath = project.storage_path || projectStorageRoot(project.apx_id);
|
|
141
|
+
const routines = listRoutines(storagePath);
|
|
142
|
+
const match = routines.find((r) => r.id === ref || r.name === ref);
|
|
143
|
+
if (!match) throw new Error(`routine "${ref}" not found in project #${pid}`);
|
|
144
|
+
return { id: match.id, name: match.name, storagePath };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export async function cmdRoutineMemory(args) {
|
|
148
|
+
const sub = args._[0];
|
|
149
|
+
const ref = args._[1];
|
|
150
|
+
const pid = await resolveProjectId(args?.flags?.project);
|
|
151
|
+
|
|
152
|
+
if (!sub || (sub !== "show" && sub !== "add" && sub !== "path")) {
|
|
153
|
+
throw new Error("usage: apx routine memory <show|add|path> <name|id> [note]");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const { id, name, storagePath } = await resolveRoutineRef(pid, ref);
|
|
157
|
+
const file = routineMemoryPath(storagePath, id);
|
|
158
|
+
|
|
159
|
+
if (sub === "path") {
|
|
160
|
+
console.log(file);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (sub === "show") {
|
|
164
|
+
ensureRoutineMemory(storagePath, id, name);
|
|
165
|
+
const body = readRoutineMemory(storagePath, id);
|
|
166
|
+
if (!body.trim()) {
|
|
167
|
+
console.log(`(empty — ${file})`);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
process.stdout.write(body);
|
|
171
|
+
if (!body.endsWith("\n")) console.log("");
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// add
|
|
175
|
+
const note = args._.slice(2).join(" ").trim();
|
|
176
|
+
if (!note) throw new Error("apx routine memory add: missing <note>");
|
|
177
|
+
const result = appendRoutineMemory(storagePath, id, note, { routineName: name });
|
|
178
|
+
console.log(`appended to ${result.path}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
123
181
|
export async function cmdRoutineHistory(args) {
|
|
124
182
|
const name = args._[0];
|
|
125
183
|
if (!name) throw new Error("apx routine history: missing <name>");
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Uses the daemon's tools/search.js module directly (no HTTP roundtrip,
|
|
4
4
|
// no need to have `apx daemon start` running).
|
|
5
5
|
|
|
6
|
-
import { webSearch } from "
|
|
6
|
+
import { webSearch } from "#core/tools/search.js";
|
|
7
7
|
|
|
8
8
|
const DIM = "\x1b[2m";
|
|
9
9
|
const BOLD = "\x1b[1m";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
|
-
import { findApfRoot, readAgents } from "
|
|
5
|
-
import { getOrCreateApxId } from "
|
|
6
|
-
import { generateSessionId } from "
|
|
7
|
-
import { projectStorageRoot, ensureProjectStorage } from "
|
|
4
|
+
import { findApfRoot, readAgents } from "#core/apc/parser.js";
|
|
5
|
+
import { getOrCreateApxId } from "#core/apc/scaffold.js";
|
|
6
|
+
import { generateSessionId } from "#core/stores/sessions.js";
|
|
7
|
+
import { projectStorageRoot, ensureProjectStorage } from "#core/config/index.js";
|
|
8
8
|
import { http } from "../http.js";
|
|
9
9
|
import { resolveProjectId } from "./project.js";
|
|
10
10
|
import {
|
|
@@ -7,9 +7,10 @@ import https from "node:https";
|
|
|
7
7
|
import http from "node:http";
|
|
8
8
|
import readline from "node:readline";
|
|
9
9
|
import { spawnSync } from "node:child_process";
|
|
10
|
-
import { readConfig, writeConfig } from "
|
|
11
|
-
import { mascot } from "
|
|
10
|
+
import { readConfig, writeConfig } from "#core/config/index.js";
|
|
11
|
+
import { mascot } from "#core/mascot.js";
|
|
12
12
|
import { setupClaudePermissions } from "../claude-permissions.js";
|
|
13
|
+
import { PERMISSION_MODES, DEFAULT_PERMISSION_MODE } from "#core/constants/permissions.js";
|
|
13
14
|
|
|
14
15
|
// ── ANSI helpers ──────────────────────────────────────────────────────────────
|
|
15
16
|
const c = {
|
|
@@ -295,7 +296,7 @@ export async function cmdSetup() {
|
|
|
295
296
|
cfg.super_agent.enabled = true;
|
|
296
297
|
cfg.super_agent.model = chosenModel;
|
|
297
298
|
cfg.super_agent.system = "";
|
|
298
|
-
cfg.super_agent.permission_mode = cfg.super_agent.permission_mode ||
|
|
299
|
+
cfg.super_agent.permission_mode = cfg.super_agent.permission_mode || DEFAULT_PERMISSION_MODE;
|
|
299
300
|
|
|
300
301
|
if (provider.id === "ollama") {
|
|
301
302
|
cfg.engines.ollama.base_url = ollamaUrl;
|
|
@@ -3,14 +3,15 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import readline from "node:readline";
|
|
6
|
-
import { findApfRoot } from "
|
|
6
|
+
import { findApfRoot } from "#core/apc/parser.js";
|
|
7
|
+
import { http } from "../http.js";
|
|
7
8
|
import {
|
|
8
9
|
IDE_TARGETS,
|
|
9
10
|
installIdeSkills,
|
|
10
11
|
installGlobalSkills,
|
|
11
12
|
listBundledSkillSlugs,
|
|
12
13
|
listBundledSkills,
|
|
13
|
-
} from "
|
|
14
|
+
} from "#core/apc/scaffold.js";
|
|
14
15
|
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
17
|
// Prompt helper
|
|
@@ -182,7 +183,27 @@ export async function cmdSkillsSync(args) {
|
|
|
182
183
|
// apx skills list
|
|
183
184
|
// ---------------------------------------------------------------------------
|
|
184
185
|
|
|
185
|
-
export async function cmdSkillsList() {
|
|
186
|
+
export async function cmdSkillsList(args = {}) {
|
|
187
|
+
// --all queries the daemon, which returns project + global + bundled +
|
|
188
|
+
// runtime-skills (same catalog the super-agent sees and the web picker uses).
|
|
189
|
+
// Without --all we only list `.apc/skills/` (what the user installed in
|
|
190
|
+
// THIS project), matching the historical behaviour.
|
|
191
|
+
if (args?.flags?.all) {
|
|
192
|
+
const root = findApfRoot();
|
|
193
|
+
const params = root ? `?project_path=${encodeURIComponent(root)}` : "";
|
|
194
|
+
const out = await http.get(`/skills${params}`);
|
|
195
|
+
if (!out.count) {
|
|
196
|
+
console.log("(no skills available)");
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
console.log(`SLUG`.padEnd(28) + "SOURCE".padEnd(10) + "DESCRIPTION");
|
|
200
|
+
for (const s of out.skills) {
|
|
201
|
+
const desc = (s.description || "").slice(0, 70);
|
|
202
|
+
console.log(s.slug.padEnd(28) + (s.source || "?").padEnd(10) + desc);
|
|
203
|
+
}
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
186
207
|
const root = findApfRoot();
|
|
187
208
|
const skillsDir = root ? path.join(root, ".apc", "skills") : null;
|
|
188
209
|
const files = skillsDir && fs.existsSync(skillsDir)
|
|
@@ -190,7 +211,7 @@ export async function cmdSkillsList() {
|
|
|
190
211
|
: [];
|
|
191
212
|
|
|
192
213
|
if (files.length === 0) {
|
|
193
|
-
console.log("(no skills installed in .apc/skills/)");
|
|
214
|
+
console.log("(no skills installed in .apc/skills/ — try `apx skills list --all` for the full catalog)");
|
|
194
215
|
return;
|
|
195
216
|
}
|
|
196
217
|
for (const f of files) console.log(f.replace(/\.md$/, ""));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// apx status — show full system status at a glance.
|
|
2
2
|
// Daemon, super-agent, engines, telegram, projects.
|
|
3
3
|
|
|
4
|
-
import { readConfig } from "
|
|
4
|
+
import { readConfig } from "#core/config/index.js";
|
|
5
5
|
import { http } from "../http.js";
|
|
6
6
|
|
|
7
7
|
const R = "\x1b[0m";
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import readline from "node:readline";
|
|
2
2
|
import { http } from "../http.js";
|
|
3
3
|
import { resolveProjectId } from "./project.js";
|
|
4
|
-
import { readConfig } from "
|
|
5
|
-
import { readIdentity } from "
|
|
4
|
+
import { readConfig } from "#core/config/index.js";
|
|
5
|
+
import { readIdentity } from "#core/identity/index.js";
|
|
6
|
+
import { CHANNELS } from "#core/constants/channels.js";
|
|
6
7
|
import {
|
|
7
8
|
C,
|
|
8
9
|
MODES,
|
|
@@ -40,12 +41,18 @@ export async function cmdSys(args) {
|
|
|
40
41
|
// Launch new Solid.js TUI via bun (runs TS source directly — no esbuild bundle needed)
|
|
41
42
|
if (existsSync(TUI_SRC)) {
|
|
42
43
|
const bunBin = process.env.BUN_PATH || "bun";
|
|
44
|
+
// bun must resolve node_modules/tsconfig from the apx package root, so the
|
|
45
|
+
// spawn cwd stays there — but we pass the user's actual working directory
|
|
46
|
+
// (where they ran `apx code`) via --cwd so the TUI shows the real project
|
|
47
|
+
// path + git branch instead of apx/src.
|
|
48
|
+
const userCwd = process.cwd();
|
|
43
49
|
spawnSync(bunBin, [
|
|
44
50
|
"--preload", "@opentui/solid/preload",
|
|
45
51
|
TUI_SRC,
|
|
46
52
|
"--pid", pid,
|
|
47
53
|
"--agent", routedAgentSlug || defaultAgentLabel,
|
|
48
54
|
"--model", cfg.super_agent?.model || "claude-3-5-sonnet",
|
|
55
|
+
"--cwd", userCwd,
|
|
49
56
|
], { stdio: "inherit", cwd: resolve(__dirname, "../../..") });
|
|
50
57
|
return;
|
|
51
58
|
}
|
|
@@ -425,7 +432,7 @@ async function handlePaletteKey(key, pid, cfg, state, renderScreen, close) {
|
|
|
425
432
|
!selected.startsWith("No ")
|
|
426
433
|
) {
|
|
427
434
|
state.activeModel = selected;
|
|
428
|
-
const configModule = await import("
|
|
435
|
+
const configModule = await import("#core/config/index.js");
|
|
429
436
|
const currentCfg = configModule.readConfig();
|
|
430
437
|
if (!currentCfg.super_agent) currentCfg.super_agent = {};
|
|
431
438
|
currentCfg.super_agent.model = selected;
|
|
@@ -704,7 +711,7 @@ async function runPrompt(
|
|
|
704
711
|
const currentMode = MODES[state.currentModeIdx];
|
|
705
712
|
const body = {
|
|
706
713
|
prompt: `[Mode: ${currentMode}]\n${text}`,
|
|
707
|
-
channel:
|
|
714
|
+
channel: CHANNELS.CODE,
|
|
708
715
|
channelMeta: { cwd },
|
|
709
716
|
previousMessages,
|
|
710
717
|
model: state.activeModel,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import readline from "node:readline";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { getLatestVersion } from "
|
|
4
|
+
import { getLatestVersion } from "#core/update-check.js";
|
|
5
5
|
|
|
6
6
|
const PACKAGE_NAME = "@agentprojectcontext/apx";
|
|
7
7
|
|
|
@@ -108,8 +108,8 @@ import { cmdSetup } from "./commands/setup.js";
|
|
|
108
108
|
import { cmdStatus } from "./commands/status.js";
|
|
109
109
|
import { cmdModel } from "./commands/model.js";
|
|
110
110
|
import { cmdPair, cmdPairWeb, cmdPairList, cmdPairRevoke } from "./commands/pair.js";
|
|
111
|
-
import { checkForUpdate } from "
|
|
112
|
-
import { mascot } from "
|
|
111
|
+
import { checkForUpdate } from "#core/update-check.js";
|
|
112
|
+
import { mascot } from "#core/mascot.js";
|
|
113
113
|
import {
|
|
114
114
|
cmdRoutineList,
|
|
115
115
|
cmdRoutineGet,
|
|
@@ -119,12 +119,14 @@ import {
|
|
|
119
119
|
cmdRoutineDisable,
|
|
120
120
|
cmdRoutineRun,
|
|
121
121
|
cmdRoutineHistory,
|
|
122
|
+
cmdRoutineMemory,
|
|
122
123
|
} from "./commands/routine.js";
|
|
123
124
|
import {
|
|
124
125
|
cmdArtifactCreate,
|
|
125
126
|
cmdArtifactList,
|
|
126
127
|
cmdArtifactShow,
|
|
127
128
|
cmdArtifactRemove,
|
|
129
|
+
cmdArtifactRun,
|
|
128
130
|
} from "./commands/artifact.js";
|
|
129
131
|
import {
|
|
130
132
|
cmdTaskAdd,
|
|
@@ -1273,12 +1275,14 @@ const HELP_TOPICS = new Map(Object.entries({
|
|
|
1273
1275
|
["create <name>", "Create a new empty artifact. Prints its absolute path."],
|
|
1274
1276
|
["list | ls", "List artifacts in the project."],
|
|
1275
1277
|
["show <name>", "Print artifact content."],
|
|
1278
|
+
["run <name> [args...]", "Execute a runnable artifact (shebang or +x). Stdio is inherited."],
|
|
1276
1279
|
["remove | rm <name>", "Delete an artifact."],
|
|
1277
1280
|
],
|
|
1278
1281
|
examples: [
|
|
1279
1282
|
"apx artifact create check_asana.sh --project 0",
|
|
1280
1283
|
"apx artifact list",
|
|
1281
1284
|
"apx artifact show check_asana.sh",
|
|
1285
|
+
"apx artifact run check_asana.sh",
|
|
1282
1286
|
],
|
|
1283
1287
|
}),
|
|
1284
1288
|
"artifact create": topic({
|
|
@@ -1800,7 +1804,6 @@ const HELP_TOPICS = new Map(Object.entries({
|
|
|
1800
1804
|
const HELP_ALIASES = new Map(Object.entries({
|
|
1801
1805
|
"project ls": "project list",
|
|
1802
1806
|
"project rm": "project remove",
|
|
1803
|
-
"sys": "code",
|
|
1804
1807
|
"agent ls": "agent list",
|
|
1805
1808
|
"agent show": "agent get",
|
|
1806
1809
|
"agent vault ls": "agent vault list",
|
|
@@ -2403,7 +2406,6 @@ async function dispatch(cmd, rest) {
|
|
|
2403
2406
|
break;
|
|
2404
2407
|
|
|
2405
2408
|
case "code":
|
|
2406
|
-
case "sys":
|
|
2407
2409
|
await cmdCode(parseArgs(rest));
|
|
2408
2410
|
break;
|
|
2409
2411
|
|
|
@@ -2478,6 +2480,7 @@ async function dispatch(cmd, rest) {
|
|
|
2478
2480
|
else if (sub === "disable") await cmdRoutineDisable(a);
|
|
2479
2481
|
else if (sub === "run") await cmdRoutineRun(a);
|
|
2480
2482
|
else if (sub === "history" || sub === "hist") await cmdRoutineHistory(a);
|
|
2483
|
+
else if (sub === "memory" || sub === "mem") await cmdRoutineMemory(a);
|
|
2481
2484
|
else die(`unknown routine subcommand: ${sub}`);
|
|
2482
2485
|
break;
|
|
2483
2486
|
}
|
|
@@ -2490,6 +2493,7 @@ async function dispatch(cmd, rest) {
|
|
|
2490
2493
|
else if (sub === "create" || sub === "new") await cmdArtifactCreate(a);
|
|
2491
2494
|
else if (sub === "show" || sub === "get") await cmdArtifactShow(a);
|
|
2492
2495
|
else if (sub === "remove" || sub === "rm") await cmdArtifactRemove(a);
|
|
2496
|
+
else if (sub === "run") await cmdArtifactRun(a);
|
|
2493
2497
|
else die(`unknown artifact subcommand: ${sub}`);
|
|
2494
2498
|
break;
|
|
2495
2499
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Runs automatically after `npm install -g apx` and `npm update -g apx`.
|
|
3
3
|
import os from "node:os";
|
|
4
|
-
import { refreshApcContextSkill } from "
|
|
5
|
-
import { installGlobalSkills } from "
|
|
4
|
+
import { refreshApcContextSkill } from "#core/apc/skill-sync.js";
|
|
5
|
+
import { installGlobalSkills } from "#core/apc/scaffold.js";
|
|
6
6
|
|
|
7
7
|
try {
|
|
8
8
|
const refresh = process.env.APX_SKIP_SKILL_REFRESH
|
|
@@ -326,11 +326,31 @@ function transcriptLines(transcript, width) {
|
|
|
326
326
|
if (isQuestion && trace.args?.questions) {
|
|
327
327
|
addLine(lines, "", C.bg);
|
|
328
328
|
addLine(lines, margin + label + C.muted + " (…)" + C.bg, C.bg);
|
|
329
|
-
for (const
|
|
330
|
-
|
|
329
|
+
for (const rawQ of trace.args.questions) {
|
|
330
|
+
// Rich shape: {question, options[], multiSelect, allowText}. Legacy: string.
|
|
331
|
+
const q = typeof rawQ === "string" ? { question: rawQ } : (rawQ || {});
|
|
332
|
+
const qText = typeof q.question === "string" ? q.question : "";
|
|
333
|
+
if (!qText) continue;
|
|
334
|
+
const qWrapped = wrapText(`• ${qText}`, inner - 2);
|
|
331
335
|
for (const line of qWrapped) {
|
|
332
336
|
addLine(lines, margin + C.primary + "┃ " + C.text + padAnsi(line, inner - 2), C.bg);
|
|
333
337
|
}
|
|
338
|
+
const opts = Array.isArray(q.options) ? q.options : [];
|
|
339
|
+
if (opts.length > 0) {
|
|
340
|
+
const marker = q.multiSelect ? "[ ]" : "( )";
|
|
341
|
+
opts.forEach((opt, i) => {
|
|
342
|
+
const label = (opt && typeof opt === "object" && typeof opt.label === "string")
|
|
343
|
+
? opt.label
|
|
344
|
+
: (typeof opt === "string" ? opt : "");
|
|
345
|
+
if (!label) return;
|
|
346
|
+
const desc = (opt && typeof opt === "object" && typeof opt.description === "string")
|
|
347
|
+
? ` — ${opt.description}` : "";
|
|
348
|
+
const optLine = ` ${marker} ${i + 1}. ${label}${desc}`;
|
|
349
|
+
for (const line of wrapText(optLine, inner - 2)) {
|
|
350
|
+
addLine(lines, margin + C.primary + "┃ " + C.muted + padAnsi(line, inner - 2), C.bg);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
334
354
|
}
|
|
335
355
|
} else {
|
|
336
356
|
addLine(lines, margin + label + " " + name + C.bg, C.bg);
|
|
@@ -18,7 +18,7 @@ import { fileURLToPath } from "node:url";
|
|
|
18
18
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19
19
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
20
20
|
import { z } from "zod";
|
|
21
|
-
import { findApfRoot } from "
|
|
21
|
+
import { findApfRoot } from "#core/apc/parser.js";
|
|
22
22
|
import { ensureDaemon, http } from "../../cli/http.js";
|
|
23
23
|
|
|
24
24
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -1569,7 +1569,9 @@ export function Prompt(props: PromptProps) {
|
|
|
1569
1569
|
{(agent) => (
|
|
1570
1570
|
<>
|
|
1571
1571
|
<text fg={fadeColor(highlight(), agentMetaAlpha())}>
|
|
1572
|
-
{
|
|
1572
|
+
{/* APX: show the coding mode (Build) here, not the agent —
|
|
1573
|
+
the agent (Roby) is shown in the sidebar. */}
|
|
1574
|
+
{store.mode === "shell" ? "Shell" : "Build"}
|
|
1573
1575
|
</text>
|
|
1574
1576
|
<Show when={store.mode === "normal"}>
|
|
1575
1577
|
<box flexDirection="row" gap={1}>
|
|
@@ -4,10 +4,23 @@ import { onCleanup } from "solid-js"
|
|
|
4
4
|
import fs from "node:fs"
|
|
5
5
|
import os from "node:os"
|
|
6
6
|
import path from "node:path"
|
|
7
|
-
import { spawn } from "node:child_process"
|
|
7
|
+
import { spawn, execSync } from "node:child_process"
|
|
8
8
|
|
|
9
9
|
const TOKEN_PATH = path.join(os.homedir(), ".apx", "daemon.token")
|
|
10
10
|
|
|
11
|
+
/** Current git branch for `dir`, or "" when not a repo. Cheap, best-effort. */
|
|
12
|
+
function gitBranch(dir: string): string {
|
|
13
|
+
try {
|
|
14
|
+
return execSync("git rev-parse --abbrev-ref HEAD", {
|
|
15
|
+
cwd: dir,
|
|
16
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
}).trim()
|
|
19
|
+
} catch {
|
|
20
|
+
return ""
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
11
24
|
function readToken(): string {
|
|
12
25
|
try {
|
|
13
26
|
return fs.readFileSync(TOKEN_PATH, "utf8").trim()
|
|
@@ -74,10 +87,21 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|
|
74
87
|
prompt: string,
|
|
75
88
|
previousMessages: Array<{ role: string; content: string }> = [],
|
|
76
89
|
) {
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
// the
|
|
80
|
-
|
|
90
|
+
// Run on the `code` channel and hand the daemon our working directory so
|
|
91
|
+
// the agent knows WHERE it is (CWD/project) — otherwise it falls back to
|
|
92
|
+
// the generic API channel with no cwd and asks "which file? which project?".
|
|
93
|
+
// maxIters gives room to chain read→edit→verify; the code.md prompt already
|
|
94
|
+
// carries the "keep going until done" guidance. We deliberately do NOT send
|
|
95
|
+
// completionContract here — on weaker models (e.g. gemini-flash) the hard
|
|
96
|
+
// loop-until-finish contract causes runaway edit/rewrite loops.
|
|
97
|
+
const body: Record<string, unknown> = {
|
|
98
|
+
prompt,
|
|
99
|
+
previousMessages,
|
|
100
|
+
channel: "code",
|
|
101
|
+
channelMeta: { cwd: props.directory ?? process.cwd() },
|
|
102
|
+
maxIters: 40,
|
|
103
|
+
maxTokens: 8192,
|
|
104
|
+
}
|
|
81
105
|
if (currentModel) body.model = currentModel
|
|
82
106
|
const res = await fetch(`${props.url}/projects/${props.pid}/super-agent/chat/stream`, {
|
|
83
107
|
method: "POST",
|
|
@@ -101,7 +125,12 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|
|
101
125
|
const reader = res.body.getReader()
|
|
102
126
|
const dec = new TextDecoder()
|
|
103
127
|
let buf = ""
|
|
104
|
-
|
|
128
|
+
// The daemon may keep the HTTP connection open after the final event, so
|
|
129
|
+
// we can't rely on stream-close to know the turn is done. Resolve as soon
|
|
130
|
+
// as we see `final` or `error` — otherwise the caller's `await` hangs and
|
|
131
|
+
// the next message queues forever.
|
|
132
|
+
let finished = false
|
|
133
|
+
while (!finished) {
|
|
105
134
|
const { done, value } = await reader.read()
|
|
106
135
|
if (done) break
|
|
107
136
|
buf += dec.decode(value, { stream: true })
|
|
@@ -158,16 +187,25 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|
|
158
187
|
usage: ev.result?.usage,
|
|
159
188
|
name: ev.result?.name,
|
|
160
189
|
})
|
|
190
|
+
finished = true
|
|
161
191
|
break
|
|
162
192
|
case "error":
|
|
163
193
|
emitter.emit("event", { type: "error", sessionID, error: ev.error })
|
|
194
|
+
finished = true
|
|
164
195
|
break
|
|
165
196
|
}
|
|
166
197
|
} catch {
|
|
167
198
|
// ignore parse errors for partial lines
|
|
168
199
|
}
|
|
200
|
+
if (finished) break
|
|
169
201
|
}
|
|
170
202
|
}
|
|
203
|
+
// Stop reading and release the connection so the awaiting caller resumes.
|
|
204
|
+
try {
|
|
205
|
+
await reader.cancel()
|
|
206
|
+
} catch {
|
|
207
|
+
/* already closed */
|
|
208
|
+
}
|
|
171
209
|
}
|
|
172
210
|
|
|
173
211
|
// The APX daemon has no generic "create session" route — a chat turn is
|
|
@@ -296,8 +334,10 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|
|
296
334
|
// passed, show "APX" in the sidebar.
|
|
297
335
|
agent: props.agent ?? "APX",
|
|
298
336
|
model: props.model ?? "claude-3-5-sonnet",
|
|
299
|
-
//
|
|
337
|
+
// Working directory (the user's project root, passed via --cwd) and its
|
|
338
|
+
// current git branch — shown in the sidebar / footer like OpenCode.
|
|
300
339
|
directory: props.directory ?? process.cwd(),
|
|
340
|
+
branch: gitBranch(props.directory ?? process.cwd()),
|
|
301
341
|
event: emitter,
|
|
302
342
|
client,
|
|
303
343
|
streamChat,
|
|
@@ -45,6 +45,10 @@ export interface ApxMessage {
|
|
|
45
45
|
/** shell: process exit code (undefined while running) */
|
|
46
46
|
exitCode?: number | null
|
|
47
47
|
createdAt: number
|
|
48
|
+
/** assistant: model that produced the turn (from model_start). */
|
|
49
|
+
model?: string
|
|
50
|
+
/** assistant: when the final answer landed (for response-time display). */
|
|
51
|
+
completedAt?: number
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
export interface ApxUsage {
|
|
@@ -133,9 +137,11 @@ export const { use: useApxSync, provider: ApxSyncProvider } = createSimpleContex
|
|
|
133
137
|
pushUser(event.sessionID, event.text)
|
|
134
138
|
break
|
|
135
139
|
|
|
136
|
-
case "model_start":
|
|
137
|
-
ensureAssistant(event.sessionID)
|
|
140
|
+
case "model_start": {
|
|
141
|
+
const id = ensureAssistant(event.sessionID)
|
|
142
|
+
if (event.model) patchAssistant(event.sessionID, id, (msg) => { if (!msg.model) msg.model = event.model })
|
|
138
143
|
break
|
|
144
|
+
}
|
|
139
145
|
|
|
140
146
|
case "assistant_text": {
|
|
141
147
|
if (!event.text) break
|
|
@@ -205,6 +211,7 @@ export const { use: useApxSync, provider: ApxSyncProvider } = createSimpleContex
|
|
|
205
211
|
const id = activeAssistant.id
|
|
206
212
|
patchAssistant(sessionID, id, (msg) => {
|
|
207
213
|
msg.streaming = false
|
|
214
|
+
msg.completedAt = Date.now()
|
|
208
215
|
const parts = msg.parts ?? (msg.parts = [])
|
|
209
216
|
const finalText = (event.text ?? "").trim()
|
|
210
217
|
const lastText = [...parts].reverse().find((p) => p.kind === "text") as
|
|
@@ -376,6 +383,17 @@ export const { use: useApxSync, provider: ApxSyncProvider } = createSimpleContex
|
|
|
376
383
|
}
|
|
377
384
|
|
|
378
385
|
return {
|
|
386
|
+
// The opencode sync shim (context/sync.tsx) reads these. apx has no async
|
|
387
|
+
// bootstrap / message-fetch, so we're always "ready". `data.messages` is
|
|
388
|
+
// only consumed by the Prompt's cost footer, which expects opencode's
|
|
389
|
+
// Message shape (item.tokens, providerID, …) that ApxMessage doesn't have.
|
|
390
|
+
// We render our own message list from session.messages(), so an empty map
|
|
391
|
+
// here is correct and avoids the Prompt crashing on missing fields.
|
|
392
|
+
status: "ready" as const,
|
|
393
|
+
ready: true,
|
|
394
|
+
data: {
|
|
395
|
+
messages: {} as Record<string, ApxMessage[]>,
|
|
396
|
+
},
|
|
379
397
|
session: {
|
|
380
398
|
current: currentSession,
|
|
381
399
|
messages: messagesFor,
|
|
@@ -40,7 +40,8 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
|
|
40
40
|
const apxModelKey = () => args.model || "apx-default"
|
|
41
41
|
const apxProvider = () => ({
|
|
42
42
|
id: "apx",
|
|
43
|
-
|
|
43
|
+
// Shown as the gray label in the prompt status line: "Build · model · APX Code".
|
|
44
|
+
name: "APX Code",
|
|
44
45
|
models: {
|
|
45
46
|
[apxModelKey()]: {
|
|
46
47
|
id: apxModelKey(),
|