@agentprojectcontext/apx 1.77.3 → 1.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -9
- package/package.json +12 -12
- package/src/core/agent/build-agent-system.js +3 -2
- package/src/core/agent/constants.js +3 -2
- package/src/core/agent/loop/greeting-guard.js +55 -0
- package/src/core/agent/loop/side-effects.js +52 -0
- package/src/core/agent/prompt-builder.js +49 -8
- package/src/core/agent/run-agent.js +43 -53
- package/src/core/agent/security.js +1 -1
- package/src/core/agent/self-memory.js +4 -2
- package/src/core/agent/skills/index-store.js +2 -2
- package/src/core/agent/skills/loader.js +3 -22
- package/src/core/agent/super-agent.js +0 -2
- package/src/core/agent/tool-summary.js +65 -0
- package/src/core/agent/tools/handlers/call-runtime.js +4 -4
- package/src/core/agent/tools/handlers/list-commitments.js +80 -0
- package/src/core/agent/tools/handlers/list-tasks.js +66 -27
- package/src/core/agent/tools/handlers/record-commitment.js +68 -0
- package/src/core/agent/tools/handlers/search-sessions.js +1 -1
- package/src/core/agent/tools/handlers/send-telegram.js +68 -2
- package/src/core/agent/tools/handlers/set-permission-mode.js +11 -4
- package/src/core/agent/tools/names.js +64 -0
- package/src/core/agent/tools/registry.js +9 -0
- package/src/core/agent/tools/tool-call-parser.js +70 -1
- package/src/core/apc/context-copy.js +1 -1
- package/src/core/apc/frontmatter.js +85 -0
- package/src/core/apc/parser.js +9 -21
- package/src/core/apc/paths.js +8 -8
- package/src/core/apc/scaffold.js +5 -4
- package/src/core/channels/telegram/ask-callbacks.js +35 -0
- package/src/core/channels/telegram/config.js +201 -0
- package/src/core/channels/telegram/dispatch.js +3 -0
- package/src/core/channels/telegram/reply.js +30 -5
- package/src/core/config/index.js +25 -183
- package/src/core/config/paths.js +57 -1
- package/src/core/config/redact.js +22 -0
- package/src/core/confirmation/adapters/web.js +1 -1
- package/src/core/daemon/service.js +238 -0
- package/src/core/deck/manifest.js +12 -12
- package/src/core/desktop/autostart.js +3 -2
- package/src/core/desktop/process.js +4 -4
- package/src/core/engines/gemini.js +322 -60
- package/src/core/engines/openai-compatible.js +21 -2
- package/src/core/engines/presets.js +2 -2
- package/src/core/http-tools/browser.js +1 -1
- package/src/core/http-tools/catalog.js +551 -0
- package/src/core/http-tools/fetch.js +1 -1
- package/src/core/http-tools/glob.js +3 -3
- package/src/core/http-tools/grep.js +2 -9
- package/src/core/http-tools/inline-handlers.js +59 -0
- package/src/core/http-tools/registry.js +31 -615
- package/src/core/http-tools/search.js +2 -2
- package/src/core/identity/self.js +6 -7
- package/src/core/identity/telegram.js +3 -3
- package/src/core/logging.js +6 -5
- package/src/core/mcp/sources.js +12 -16
- package/src/core/memory/consolidate.js +225 -0
- package/src/core/memory/indexer.js +2 -5
- package/src/core/nudge/index.js +192 -0
- package/src/core/nudge/policy.js +143 -0
- package/src/core/nudge/store.js +141 -0
- package/src/core/profiles/bundled/secretary/PROFILE.md +8 -9
- package/src/core/profiles/bundled/secretary/config.schema.json +33 -3
- package/src/core/profiles/bundled/secretary/routines/day-close.json +7 -3
- package/src/core/profiles/bundled/secretary/routines/day-open.json +7 -3
- package/src/core/profiles/bundled/secretary/routines/watch.json +13 -0
- package/src/core/profiles/lifecycle.js +0 -2
- package/src/core/profiles/store.js +2 -7
- package/src/core/routines/runner.js +103 -4
- package/src/core/routines/signals.js +270 -0
- package/src/core/runtime-skills/apx-agency-agents/SKILL.md +2 -2
- package/src/core/runtime-skills/apx-profile/SKILL.md +3 -3
- package/src/core/runtime-skills/apx-project/SKILL.md +1 -1
- package/src/core/runtime-skills/apx-task/SKILL.md +8 -8
- package/src/core/runtime-skills/apx-telegram/SKILL.md +4 -4
- package/src/core/runtime-skills/apx-voice/SKILL.md +4 -4
- package/src/core/runtimes/detect.js +2 -2
- package/src/core/sessions/index.js +800 -0
- package/src/core/stores/code-sessions.js +3 -14
- package/src/core/stores/commitments.js +331 -0
- package/src/core/stores/engine-sessions.js +0 -4
- package/src/core/stores/messages.js +4 -5
- package/src/core/stores/organization.js +9 -11
- package/src/core/stores/routines.js +23 -14
- package/src/core/stores/runtime-callbacks.js +2 -1
- package/src/core/util/json-file.js +128 -0
- package/src/core/util/thinking.js +51 -0
- package/src/core/vars/sources.js +14 -21
- package/src/core/voice/stt-models.js +1 -1
- package/src/core/voice/tts.js +5 -4
- package/src/host/daemon/api/admin-config.js +5 -5
- package/src/host/daemon/api/admin.js +8 -7
- package/src/host/daemon/api/agents.js +16 -16
- package/src/host/daemon/api/artifact-preview.js +8 -8
- package/src/host/daemon/api/artifacts.js +7 -7
- package/src/host/daemon/api/code.js +8 -8
- package/src/host/daemon/api/commitments.js +135 -0
- package/src/host/daemon/api/config.js +6 -6
- package/src/host/daemon/api/confirm.js +2 -2
- package/src/host/daemon/api/connections.js +2 -2
- package/src/host/daemon/api/conversations.js +12 -12
- package/src/host/daemon/api/deck.js +6 -6
- package/src/host/daemon/api/desktop.js +8 -8
- package/src/host/daemon/api/embeddings.js +4 -4
- package/src/host/daemon/api/engines.js +8 -7
- package/src/host/daemon/api/exec.js +5 -4
- package/src/host/daemon/api/files-project.js +6 -6
- package/src/host/daemon/api/health.js +2 -2
- package/src/host/daemon/api/identity.js +3 -3
- package/src/host/daemon/api/inbox.js +2 -2
- package/src/host/daemon/api/integrations.js +23 -19
- package/src/host/daemon/api/mcps.js +16 -12
- package/src/host/daemon/api/messages.js +5 -5
- package/src/host/daemon/api/nudges.js +112 -0
- package/src/host/daemon/api/organization.js +8 -8
- package/src/host/daemon/api/pairing.js +6 -6
- package/src/host/daemon/api/plugins.js +3 -3
- package/src/host/daemon/api/prefix.js +20 -0
- package/src/host/daemon/api/profiles.js +9 -9
- package/src/host/daemon/api/projects.js +5 -5
- package/src/host/daemon/api/routines.js +32 -8
- package/src/host/daemon/api/run.js +2 -2
- package/src/host/daemon/api/runtimes.js +6 -6
- package/src/host/daemon/api/self-memory.js +50 -0
- package/src/host/daemon/api/sessions-search.js +18 -11
- package/src/host/daemon/api/sessions.js +6 -6
- package/src/host/daemon/api/shared.js +59 -13
- package/src/host/daemon/api/skills.js +12 -12
- package/src/host/daemon/api/super-agent.js +4 -4
- package/src/host/daemon/api/tasks.js +11 -11
- package/src/host/daemon/api/telegram.js +61 -24
- package/src/host/daemon/api/tools.js +7 -7
- package/src/host/daemon/api/top-level.js +7 -7
- package/src/host/daemon/api/transcribe.js +6 -6
- package/src/host/daemon/api/tts.js +3 -3
- package/src/host/daemon/api/vars.js +11 -8
- package/src/host/daemon/api/voice.js +9 -7
- package/src/host/daemon/api/web.js +28 -32
- package/src/host/daemon/api.js +83 -48
- package/src/host/daemon/callback-reconciler.js +16 -0
- package/src/host/daemon/db.js +1 -1
- package/src/host/daemon/desktop-ws.js +7 -3
- package/src/host/daemon/index.js +11 -5
- package/src/host/daemon/plugins/desktop/index.js +8 -2
- package/src/host/daemon/plugins/telegram/index.js +7 -2
- package/src/host/daemon/stt-venv.js +20 -81
- package/src/host/daemon/wakeup.js +18 -4
- package/src/interfaces/acp/index.js +3 -3
- package/src/interfaces/acp/session.js +2 -2
- package/src/interfaces/cli/commands/a2a.js +2 -2
- package/src/interfaces/cli/commands/agent.js +3 -3
- package/src/interfaces/cli/commands/artifact.js +13 -13
- package/src/interfaces/cli/commands/chat.js +3 -3
- package/src/interfaces/cli/commands/command.js +2 -2
- package/src/interfaces/cli/commands/commitment.js +154 -0
- package/src/interfaces/cli/commands/config.js +4 -4
- package/src/interfaces/cli/commands/daemon.js +74 -18
- package/src/interfaces/cli/commands/desktop.js +7 -14
- package/src/interfaces/cli/commands/exec.js +2 -2
- package/src/interfaces/cli/commands/log.js +3 -4
- package/src/interfaces/cli/commands/mcp.js +9 -9
- package/src/interfaces/cli/commands/memory.js +75 -2
- package/src/interfaces/cli/commands/messages.js +5 -5
- package/src/interfaces/cli/commands/model.js +0 -18
- package/src/interfaces/cli/commands/nudge.js +130 -0
- package/src/interfaces/cli/commands/obsidian.js +5 -5
- package/src/interfaces/cli/commands/org.js +5 -5
- package/src/interfaces/cli/commands/pair.js +6 -6
- package/src/interfaces/cli/commands/plugins.js +2 -2
- package/src/interfaces/cli/commands/profile.js +10 -10
- package/src/interfaces/cli/commands/project-config.js +6 -6
- package/src/interfaces/cli/commands/project.js +10 -10
- package/src/interfaces/cli/commands/routine.js +8 -9
- package/src/interfaces/cli/commands/runtime.js +2 -2
- package/src/interfaces/cli/commands/search.js +0 -1
- package/src/interfaces/cli/commands/session.js +12 -40
- package/src/interfaces/cli/commands/sessions.js +21 -798
- package/src/interfaces/cli/commands/setup.js +16 -6
- package/src/interfaces/cli/commands/skills.js +1 -2
- package/src/interfaces/cli/commands/status.js +3 -3
- package/src/interfaces/cli/commands/task.js +8 -8
- package/src/interfaces/cli/commands/telegram.js +21 -21
- package/src/interfaces/cli/commands/voice.js +6 -6
- package/src/interfaces/cli/help/index.js +2245 -0
- package/src/interfaces/cli/http.js +9 -4
- package/src/interfaces/cli/index.js +14 -2857
- package/src/interfaces/cli/routes/acp.js +13 -0
- package/src/interfaces/cli/routes/agent.js +27 -0
- package/src/interfaces/cli/routes/artifact.js +28 -0
- package/src/interfaces/cli/routes/chat.js +11 -0
- package/src/interfaces/cli/routes/code.js +11 -0
- package/src/interfaces/cli/routes/command.js +21 -0
- package/src/interfaces/cli/routes/commitment.js +19 -0
- package/src/interfaces/cli/routes/config.js +16 -0
- package/src/interfaces/cli/routes/connections.js +11 -0
- package/src/interfaces/cli/routes/conversations.js +21 -0
- package/src/interfaces/cli/routes/daemon.js +25 -0
- package/src/interfaces/cli/routes/desktop.js +20 -0
- package/src/interfaces/cli/routes/env.js +13 -0
- package/src/interfaces/cli/routes/exec.js +11 -0
- package/src/interfaces/cli/routes/identity.js +11 -0
- package/src/interfaces/cli/routes/index.js +75 -0
- package/src/interfaces/cli/routes/init.js +11 -0
- package/src/interfaces/cli/routes/log.js +20 -0
- package/src/interfaces/cli/routes/mcp.js +22 -0
- package/src/interfaces/cli/routes/memory.js +19 -0
- package/src/interfaces/cli/routes/messages.js +16 -0
- package/src/interfaces/cli/routes/model.js +11 -0
- package/src/interfaces/cli/routes/nudge.js +17 -0
- package/src/interfaces/cli/routes/obsidian.js +17 -0
- package/src/interfaces/cli/routes/org.js +34 -0
- package/src/interfaces/cli/routes/overlay.js +10 -0
- package/src/interfaces/cli/routes/pair.js +17 -0
- package/src/interfaces/cli/routes/panel.js +16 -0
- package/src/interfaces/cli/routes/permission.js +11 -0
- package/src/interfaces/cli/routes/plugins.js +21 -0
- package/src/interfaces/cli/routes/profile.js +27 -0
- package/src/interfaces/cli/routes/project.js +41 -0
- package/src/interfaces/cli/routes/restart.js +15 -0
- package/src/interfaces/cli/routes/routine.js +28 -0
- package/src/interfaces/cli/routes/run.js +11 -0
- package/src/interfaces/cli/routes/search.js +11 -0
- package/src/interfaces/cli/routes/send.js +11 -0
- package/src/interfaces/cli/routes/session.js +26 -0
- package/src/interfaces/cli/routes/sessions.js +15 -0
- package/src/interfaces/cli/routes/setup.js +18 -0
- package/src/interfaces/cli/routes/skills.js +20 -0
- package/src/interfaces/cli/routes/status.js +12 -0
- package/src/interfaces/cli/routes/task.js +26 -0
- package/src/interfaces/cli/routes/telegram.js +39 -0
- package/src/interfaces/cli/routes/update.js +24 -0
- package/src/interfaces/cli/routes/voice.js +17 -0
- package/src/interfaces/desktop/main.js +6 -7
- package/src/interfaces/desktop/renderer.js +0 -5
- package/src/interfaces/mcp-server/index.js +15 -14
- package/src/interfaces/tui/_shims/globals.d.ts +8 -0
- package/src/interfaces/tui/tsconfig.json +4 -1
- package/src/interfaces/web/README.md +6 -6
- package/src/interfaces/web/dist/assets/index-CvEoGtTf.js +849 -0
- package/src/interfaces/web/dist/assets/index-CvEoGtTf.js.map +1 -0
- package/src/interfaces/web/dist/assets/index-DzBBXFaO.css +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/package-lock.json +11 -10
- package/src/interfaces/web/src/components/AddProjectDialog.tsx +1 -1
- package/src/interfaces/web/src/components/Section.tsx +18 -3
- package/src/interfaces/web/src/components/agents/AgentFormFields.tsx +1 -1
- package/src/interfaces/web/src/components/chat/ChatList.tsx +2 -2
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +13 -0
- package/src/interfaces/web/src/components/chat/SkillPicker.tsx +1 -1
- package/src/interfaces/web/src/components/code/CodeFileTree.tsx +1 -1
- package/src/interfaces/web/src/components/code/CodeTerminal.tsx +1 -1
- package/src/interfaces/web/src/components/cron/CronPicker.tsx +196 -0
- package/src/interfaces/web/src/components/desktop/DesktopStatusCard.tsx +1 -1
- package/src/interfaces/web/src/components/files/FileBrowser.tsx +2 -2
- package/src/interfaces/web/src/components/inbox/InboxList.tsx +145 -0
- package/src/interfaces/web/src/components/memory/MemoryBrowser.tsx +36 -6
- package/src/interfaces/web/src/components/routines/ExecutionsList.tsx +1 -1
- package/src/interfaces/web/src/components/routines/RoutineDetail.tsx +16 -4
- package/src/interfaces/web/src/components/routines/RoutineEditor.tsx +14 -4
- package/src/interfaces/web/src/components/routines/shared.ts +14 -5
- package/src/interfaces/web/src/components/settings/DesktopSettingsPanel.tsx +1 -1
- package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +1 -1
- package/src/interfaces/web/src/components/settings/NudgePanel.tsx +183 -0
- package/src/interfaces/web/src/components/settings/ProfilePanel.tsx +36 -12
- package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +1 -1
- package/src/interfaces/web/src/components/settings/SkillsManager.tsx +2 -2
- package/src/interfaces/web/src/components/tasks/TaskDetailPanel.tsx +1 -1
- package/src/interfaces/web/src/components/ui/filter-chips.tsx +47 -0
- package/src/interfaces/web/src/components/ui.tsx +1 -0
- package/src/interfaces/web/src/constants/index.ts +1 -0
- package/src/interfaces/web/src/hooks/useChat.ts +5 -1
- package/src/interfaces/web/src/hooks/useDaemonStatus.ts +1 -1
- package/src/interfaces/web/src/hooks/useDevices.ts +1 -1
- package/src/interfaces/web/src/hooks/useEngines.ts +1 -1
- package/src/interfaces/web/src/hooks/useGlobalConfig.ts +2 -2
- package/src/interfaces/web/src/hooks/useIdentity.ts +1 -1
- package/src/interfaces/web/src/hooks/useInbox.ts +1 -1
- package/src/interfaces/web/src/hooks/useNudges.ts +38 -0
- package/src/interfaces/web/src/hooks/useProfiles.ts +3 -3
- package/src/interfaces/web/src/hooks/useProjects.ts +1 -1
- package/src/interfaces/web/src/hooks/useTelegram.ts +3 -3
- package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +3 -3
- package/src/interfaces/web/src/i18n/en.ts +127 -0
- package/src/interfaces/web/src/i18n/es.ts +127 -0
- package/src/interfaces/web/src/lib/api/admin.ts +11 -11
- package/src/interfaces/web/src/lib/api/agents.ts +14 -14
- package/src/interfaces/web/src/lib/api/artifacts.ts +11 -11
- package/src/interfaces/web/src/lib/api/code.ts +1 -1
- package/src/interfaces/web/src/lib/api/commitments.ts +57 -0
- package/src/interfaces/web/src/lib/api/conversations.ts +8 -8
- package/src/interfaces/web/src/lib/api/deck.ts +3 -3
- package/src/interfaces/web/src/lib/api/desktop.ts +8 -8
- package/src/interfaces/web/src/lib/api/embeddings.ts +3 -3
- package/src/interfaces/web/src/lib/api/engines.ts +3 -3
- package/src/interfaces/web/src/lib/api/filesystem.ts +2 -2
- package/src/interfaces/web/src/lib/api/health.ts +1 -1
- package/src/interfaces/web/src/lib/api/identity.ts +2 -2
- package/src/interfaces/web/src/lib/api/inbox.ts +1 -1
- package/src/interfaces/web/src/lib/api/integrations.ts +8 -8
- package/src/interfaces/web/src/lib/api/mcps.ts +6 -6
- package/src/interfaces/web/src/lib/api/messages.ts +3 -3
- package/src/interfaces/web/src/lib/api/notebook.ts +23 -0
- package/src/interfaces/web/src/lib/api/nudges.ts +53 -0
- package/src/interfaces/web/src/lib/api/organization.ts +7 -7
- package/src/interfaces/web/src/lib/api/profiles.ts +8 -8
- package/src/interfaces/web/src/lib/api/projectFiles.ts +5 -5
- package/src/interfaces/web/src/lib/api/projects.ts +12 -12
- package/src/interfaces/web/src/lib/api/routines.ts +7 -7
- package/src/interfaces/web/src/lib/api/sessions.ts +2 -2
- package/src/interfaces/web/src/lib/api/skills.ts +11 -11
- package/src/interfaces/web/src/lib/api/super_agent.ts +3 -3
- package/src/interfaces/web/src/lib/api/tasks.ts +12 -12
- package/src/interfaces/web/src/lib/api/telegram.ts +14 -14
- package/src/interfaces/web/src/lib/api/tools.ts +1 -1
- package/src/interfaces/web/src/lib/api/vars.ts +4 -4
- package/src/interfaces/web/src/lib/api/voice.ts +6 -6
- package/src/interfaces/web/src/lib/cron.ts +196 -0
- package/src/interfaces/web/src/lib/when.ts +32 -0
- package/src/interfaces/web/src/screens/InboxScreen.tsx +107 -77
- package/src/interfaces/web/src/screens/ProjectScreen.tsx +5 -2
- package/src/interfaces/web/src/screens/SettingsScreen.tsx +17 -3
- package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +1 -1
- package/src/interfaces/web/src/screens/base/CommitmentsTab.tsx +239 -0
- package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +103 -20
- package/src/interfaces/web/src/screens/base/LogsTab.tsx +18 -3
- package/src/interfaces/web/src/screens/base/SessionsTab.tsx +1 -1
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +8 -8
- package/src/interfaces/web/src/screens/project/AgentsTab.tsx +2 -2
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +24 -6
- package/src/interfaces/web/src/screens/project/ConfigTab.tsx +1 -1
- package/src/interfaces/web/src/screens/project/McpsTab.tsx +3 -3
- package/src/interfaces/web/src/screens/project/Overview.tsx +6 -6
- package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +15 -13
- package/src/interfaces/web/src/screens/project/StructureTab.tsx +1 -1
- package/src/interfaces/web/src/screens/project/TasksTab.tsx +1 -1
- package/src/interfaces/web/src/screens/project/VarsTab.tsx +1 -1
- package/src/interfaces/web/src/types/daemon.ts +10 -1
- package/src/interfaces/web/vite.config.ts +13 -18
- package/src/interfaces/web/dist/assets/index-BptlbKjU.js +0 -824
- package/src/interfaces/web/dist/assets/index-BptlbKjU.js.map +0 -1
- package/src/interfaces/web/dist/assets/index-D_EJEA1n.css +0 -1
- package/src/skills/apc-context/SKILL.md +0 -159
- /package/src/{host/daemon → core}/runtimes/_spawn.js +0 -0
- /package/src/{host/daemon → core}/runtimes/aider.js +0 -0
- /package/src/{host/daemon → core}/runtimes/antigravity.js +0 -0
- /package/src/{host/daemon → core}/runtimes/claude-code.js +0 -0
- /package/src/{host/daemon → core}/runtimes/codex.js +0 -0
- /package/src/{host/daemon → core}/runtimes/cursor-agent.js +0 -0
- /package/src/{host/daemon → core}/runtimes/gemini-cli.js +0 -0
- /package/src/{host/daemon → core}/runtimes/index.js +0 -0
- /package/src/{host/daemon → core}/runtimes/opencode.js +0 -0
- /package/src/{host/daemon → core}/runtimes/qwen-code.js +0 -0
|
@@ -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(
|
|
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;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// apx commitment — what you promised, to whom, by when.
|
|
2
|
+
//
|
|
3
|
+
// apx commitment add "<what>" --to "<person>" [--due 2026-05-30] [--project X]
|
|
4
|
+
// [--channel telegram] [--ref <message id>]
|
|
5
|
+
// apx commitment list [--all | --project X] [--to X] [--state open|kept|missed|all]
|
|
6
|
+
// [--overdue] [--due-before ISO] [--limit N]
|
|
7
|
+
// apx commitment show <id> [--project X]
|
|
8
|
+
// apx commitment kept <id> [--project X] [--note "..."]
|
|
9
|
+
// apx commitment missed <id> [--project X] [--note "..."]
|
|
10
|
+
// apx commitment renegotiate <id> --due <ISO> [--project X] [--note "..."]
|
|
11
|
+
//
|
|
12
|
+
// A task is something to do; a commitment is something you promised a person.
|
|
13
|
+
// Kept separate on purpose — see core/stores/commitments.js.
|
|
14
|
+
import { http } from "../http.js";
|
|
15
|
+
import { resolveProjectId } from "./project.js";
|
|
16
|
+
|
|
17
|
+
export const COMMITMENT_USAGE = {
|
|
18
|
+
add: 'apx commitment add "<what>" --to "<person>" [--due ISO] [--project X] [--channel C] [--ref R]',
|
|
19
|
+
list: "apx commitment list [--all | --project X] [--to X] [--state open|kept|missed|all] [--overdue] [--due-before ISO] [--limit N]",
|
|
20
|
+
show: "apx commitment show <id> [--project X]",
|
|
21
|
+
kept: 'apx commitment kept <id> [--project X] [--note "..."]',
|
|
22
|
+
missed: 'apx commitment missed <id> [--project X] [--note "..."]',
|
|
23
|
+
renegotiate: 'apx commitment renegotiate <id> --due <ISO> [--project X] [--note "..."]',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function fail(sub, msg) {
|
|
27
|
+
console.error(`apx commitment ${sub}: ${msg}`);
|
|
28
|
+
console.error(`Usage: ${COMMITMENT_USAGE[sub]}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function shortDate(iso) {
|
|
33
|
+
if (!iso) return "";
|
|
34
|
+
return String(iso).replace(/T/, " ").replace(/Z$/, "").slice(0, 16);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Is this promise past its date and still open? */
|
|
38
|
+
function isOverdue(c) {
|
|
39
|
+
return c.state === "open" && c.due && c.due < new Date().toISOString();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function renderTable(rows, { showProject = false } = {}) {
|
|
43
|
+
if (!rows.length) {
|
|
44
|
+
console.log("(no commitments)");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const idW = Math.max(...rows.map((r) => String(r.id).length), 2);
|
|
48
|
+
const whoW = Math.min(Math.max(...rows.map((r) => String(r.counterparty || "").length), 3), 20);
|
|
49
|
+
const projW = showProject
|
|
50
|
+
? Math.min(Math.max(...rows.map((r) => String(r.project_name || "").length), 7), 18)
|
|
51
|
+
: 0;
|
|
52
|
+
|
|
53
|
+
for (const c of rows) {
|
|
54
|
+
const proj = showProject
|
|
55
|
+
? String(c.project_name || "").slice(0, projW).padEnd(projW) + " "
|
|
56
|
+
: "";
|
|
57
|
+
// The flag carries the whole point of the type: a broken promise should be
|
|
58
|
+
// impossible to skim past.
|
|
59
|
+
const flag =
|
|
60
|
+
c.state === "kept" ? "✓" :
|
|
61
|
+
c.state === "missed" ? "✗" :
|
|
62
|
+
isOverdue(c) ? "!" : " ";
|
|
63
|
+
const moved = c.renegotiated_count ? ` (moved ×${c.renegotiated_count})` : "";
|
|
64
|
+
console.log(
|
|
65
|
+
`${flag} ${String(c.id).padEnd(idW)} ${proj}` +
|
|
66
|
+
`${String(c.counterparty || "").slice(0, whoW).padEnd(whoW)} ` +
|
|
67
|
+
`${(c.due ? shortDate(c.due).slice(0, 10) : "—").padEnd(10)} ` +
|
|
68
|
+
`${String(c.body || "").slice(0, 48)}${moved}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const overdue = rows.filter(isOverdue).length;
|
|
72
|
+
if (overdue) console.log(`\n${overdue} past their date.`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function cmdCommitmentAdd(args) {
|
|
76
|
+
const body = args?._?.[0];
|
|
77
|
+
const to = args?.flags?.to;
|
|
78
|
+
if (!body) fail("add", "what you promised is required");
|
|
79
|
+
if (!to) fail("add", "--to <person> is required — without a counterparty this is a task");
|
|
80
|
+
|
|
81
|
+
const pid = await resolveProjectId(args?.flags?.project);
|
|
82
|
+
const created = await http.post(`/api/projects/${pid}/commitments`, {
|
|
83
|
+
counterparty: to,
|
|
84
|
+
body,
|
|
85
|
+
due: args?.flags?.due || null,
|
|
86
|
+
origin_channel: args?.flags?.channel || "cli",
|
|
87
|
+
origin_message_ref: args?.flags?.ref || null,
|
|
88
|
+
});
|
|
89
|
+
console.log(`${created.id} → ${created.counterparty}${created.due ? ` by ${shortDate(created.due).slice(0, 10)}` : ""}`);
|
|
90
|
+
console.log(` ${created.body}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function cmdCommitmentList(args) {
|
|
94
|
+
const f = args?.flags || {};
|
|
95
|
+
const q = new URLSearchParams();
|
|
96
|
+
if (f.state) q.set("state", f.state);
|
|
97
|
+
if (f.to) q.set("counterparty", f.to);
|
|
98
|
+
if (f.overdue) q.set("overdue", "1");
|
|
99
|
+
if (f["due-before"]) q.set("due_before", f["due-before"]);
|
|
100
|
+
if (f.limit) q.set("limit", f.limit);
|
|
101
|
+
|
|
102
|
+
if (f.all) {
|
|
103
|
+
const { data } = await http.get(`/api/commitments?${q.toString()}`);
|
|
104
|
+
renderTable(data || [], { showProject: true });
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const pid = await resolveProjectId(args?.flags?.project);
|
|
108
|
+
const { data } = await http.get(`/api/projects/${pid}/commitments?${q.toString()}`);
|
|
109
|
+
renderTable(data || []);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function cmdCommitmentShow(args) {
|
|
113
|
+
const id = args?._?.[0];
|
|
114
|
+
if (!id) fail("show", "id required");
|
|
115
|
+
const pid = await resolveProjectId(args?.flags?.project);
|
|
116
|
+
const c = await http.get(`/api/projects/${pid}/commitments/${encodeURIComponent(id)}`);
|
|
117
|
+
console.log(`${c.id} [${c.state}${isOverdue(c) ? " · OVERDUE" : ""}]`);
|
|
118
|
+
console.log(` To: ${c.counterparty}`);
|
|
119
|
+
console.log(` What: ${c.body}`);
|
|
120
|
+
console.log(` Promised: ${shortDate(c.promised_at)}${c.origin_channel ? ` on ${c.origin_channel}` : ""}`);
|
|
121
|
+
console.log(` Due: ${c.due ? shortDate(c.due) : "(no date)"}`);
|
|
122
|
+
if (c.note) console.log(` Note: ${c.note}`);
|
|
123
|
+
// The history is the relationship record — print it, it is the reason the
|
|
124
|
+
// renegotiate event exists at all.
|
|
125
|
+
for (const h of c.history || []) {
|
|
126
|
+
console.log(` Moved: ${shortDate(h.due)?.slice(0, 10) || "?"} → (on ${shortDate(h.moved_at)})${h.note ? ` — ${h.note}` : ""}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function close(args, sub) {
|
|
131
|
+
const id = args?._?.[0];
|
|
132
|
+
if (!id) fail(sub, "id required");
|
|
133
|
+
const pid = await resolveProjectId(args?.flags?.project);
|
|
134
|
+
const c = await http.post(`/api/projects/${pid}/commitments/${encodeURIComponent(id)}/${sub}`, {
|
|
135
|
+
note: args?.flags?.note || null,
|
|
136
|
+
});
|
|
137
|
+
console.log(`${c.id} → ${c.state}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export const cmdCommitmentKept = (args) => close(args, "kept");
|
|
141
|
+
export const cmdCommitmentMissed = (args) => close(args, "missed");
|
|
142
|
+
|
|
143
|
+
export async function cmdCommitmentRenegotiate(args) {
|
|
144
|
+
const id = args?._?.[0];
|
|
145
|
+
const due = args?.flags?.due;
|
|
146
|
+
if (!id) fail("renegotiate", "id required");
|
|
147
|
+
if (!due) fail("renegotiate", "--due <ISO> is required — a promise with no new date is a promise that vanished");
|
|
148
|
+
const pid = await resolveProjectId(args?.flags?.project);
|
|
149
|
+
const c = await http.post(`/api/projects/${pid}/commitments/${encodeURIComponent(id)}/renegotiate`, {
|
|
150
|
+
due,
|
|
151
|
+
note: args?.flags?.note || null,
|
|
152
|
+
});
|
|
153
|
+
console.log(`${c.id} → new date ${shortDate(c.due).slice(0, 10)} (moved ×${c.renegotiated_count})`);
|
|
154
|
+
}
|
|
@@ -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 {
|
|
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,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import
|
|
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";
|
|
4
|
+
import { installService, uninstallService, serviceStatus } from "#core/daemon/service.js";
|
|
5
5
|
|
|
6
6
|
// Wait until nothing answers on the daemon port (old process fully exited and
|
|
7
7
|
// released it), so a fresh start can bind it. Resolves true when down.
|
|
@@ -13,8 +13,8 @@ async function waitForPortReleased({ tries = 40, intervalMs = 150 } = {}) {
|
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
|
|
17
|
+
|
|
18
18
|
|
|
19
19
|
// ── ANSI helpers ─────────────────────────────────────────────────────────────
|
|
20
20
|
const c = {
|
|
@@ -56,8 +56,8 @@ function debugRaw(label, data) {
|
|
|
56
56
|
export async function cmdDaemonStart(args = {}) {
|
|
57
57
|
const debug = args.flags?.debug;
|
|
58
58
|
await ensureDaemon();
|
|
59
|
-
const status = await http.get("/health");
|
|
60
|
-
if (debug) debugRaw("/health", status);
|
|
59
|
+
const status = await http.get("/api/health");
|
|
60
|
+
if (debug) debugRaw("/api/health", status);
|
|
61
61
|
console.log(
|
|
62
62
|
`\n ${fmt.green("●")} ${fmt.bold("apx daemon")} ${fmt.dim("v" + status.version)}` +
|
|
63
63
|
` ${fmt.gray("·")} ${fmt.cyan("port")} ${status.port ?? (process.env.APX_PORT || 7430)}` +
|
|
@@ -77,13 +77,13 @@ export async function cmdDaemonStatus(args = {}) {
|
|
|
77
77
|
process.exit(1);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
const h = await http.get("/health", { autoStart: false });
|
|
81
|
-
const projects = await http.get("/projects", { autoStart: false });
|
|
80
|
+
const h = await http.get("/api/health", { autoStart: false });
|
|
81
|
+
const projects = await http.get("/api/projects", { autoStart: false });
|
|
82
82
|
const pid = fs.existsSync(PID_PATH) ? fs.readFileSync(PID_PATH, "utf8").trim() : "?";
|
|
83
83
|
|
|
84
84
|
if (debug) {
|
|
85
|
-
debugRaw("/health", h);
|
|
86
|
-
debugRaw("/projects", projects);
|
|
85
|
+
debugRaw("/api/health", h);
|
|
86
|
+
debugRaw("/api/projects", projects);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
console.log(
|
|
@@ -113,8 +113,8 @@ export async function cmdDaemonReload(args = {}) {
|
|
|
113
113
|
console.log(`\n ${fmt.yellow("○")} ${fmt.bold("apx daemon")} ${fmt.dim("not running — start first")}\n`);
|
|
114
114
|
process.exit(1);
|
|
115
115
|
}
|
|
116
|
-
const res = await http.post("/admin/reload", undefined, { autoStart: false });
|
|
117
|
-
if (debug) debugRaw("/admin/reload", res);
|
|
116
|
+
const res = await http.post("/api/admin/reload", undefined, { autoStart: false });
|
|
117
|
+
if (debug) debugRaw("/api/admin/reload", res);
|
|
118
118
|
console.log(`\n ${fmt.green("↻")} ${fmt.bold("config reloaded")}`);
|
|
119
119
|
if (res.super_agent_model) console.log(fmt.kv("model", fmt.cyan(res.super_agent_model)));
|
|
120
120
|
if (res.fallback_order?.length) console.log(fmt.kv("fallback", fmt.cyan(res.fallback_order.join(" → "))));
|
|
@@ -129,8 +129,8 @@ export async function cmdDaemonRestart(args = {}) {
|
|
|
129
129
|
// Ask the daemon to shut down cleanly; fall back to a PID kill if the
|
|
130
130
|
// HTTP shutdown route is unreachable (same fallback as `stop`).
|
|
131
131
|
try {
|
|
132
|
-
const res = await http.post("/admin/shutdown", undefined, { autoStart: false });
|
|
133
|
-
if (debug) debugRaw("/admin/shutdown", res);
|
|
132
|
+
const res = await http.post("/api/admin/shutdown", undefined, { autoStart: false });
|
|
133
|
+
if (debug) debugRaw("/api/admin/shutdown", res);
|
|
134
134
|
} catch {
|
|
135
135
|
if (fs.existsSync(PID_PATH)) {
|
|
136
136
|
try {
|
|
@@ -154,8 +154,8 @@ export async function cmdDaemonRestart(args = {}) {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
await ensureDaemon({ silent: true });
|
|
157
|
-
const status = await http.get("/health", { autoStart: false });
|
|
158
|
-
if (debug) debugRaw("/health", status);
|
|
157
|
+
const status = await http.get("/api/health", { autoStart: false });
|
|
158
|
+
if (debug) debugRaw("/api/health", status);
|
|
159
159
|
console.log(
|
|
160
160
|
`\n ${fmt.green("●")} ${fmt.bold("apx daemon")} ${fmt.dim("v" + status.version)}` +
|
|
161
161
|
` ${fmt.gray("·")} ${fmt.green(wasRunning ? "restarted" : "started")}` +
|
|
@@ -173,8 +173,8 @@ export async function cmdDaemonStop(args = {}) {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
try {
|
|
176
|
-
const res = await http.post("/admin/shutdown", undefined, { autoStart: false });
|
|
177
|
-
if (debug) debugRaw("/admin/shutdown", res);
|
|
176
|
+
const res = await http.post("/api/admin/shutdown", undefined, { autoStart: false });
|
|
177
|
+
if (debug) debugRaw("/api/admin/shutdown", res);
|
|
178
178
|
console.log(`\n ${fmt.red("○")} ${fmt.bold("apx daemon")} ${fmt.dim("stopped")}\n`);
|
|
179
179
|
} catch {
|
|
180
180
|
if (fs.existsSync(PID_PATH)) {
|
|
@@ -245,3 +245,59 @@ export async function cmdDaemonLogs(args) {
|
|
|
245
245
|
return new Promise(() => {});
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
|
+
|
|
249
|
+
// ── Service (opt-in supervision) ─────────────────────────────────────────────
|
|
250
|
+
|
|
251
|
+
export async function cmdDaemonInstallService() {
|
|
252
|
+
const before = serviceStatus();
|
|
253
|
+
if (!before.supervised && before.platform !== "win32") {
|
|
254
|
+
console.error(`apx daemon install-service: ${before.note || "not supported here"}`);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const r = installService();
|
|
259
|
+
if (!r.ok) {
|
|
260
|
+
console.error(`apx daemon install-service: ${r.error}`);
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
console.log(`\n ${fmt.green("●")} ${fmt.bold("apx daemon")} is now a service`);
|
|
265
|
+
console.log(` ${fmt.gray("·")} ${fmt.cyan("unit")} ${r.path}`);
|
|
266
|
+
if (r.log) console.log(` ${fmt.gray("·")} ${fmt.cyan("log")} ${r.log}`);
|
|
267
|
+
console.log("");
|
|
268
|
+
if (r.supervised) {
|
|
269
|
+
console.log(" If it dies, it comes back. It survives a reboot.");
|
|
270
|
+
} else {
|
|
271
|
+
// Never let the headline promise more than the platform delivers.
|
|
272
|
+
console.log(` ${fmt.yellow("Note")}: ${r.note}`);
|
|
273
|
+
}
|
|
274
|
+
if (r.note && r.supervised) console.log(` ${fmt.yellow("Note")}: ${r.note}`);
|
|
275
|
+
console.log(`\n Undo any time: ${fmt.cyan("apx daemon uninstall-service")}\n`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export async function cmdDaemonUninstallService() {
|
|
279
|
+
const r = uninstallService();
|
|
280
|
+
if (!r.ok) {
|
|
281
|
+
console.error(`apx daemon uninstall-service: ${r.error}`);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
console.log(r.removed
|
|
285
|
+
? `\n service removed — ${r.path}\n The daemon keeps working; it just is not supervised any more.\n`
|
|
286
|
+
: "\n no service was installed — nothing to remove\n");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export async function cmdDaemonServiceStatus() {
|
|
290
|
+
const s = serviceStatus();
|
|
291
|
+
if (!s.installed) {
|
|
292
|
+
console.log(`\n daemon service: ${fmt.dim("not installed")}`);
|
|
293
|
+
console.log(" The daemon starts when a command needs it, and nothing restarts it if it dies.");
|
|
294
|
+
console.log(` Install: ${fmt.cyan("apx daemon install-service")}\n`);
|
|
295
|
+
if (s.note) console.log(` ${fmt.yellow("Note")}: ${s.note}\n`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
console.log(`\n daemon service: ${fmt.green("installed")} ${fmt.gray("·")} ${s.path}`);
|
|
299
|
+
console.log(s.supervised
|
|
300
|
+
? " Supervised: it restarts on its own and survives a reboot."
|
|
301
|
+
: ` ${fmt.yellow("Not supervised")}: ${s.note}`);
|
|
302
|
+
console.log("");
|
|
303
|
+
}
|
|
@@ -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 {
|
|
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,
|
|
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 =
|
|
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(
|
|
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
|
|
14
|
-
|
|
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",
|
|
@@ -41,7 +41,7 @@ function sourceToScope(source) {
|
|
|
41
41
|
export async function cmdMcpList(args = {}) {
|
|
42
42
|
const scope = resolveListScope(args?.flags);
|
|
43
43
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
44
|
-
const mcps = await http.get(`/projects/${pid}/mcps`);
|
|
44
|
+
const mcps = await http.get(`/api/projects/${pid}/mcps`);
|
|
45
45
|
const filtered = scope === "all"
|
|
46
46
|
? mcps
|
|
47
47
|
: mcps.filter((m) => sourceToScope(m.source) === scope);
|
|
@@ -90,7 +90,7 @@ export async function cmdMcpAdd(args) {
|
|
|
90
90
|
|
|
91
91
|
const scope = resolveWriteScope(args.flags);
|
|
92
92
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
93
|
-
const result = await http.post(`/projects/${pid}/mcps?scope=${encodeURIComponent(scope)}`, {
|
|
93
|
+
const result = await http.post(`/api/projects/${pid}/mcps?scope=${encodeURIComponent(scope)}`, {
|
|
94
94
|
name,
|
|
95
95
|
command,
|
|
96
96
|
args: mcpArgs,
|
|
@@ -105,7 +105,7 @@ export async function cmdMcpRemove(args) {
|
|
|
105
105
|
if (!name) throw new Error("apx mcp remove: missing <name>");
|
|
106
106
|
const scope = resolveWriteScope(args.flags);
|
|
107
107
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
108
|
-
await http.delete(`/projects/${pid}/mcps/${name}?scope=${encodeURIComponent(scope)}`);
|
|
108
|
+
await http.delete(`/api/projects/${pid}/mcps/${name}?scope=${encodeURIComponent(scope)}`);
|
|
109
109
|
console.log(`Removed MCP "${name}" (scope: ${scope})`);
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -120,7 +120,7 @@ async function toggleEnabled(args, enabled) {
|
|
|
120
120
|
const name = args._[0];
|
|
121
121
|
if (!name) throw new Error(`apx mcp ${enabled ? "enable" : "disable"}: missing <name>`);
|
|
122
122
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
123
|
-
const all = await http.get(`/projects/${pid}/mcps`);
|
|
123
|
+
const all = await http.get(`/api/projects/${pid}/mcps`);
|
|
124
124
|
const m = all.find((x) => x.name === name);
|
|
125
125
|
if (!m) throw new Error(`MCP "${name}" not registered`);
|
|
126
126
|
// Write back to the scope it lives in so we don't accidentally shadow it.
|
|
@@ -132,7 +132,7 @@ async function toggleEnabled(args, enabled) {
|
|
|
132
132
|
`MCP "${name}" comes from foreign source "${m.source}" — toggle it in that IDE's config directly.`
|
|
133
133
|
);
|
|
134
134
|
}
|
|
135
|
-
await http.post(`/projects/${pid}/mcps?scope=${encodeURIComponent(scope)}`, {
|
|
135
|
+
await http.post(`/api/projects/${pid}/mcps?scope=${encodeURIComponent(scope)}`, {
|
|
136
136
|
name: m.name,
|
|
137
137
|
command: m.command,
|
|
138
138
|
args: m.args,
|
|
@@ -155,7 +155,7 @@ export async function cmdMcpRun(args) {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
158
|
-
const result = await http.post(`/projects/${pid}/mcps/${name}/call`, { tool, params });
|
|
158
|
+
const result = await http.post(`/api/projects/${pid}/mcps/${name}/call`, { tool, params });
|
|
159
159
|
process.stdout.write(JSON.stringify(result.result, null, 2) + "\n");
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -217,7 +217,7 @@ export async function cmdMcpTools(args) {
|
|
|
217
217
|
if (!name) throw new Error("apx mcp tools: usage: apx mcp tools <name> [<tool>] [--json]");
|
|
218
218
|
const toolFilter = args._[1];
|
|
219
219
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
220
|
-
const data = await http.get(`/projects/${pid}/mcps/${name}/tools`);
|
|
220
|
+
const data = await http.get(`/api/projects/${pid}/mcps/${name}/tools`);
|
|
221
221
|
const tools = data.tools || [];
|
|
222
222
|
|
|
223
223
|
if (toolFilter) {
|
|
@@ -256,7 +256,7 @@ export async function cmdMcpLogs(args) {
|
|
|
256
256
|
const name = args._[0];
|
|
257
257
|
if (!name) throw new Error("apx mcp logs: missing <name>");
|
|
258
258
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
259
|
-
const logs = await http.get(`/projects/${pid}/mcps/${name}/logs`);
|
|
259
|
+
const logs = await http.get(`/api/projects/${pid}/mcps/${name}/logs`);
|
|
260
260
|
if (args?.flags?.json) {
|
|
261
261
|
process.stdout.write(JSON.stringify(logs, null, 2) + "\n");
|
|
262
262
|
return;
|
|
@@ -287,7 +287,7 @@ export async function cmdMcpLogs(args) {
|
|
|
287
287
|
|
|
288
288
|
export async function cmdMcpCheck(args = {}) {
|
|
289
289
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
290
|
-
const data = await http.get(`/projects/${pid}/mcps/check`);
|
|
290
|
+
const data = await http.get(`/api/projects/${pid}/mcps/check`);
|
|
291
291
|
|
|
292
292
|
console.log("Source files:");
|
|
293
293
|
for (const s of data.sources) {
|