@agentprojectcontext/apx 1.77.3 → 1.78.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.
Files changed (293) hide show
  1. package/README.md +23 -9
  2. package/package.json +12 -12
  3. package/src/core/agent/build-agent-system.js +3 -2
  4. package/src/core/agent/constants.js +3 -2
  5. package/src/core/agent/loop/greeting-guard.js +55 -0
  6. package/src/core/agent/loop/side-effects.js +52 -0
  7. package/src/core/agent/prompt-builder.js +49 -8
  8. package/src/core/agent/run-agent.js +13 -48
  9. package/src/core/agent/security.js +1 -1
  10. package/src/core/agent/self-memory.js +4 -2
  11. package/src/core/agent/skills/index-store.js +2 -2
  12. package/src/core/agent/skills/loader.js +3 -22
  13. package/src/core/agent/super-agent.js +0 -2
  14. package/src/core/agent/tools/handlers/call-runtime.js +4 -4
  15. package/src/core/agent/tools/handlers/search-sessions.js +1 -1
  16. package/src/core/agent/tools/handlers/set-permission-mode.js +11 -4
  17. package/src/core/agent/tools/names.js +58 -0
  18. package/src/core/apc/context-copy.js +1 -1
  19. package/src/core/apc/frontmatter.js +85 -0
  20. package/src/core/apc/parser.js +9 -21
  21. package/src/core/apc/paths.js +8 -8
  22. package/src/core/apc/scaffold.js +5 -4
  23. package/src/core/channels/telegram/config.js +201 -0
  24. package/src/core/config/index.js +25 -183
  25. package/src/core/config/paths.js +54 -1
  26. package/src/core/confirmation/adapters/web.js +1 -1
  27. package/src/core/deck/manifest.js +12 -12
  28. package/src/core/desktop/autostart.js +3 -2
  29. package/src/core/desktop/process.js +4 -4
  30. package/src/core/engines/presets.js +2 -2
  31. package/src/core/http-tools/browser.js +1 -1
  32. package/src/core/http-tools/catalog.js +551 -0
  33. package/src/core/http-tools/fetch.js +1 -1
  34. package/src/core/http-tools/glob.js +3 -3
  35. package/src/core/http-tools/grep.js +2 -9
  36. package/src/core/http-tools/inline-handlers.js +59 -0
  37. package/src/core/http-tools/registry.js +31 -615
  38. package/src/core/http-tools/search.js +2 -2
  39. package/src/core/identity/self.js +6 -7
  40. package/src/core/identity/telegram.js +3 -3
  41. package/src/core/logging.js +6 -5
  42. package/src/core/mcp/sources.js +12 -16
  43. package/src/core/memory/indexer.js +2 -5
  44. package/src/core/profiles/lifecycle.js +0 -2
  45. package/src/core/profiles/store.js +2 -7
  46. package/src/core/routines/runner.js +1 -1
  47. package/src/core/runtime-skills/apx-agency-agents/SKILL.md +2 -2
  48. package/src/core/runtime-skills/apx-profile/SKILL.md +3 -3
  49. package/src/core/runtime-skills/apx-project/SKILL.md +1 -1
  50. package/src/core/runtime-skills/apx-task/SKILL.md +8 -8
  51. package/src/core/runtime-skills/apx-telegram/SKILL.md +4 -4
  52. package/src/core/runtime-skills/apx-voice/SKILL.md +4 -4
  53. package/src/core/runtimes/detect.js +2 -2
  54. package/src/core/sessions/index.js +800 -0
  55. package/src/core/stores/code-sessions.js +3 -14
  56. package/src/core/stores/engine-sessions.js +0 -4
  57. package/src/core/stores/messages.js +0 -5
  58. package/src/core/stores/organization.js +9 -11
  59. package/src/core/stores/routines.js +6 -11
  60. package/src/core/stores/runtime-callbacks.js +2 -1
  61. package/src/core/util/json-file.js +128 -0
  62. package/src/core/vars/sources.js +14 -21
  63. package/src/core/voice/stt-models.js +1 -1
  64. package/src/core/voice/tts.js +5 -4
  65. package/src/host/daemon/api/admin-config.js +5 -5
  66. package/src/host/daemon/api/admin.js +8 -7
  67. package/src/host/daemon/api/agents.js +16 -16
  68. package/src/host/daemon/api/artifact-preview.js +8 -8
  69. package/src/host/daemon/api/artifacts.js +7 -7
  70. package/src/host/daemon/api/code.js +8 -8
  71. package/src/host/daemon/api/config.js +6 -6
  72. package/src/host/daemon/api/confirm.js +2 -2
  73. package/src/host/daemon/api/connections.js +2 -2
  74. package/src/host/daemon/api/conversations.js +12 -12
  75. package/src/host/daemon/api/deck.js +6 -6
  76. package/src/host/daemon/api/desktop.js +8 -8
  77. package/src/host/daemon/api/embeddings.js +4 -4
  78. package/src/host/daemon/api/engines.js +8 -7
  79. package/src/host/daemon/api/exec.js +5 -4
  80. package/src/host/daemon/api/files-project.js +6 -6
  81. package/src/host/daemon/api/health.js +2 -2
  82. package/src/host/daemon/api/identity.js +3 -3
  83. package/src/host/daemon/api/inbox.js +2 -2
  84. package/src/host/daemon/api/integrations.js +23 -19
  85. package/src/host/daemon/api/mcps.js +16 -12
  86. package/src/host/daemon/api/messages.js +5 -5
  87. package/src/host/daemon/api/organization.js +8 -8
  88. package/src/host/daemon/api/pairing.js +6 -6
  89. package/src/host/daemon/api/plugins.js +3 -3
  90. package/src/host/daemon/api/prefix.js +20 -0
  91. package/src/host/daemon/api/profiles.js +9 -9
  92. package/src/host/daemon/api/projects.js +5 -5
  93. package/src/host/daemon/api/routines.js +8 -8
  94. package/src/host/daemon/api/run.js +2 -2
  95. package/src/host/daemon/api/runtimes.js +6 -6
  96. package/src/host/daemon/api/sessions-search.js +18 -11
  97. package/src/host/daemon/api/sessions.js +6 -6
  98. package/src/host/daemon/api/shared.js +59 -13
  99. package/src/host/daemon/api/skills.js +12 -12
  100. package/src/host/daemon/api/super-agent.js +4 -4
  101. package/src/host/daemon/api/tasks.js +11 -11
  102. package/src/host/daemon/api/telegram.js +19 -20
  103. package/src/host/daemon/api/tools.js +7 -7
  104. package/src/host/daemon/api/top-level.js +7 -7
  105. package/src/host/daemon/api/transcribe.js +6 -6
  106. package/src/host/daemon/api/tts.js +3 -3
  107. package/src/host/daemon/api/vars.js +11 -8
  108. package/src/host/daemon/api/voice.js +6 -6
  109. package/src/host/daemon/api/web.js +28 -32
  110. package/src/host/daemon/api.js +77 -48
  111. package/src/host/daemon/db.js +1 -1
  112. package/src/host/daemon/desktop-ws.js +7 -3
  113. package/src/host/daemon/index.js +11 -5
  114. package/src/host/daemon/plugins/desktop/index.js +1 -1
  115. package/src/host/daemon/plugins/telegram/index.js +1 -1
  116. package/src/host/daemon/stt-venv.js +20 -81
  117. package/src/host/daemon/wakeup.js +1 -1
  118. package/src/interfaces/acp/index.js +3 -3
  119. package/src/interfaces/acp/session.js +2 -2
  120. package/src/interfaces/cli/commands/a2a.js +2 -2
  121. package/src/interfaces/cli/commands/agent.js +3 -3
  122. package/src/interfaces/cli/commands/artifact.js +13 -13
  123. package/src/interfaces/cli/commands/chat.js +3 -3
  124. package/src/interfaces/cli/commands/command.js +2 -2
  125. package/src/interfaces/cli/commands/config.js +4 -4
  126. package/src/interfaces/cli/commands/daemon.js +17 -18
  127. package/src/interfaces/cli/commands/desktop.js +7 -14
  128. package/src/interfaces/cli/commands/exec.js +2 -2
  129. package/src/interfaces/cli/commands/log.js +3 -4
  130. package/src/interfaces/cli/commands/mcp.js +9 -9
  131. package/src/interfaces/cli/commands/memory.js +2 -2
  132. package/src/interfaces/cli/commands/messages.js +5 -5
  133. package/src/interfaces/cli/commands/model.js +0 -18
  134. package/src/interfaces/cli/commands/obsidian.js +5 -5
  135. package/src/interfaces/cli/commands/org.js +5 -5
  136. package/src/interfaces/cli/commands/pair.js +6 -6
  137. package/src/interfaces/cli/commands/plugins.js +2 -2
  138. package/src/interfaces/cli/commands/profile.js +10 -10
  139. package/src/interfaces/cli/commands/project-config.js +6 -6
  140. package/src/interfaces/cli/commands/project.js +10 -10
  141. package/src/interfaces/cli/commands/routine.js +8 -9
  142. package/src/interfaces/cli/commands/runtime.js +2 -2
  143. package/src/interfaces/cli/commands/search.js +0 -1
  144. package/src/interfaces/cli/commands/session.js +12 -40
  145. package/src/interfaces/cli/commands/sessions.js +21 -798
  146. package/src/interfaces/cli/commands/setup.js +16 -6
  147. package/src/interfaces/cli/commands/skills.js +1 -2
  148. package/src/interfaces/cli/commands/status.js +3 -3
  149. package/src/interfaces/cli/commands/task.js +8 -8
  150. package/src/interfaces/cli/commands/telegram.js +21 -21
  151. package/src/interfaces/cli/commands/voice.js +6 -6
  152. package/src/interfaces/cli/help/index.js +2245 -0
  153. package/src/interfaces/cli/http.js +9 -4
  154. package/src/interfaces/cli/index.js +14 -2857
  155. package/src/interfaces/cli/routes/acp.js +13 -0
  156. package/src/interfaces/cli/routes/agent.js +27 -0
  157. package/src/interfaces/cli/routes/artifact.js +28 -0
  158. package/src/interfaces/cli/routes/chat.js +11 -0
  159. package/src/interfaces/cli/routes/code.js +11 -0
  160. package/src/interfaces/cli/routes/command.js +21 -0
  161. package/src/interfaces/cli/routes/config.js +16 -0
  162. package/src/interfaces/cli/routes/connections.js +11 -0
  163. package/src/interfaces/cli/routes/conversations.js +21 -0
  164. package/src/interfaces/cli/routes/daemon.js +19 -0
  165. package/src/interfaces/cli/routes/desktop.js +20 -0
  166. package/src/interfaces/cli/routes/env.js +13 -0
  167. package/src/interfaces/cli/routes/exec.js +11 -0
  168. package/src/interfaces/cli/routes/identity.js +11 -0
  169. package/src/interfaces/cli/routes/index.js +71 -0
  170. package/src/interfaces/cli/routes/init.js +11 -0
  171. package/src/interfaces/cli/routes/log.js +20 -0
  172. package/src/interfaces/cli/routes/mcp.js +22 -0
  173. package/src/interfaces/cli/routes/memory.js +11 -0
  174. package/src/interfaces/cli/routes/messages.js +16 -0
  175. package/src/interfaces/cli/routes/model.js +11 -0
  176. package/src/interfaces/cli/routes/obsidian.js +17 -0
  177. package/src/interfaces/cli/routes/org.js +34 -0
  178. package/src/interfaces/cli/routes/overlay.js +10 -0
  179. package/src/interfaces/cli/routes/pair.js +17 -0
  180. package/src/interfaces/cli/routes/panel.js +16 -0
  181. package/src/interfaces/cli/routes/permission.js +11 -0
  182. package/src/interfaces/cli/routes/plugins.js +21 -0
  183. package/src/interfaces/cli/routes/profile.js +27 -0
  184. package/src/interfaces/cli/routes/project.js +41 -0
  185. package/src/interfaces/cli/routes/restart.js +15 -0
  186. package/src/interfaces/cli/routes/routine.js +28 -0
  187. package/src/interfaces/cli/routes/run.js +11 -0
  188. package/src/interfaces/cli/routes/search.js +11 -0
  189. package/src/interfaces/cli/routes/send.js +11 -0
  190. package/src/interfaces/cli/routes/session.js +26 -0
  191. package/src/interfaces/cli/routes/sessions.js +15 -0
  192. package/src/interfaces/cli/routes/setup.js +18 -0
  193. package/src/interfaces/cli/routes/skills.js +20 -0
  194. package/src/interfaces/cli/routes/status.js +12 -0
  195. package/src/interfaces/cli/routes/task.js +26 -0
  196. package/src/interfaces/cli/routes/telegram.js +39 -0
  197. package/src/interfaces/cli/routes/update.js +24 -0
  198. package/src/interfaces/cli/routes/voice.js +17 -0
  199. package/src/interfaces/desktop/main.js +6 -7
  200. package/src/interfaces/desktop/renderer.js +0 -5
  201. package/src/interfaces/mcp-server/index.js +15 -14
  202. package/src/interfaces/tui/_shims/globals.d.ts +8 -0
  203. package/src/interfaces/tui/tsconfig.json +4 -1
  204. package/src/interfaces/web/README.md +6 -6
  205. package/src/interfaces/web/dist/assets/{index-BptlbKjU.js → index-CBR_-QyA.js} +52 -52
  206. package/src/interfaces/web/dist/assets/index-CBR_-QyA.js.map +1 -0
  207. package/src/interfaces/web/dist/index.html +1 -1
  208. package/src/interfaces/web/src/components/AddProjectDialog.tsx +1 -1
  209. package/src/interfaces/web/src/components/agents/AgentFormFields.tsx +1 -1
  210. package/src/interfaces/web/src/components/chat/ChatList.tsx +2 -2
  211. package/src/interfaces/web/src/components/chat/SkillPicker.tsx +1 -1
  212. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +1 -1
  213. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +1 -1
  214. package/src/interfaces/web/src/components/desktop/DesktopStatusCard.tsx +1 -1
  215. package/src/interfaces/web/src/components/files/FileBrowser.tsx +2 -2
  216. package/src/interfaces/web/src/components/memory/MemoryBrowser.tsx +2 -2
  217. package/src/interfaces/web/src/components/routines/ExecutionsList.tsx +1 -1
  218. package/src/interfaces/web/src/components/routines/RoutineEditor.tsx +2 -2
  219. package/src/interfaces/web/src/components/settings/DesktopSettingsPanel.tsx +1 -1
  220. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +1 -1
  221. package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +1 -1
  222. package/src/interfaces/web/src/components/settings/SkillsManager.tsx +2 -2
  223. package/src/interfaces/web/src/components/tasks/TaskDetailPanel.tsx +1 -1
  224. package/src/interfaces/web/src/hooks/useDaemonStatus.ts +1 -1
  225. package/src/interfaces/web/src/hooks/useDevices.ts +1 -1
  226. package/src/interfaces/web/src/hooks/useEngines.ts +1 -1
  227. package/src/interfaces/web/src/hooks/useGlobalConfig.ts +2 -2
  228. package/src/interfaces/web/src/hooks/useIdentity.ts +1 -1
  229. package/src/interfaces/web/src/hooks/useInbox.ts +1 -1
  230. package/src/interfaces/web/src/hooks/useProfiles.ts +3 -3
  231. package/src/interfaces/web/src/hooks/useProjects.ts +1 -1
  232. package/src/interfaces/web/src/hooks/useTelegram.ts +3 -3
  233. package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +3 -3
  234. package/src/interfaces/web/src/lib/api/admin.ts +11 -11
  235. package/src/interfaces/web/src/lib/api/agents.ts +14 -14
  236. package/src/interfaces/web/src/lib/api/artifacts.ts +11 -11
  237. package/src/interfaces/web/src/lib/api/code.ts +1 -1
  238. package/src/interfaces/web/src/lib/api/conversations.ts +8 -8
  239. package/src/interfaces/web/src/lib/api/deck.ts +3 -3
  240. package/src/interfaces/web/src/lib/api/desktop.ts +8 -8
  241. package/src/interfaces/web/src/lib/api/embeddings.ts +3 -3
  242. package/src/interfaces/web/src/lib/api/engines.ts +3 -3
  243. package/src/interfaces/web/src/lib/api/filesystem.ts +2 -2
  244. package/src/interfaces/web/src/lib/api/health.ts +1 -1
  245. package/src/interfaces/web/src/lib/api/identity.ts +2 -2
  246. package/src/interfaces/web/src/lib/api/inbox.ts +1 -1
  247. package/src/interfaces/web/src/lib/api/integrations.ts +8 -8
  248. package/src/interfaces/web/src/lib/api/mcps.ts +6 -6
  249. package/src/interfaces/web/src/lib/api/messages.ts +3 -3
  250. package/src/interfaces/web/src/lib/api/organization.ts +7 -7
  251. package/src/interfaces/web/src/lib/api/profiles.ts +8 -8
  252. package/src/interfaces/web/src/lib/api/projectFiles.ts +5 -5
  253. package/src/interfaces/web/src/lib/api/projects.ts +12 -12
  254. package/src/interfaces/web/src/lib/api/routines.ts +7 -7
  255. package/src/interfaces/web/src/lib/api/sessions.ts +2 -2
  256. package/src/interfaces/web/src/lib/api/skills.ts +11 -11
  257. package/src/interfaces/web/src/lib/api/super_agent.ts +3 -3
  258. package/src/interfaces/web/src/lib/api/tasks.ts +12 -12
  259. package/src/interfaces/web/src/lib/api/telegram.ts +14 -14
  260. package/src/interfaces/web/src/lib/api/tools.ts +1 -1
  261. package/src/interfaces/web/src/lib/api/vars.ts +4 -4
  262. package/src/interfaces/web/src/lib/api/voice.ts +6 -6
  263. package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +1 -1
  264. package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +1 -1
  265. package/src/interfaces/web/src/screens/base/LogsTab.tsx +3 -3
  266. package/src/interfaces/web/src/screens/base/SessionsTab.tsx +1 -1
  267. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +1 -1
  268. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +1 -1
  269. package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +1 -1
  270. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +1 -1
  271. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +8 -8
  272. package/src/interfaces/web/src/screens/project/AgentsTab.tsx +2 -2
  273. package/src/interfaces/web/src/screens/project/ChatTab.tsx +3 -3
  274. package/src/interfaces/web/src/screens/project/ConfigTab.tsx +1 -1
  275. package/src/interfaces/web/src/screens/project/McpsTab.tsx +3 -3
  276. package/src/interfaces/web/src/screens/project/Overview.tsx +6 -6
  277. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +2 -2
  278. package/src/interfaces/web/src/screens/project/StructureTab.tsx +1 -1
  279. package/src/interfaces/web/src/screens/project/TasksTab.tsx +1 -1
  280. package/src/interfaces/web/src/screens/project/VarsTab.tsx +1 -1
  281. package/src/interfaces/web/vite.config.ts +13 -18
  282. package/src/interfaces/web/dist/assets/index-BptlbKjU.js.map +0 -1
  283. package/src/skills/apc-context/SKILL.md +0 -159
  284. /package/src/{host/daemon → core}/runtimes/_spawn.js +0 -0
  285. /package/src/{host/daemon → core}/runtimes/aider.js +0 -0
  286. /package/src/{host/daemon → core}/runtimes/antigravity.js +0 -0
  287. /package/src/{host/daemon → core}/runtimes/claude-code.js +0 -0
  288. /package/src/{host/daemon → core}/runtimes/codex.js +0 -0
  289. /package/src/{host/daemon → core}/runtimes/cursor-agent.js +0 -0
  290. /package/src/{host/daemon → core}/runtimes/gemini-cli.js +0 -0
  291. /package/src/{host/daemon → core}/runtimes/index.js +0 -0
  292. /package/src/{host/daemon → core}/runtimes/opencode.js +0 -0
  293. /package/src/{host/daemon → core}/runtimes/qwen-code.js +0 -0
@@ -1,27 +1,33 @@
1
- // Dedicated Python virtualenv for the STT engines.
1
+ // Which Python runs whisper-server.py.
2
2
  //
3
- // We never install into the system or user-site Python — mlx-whisper drags in
3
+ // APX owns a dedicated virtualenv at ~/.apx/runtime/whisper-venv rather than
4
+ // installing into the system or user-site Python: mlx-whisper drags in
4
5
  // torch/scipy/numba and would pollute (or clash with) the user's other
5
- // projects. Instead APX owns ~/.apx/runtime/whisper-venv: create it, install
6
- // faster-whisper / mlx-whisper into it, and spawn whisper-server.py with its
7
- // interpreter. "Reset the engine" = delete the folder and recreate it.
8
- import os from "node:os";
6
+ // projects.
7
+ //
8
+ // This module used to also create that venv and pip-install into it
9
+ // (ensureVenv, pipInstall, venvHasModule, removeVenv, ENGINE_PACKAGES). None of
10
+ // it was ever called — the installer path was built and then superseded — so it
11
+ // was ~120 lines of dead code sitting next to a live one-liner. Removed. If
12
+ // venv provisioning comes back, it belongs in its own module with a caller.
9
13
  import path from "node:path";
10
14
  import fs from "node:fs";
11
- import { spawn } from "node:child_process";
12
-
13
- export const VENV_DIR = path.join(os.homedir(), ".apx", "runtime", "whisper-venv");
15
+ import { WHISPER_VENV_DIR } from "#core/config/paths.js";
14
16
 
15
17
  /** Path to the venv's python (…/bin/python on POSIX, …/Scripts on Windows). */
16
- export function venvPython() {
18
+ function venvPython() {
17
19
  return process.platform === "win32"
18
- ? path.join(VENV_DIR, "Scripts", "python.exe")
19
- : path.join(VENV_DIR, "bin", "python");
20
+ ? path.join(WHISPER_VENV_DIR, "Scripts", "python.exe")
21
+ : path.join(WHISPER_VENV_DIR, "bin", "python");
20
22
  }
21
23
 
22
24
  /** True once the venv has a usable interpreter. */
23
- export function venvExists() {
24
- try { return fs.existsSync(venvPython()); } catch { return false; }
25
+ function venvExists() {
26
+ try {
27
+ return fs.existsSync(venvPython());
28
+ } catch {
29
+ return false;
30
+ }
25
31
  }
26
32
 
27
33
  /**
@@ -31,70 +37,3 @@ export function venvExists() {
31
37
  export function pythonForWhisper() {
32
38
  return venvExists() ? venvPython() : "python3";
33
39
  }
34
-
35
- function run(cmd, args, onLine) {
36
- return new Promise((resolve) => {
37
- let proc;
38
- try {
39
- proc = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
40
- } catch (e) {
41
- onLine?.(`spawn failed: ${e.message}`);
42
- return resolve({ ok: false, code: -1 });
43
- }
44
- const pump = (chunk) => {
45
- for (const line of chunk.toString().split(/\r?\n/)) {
46
- if (line.trim()) onLine?.(line);
47
- }
48
- };
49
- proc.stdout.on("data", pump);
50
- proc.stderr.on("data", pump);
51
- proc.on("exit", (code) => resolve({ ok: code === 0, code }));
52
- proc.on("error", (e) => { onLine?.(e.message); resolve({ ok: false, code: -1 }); });
53
- });
54
- }
55
-
56
- /** Create the venv (idempotent). Streams progress lines to onLine. */
57
- export async function ensureVenv(onLine) {
58
- if (venvExists()) return { ok: true, created: false };
59
- fs.mkdirSync(path.dirname(VENV_DIR), { recursive: true });
60
- onLine?.(`creating venv at ${VENV_DIR}…`);
61
- const r = await run("python3", ["-m", "venv", VENV_DIR], onLine);
62
- if (!r.ok || !venvExists()) return { ok: false, error: "venv creation failed" };
63
- // Upgrade pip once so wheel resolution is fast/modern.
64
- await run(venvPython(), ["-m", "pip", "install", "--upgrade", "pip", "wheel"], onLine);
65
- return { ok: true, created: true };
66
- }
67
-
68
- /** Is a module importable inside the venv? */
69
- export function venvHasModule(mod) {
70
- return new Promise((resolve) => {
71
- if (!venvExists()) return resolve(false);
72
- const p = spawn(venvPython(), ["-c", `import ${mod}`], { stdio: "ignore" });
73
- p.on("exit", (code) => resolve(code === 0));
74
- p.on("error", () => resolve(false));
75
- });
76
- }
77
-
78
- /** pip install <pkgs> into the venv, streaming progress. Creates the venv first. */
79
- export async function pipInstall(pkgs, onLine) {
80
- const ensured = await ensureVenv(onLine);
81
- if (!ensured.ok) return ensured;
82
- const list = Array.isArray(pkgs) ? pkgs : [pkgs];
83
- onLine?.(`installing ${list.join(", ")}…`);
84
- const r = await run(venvPython(), ["-m", "pip", "install", "--upgrade", ...list], onLine);
85
- return { ok: r.ok, code: r.code };
86
- }
87
-
88
- /** Delete the whole venv (so the engine can be reinstalled clean). */
89
- export async function removeVenv(onLine) {
90
- if (!fs.existsSync(VENV_DIR)) return { ok: true, removed: false };
91
- onLine?.(`removing ${VENV_DIR}…`);
92
- await fs.promises.rm(VENV_DIR, { recursive: true, force: true });
93
- return { ok: !fs.existsSync(VENV_DIR), removed: true };
94
- }
95
-
96
- /** Engine → the pip package(s) it needs in the venv. */
97
- export const ENGINE_PACKAGES = {
98
- faster: ["faster-whisper"],
99
- mlx: ["mlx-whisper"],
100
- };
@@ -18,7 +18,7 @@ export function detectLanguage(identity, config) {
18
18
  if (cfgLang) return ISO_TO_LANGUAGE[cfgLang.toLowerCase()] || cfgLang;
19
19
  if (identity?.language) return identity.language;
20
20
  const lang = process.env.LANG || process.env.LC_MESSAGES || process.env.LC_ALL || "";
21
- const code = lang.split(/[_\.]/)[0].toLowerCase();
21
+ const code = lang.split(/[_.]/)[0].toLowerCase();
22
22
  return ISO_TO_LANGUAGE[code] || "English";
23
23
  }
24
24
 
@@ -6,7 +6,7 @@
6
6
  //
7
7
  // Like the mcp-server surface, this is a thin adapter over the daemon HTTP
8
8
  // API: each `session/prompt` becomes a POST to the NDJSON stream endpoint
9
- // `/projects/:pid/super-agent/chat/stream` and the stream events are mapped
9
+ // `/api/projects/:pid/super-agent/chat/stream` and the stream events are mapped
10
10
  // onto ACP `session/update` notifications:
11
11
  //
12
12
  // assistant_text → agent_message_chunk
@@ -179,7 +179,7 @@ export class AcpAgentServer {
179
179
  session.activeTurn = turn;
180
180
  try {
181
181
  const final = await this.client.streamPost(
182
- `/projects/${session.project.id}/super-agent/chat/stream`,
182
+ `/api/projects/${session.project.id}/super-agent/chat/stream`,
183
183
  {
184
184
  prompt: promptText,
185
185
  // ACP clients are coding surfaces (IDEs) — the `code` channel gives
@@ -314,7 +314,7 @@ export class AcpAgentServer {
314
314
  }
315
315
  try {
316
316
  await this.client.post(
317
- `/super-agent/confirm/${encodeURIComponent(event.correlationId)}`,
317
+ `/api/super-agent/confirm/${encodeURIComponent(event.correlationId)}`,
318
318
  { confirmed }
319
319
  );
320
320
  } catch (e) {
@@ -129,12 +129,12 @@ export async function resolveProjectForCwd(client, cwd) {
129
129
  `No APC project found at or above: ${cwd}. Run \`apx init\` in the workspace first.`
130
130
  );
131
131
  }
132
- const projects = await client.get("/projects");
132
+ const projects = await client.get("/api/projects");
133
133
  const match = (projects || []).find(
134
134
  (p) => path.resolve(p.path) === path.resolve(root)
135
135
  );
136
136
  if (match) return match;
137
- return client.post("/projects", { path: root });
137
+ return client.post("/api/projects", { path: root });
138
138
  }
139
139
 
140
140
  /** Flatten an ACP prompt (ContentBlock[]) into the text the daemon expects. */
@@ -26,7 +26,7 @@ export async function cmdSend(args) {
26
26
  if (!body) throw new Error("apx send: body is empty");
27
27
 
28
28
  const pid = await resolveProjectId(args?.flags?.project);
29
- const result = await http.post(`/projects/${pid}/send`, {
29
+ const result = await http.post(`/api/projects/${pid}/send`, {
30
30
  from,
31
31
  to,
32
32
  body,
@@ -48,7 +48,7 @@ export async function cmdConnections(args) {
48
48
  const slug = args._[0];
49
49
  if (!slug) throw new Error("apx connections: missing <agent-slug>");
50
50
  const pid = await resolveProjectId(args?.flags?.project);
51
- const peers = await http.get(`/projects/${pid}/agents/${slug}/connections`);
51
+ const peers = await http.get(`/api/projects/${pid}/agents/${slug}/connections`);
52
52
  if (peers.length === 0) {
53
53
  console.log(`(no connections logged for ${slug} yet)`);
54
54
  return;
@@ -24,9 +24,9 @@ function requireRoot() {
24
24
  async function nudgeDaemon(root) {
25
25
  try {
26
26
  if (!(await http.ping())) return;
27
- const projects = await http.get("/projects", { autoStart: false });
27
+ const projects = await http.get("/api/projects", { autoStart: false });
28
28
  const me = projects.find((p) => p.path === root);
29
- if (me) await http.post(`/projects/${me.id}/rebuild`, undefined, { autoStart: false });
29
+ if (me) await http.post(`/api/projects/${me.id}/rebuild`, undefined, { autoStart: false });
30
30
  } catch { /* daemon hiccup */ }
31
31
  }
32
32
 
@@ -116,7 +116,7 @@ export async function cmdAgentRemove(args) {
116
116
  }
117
117
  }
118
118
  const pid = await resolveProjectId(args?.flags?.project);
119
- await http.delete(`/projects/${pid}/agents/${slug}`);
119
+ await http.delete(`/api/projects/${pid}/agents/${slug}`);
120
120
  console.log(`${tag("removed")} ${bold(slug)} ${gray("(agent file + runtime memory deleted)")}`);
121
121
  }
122
122
 
@@ -51,13 +51,13 @@ export async function cmdArtifactCreate(args) {
51
51
  if (!name) throw new Error("apx artifact create: missing <name>");
52
52
  const pid = await resolveProjectId(args?.flags?.project);
53
53
  const content = args.flags.content && args.flags.content !== true ? String(args.flags.content) : "";
54
- const r = await http.post(`/projects/${pid}/artifacts`, { name, content });
54
+ const r = await http.post(`/api/projects/${pid}/artifacts`, { name, content });
55
55
  console.log(r.path);
56
56
  }
57
57
 
58
58
  export async function cmdArtifactList(args = {}) {
59
59
  const pid = await resolveProjectId(args?.flags?.project);
60
- const rows = await http.get(`/projects/${pid}/artifacts`);
60
+ const rows = await http.get(`/api/projects/${pid}/artifacts`);
61
61
  if (rows.length === 0) {
62
62
  console.log(`(no artifacts in project #${pid})`);
63
63
  return;
@@ -77,7 +77,7 @@ export async function cmdArtifactShow(args) {
77
77
  const name = args._[0];
78
78
  if (!name) throw new Error("apx artifact show: missing <name>");
79
79
  const pid = await resolveProjectId(args?.flags?.project);
80
- const r = await http.get(`/projects/${pid}/artifacts/${encodeURIComponent(name)}`);
80
+ const r = await http.get(`/api/projects/${pid}/artifacts/${encodeURIComponent(name)}`);
81
81
  process.stdout.write(r.content);
82
82
  }
83
83
 
@@ -85,7 +85,7 @@ export async function cmdArtifactRemove(args) {
85
85
  const name = args._[0];
86
86
  if (!name) throw new Error("apx artifact remove: missing <name>");
87
87
  const pid = await resolveProjectId(args?.flags?.project);
88
- await http.delete(`/projects/${pid}/artifacts/${encodeURIComponent(name)}`);
88
+ await http.delete(`/api/projects/${pid}/artifacts/${encodeURIComponent(name)}`);
89
89
  console.log(`removed artifact "${name}"`);
90
90
  }
91
91
 
@@ -106,7 +106,7 @@ export async function cmdArtifactRun(args) {
106
106
  // Pull the artifact record from the daemon for the absolute path.
107
107
  let entry;
108
108
  try {
109
- entry = await http.get(`/projects/${pid}/artifacts/${encodeURIComponent(name)}`);
109
+ entry = await http.get(`/api/projects/${pid}/artifacts/${encodeURIComponent(name)}`);
110
110
  } catch (e) {
111
111
  throw new Error(`artifact "${name}" not found in project #${pid}: ${e.message}`);
112
112
  }
@@ -170,7 +170,7 @@ export async function cmdArtifactPreview(args) {
170
170
  let view;
171
171
  try {
172
172
  view = await http.post(
173
- `/projects/${pid}/artifacts/${encodeURIComponent(name)}/preview`,
173
+ `/api/projects/${pid}/artifacts/${encodeURIComponent(name)}/preview`,
174
174
  { watch }
175
175
  );
176
176
  } catch (e) {
@@ -196,7 +196,7 @@ export async function cmdArtifactPreview(args) {
196
196
  async function sharePreview(previewId, { open: doOpen = false } = {}) {
197
197
  let tunnel;
198
198
  try {
199
- tunnel = await http.post(`/previews/${previewId}/tunnel`, {});
199
+ tunnel = await http.post(`/api/previews/${previewId}/tunnel`, {});
200
200
  } catch (e) {
201
201
  throw new Error(`could not create tunnel: ${e.message}`);
202
202
  }
@@ -217,7 +217,7 @@ export async function cmdArtifactShare(args) {
217
217
  const watch = args.flags["no-watch"] ? false : true;
218
218
 
219
219
  const view = await http.post(
220
- `/projects/${pid}/artifacts/${encodeURIComponent(name)}/preview`,
220
+ `/api/projects/${pid}/artifacts/${encodeURIComponent(name)}/preview`,
221
221
  { watch }
222
222
  );
223
223
  console.log(`sharing ${view.kind} artifact "${view.name}"`);
@@ -227,8 +227,8 @@ export async function cmdArtifactShare(args) {
227
227
  }
228
228
 
229
229
  // `apx artifact previews` — list running preview servers.
230
- export async function cmdArtifactPreviews(args = {}) {
231
- const rows = await http.get(`/previews`);
230
+ export async function cmdArtifactPreviews(_args = {}) {
231
+ const rows = await http.get(`/api/previews`);
232
232
  if (!rows.length) {
233
233
  console.log("(no running previews)");
234
234
  return;
@@ -247,13 +247,13 @@ export async function cmdArtifactPreviews(args = {}) {
247
247
  // `apx artifact stop <id> | --all` — stop preview server(s).
248
248
  export async function cmdArtifactStop(args) {
249
249
  if (args.flags.all) {
250
- const rows = await http.get(`/previews`);
251
- for (const r of rows) await http.delete(`/previews/${r.id}`);
250
+ const rows = await http.get(`/api/previews`);
251
+ for (const r of rows) await http.delete(`/api/previews/${r.id}`);
252
252
  console.log(`stopped ${rows.length} preview(s)`);
253
253
  return;
254
254
  }
255
255
  const id = args._[0];
256
256
  if (!id) throw new Error("apx artifact stop: missing <id> (or --all)");
257
- await http.delete(`/previews/${encodeURIComponent(id)}`);
257
+ await http.delete(`/api/previews/${encodeURIComponent(id)}`);
258
258
  console.log(`stopped preview ${id}`);
259
259
  }
@@ -42,7 +42,7 @@ export async function cmdChat(args) {
42
42
  if (convId) body.conversation_id = convId;
43
43
  if (overrideModel) body.model = overrideModel;
44
44
 
45
- const result = await http.post(`/projects/${pid}/agents/${slug}/chat`, body);
45
+ const result = await http.post(`/api/projects/${pid}/agents/${slug}/chat`, body);
46
46
  convId = result.conversation_id;
47
47
  process.stdout.write("\n" + result.text + "\n\n");
48
48
  } catch (e) {
@@ -61,7 +61,7 @@ export async function cmdConversationsList(args) {
61
61
  // No slug → the super-agent (default conversational agent).
62
62
  const slug = args._[0] || superAgentSlug();
63
63
  const pid = await resolveProjectId(args?.flags?.project);
64
- const rows = await http.get(`/projects/${pid}/agents/${slug}/conversations`);
64
+ const rows = await http.get(`/api/projects/${pid}/agents/${slug}/conversations`);
65
65
  if (rows.length === 0) {
66
66
  console.log(`(no conversations for ${slug})`);
67
67
  return;
@@ -85,7 +85,7 @@ export async function cmdConversationsGet(args) {
85
85
  else { slug = superAgentSlug(); id = args._[0]; }
86
86
  if (!id) throw new Error("apx conversations get: usage: apx conversations get [<agent>] <id>");
87
87
  const pid = await resolveProjectId(args?.flags?.project);
88
- const conv = await http.get(`/projects/${pid}/agents/${slug}/conversations/${id}`);
88
+ const conv = await http.get(`/api/projects/${pid}/agents/${slug}/conversations/${id}`);
89
89
  process.stdout.write(`# Conversation ${id} (${slug})\n`);
90
90
  for (const t of conv.turns) {
91
91
  process.stdout.write(`\n## ${t.role} — ${t.ts}\n${t.content}\n`);
@@ -18,7 +18,7 @@ async function resolveCommandRoot(args = {}) {
18
18
  const explicitProject = args?.flags?.project;
19
19
  if (explicitProject !== undefined && explicitProject !== null && explicitProject !== "") {
20
20
  const pid = await resolveProjectId(explicitProject);
21
- const projects = await http.get("/projects");
21
+ const projects = await http.get("/api/projects");
22
22
  const project = projects.find((p) => p.id === pid);
23
23
  if (!project) throw new Error(`project ${pid} not found`);
24
24
  return project.path;
@@ -28,7 +28,7 @@ async function resolveCommandRoot(args = {}) {
28
28
  if (root) return root;
29
29
 
30
30
  const pid = await resolveProjectId();
31
- const projects = await http.get("/projects");
31
+ const projects = await http.get("/api/projects");
32
32
  const project = projects.find((p) => p.id === pid);
33
33
  if (!project) throw new Error(`project ${pid} not found`);
34
34
  return project.path;
@@ -1,7 +1,7 @@
1
1
  import { http } from "../http.js";
2
2
  import { resolveProjectId } from "./project.js";
3
3
  import { readConfig, writeConfig } from "#core/config/index.js";
4
- import { PERMISSION_MODES, DEFAULT_PERMISSION_MODE } from "#core/constants/permissions.js";
4
+ import { DEFAULT_PERMISSION_MODE } from "#core/constants/permissions.js";
5
5
 
6
6
  function parseValue(raw) {
7
7
  // best-effort: try JSON first (covers numbers, bools, objects, arrays, null,
@@ -15,7 +15,7 @@ function parseValue(raw) {
15
15
 
16
16
  export async function cmdConfigShow(args) {
17
17
  const pid = await resolveProjectId(args?.flags?.project);
18
- const data = await http.get(`/projects/${pid}/config`);
18
+ const data = await http.get(`/api/projects/${pid}/config`);
19
19
  if (args.flags.effective) {
20
20
  process.stdout.write(JSON.stringify(data.effective, null, 2) + "\n");
21
21
  return;
@@ -45,7 +45,7 @@ export async function cmdConfigSet(args) {
45
45
  }
46
46
  const pid = await resolveProjectId(args?.flags?.project);
47
47
  const value = parseValue(valueRaw);
48
- await http.patch(`/projects/${pid}/config`, { set: { [key]: value } });
48
+ await http.patch(`/api/projects/${pid}/config`, { set: { [key]: value } });
49
49
  console.log(`set ${key} = ${JSON.stringify(value)}`);
50
50
  }
51
51
 
@@ -53,7 +53,7 @@ export async function cmdConfigUnset(args) {
53
53
  const key = args._[0];
54
54
  if (!key) throw new Error("apx config unset: usage: apx config unset <key.path>");
55
55
  const pid = await resolveProjectId(args?.flags?.project);
56
- await http.patch(`/projects/${pid}/config`, { unset: [key] });
56
+ await http.patch(`/api/projects/${pid}/config`, { unset: [key] });
57
57
  console.log(`unset ${key}`);
58
58
  }
59
59
 
@@ -1,6 +1,5 @@
1
1
  import fs from "node:fs";
2
- import os from "node:os";
3
- import path from "node:path";
2
+ import { PID_PATH, LOG_PATH } from "#core/config/paths.js";
4
3
  import { ensureDaemon, http } from "../http.js";
5
4
 
6
5
  // Wait until nothing answers on the daemon port (old process fully exited and
@@ -13,8 +12,8 @@ async function waitForPortReleased({ tries = 40, intervalMs = 150 } = {}) {
13
12
  return false;
14
13
  }
15
14
 
16
- const PID_PATH = path.join(os.homedir(), ".apx", "daemon.pid");
17
- const LOG_PATH = path.join(os.homedir(), ".apx", "daemon.log");
15
+
16
+
18
17
 
19
18
  // ── ANSI helpers ─────────────────────────────────────────────────────────────
20
19
  const c = {
@@ -56,8 +55,8 @@ function debugRaw(label, data) {
56
55
  export async function cmdDaemonStart(args = {}) {
57
56
  const debug = args.flags?.debug;
58
57
  await ensureDaemon();
59
- const status = await http.get("/health");
60
- if (debug) debugRaw("/health", status);
58
+ const status = await http.get("/api/health");
59
+ if (debug) debugRaw("/api/health", status);
61
60
  console.log(
62
61
  `\n ${fmt.green("●")} ${fmt.bold("apx daemon")} ${fmt.dim("v" + status.version)}` +
63
62
  ` ${fmt.gray("·")} ${fmt.cyan("port")} ${status.port ?? (process.env.APX_PORT || 7430)}` +
@@ -77,13 +76,13 @@ export async function cmdDaemonStatus(args = {}) {
77
76
  process.exit(1);
78
77
  }
79
78
 
80
- const h = await http.get("/health", { autoStart: false });
81
- const projects = await http.get("/projects", { autoStart: false });
79
+ const h = await http.get("/api/health", { autoStart: false });
80
+ const projects = await http.get("/api/projects", { autoStart: false });
82
81
  const pid = fs.existsSync(PID_PATH) ? fs.readFileSync(PID_PATH, "utf8").trim() : "?";
83
82
 
84
83
  if (debug) {
85
- debugRaw("/health", h);
86
- debugRaw("/projects", projects);
84
+ debugRaw("/api/health", h);
85
+ debugRaw("/api/projects", projects);
87
86
  }
88
87
 
89
88
  console.log(
@@ -113,8 +112,8 @@ export async function cmdDaemonReload(args = {}) {
113
112
  console.log(`\n ${fmt.yellow("○")} ${fmt.bold("apx daemon")} ${fmt.dim("not running — start first")}\n`);
114
113
  process.exit(1);
115
114
  }
116
- const res = await http.post("/admin/reload", undefined, { autoStart: false });
117
- if (debug) debugRaw("/admin/reload", res);
115
+ const res = await http.post("/api/admin/reload", undefined, { autoStart: false });
116
+ if (debug) debugRaw("/api/admin/reload", res);
118
117
  console.log(`\n ${fmt.green("↻")} ${fmt.bold("config reloaded")}`);
119
118
  if (res.super_agent_model) console.log(fmt.kv("model", fmt.cyan(res.super_agent_model)));
120
119
  if (res.fallback_order?.length) console.log(fmt.kv("fallback", fmt.cyan(res.fallback_order.join(" → "))));
@@ -129,8 +128,8 @@ export async function cmdDaemonRestart(args = {}) {
129
128
  // Ask the daemon to shut down cleanly; fall back to a PID kill if the
130
129
  // HTTP shutdown route is unreachable (same fallback as `stop`).
131
130
  try {
132
- const res = await http.post("/admin/shutdown", undefined, { autoStart: false });
133
- if (debug) debugRaw("/admin/shutdown", res);
131
+ const res = await http.post("/api/admin/shutdown", undefined, { autoStart: false });
132
+ if (debug) debugRaw("/api/admin/shutdown", res);
134
133
  } catch {
135
134
  if (fs.existsSync(PID_PATH)) {
136
135
  try {
@@ -154,8 +153,8 @@ export async function cmdDaemonRestart(args = {}) {
154
153
  }
155
154
 
156
155
  await ensureDaemon({ silent: true });
157
- const status = await http.get("/health", { autoStart: false });
158
- if (debug) debugRaw("/health", status);
156
+ const status = await http.get("/api/health", { autoStart: false });
157
+ if (debug) debugRaw("/api/health", status);
159
158
  console.log(
160
159
  `\n ${fmt.green("●")} ${fmt.bold("apx daemon")} ${fmt.dim("v" + status.version)}` +
161
160
  ` ${fmt.gray("·")} ${fmt.green(wasRunning ? "restarted" : "started")}` +
@@ -173,8 +172,8 @@ export async function cmdDaemonStop(args = {}) {
173
172
  }
174
173
 
175
174
  try {
176
- const res = await http.post("/admin/shutdown", undefined, { autoStart: false });
177
- if (debug) debugRaw("/admin/shutdown", res);
175
+ const res = await http.post("/api/admin/shutdown", undefined, { autoStart: false });
176
+ if (debug) debugRaw("/api/admin/shutdown", res);
178
177
  console.log(`\n ${fmt.red("○")} ${fmt.bold("apx daemon")} ${fmt.dim("stopped")}\n`);
179
178
  } catch {
180
179
  if (fs.existsSync(PID_PATH)) {
@@ -1,8 +1,8 @@
1
1
  // apx desktop — launch/manage the floating voice desktop window (Electron).
2
2
  import fs from "node:fs";
3
- import os from "node:os";
4
3
  import path from "node:path";
5
- import { spawn, execFileSync } from "node:child_process";
4
+ import { DESKTOP_LOG_PATH, CONFIG_PATH } from "#core/config/paths.js";
5
+ import { spawn } from "node:child_process";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { http } from "../http.js";
8
8
  import {
@@ -11,18 +11,11 @@ import {
11
11
  autostartUninstall,
12
12
  getApxRunner as _getApxRunner,
13
13
  buildPlist as _buildPlist,
14
- MAC_PLIST_PATH,
15
- LINUX_DESKTOP_PATH,
16
- WIN_RUN_KEY,
17
- WIN_RUN_NAME,
18
14
  } from "#core/desktop/autostart.js";
19
15
  import {
20
16
  DESKTOP_MAIN,
21
- readPid, writePid, clearPid, pidAlive, isDesktopRunning,
22
- findElectron as _findElectron,
17
+ readPid, writePid, clearPid, pidAlive, findElectron as _findElectron,
23
18
  buildElectronSpawn as _buildElectronSpawn,
24
- startDesktopDetached,
25
- stopDesktop,
26
19
  } from "#core/desktop/process.js";
27
20
 
28
21
  // Re-exports — kept so existing tests (tests/desktop-autostart.test.js)
@@ -75,13 +68,13 @@ export async function cmdDesktopStart(args = {}) {
75
68
  // Get daemon port from running daemon or env
76
69
  let daemonPort = process.env.APX_PORT || "7430";
77
70
  try {
78
- const health = await http.get("/health").catch(() => null);
71
+ const health = await http.get("/api/health").catch(() => null);
79
72
  if (health?.port) daemonPort = String(health.port);
80
73
  } catch {}
81
74
 
82
75
  const { cmd, argv } = buildElectronSpawn(electronDescriptor, DESKTOP_MAIN, daemonPort);
83
76
 
84
- const logFile = path.join(os.homedir(), ".apx", "desktop.log");
77
+ const logFile = DESKTOP_LOG_PATH;
85
78
 
86
79
  if (debug) {
87
80
  // ── Debug mode: start desktop normally, then tail -f the log ─────────
@@ -191,7 +184,7 @@ export async function cmdDesktopStart(args = {}) {
191
184
  // Read configured shortcut (if any) for display
192
185
  let shortcutHint = "⌘G (macOS) / Ctrl+G (Win/Linux)";
193
186
  try {
194
- const cfg = JSON.parse(fs.readFileSync(path.join(os.homedir(), ".apx", "config.json"), "utf8"));
187
+ const cfg = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
195
188
  const sc = cfg?.desktop?.shortcut || cfg?.overlay?.shortcut;
196
189
  if (sc) shortcutHint = sc;
197
190
  } catch {}
@@ -254,7 +247,7 @@ export async function cmdDesktopStatus(_args = {}) {
254
247
 
255
248
  let daemonClients = 0;
256
249
  try {
257
- const s = await http.get("/desktop/status").catch(() => null);
250
+ const s = await http.get("/api/desktop/status").catch(() => null);
258
251
  daemonClients = s?.connected_clients ?? 0;
259
252
  } catch {}
260
253
 
@@ -171,7 +171,7 @@ export async function cmdExec(args) {
171
171
  let result;
172
172
  try {
173
173
  result = await http.streamPost(
174
- `/projects/${pid}/super-agent/chat/stream`,
174
+ `/api/projects/${pid}/super-agent/chat/stream`,
175
175
  { ...body, confirm: false },
176
176
  (event) => status.set(labelForEvent(event))
177
177
  );
@@ -187,7 +187,7 @@ export async function cmdExec(args) {
187
187
  return;
188
188
  }
189
189
 
190
- const result = await http.post(`/projects/${pid}/agents/${slug}/exec`, body);
190
+ const result = await http.post(`/api/projects/${pid}/agents/${slug}/exec`, body);
191
191
 
192
192
  process.stdout.write(result.text + "\n");
193
193
  if (process.stderr.isTTY || args.flags.verbose) {
@@ -10,11 +10,10 @@
10
10
  // here, regardless of which module produced it (telegram, whisper, super-agent…).
11
11
 
12
12
  import fs from "node:fs";
13
- import os from "node:os";
14
- import path from "node:path";
13
+ import { APX_LOG_PATH, ERROR_TRACE_PATH } from "#core/config/paths.js";
14
+
15
+
15
16
 
16
- const APX_LOG_PATH = path.join(os.homedir(), ".apx", "logs", "apx.log");
17
- const ERROR_TRACE_PATH = path.join(os.homedir(), ".apx", "logs", "errors.jsonl");
18
17
 
19
18
  const c = {
20
19
  reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m",