@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
|
@@ -2,6 +2,10 @@ import fs from "node:fs";
|
|
|
2
2
|
import { findApfRoot } from "#core/apc/parser.js";
|
|
3
3
|
import { agentMemoryPath, readAgentMemory, writeAgentMemory, ensureAgentRuntimeDir } from "#core/agent/memory.js";
|
|
4
4
|
import { http } from "../http.js";
|
|
5
|
+
import {
|
|
6
|
+
proposeConsolidation, applyConsolidation, revertConsolidation, notebookSize,
|
|
7
|
+
} from "#core/memory/consolidate.js";
|
|
8
|
+
import { readSelfMemory } from "#core/agent/self-memory.js";
|
|
5
9
|
|
|
6
10
|
function requireRoot() {
|
|
7
11
|
const root = findApfRoot();
|
|
@@ -12,9 +16,9 @@ function requireRoot() {
|
|
|
12
16
|
async function nudgeDaemon(root) {
|
|
13
17
|
try {
|
|
14
18
|
if (!(await http.ping())) return;
|
|
15
|
-
const projects = await http.get("/projects", { autoStart: false });
|
|
19
|
+
const projects = await http.get("/api/projects", { autoStart: false });
|
|
16
20
|
const me = projects.find((p) => p.path === root);
|
|
17
|
-
if (me) await http.post(`/projects/${me.id}/rebuild`, undefined, { autoStart: false });
|
|
21
|
+
if (me) await http.post(`/api/projects/${me.id}/rebuild`, undefined, { autoStart: false });
|
|
18
22
|
} catch {}
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -66,3 +70,72 @@ function readStdinSync() {
|
|
|
66
70
|
} catch {}
|
|
67
71
|
return chunks.join("");
|
|
68
72
|
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
// ── The super-agent's own notebook (~/.apx/memory.md) ────────────────────────
|
|
76
|
+
//
|
|
77
|
+
// Distinct from `apx memory <agent-slug>` above, which is a PROJECT agent's
|
|
78
|
+
// memory. This one ships in every super-agent prompt on every channel, which
|
|
79
|
+
// is why its size is worth showing and its growth worth controlling.
|
|
80
|
+
|
|
81
|
+
export async function cmdMemoryNotebook() {
|
|
82
|
+
const s = notebookSize();
|
|
83
|
+
console.log(`\nnotebook: ${s.entries} entries · ${s.chars} chars · ~${s.approx_tokens} tokens`);
|
|
84
|
+
// The number that matters: this is paid on every turn, of every channel.
|
|
85
|
+
console.log(` ${s.consolidated} of them written by consolidation.`);
|
|
86
|
+
console.log(" This file is injected into every super-agent prompt.\n");
|
|
87
|
+
const body = readSelfMemory();
|
|
88
|
+
if (body.trim()) process.stdout.write(body.endsWith("\n") ? body : body + "\n");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* apx memory consolidate [--apply] [--limit N]
|
|
93
|
+
*
|
|
94
|
+
* Candidates arrive on STDIN, one per line. The DISTILLING is the caller's job
|
|
95
|
+
* — a routine with a model behind it, or a person — and the JUDGEMENT about
|
|
96
|
+
* what survives lives in core, so the same rules apply whoever proposes.
|
|
97
|
+
*
|
|
98
|
+
* Proposes by default. Writing needs --apply, because a background job that
|
|
99
|
+
* silently edits the file the agent believes about itself is not something to
|
|
100
|
+
* switch on quietly.
|
|
101
|
+
*/
|
|
102
|
+
export async function cmdMemoryConsolidate(args) {
|
|
103
|
+
const raw = readStdinSync();
|
|
104
|
+
const candidates = raw.split("\n").map((l) => l.replace(/^[-*]\s*/, "").trim()).filter(Boolean);
|
|
105
|
+
if (!candidates.length) {
|
|
106
|
+
console.error("apx memory consolidate: no candidates on stdin (one fact per line)");
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const limits = args?.flags?.limit ? { max_candidates: Number(args.flags.limit) } : undefined;
|
|
111
|
+
const { kept, rejected } = proposeConsolidation(candidates, limits ? { limits } : {});
|
|
112
|
+
|
|
113
|
+
if (!kept.length) {
|
|
114
|
+
console.log("nothing worth saving.");
|
|
115
|
+
for (const r of rejected) console.log(` skipped: ${r.reason} — ${r.text.slice(0, 60)}`);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!args?.flags?.apply) {
|
|
120
|
+
console.log(`would save ${kept.length}:`);
|
|
121
|
+
for (const k of kept) console.log(` + ${k}`);
|
|
122
|
+
if (rejected.length) {
|
|
123
|
+
console.log(`\nskipped ${rejected.length}:`);
|
|
124
|
+
for (const r of rejected) console.log(` - ${r.reason} — ${r.text.slice(0, 60)}`);
|
|
125
|
+
}
|
|
126
|
+
console.log("\nNothing was written. Add --apply to save.");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const { written } = applyConsolidation(kept);
|
|
131
|
+
console.log(`saved ${written.length} to the notebook:`);
|
|
132
|
+
for (const w of written) console.log(` + ${w}`);
|
|
133
|
+
console.log("\nUndo: apx memory revert");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export async function cmdMemoryRevert(args) {
|
|
137
|
+
const { removed } = revertConsolidation(args?.flags?.since ? { since: String(args.flags.since) } : {});
|
|
138
|
+
console.log(removed
|
|
139
|
+
? `removed ${removed} consolidated ${removed === 1 ? "entry" : "entries"} — hand-written notes untouched`
|
|
140
|
+
: "nothing to revert (no consolidated entries)");
|
|
141
|
+
}
|
|
@@ -22,7 +22,7 @@ export async function cmdMessagesTail(args) {
|
|
|
22
22
|
// Read from global store — no project needed
|
|
23
23
|
const params = new URLSearchParams({ limit: String(n) });
|
|
24
24
|
if (channel) params.set("channel", channel);
|
|
25
|
-
const rows = await http.get(`/messages/global?${params}`);
|
|
25
|
+
const rows = await http.get(`/api/messages/global?${params}`);
|
|
26
26
|
if (rows.length === 0) {
|
|
27
27
|
console.log("(no messages)");
|
|
28
28
|
return;
|
|
@@ -39,7 +39,7 @@ export async function cmdMessagesTail(args) {
|
|
|
39
39
|
const params = new URLSearchParams({ limit: String(n) });
|
|
40
40
|
if (args.flags.agent && args.flags.agent !== true) params.set("agent", args.flags.agent);
|
|
41
41
|
if (channel) params.set("channel", channel);
|
|
42
|
-
const rows = await http.get(`/projects/${pid}/messages?${params}`);
|
|
42
|
+
const rows = await http.get(`/api/projects/${pid}/messages?${params}`);
|
|
43
43
|
if (rows.length === 0) {
|
|
44
44
|
console.log("(no messages)");
|
|
45
45
|
return;
|
|
@@ -82,7 +82,7 @@ export async function cmdMessagesChat(args) {
|
|
|
82
82
|
if (isGlobal) {
|
|
83
83
|
const params = new URLSearchParams({ limit: String(n) });
|
|
84
84
|
if (channel) params.set("channel", channel);
|
|
85
|
-
const rows = await http.get(`/messages/global?${params}`);
|
|
85
|
+
const rows = await http.get(`/api/messages/global?${params}`);
|
|
86
86
|
printChatRows(rows);
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
@@ -91,7 +91,7 @@ export async function cmdMessagesChat(args) {
|
|
|
91
91
|
const params = new URLSearchParams({ limit: String(n) });
|
|
92
92
|
if (args.flags.agent && args.flags.agent !== true) params.set("agent", args.flags.agent);
|
|
93
93
|
if (channel) params.set("channel", channel);
|
|
94
|
-
const rows = await http.get(`/projects/${pid}/messages?${params}`);
|
|
94
|
+
const rows = await http.get(`/api/projects/${pid}/messages?${params}`);
|
|
95
95
|
printChatRows(rows.reverse());
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -99,7 +99,7 @@ export async function cmdMessagesSearch(args) {
|
|
|
99
99
|
const q = args._[0];
|
|
100
100
|
if (!q) throw new Error("apx messages search: missing <query>");
|
|
101
101
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
102
|
-
const rows = await http.get(`/projects/${pid}/messages/search?q=${encodeURIComponent(q)}`);
|
|
102
|
+
const rows = await http.get(`/api/projects/${pid}/messages/search?q=${encodeURIComponent(q)}`);
|
|
103
103
|
if (rows.length === 0) {
|
|
104
104
|
console.log("(no matches)");
|
|
105
105
|
return;
|
|
@@ -18,24 +18,6 @@ function providersFromFallback(cfg) {
|
|
|
18
18
|
return seen.length ? seen : [...DEFAULT_FALLBACK_ORDER];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function parseValue(raw) {
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(raw);
|
|
24
|
-
} catch {
|
|
25
|
-
return raw;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function setNested(obj, keyPath, value) {
|
|
30
|
-
const parts = keyPath.split(".");
|
|
31
|
-
let cur = obj;
|
|
32
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
33
|
-
const p = parts[i];
|
|
34
|
-
if (!cur[p] || typeof cur[p] !== "object") cur[p] = {};
|
|
35
|
-
cur = cur[p];
|
|
36
|
-
}
|
|
37
|
-
cur[parts[parts.length - 1]] = value;
|
|
38
|
-
}
|
|
39
21
|
|
|
40
22
|
function ensureFallback(cfg) {
|
|
41
23
|
cfg.super_agent = cfg.super_agent || {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// apx nudge — the interruption budget: what APX said without being asked,
|
|
2
|
+
// what you thought of it, and how much room is left.
|
|
3
|
+
//
|
|
4
|
+
// apx nudge status
|
|
5
|
+
// apx nudge list [--limit N] [--kind K] [--project P] [--rated | --unrated]
|
|
6
|
+
// apx nudge set [--enabled true|false] [--daily-max N] [--quiet 22:00-07:30]
|
|
7
|
+
// [--cooldown N] [--project-cooldown N] [--kind-cooldown N]
|
|
8
|
+
// apx nudge check --kind K [--severity critical]
|
|
9
|
+
// apx nudge feedback <id> --useful | --noise [--note "..."]
|
|
10
|
+
import { http } from "../http.js";
|
|
11
|
+
|
|
12
|
+
export const NUDGE_USAGE = {
|
|
13
|
+
status: "apx nudge status",
|
|
14
|
+
list: "apx nudge list [--limit N] [--kind K] [--project P] [--rated|--unrated]",
|
|
15
|
+
set: "apx nudge set [--enabled true|false] [--daily-max N] [--quiet HH:MM-HH:MM] [--cooldown N] [--project-cooldown N] [--kind-cooldown N]",
|
|
16
|
+
check: "apx nudge check --kind K [--severity low|normal|high|critical]",
|
|
17
|
+
feedback: 'apx nudge feedback <id> --useful|--noise [--note "..."]',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function fail(sub, msg) {
|
|
21
|
+
console.error(`apx nudge ${sub}: ${msg}`);
|
|
22
|
+
console.error(`Usage: ${NUDGE_USAGE[sub]}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function shortTs(iso) {
|
|
27
|
+
if (!iso) return "";
|
|
28
|
+
return String(iso).replace(/T/, " ").replace(/Z$/, "").slice(0, 16);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function cmdNudgeStatus() {
|
|
32
|
+
const { policy, source, user_overrides } = await http.get("/api/nudges/policy");
|
|
33
|
+
const { meta } = await http.get("/api/nudges?limit=1");
|
|
34
|
+
const stats = meta?.stats || { total: 0, today: 0, rated: 0, by_kind: [] };
|
|
35
|
+
|
|
36
|
+
if (!policy.enabled) {
|
|
37
|
+
console.log("interruption budget: OFF — every unrequested message goes out.");
|
|
38
|
+
console.log(" Nothing is blocked, but everything is still recorded below.");
|
|
39
|
+
console.log(" Turn it on: apx nudge set --enabled true --daily-max 3");
|
|
40
|
+
} else {
|
|
41
|
+
const left = policy.daily_max > 0 ? Math.max(0, policy.daily_max - stats.today) : "∞";
|
|
42
|
+
console.log(`interruption budget: ON — ${stats.today} sent today, ${left} left`);
|
|
43
|
+
if (policy.daily_max > 0) console.log(` Daily max: ${policy.daily_max}`);
|
|
44
|
+
if (policy.quiet_hours) console.log(` Quiet hours: ${policy.quiet_hours}`);
|
|
45
|
+
if (policy.cooldown_minutes) console.log(` Cooldown: ${policy.cooldown_minutes}m between any two`);
|
|
46
|
+
if (policy.project_cooldown_minutes) console.log(` Per project: ${policy.project_cooldown_minutes}m`);
|
|
47
|
+
if (policy.kind_cooldown_minutes) console.log(` Per kind: ${policy.kind_cooldown_minutes}m`);
|
|
48
|
+
console.log(` Critical: ${policy.critical_bypasses_budget ? "may bypass (logged)" : "no bypass"}`);
|
|
49
|
+
}
|
|
50
|
+
// Provenance matters: a number the user did not choose should say who did.
|
|
51
|
+
console.log(` Set by: ${source.join(" → ")}`);
|
|
52
|
+
if (Object.keys(user_overrides || {}).length) {
|
|
53
|
+
console.log(` Your overrides: ${Object.entries(user_overrides).map(([k, v]) => `${k}=${v}`).join(", ")}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log("");
|
|
57
|
+
console.log(`recorded: ${stats.total} total, ${stats.rated} rated`);
|
|
58
|
+
for (const k of stats.by_kind.slice(0, 8)) {
|
|
59
|
+
const verdict = k.useful || k.noise ? ` (👍 ${k.useful} / 👎 ${k.noise})` : "";
|
|
60
|
+
console.log(` ${k.kind.padEnd(18)} ${String(k.sent).padStart(4)}${verdict}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function cmdNudgeList(args) {
|
|
65
|
+
const q = new URLSearchParams();
|
|
66
|
+
if (args?.flags?.limit) q.set("limit", args.flags.limit);
|
|
67
|
+
if (args?.flags?.kind) q.set("kind", args.flags.kind);
|
|
68
|
+
if (args?.flags?.project) q.set("project_id", args.flags.project);
|
|
69
|
+
if (args?.flags?.rated) q.set("with_feedback", "1");
|
|
70
|
+
if (args?.flags?.unrated) q.set("with_feedback", "0");
|
|
71
|
+
|
|
72
|
+
const { data } = await http.get(`/api/nudges?${q.toString()}`);
|
|
73
|
+
if (!data?.length) {
|
|
74
|
+
console.log("(nothing sent unprompted yet)");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const idW = Math.max(...data.map((r) => r.id.length), 2);
|
|
78
|
+
const kindW = Math.max(...data.map((r) => String(r.kind).length), 4);
|
|
79
|
+
for (const row of data) {
|
|
80
|
+
const rating = row.feedback ? (row.feedback.useful ? "👍" : "👎") : " ";
|
|
81
|
+
const flag = row.bypassed_budget ? " ⚠︎bypass" : "";
|
|
82
|
+
console.log(
|
|
83
|
+
`${row.id.padEnd(idW)} ${shortTs(row.at)} ${rating} ` +
|
|
84
|
+
`${String(row.kind).padEnd(kindW)} ${String(row.preview || "").slice(0, 60)}${flag}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function cmdNudgeSet(args) {
|
|
90
|
+
const f = args?.flags || {};
|
|
91
|
+
const body = {};
|
|
92
|
+
if (f.enabled !== undefined) body.enabled = String(f.enabled) !== "false";
|
|
93
|
+
if (f["daily-max"] !== undefined) body.daily_max = Number(f["daily-max"]);
|
|
94
|
+
if (f.quiet !== undefined) body.quiet_hours = String(f.quiet);
|
|
95
|
+
if (f.cooldown !== undefined) body.cooldown_minutes = Number(f.cooldown);
|
|
96
|
+
if (f["project-cooldown"] !== undefined) body.project_cooldown_minutes = Number(f["project-cooldown"]);
|
|
97
|
+
if (f["kind-cooldown"] !== undefined) body.kind_cooldown_minutes = Number(f["kind-cooldown"]);
|
|
98
|
+
if (!Object.keys(body).length) fail("set", "nothing to set");
|
|
99
|
+
|
|
100
|
+
const { policy, source } = await http.put("/api/nudges/policy", body);
|
|
101
|
+
console.log(`budget updated (${source.join(" → ")})`);
|
|
102
|
+
console.log(` enabled: ${policy.enabled} · daily max: ${policy.daily_max || "∞"} · quiet: ${policy.quiet_hours || "none"}`);
|
|
103
|
+
console.log(" Applies to the next unrequested message; nothing to restart.");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function cmdNudgeCheck(args) {
|
|
107
|
+
const kind = args?.flags?.kind;
|
|
108
|
+
if (!kind) fail("check", "--kind required");
|
|
109
|
+
const r = await http.post("/api/nudges/check", {
|
|
110
|
+
kind,
|
|
111
|
+
severity: args?.flags?.severity || "normal",
|
|
112
|
+
project_id: args?.flags?.project || null,
|
|
113
|
+
});
|
|
114
|
+
console.log(r.allowed ? `would send — ${r.reason}` : `would be held — ${r.reason}`);
|
|
115
|
+
if (!r.allowed && r.retry_after_ms) {
|
|
116
|
+
console.log(` Retry in ~${Math.ceil(r.retry_after_ms / 60000)} min.`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export async function cmdNudgeFeedback(args) {
|
|
121
|
+
const id = args?._?.[0];
|
|
122
|
+
if (!id) fail("feedback", "nudge id required");
|
|
123
|
+
const f = args?.flags || {};
|
|
124
|
+
if (!f.useful && !f.noise) fail("feedback", "--useful or --noise required");
|
|
125
|
+
await http.post(`/api/nudges/${encodeURIComponent(id)}/feedback`, {
|
|
126
|
+
useful: !!f.useful,
|
|
127
|
+
note: f.note || "",
|
|
128
|
+
});
|
|
129
|
+
console.log(f.useful ? "noted: useful" : "noted: not useful");
|
|
130
|
+
}
|
|
@@ -34,9 +34,9 @@ export async function cmdObsidianSet(args) {
|
|
|
34
34
|
if (args.flags.memory || args.flags["memory-sync"]) body.memory_sync = true;
|
|
35
35
|
|
|
36
36
|
const q = scopeQuery(scope);
|
|
37
|
-
await http.post(`/projects/${pid}/integrations/${SLUG}/configure${q}`, body);
|
|
37
|
+
await http.post(`/api/projects/${pid}/integrations/${SLUG}/configure${q}`, body);
|
|
38
38
|
try {
|
|
39
|
-
const r = await http.post(`/projects/${pid}/integrations/${SLUG}/validate${q}`, {});
|
|
39
|
+
const r = await http.post(`/api/projects/${pid}/integrations/${SLUG}/validate${q}`, {});
|
|
40
40
|
const badge = r.is_vault ? "Obsidian vault" : "folder (no .obsidian)";
|
|
41
41
|
console.log(`✓ Obsidian connected (${scope}) — ${r.vault_name} · ${r.note_count} notes · ${badge}`);
|
|
42
42
|
console.log(` ${r.vault_path}`);
|
|
@@ -50,7 +50,7 @@ export async function cmdObsidianSet(args) {
|
|
|
50
50
|
export async function cmdObsidianStatus(args) {
|
|
51
51
|
const scope = resolveScope(args.flags);
|
|
52
52
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
53
|
-
const s = await http.get(`/projects/${pid}/integrations/${SLUG}${scopeQuery(scope)}`);
|
|
53
|
+
const s = await http.get(`/api/projects/${pid}/integrations/${SLUG}${scopeQuery(scope)}`);
|
|
54
54
|
if (!s || s.status === "disconnected") {
|
|
55
55
|
console.log(`(Obsidian not configured in scope "${scope}")`);
|
|
56
56
|
return;
|
|
@@ -66,7 +66,7 @@ export async function cmdObsidianStatus(args) {
|
|
|
66
66
|
export async function cmdObsidianSync(args) {
|
|
67
67
|
const scope = resolveScope(args.flags);
|
|
68
68
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
69
|
-
const r = await http.post(`/projects/${pid}/integrations/${SLUG}/action/sync_memory${scopeQuery(scope)}`, {});
|
|
69
|
+
const r = await http.post(`/api/projects/${pid}/integrations/${SLUG}/action/sync_memory${scopeQuery(scope)}`, {});
|
|
70
70
|
console.log(`✓ Synced ${r.count} memory file(s) → vault folder "${r.folder}" (${r.changed} changed)`);
|
|
71
71
|
for (const n of r.notes || []) console.log(` ${n.changed ? "↑" : "="} ${n.note}`);
|
|
72
72
|
}
|
|
@@ -74,6 +74,6 @@ export async function cmdObsidianSync(args) {
|
|
|
74
74
|
export async function cmdObsidianRemove(args) {
|
|
75
75
|
const scope = resolveScope(args.flags);
|
|
76
76
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
77
|
-
await http.delete(`/projects/${pid}/integrations/${SLUG}${scopeQuery(scope)}`);
|
|
77
|
+
await http.delete(`/api/projects/${pid}/integrations/${SLUG}${scopeQuery(scope)}`);
|
|
78
78
|
console.log(`Removed Obsidian integration (scope: ${scope})`);
|
|
79
79
|
}
|
|
@@ -27,7 +27,7 @@ function fail(key, msg) {
|
|
|
27
27
|
|
|
28
28
|
export async function cmdOrgShow(args) {
|
|
29
29
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
30
|
-
const org = await http.get(`/projects/${pid}/organization`);
|
|
30
|
+
const org = await http.get(`/api/projects/${pid}/organization`);
|
|
31
31
|
if (!org.areas.length && !org.roles.length) {
|
|
32
32
|
console.log("(no organization structure yet)");
|
|
33
33
|
return;
|
|
@@ -44,7 +44,7 @@ export async function cmdOrgAreaAdd(args) {
|
|
|
44
44
|
const name = (args._ || []).slice(1).join(" ").trim();
|
|
45
45
|
if (!name) return fail("areaAdd", "name required");
|
|
46
46
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
47
|
-
const area = await http.post(`/projects/${pid}/organization/areas`, {
|
|
47
|
+
const area = await http.post(`/api/projects/${pid}/organization/areas`, {
|
|
48
48
|
name, slug: args.flags?.slug, goal: args.flags?.goal,
|
|
49
49
|
});
|
|
50
50
|
console.log(`added area ${area.name} (${area.slug})`);
|
|
@@ -54,7 +54,7 @@ export async function cmdOrgAreaRm(args) {
|
|
|
54
54
|
const slug = (args._ || [])[1];
|
|
55
55
|
if (!slug) return fail("areaRm", "slug required");
|
|
56
56
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
57
|
-
await http.delete(`/projects/${pid}/organization/areas/${encodeURIComponent(slug)}`);
|
|
57
|
+
await http.delete(`/api/projects/${pid}/organization/areas/${encodeURIComponent(slug)}`);
|
|
58
58
|
console.log(`removed area ${slug}`);
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -62,7 +62,7 @@ export async function cmdOrgRoleAdd(args) {
|
|
|
62
62
|
const name = (args._ || []).slice(1).join(" ").trim();
|
|
63
63
|
if (!name) return fail("roleAdd", "name required");
|
|
64
64
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
65
|
-
const role = await http.post(`/projects/${pid}/organization/roles`, {
|
|
65
|
+
const role = await http.post(`/api/projects/${pid}/organization/roles`, {
|
|
66
66
|
name, slug: args.flags?.slug, area: args.flags?.area, description: args.flags?.desc,
|
|
67
67
|
});
|
|
68
68
|
console.log(`added role ${role.name} (${role.slug})${role.area ? ` in ${role.area}` : ""}`);
|
|
@@ -72,6 +72,6 @@ export async function cmdOrgRoleRm(args) {
|
|
|
72
72
|
const slug = (args._ || [])[1];
|
|
73
73
|
if (!slug) return fail("roleRm", "slug required");
|
|
74
74
|
const pid = await resolveProjectId(args?.flags?.project);
|
|
75
|
-
await http.delete(`/projects/${pid}/organization/roles/${encodeURIComponent(slug)}`);
|
|
75
|
+
await http.delete(`/api/projects/${pid}/organization/roles/${encodeURIComponent(slug)}`);
|
|
76
76
|
console.log(`removed role ${slug}`);
|
|
77
77
|
}
|
|
@@ -34,7 +34,7 @@ const fmt = {
|
|
|
34
34
|
// pointing at 127.0.0.1 works through the USB bridge. For pure WiFi
|
|
35
35
|
// pairing, the user should bind APX_HOST=0.0.0.0 and we'll emit the
|
|
36
36
|
// LAN IP here instead.
|
|
37
|
-
function pickHostForQr({ host
|
|
37
|
+
function pickHostForQr({ host }) {
|
|
38
38
|
if (host && host !== "0.0.0.0" && host !== "::" && host !== "127.0.0.1") {
|
|
39
39
|
return host;
|
|
40
40
|
}
|
|
@@ -74,7 +74,7 @@ async function runPairing(args, channel) {
|
|
|
74
74
|
// 1. Ask daemon for a pairing nonce.
|
|
75
75
|
let init;
|
|
76
76
|
try {
|
|
77
|
-
init = await http.post("/pair/init", {});
|
|
77
|
+
init = await http.post("/api/pair/init", {});
|
|
78
78
|
} catch (e) {
|
|
79
79
|
console.error(fmt.red(`pair init failed: ${e.message}`));
|
|
80
80
|
process.exit(1);
|
|
@@ -117,7 +117,7 @@ async function runPairing(args, channel) {
|
|
|
117
117
|
while (Date.now() < deadline) {
|
|
118
118
|
await sleep(1500);
|
|
119
119
|
try {
|
|
120
|
-
const s = await http.get(`/pair/status/${init.pairing_id}`);
|
|
120
|
+
const s = await http.get(`/api/pair/status/${init.pairing_id}`);
|
|
121
121
|
if (s.status === "confirmed") {
|
|
122
122
|
console.log(` ${fmt.green("●")} ${fmt.bold("paired")} ${fmt.gray("·")} ${s.device_label || ""}`);
|
|
123
123
|
console.log(` ${fmt.gray("client_id:")} ${s.client_id}`);
|
|
@@ -138,7 +138,7 @@ async function runPairing(args, channel) {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
export async function cmdPairList() {
|
|
141
|
-
const { clients } = await http.get("/pair/list");
|
|
141
|
+
const { clients } = await http.get("/api/pair/list");
|
|
142
142
|
if (!clients.length) {
|
|
143
143
|
console.log(`\n ${fmt.dim("no paired devices")}\n`);
|
|
144
144
|
return;
|
|
@@ -160,12 +160,12 @@ export async function cmdPairRevoke(args = {}) {
|
|
|
160
160
|
process.exit(1);
|
|
161
161
|
}
|
|
162
162
|
// Allow short prefix: resolve via /pair/list.
|
|
163
|
-
const { clients } = await http.get("/pair/list");
|
|
163
|
+
const { clients } = await http.get("/api/pair/list");
|
|
164
164
|
const match = clients.find((c) => c.id === id || c.id.startsWith(id));
|
|
165
165
|
if (!match) {
|
|
166
166
|
console.error(fmt.red(`no paired device matches "${id}"`));
|
|
167
167
|
process.exit(1);
|
|
168
168
|
}
|
|
169
|
-
await http.delete(`/pair/revoke/${match.id}`);
|
|
169
|
+
await http.delete(`/api/pair/revoke/${match.id}`);
|
|
170
170
|
console.log(` ${fmt.green("●")} revoked ${match.label} ${fmt.gray(`(${match.id.slice(0, 8)})`)}`);
|
|
171
171
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { http } from "../http.js";
|
|
2
2
|
|
|
3
3
|
export async function cmdPluginsList() {
|
|
4
|
-
const data = await http.get("/plugins");
|
|
4
|
+
const data = await http.get("/api/plugins");
|
|
5
5
|
const ids = Object.keys(data);
|
|
6
6
|
if (ids.length === 0) {
|
|
7
7
|
console.log("(no plugins loaded)");
|
|
@@ -18,6 +18,6 @@ export async function cmdPluginsList() {
|
|
|
18
18
|
export async function cmdPluginStatus(args) {
|
|
19
19
|
const id = args._[0];
|
|
20
20
|
if (!id) throw new Error("apx plugins status: missing <plugin-id>");
|
|
21
|
-
const s = await http.get(`/plugins/${id}/status`);
|
|
21
|
+
const s = await http.get(`/api/plugins/${id}/status`);
|
|
22
22
|
console.log(JSON.stringify(s, null, 2));
|
|
23
23
|
}
|
|
@@ -73,7 +73,7 @@ function printDoctor(report) {
|
|
|
73
73
|
// ── list ────────────────────────────────────────────────────────────────────
|
|
74
74
|
|
|
75
75
|
export async function cmdProfileList() {
|
|
76
|
-
const { active, profiles } = await http.get("/profiles");
|
|
76
|
+
const { active, profiles } = await http.get("/api/profiles");
|
|
77
77
|
if (!profiles.length) {
|
|
78
78
|
console.log("(no profiles available)");
|
|
79
79
|
return;
|
|
@@ -94,7 +94,7 @@ export async function cmdProfileShow(args) {
|
|
|
94
94
|
const id = args._[0];
|
|
95
95
|
if (!id) fail("show", "missing <id>");
|
|
96
96
|
|
|
97
|
-
const p = await http.get(`/profiles/${encodeURIComponent(id)}`);
|
|
97
|
+
const p = await http.get(`/api/profiles/${encodeURIComponent(id)}`);
|
|
98
98
|
console.log(`${p.name} (${p.id}) v${p.version || "?"} — ${p.source}${p.active ? " — ACTIVE" : ""}`);
|
|
99
99
|
if (p.description) console.log(p.description);
|
|
100
100
|
console.log(`languages: ${p.languages.join(", ") || "en"}`);
|
|
@@ -119,7 +119,7 @@ export async function cmdProfileInstall(args) {
|
|
|
119
119
|
const source = args._[0];
|
|
120
120
|
if (!source) fail("install", "missing <id|path>");
|
|
121
121
|
|
|
122
|
-
const r = await http.post("/profiles/install", { source, force: !!args?.flags?.force });
|
|
122
|
+
const r = await http.post("/api/profiles/install", { source, force: !!args?.flags?.force });
|
|
123
123
|
console.log(`installed ${r.profile.name} (${r.profile.id}) v${r.profile.version || "?"}`);
|
|
124
124
|
console.log(` prompt: ~${r.tokens} tokens`);
|
|
125
125
|
printWarnings(r.warnings);
|
|
@@ -133,7 +133,7 @@ export async function cmdProfileUse(args) {
|
|
|
133
133
|
const id = args._[0];
|
|
134
134
|
if (!id) fail("use", "missing <id>");
|
|
135
135
|
|
|
136
|
-
const r = await http.post("/profiles/use", { id, force: !!args?.flags?.force });
|
|
136
|
+
const r = await http.post("/api/profiles/use", { id, force: !!args?.flags?.force });
|
|
137
137
|
console.log(`active profile: ${r.profile.name} (${r.profile.id})`);
|
|
138
138
|
printWarnings(r.warnings);
|
|
139
139
|
|
|
@@ -146,7 +146,7 @@ export async function cmdProfileUse(args) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
export async function cmdProfileOff() {
|
|
149
|
-
const r = await http.post("/profiles/off", {});
|
|
149
|
+
const r = await http.post("/api/profiles/off", {});
|
|
150
150
|
if (!r.was) {
|
|
151
151
|
console.log("no profile was active — nothing to do");
|
|
152
152
|
return;
|
|
@@ -185,14 +185,14 @@ async function interactiveConfig(profile) {
|
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
export async function cmdProfileConfig(args) {
|
|
188
|
-
const { active } = await http.get("/profiles");
|
|
188
|
+
const { active } = await http.get("/api/profiles");
|
|
189
189
|
const id = args?.flags?.profile || active;
|
|
190
190
|
if (!id) {
|
|
191
191
|
console.error("apx profile config: no profile is active — run: apx profile use <id>");
|
|
192
192
|
process.exit(1);
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
const profile = await http.get(`/profiles/${encodeURIComponent(id)}?preview=0`);
|
|
195
|
+
const profile = await http.get(`/api/profiles/${encodeURIComponent(id)}?preview=0`);
|
|
196
196
|
|
|
197
197
|
let values = parseSetFlags(args?.flags);
|
|
198
198
|
if (args?.flags?.interactive) {
|
|
@@ -217,7 +217,7 @@ export async function cmdProfileConfig(args) {
|
|
|
217
217
|
return;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
const r = await http.patch("/profiles/config", { values, id });
|
|
220
|
+
const r = await http.patch("/api/profiles/config", { values, id });
|
|
221
221
|
console.log(`updated: ${r.changed.join(", ")}`);
|
|
222
222
|
for (const k of r.changed) console.log(` ${k.padEnd(24)} ${r.config[k]}`);
|
|
223
223
|
|
|
@@ -233,14 +233,14 @@ export async function cmdProfileConfig(args) {
|
|
|
233
233
|
export async function cmdProfileDoctor(args) {
|
|
234
234
|
const id = args._[0];
|
|
235
235
|
const q = id ? `?id=${encodeURIComponent(id)}` : "";
|
|
236
|
-
printDoctor(await http.get(`/profiles/doctor${q}`));
|
|
236
|
+
printDoctor(await http.get(`/api/profiles/doctor${q}`));
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
export async function cmdProfileUninstall(args) {
|
|
240
240
|
const id = args._[0];
|
|
241
241
|
if (!id) fail("uninstall", "missing <id>");
|
|
242
242
|
|
|
243
|
-
const r = await http.delete(`/profiles/${encodeURIComponent(id)}`);
|
|
243
|
+
const r = await http.delete(`/api/profiles/${encodeURIComponent(id)}`);
|
|
244
244
|
console.log(`uninstalled "${r.id}" (${r.source})`);
|
|
245
245
|
if (r.routines?.removed?.length) console.log(` routines removed: ${r.routines.removed.join(", ")}`);
|
|
246
246
|
if (r.routines?.kept?.length) {
|
|
@@ -18,7 +18,7 @@ import { resolveProjectId } from "./project.js";
|
|
|
18
18
|
|
|
19
19
|
async function reloadDaemon() {
|
|
20
20
|
try {
|
|
21
|
-
await http.post("/admin/reload", {});
|
|
21
|
+
await http.post("/api/admin/reload", {});
|
|
22
22
|
} catch (e) {
|
|
23
23
|
console.log(`⚠️ reload failed: ${e.message} (changes saved, restart daemon to apply)`);
|
|
24
24
|
}
|
|
@@ -65,7 +65,7 @@ async function projectIdFromArg(target) {
|
|
|
65
65
|
export async function cmdProjectConfigShow(args) {
|
|
66
66
|
const target = args._[0];
|
|
67
67
|
const id = await projectIdFromArg(target);
|
|
68
|
-
const data = await http.get(`/projects/${id}/config`);
|
|
68
|
+
const data = await http.get(`/api/projects/${id}/config`);
|
|
69
69
|
const key = args.flags.key;
|
|
70
70
|
if (key) {
|
|
71
71
|
const eff = readDotted(data.effective || {}, key);
|
|
@@ -89,7 +89,7 @@ export async function cmdProjectConfigSet(args) {
|
|
|
89
89
|
if (raw === undefined) throw new Error("apx project config set: missing <value>");
|
|
90
90
|
const id = await projectIdFromArg(target);
|
|
91
91
|
const value = coerceValue(raw);
|
|
92
|
-
await http.patch(`/projects/${id}/config`, { set: { [dotted]: value } });
|
|
92
|
+
await http.patch(`/api/projects/${id}/config`, { set: { [dotted]: value } });
|
|
93
93
|
await reloadDaemon();
|
|
94
94
|
console.log(`✅ set ${dotted} = ${JSON.stringify(value)}`);
|
|
95
95
|
}
|
|
@@ -99,7 +99,7 @@ export async function cmdProjectConfigUnset(args) {
|
|
|
99
99
|
const dotted = args._[1];
|
|
100
100
|
if (!dotted) throw new Error("apx project config unset: missing <dotted.key>");
|
|
101
101
|
const id = await projectIdFromArg(target);
|
|
102
|
-
await http.patch(`/projects/${id}/config`, { unset: [dotted] });
|
|
102
|
+
await http.patch(`/api/projects/${id}/config`, { unset: [dotted] });
|
|
103
103
|
await reloadDaemon();
|
|
104
104
|
console.log(`✅ unset ${dotted}`);
|
|
105
105
|
}
|
|
@@ -107,7 +107,7 @@ export async function cmdProjectConfigUnset(args) {
|
|
|
107
107
|
export async function cmdProjectConfigEdit(args) {
|
|
108
108
|
const target = args._[0];
|
|
109
109
|
const id = await projectIdFromArg(target);
|
|
110
|
-
const data = await http.get(`/projects/${id}/config`);
|
|
110
|
+
const data = await http.get(`/api/projects/${id}/config`);
|
|
111
111
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "apx-cfg-"));
|
|
112
112
|
const tmpFile = path.join(tmpDir, "config.json");
|
|
113
113
|
fs.writeFileSync(tmpFile, JSON.stringify(data.project_only || {}, null, 2) + "\n");
|
|
@@ -125,7 +125,7 @@ export async function cmdProjectConfigEdit(args) {
|
|
|
125
125
|
throw new Error(`invalid JSON after edit: ${e.message}`);
|
|
126
126
|
}
|
|
127
127
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
128
|
-
await http.put(`/projects/${id}/config`, updated);
|
|
128
|
+
await http.put(`/api/projects/${id}/config`, updated);
|
|
129
129
|
await reloadDaemon();
|
|
130
130
|
console.log(`✅ saved project_only config for #${id}`);
|
|
131
131
|
}
|
|
@@ -12,12 +12,12 @@ function requireRoot() {
|
|
|
12
12
|
|
|
13
13
|
export async function cmdProjectAdd(args) {
|
|
14
14
|
const target = args._[0] || requireRoot();
|
|
15
|
-
const result = await http.post("/projects", { path: path.resolve(target) });
|
|
15
|
+
const result = await http.post("/api/projects", { path: path.resolve(target) });
|
|
16
16
|
console.log(`Registered #${result.id}: ${result.path}`);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export async function cmdProjectList() {
|
|
20
|
-
const projects = await http.get("/projects");
|
|
20
|
+
const projects = await http.get("/api/projects");
|
|
21
21
|
if (projects.length === 0) {
|
|
22
22
|
console.log("(no projects registered — try `apx project add .`)");
|
|
23
23
|
return;
|
|
@@ -31,7 +31,7 @@ export async function cmdProjectList() {
|
|
|
31
31
|
export async function cmdProjectRemove(args) {
|
|
32
32
|
const target = args._[0];
|
|
33
33
|
if (!target) throw new Error("apx project remove: missing <path|id>");
|
|
34
|
-
const projects = await http.get("/projects");
|
|
34
|
+
const projects = await http.get("/api/projects");
|
|
35
35
|
let id;
|
|
36
36
|
if (/^\d+$/.test(target)) id = parseInt(target, 10);
|
|
37
37
|
else {
|
|
@@ -40,7 +40,7 @@ export async function cmdProjectRemove(args) {
|
|
|
40
40
|
if (!found) throw new Error(`not registered: ${target}`);
|
|
41
41
|
id = found.id;
|
|
42
42
|
}
|
|
43
|
-
await http.delete(`/projects/${id}`);
|
|
43
|
+
await http.delete(`/api/projects/${id}`);
|
|
44
44
|
console.log(`Removed project #${id}`);
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -51,19 +51,19 @@ export async function cmdProjectRebuild(args) {
|
|
|
51
51
|
if (/^\d+$/.test(target)) id = parseInt(target, 10);
|
|
52
52
|
else {
|
|
53
53
|
const abs = path.resolve(target);
|
|
54
|
-
const projects = await http.get("/projects");
|
|
54
|
+
const projects = await http.get("/api/projects");
|
|
55
55
|
const found = projects.find((p) => p.path === abs);
|
|
56
56
|
if (!found) throw new Error(`not registered: ${target}`);
|
|
57
57
|
id = found.id;
|
|
58
58
|
}
|
|
59
59
|
} else {
|
|
60
60
|
const root = requireRoot();
|
|
61
|
-
const projects = await http.get("/projects");
|
|
61
|
+
const projects = await http.get("/api/projects");
|
|
62
62
|
const found = projects.find((p) => p.path === root);
|
|
63
63
|
if (!found) throw new Error(`current project not registered — run \`apx project add .\``);
|
|
64
64
|
id = found.id;
|
|
65
65
|
}
|
|
66
|
-
const result = await http.post(`/projects/${id}/rebuild`);
|
|
66
|
+
const result = await http.post(`/api/projects/${id}/rebuild`);
|
|
67
67
|
console.log(`Rebuilt project #${id}: ${result.agents} agents`);
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -78,7 +78,7 @@ export async function resolveProjectId(target) {
|
|
|
78
78
|
if (typeof target === "number" || /^\d+$/.test(String(target))) {
|
|
79
79
|
return parseInt(target, 10);
|
|
80
80
|
}
|
|
81
|
-
const projects = await http.get("/projects");
|
|
81
|
+
const projects = await http.get("/api/projects");
|
|
82
82
|
const tgt = String(target);
|
|
83
83
|
|
|
84
84
|
// exact path
|
|
@@ -112,10 +112,10 @@ export async function resolveProjectId(target) {
|
|
|
112
112
|
// Fall back to the default project (id=0) — always available, no .apc/ required.
|
|
113
113
|
return 0;
|
|
114
114
|
}
|
|
115
|
-
const projects = await http.get("/projects");
|
|
115
|
+
const projects = await http.get("/api/projects");
|
|
116
116
|
const found = projects.find((p) => p.path === root);
|
|
117
117
|
if (found) return found.id;
|
|
118
118
|
// auto-register
|
|
119
|
-
const result = await http.post("/projects", { path: root });
|
|
119
|
+
const result = await http.post("/api/projects", { path: root });
|
|
120
120
|
return result.id;
|
|
121
121
|
}
|