@agentprojectcontext/apx 1.32.0 → 1.33.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 (230) hide show
  1. package/package.json +6 -1
  2. package/skills/apc-context/SKILL.md +5 -2
  3. package/skills/apx/SKILL.md +3 -3
  4. package/skills/apx-agency-agents/SKILL.md +5 -5
  5. package/skills/apx-agent/SKILL.md +7 -7
  6. package/skills/apx-mcp/SKILL.md +6 -4
  7. package/skills/apx-mcp-builder/SKILL.md +4 -7
  8. package/skills/apx-project/SKILL.md +4 -5
  9. package/skills/apx-routine/SKILL.md +14 -12
  10. package/skills/apx-runtime/SKILL.md +5 -3
  11. package/skills/apx-sessions/SKILL.md +5 -5
  12. package/skills/apx-skill-builder/SKILL.md +10 -6
  13. package/skills/apx-task/SKILL.md +8 -8
  14. package/skills/apx-telegram/SKILL.md +23 -7
  15. package/skills/apx-voice/SKILL.md +8 -6
  16. package/src/core/{agent-system.js → agent/build-agent-system.js} +10 -12
  17. package/src/core/agent/index.js +0 -2
  18. package/src/core/{agent-memory.js → agent/memory.js} +2 -2
  19. package/src/core/agent/model-router.js +21 -43
  20. package/src/core/agent/prompt-builder.js +17 -63
  21. package/src/core/agent/prompts/action-discipline.md +24 -0
  22. package/src/core/agent/prompts/channels/code.md +8 -12
  23. package/src/core/agent/prompts/channels/desktop.md +6 -4
  24. package/src/core/agent/prompts/channels/routine.md +10 -1
  25. package/src/core/agent/prompts/channels/telegram.md +10 -1
  26. package/src/core/agent/prompts/channels/web_code.md +20 -0
  27. package/src/core/agent/prompts/modes/voice.md +2 -2
  28. package/src/core/agent/prompts/super-agent-base.md +2 -2
  29. package/src/core/agent/run-agent.js +37 -35
  30. package/src/core/agent/runtime-bridge.js +42 -0
  31. package/src/core/agent/self-memory.js +19 -9
  32. package/src/core/agent/skills/catalog.js +65 -0
  33. package/src/core/agent/skills/index.js +6 -0
  34. package/src/{host/daemon/skills-loader.js → core/agent/skills/loader.js} +3 -3
  35. package/src/core/agent/skills/rag.js +91 -0
  36. package/src/core/agent/skills/trigger.js +71 -0
  37. package/src/{host/daemon → core/agent}/super-agent.js +5 -5
  38. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/add-project.js +3 -4
  39. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-agent.js +2 -2
  40. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-mcp.js +1 -2
  41. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-runtime.js +10 -11
  42. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/create-task.js +1 -1
  43. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/discover-tools.js +1 -1
  44. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/edit-file.js +1 -2
  45. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/import-agent.js +4 -5
  46. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-agents.js +1 -1
  47. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-skills.js +7 -2
  48. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-tasks.js +1 -1
  49. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-vault-agents.js +1 -1
  50. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/load-skill.js +1 -1
  51. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-agent-memory.js +1 -1
  52. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-self-memory.js +1 -1
  53. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/remember.js +1 -1
  54. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/run-shell.js +1 -2
  55. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-messages.js +1 -1
  56. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-sessions.js +1 -1
  57. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/send-telegram.js +0 -2
  58. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/set-identity.js +1 -3
  59. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/set-permission-mode.js +1 -3
  60. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/tail-messages.js +1 -1
  61. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/transcribe-audio.js +1 -1
  62. package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/write-file.js +1 -2
  63. package/src/core/agent/tools/helpers.js +74 -0
  64. package/src/{host/daemon/super-agent-tools → core/agent/tools}/registry-bridge.js +3 -3
  65. package/src/{host/daemon/super-agent-tools/index.js → core/agent/tools/registry.js} +31 -32
  66. package/src/core/apc/agents-vault.js +37 -0
  67. package/src/core/{scaffold.js → apc/scaffold.js} +4 -5
  68. package/src/core/{config.js → config/index.js} +21 -27
  69. package/src/core/config/paths.js +32 -0
  70. package/src/core/constants/actors.js +8 -0
  71. package/src/core/constants/channels.js +19 -0
  72. package/src/core/constants/index.js +5 -0
  73. package/src/core/constants/permissions.js +17 -0
  74. package/src/core/constants/roles.js +9 -0
  75. package/src/core/engines/_streaming.js +63 -0
  76. package/src/core/engines/anthropic.js +11 -22
  77. package/src/core/engines/ollama.js +7 -16
  78. package/src/core/identity/index.js +8 -0
  79. package/src/core/{identity.js → identity/self.js} +5 -5
  80. package/src/core/{telegram-identity.js → identity/telegram.js} +1 -1
  81. package/src/core/logging.js +1 -1
  82. package/src/core/mascot.js +1 -1
  83. package/src/core/memory/active-threads.js +10 -10
  84. package/src/core/memory/broker.js +9 -9
  85. package/src/core/memory/compactor.js +2 -2
  86. package/src/core/memory/index.js +2 -2
  87. package/src/core/memory/indexer.js +1 -1
  88. package/src/core/{code-sessions-store.js → stores/code-sessions.js} +7 -8
  89. package/src/core/{messages-store.js → stores/messages.js} +6 -4
  90. package/src/core/stores/routine-memory.js +71 -0
  91. package/src/core/{routines-store.js → stores/routines.js} +1 -3
  92. package/src/core/stores/runtime-sessions.js +99 -0
  93. package/src/core/{tasks-store.js → stores/tasks.js} +3 -8
  94. package/src/core/update-check.js +1 -1
  95. package/src/core/util/ids.js +14 -0
  96. package/src/core/util/index.js +2 -0
  97. package/src/core/util/time.js +9 -0
  98. package/src/core/voice/tts.js +1 -1
  99. package/src/host/daemon/api/admin-config.js +4 -3
  100. package/src/host/daemon/api/admin.js +1 -1
  101. package/src/host/daemon/api/agents.js +4 -25
  102. package/src/host/daemon/api/artifacts.js +26 -1
  103. package/src/host/daemon/api/code.js +62 -17
  104. package/src/host/daemon/api/confirm.js +1 -1
  105. package/src/host/daemon/api/connections.js +2 -2
  106. package/src/host/daemon/api/conversations.js +2 -2
  107. package/src/host/daemon/api/deck.js +1 -1
  108. package/src/host/daemon/api/desktop.js +1 -1
  109. package/src/host/daemon/api/embeddings.js +4 -4
  110. package/src/host/daemon/api/engines.js +2 -2
  111. package/src/host/daemon/api/exec.js +20 -5
  112. package/src/host/daemon/api/identity.js +1 -1
  113. package/src/host/daemon/api/mcps.js +1 -1
  114. package/src/host/daemon/api/messages.js +1 -1
  115. package/src/host/daemon/api/runtimes.js +9 -8
  116. package/src/host/daemon/api/sessions-search.js +1 -1
  117. package/src/host/daemon/api/sessions.js +2 -2
  118. package/src/host/daemon/api/shared.js +5 -4
  119. package/src/host/daemon/api/skills.js +30 -0
  120. package/src/host/daemon/api/super-agent.js +29 -9
  121. package/src/host/daemon/api/tasks.js +2 -2
  122. package/src/host/daemon/api/telegram.js +1 -1
  123. package/src/host/daemon/api/tools.js +6 -6
  124. package/src/host/daemon/api/tts.js +2 -2
  125. package/src/host/daemon/api/voice.js +14 -12
  126. package/src/host/daemon/api.js +2 -0
  127. package/src/host/daemon/compact.js +1 -1
  128. package/src/host/daemon/db.js +4 -4
  129. package/src/host/daemon/desktop-ws.js +1 -1
  130. package/src/host/daemon/index.js +4 -4
  131. package/src/host/daemon/plugins/{desktop.js → desktop/index.js} +11 -6
  132. package/src/host/daemon/plugins/index.js +2 -2
  133. package/src/host/daemon/plugins/{telegram.js → telegram/index.js} +52 -193
  134. package/src/host/daemon/plugins/telegram/media.js +162 -0
  135. package/src/host/daemon/projects-helpers.js +54 -0
  136. package/src/host/daemon/routines.js +28 -12
  137. package/src/host/daemon/smoke.js +2 -2
  138. package/src/host/daemon/token-store.js +1 -1
  139. package/src/host/daemon/transcription.js +2 -2
  140. package/src/host/daemon/wakeup.js +2 -2
  141. package/src/interfaces/cli/commands/agent.js +3 -3
  142. package/src/interfaces/cli/commands/command.js +1 -1
  143. package/src/interfaces/cli/commands/config.js +3 -2
  144. package/src/interfaces/cli/commands/desktop.js +1 -1
  145. package/src/interfaces/cli/commands/exec.js +2 -1
  146. package/src/interfaces/cli/commands/identity.js +2 -2
  147. package/src/interfaces/cli/commands/init.js +1 -1
  148. package/src/interfaces/cli/commands/mcp.js +1 -1
  149. package/src/interfaces/cli/commands/memory.js +2 -2
  150. package/src/interfaces/cli/commands/model.js +16 -6
  151. package/src/interfaces/cli/commands/project.js +1 -1
  152. package/src/interfaces/cli/commands/routine.js +58 -0
  153. package/src/interfaces/cli/commands/search.js +1 -1
  154. package/src/interfaces/cli/commands/session.js +4 -4
  155. package/src/interfaces/cli/commands/setup.js +4 -3
  156. package/src/interfaces/cli/commands/skills.js +25 -4
  157. package/src/interfaces/cli/commands/status.js +1 -1
  158. package/src/interfaces/cli/commands/sys.js +11 -4
  159. package/src/interfaces/cli/commands/update.js +1 -1
  160. package/src/interfaces/cli/index.js +4 -4
  161. package/src/interfaces/cli/postinstall.js +2 -2
  162. package/src/interfaces/mcp-server/index.js +1 -1
  163. package/src/interfaces/tui/component/prompt/index.tsx +3 -1
  164. package/src/interfaces/tui/context/sdk-apx.tsx +47 -7
  165. package/src/interfaces/tui/context/sync-apx.tsx +20 -2
  166. package/src/interfaces/tui/context/sync.tsx +2 -1
  167. package/src/interfaces/tui/routes/session/index.tsx +151 -136
  168. package/src/interfaces/tui/routes/session/sidebar-apx.tsx +37 -15
  169. package/src/interfaces/tui/run.ts +2 -0
  170. package/src/interfaces/web/dist/assets/index-7dVT2O1S.css +1 -0
  171. package/src/interfaces/web/dist/assets/index-DWsE_8Nz.js +602 -0
  172. package/src/interfaces/web/dist/assets/index-DWsE_8Nz.js.map +1 -0
  173. package/src/interfaces/web/dist/index.html +2 -2
  174. package/src/interfaces/web/package-lock.json +6 -6
  175. package/src/interfaces/web/src/App.tsx +53 -32
  176. package/src/interfaces/web/src/components/RobyBubble.tsx +12 -6
  177. package/src/interfaces/web/src/components/UiSelect.tsx +13 -3
  178. package/src/interfaces/web/src/components/chat/SkillPicker.tsx +77 -0
  179. package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +253 -111
  180. package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +10 -8
  181. package/src/interfaces/web/src/components/code/CodeComposer.tsx +20 -17
  182. package/src/interfaces/web/src/components/code/CodeContextTab.tsx +43 -18
  183. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +212 -0
  184. package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +121 -0
  185. package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +1 -1
  186. package/src/interfaces/web/src/components/code/CodeSessionList.tsx +30 -26
  187. package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +40 -21
  188. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +140 -0
  189. package/src/interfaces/web/src/components/common/TabLayout.tsx +11 -7
  190. package/src/interfaces/web/src/components/common/TabNav.tsx +3 -3
  191. package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +4 -2
  192. package/src/interfaces/web/src/components/ui/chat-input.tsx +17 -6
  193. package/src/interfaces/web/src/hooks/useChat.ts +48 -2
  194. package/src/interfaces/web/src/hooks/useNavCollapseCtx.tsx +83 -0
  195. package/src/interfaces/web/src/hooks/usePersonaName.ts +11 -0
  196. package/src/interfaces/web/src/i18n/en.ts +7 -7
  197. package/src/interfaces/web/src/i18n/es.ts +8 -8
  198. package/src/interfaces/web/src/lib/api/agents.ts +1 -1
  199. package/src/interfaces/web/src/lib/api/artifacts.ts +10 -0
  200. package/src/interfaces/web/src/lib/api/code.ts +4 -2
  201. package/src/interfaces/web/src/lib/api/skills.ts +25 -0
  202. package/src/interfaces/web/src/lib/api.ts +1 -0
  203. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +430 -86
  204. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +5 -18
  205. package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +1 -8
  206. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +39 -40
  207. package/src/interfaces/web/src/screens/project/ChatTab.tsx +16 -16
  208. package/src/skills/apc-context/SKILL.md +159 -0
  209. package/src/core/agent/ghost-guard.js +0 -24
  210. package/src/core/agent/prompts/channels/terminal.md +0 -16
  211. package/src/host/daemon/apc-runtime-context.js +0 -124
  212. package/src/host/daemon/super-agent-tools/helpers.js +0 -124
  213. package/src/host/daemon/tool-call-parser.js +0 -2
  214. package/src/interfaces/web/dist/assets/index-63P_ji1a.js +0 -571
  215. package/src/interfaces/web/dist/assets/index-63P_ji1a.js.map +0 -1
  216. package/src/interfaces/web/dist/assets/index-DLWy6dYz.css +0 -1
  217. /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/ask-questions.js +0 -0
  218. /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-files.js +0 -0
  219. /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-mcps.js +0 -0
  220. /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-projects.js +0 -0
  221. /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-file.js +0 -0
  222. /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-files.js +0 -0
  223. /package/src/core/agent/{pseudo-tools.js → tools/pseudo-tools.js} +0 -0
  224. /package/src/core/agent/{tool-call-parser.js → tools/tool-call-parser.js} +0 -0
  225. /package/src/core/{parser.js → apc/parser.js} +0 -0
  226. /package/src/core/{apc-skill-sync.js → apc/skill-sync.js} +0 -0
  227. /package/src/core/{artifacts-store.js → stores/artifacts.js} +0 -0
  228. /package/src/{host/daemon → core/stores}/engine-sessions.js +0 -0
  229. /package/src/core/{session-store.js → stores/sessions.js} +0 -0
  230. /package/src/host/daemon/plugins/{telegram-ask.js → telegram/ask.js} +0 -0
@@ -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 "../../../core/parser.js";
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 "../../../core/scaffold.js";
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 "../../../core/config.js";
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 "../../../core/config.js";
5
- import { readIdentity } from "../../../core/identity.js";
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("../../../core/config.js");
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: "terminal",
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 "../../../core/update-check.js";
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 "../../core/update-check.js";
112
- import { mascot } from "../../core/mascot.js";
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,6 +119,7 @@ import {
119
119
  cmdRoutineDisable,
120
120
  cmdRoutineRun,
121
121
  cmdRoutineHistory,
122
+ cmdRoutineMemory,
122
123
  } from "./commands/routine.js";
123
124
  import {
124
125
  cmdArtifactCreate,
@@ -1803,7 +1804,6 @@ const HELP_TOPICS = new Map(Object.entries({
1803
1804
  const HELP_ALIASES = new Map(Object.entries({
1804
1805
  "project ls": "project list",
1805
1806
  "project rm": "project remove",
1806
- "sys": "code",
1807
1807
  "agent ls": "agent list",
1808
1808
  "agent show": "agent get",
1809
1809
  "agent vault ls": "agent vault list",
@@ -2406,7 +2406,6 @@ async function dispatch(cmd, rest) {
2406
2406
  break;
2407
2407
 
2408
2408
  case "code":
2409
- case "sys":
2410
2409
  await cmdCode(parseArgs(rest));
2411
2410
  break;
2412
2411
 
@@ -2481,6 +2480,7 @@ async function dispatch(cmd, rest) {
2481
2480
  else if (sub === "disable") await cmdRoutineDisable(a);
2482
2481
  else if (sub === "run") await cmdRoutineRun(a);
2483
2482
  else if (sub === "history" || sub === "hist") await cmdRoutineHistory(a);
2483
+ else if (sub === "memory" || sub === "mem") await cmdRoutineMemory(a);
2484
2484
  else die(`unknown routine subcommand: ${sub}`);
2485
2485
  break;
2486
2486
  }
@@ -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 "../../core/apc-skill-sync.js";
5
- import { installGlobalSkills } from "../../core/scaffold.js";
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
@@ -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 "../../core/parser.js";
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
- {store.mode === "shell" ? "Shell" : Locale.titlecase(agent().name)}
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
- // Send the live model selection as `body.model` so the daemon's
78
- // super-agent honours the model the user picked via /models. When unset
79
- // the daemon falls back to ~/.apx/config.json (super_agent.model).
80
- const body: Record<string, unknown> = { prompt, previousMessages }
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
- while (true) {
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
- // Legacy opencode compat
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
- name: "APX",
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(),