@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
|
@@ -17,6 +17,35 @@
|
|
|
17
17
|
|
|
18
18
|
const THINK_RE = /<(?:think|thinking)>([\s\S]*?)<\/(?:think|thinking)>/gi;
|
|
19
19
|
|
|
20
|
+
// Untagged chain-of-thought.
|
|
21
|
+
//
|
|
22
|
+
// Some models — routed free tiers especially — emit their planning as the
|
|
23
|
+
// answer itself, with no tags at all: "We need to produce a response to user
|
|
24
|
+
// request: ...". That reached a real user's Telegram as a 668-token English
|
|
25
|
+
// wall in place of two sentences of Spanish.
|
|
26
|
+
//
|
|
27
|
+
// Detection is deliberately narrow. It only fires when the text OPENS with
|
|
28
|
+
// first-person-plural planning about producing a response, which is a register
|
|
29
|
+
// no genuine reply uses. Anything looser would eat real answers that happen to
|
|
30
|
+
// begin with "We need to".
|
|
31
|
+
const UNTAGGED_COT_OPENERS = [
|
|
32
|
+
/^we need to (produce|craft|write|generate|compose) (a |an )?(response|reply|answer|message)/i,
|
|
33
|
+
/^(the )?user (is )?(asking|says|wants|requests)\b[\s\S]{0,200}?\bwe (should|need to|must)\b/i,
|
|
34
|
+
/^okay,? (so )?(the )?user\b[\s\S]{0,120}?\bwe (should|need to)\b/i,
|
|
35
|
+
/^interpretation:\s/i,
|
|
36
|
+
/^let'?s (think|analyze|break this down)\b/i,
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* True when `text` reads as raw planning rather than a reply.
|
|
41
|
+
* Only ever consulted for the ANSWER half, after tagged blocks are removed.
|
|
42
|
+
*/
|
|
43
|
+
export function looksLikeUntaggedReasoning(text) {
|
|
44
|
+
const t = String(text || "").trimStart();
|
|
45
|
+
if (t.length < 120) return false; // too short to be a planning dump
|
|
46
|
+
return UNTAGGED_COT_OPENERS.some((re) => re.test(t));
|
|
47
|
+
}
|
|
48
|
+
|
|
20
49
|
export function splitThinking(text) {
|
|
21
50
|
if (!text || typeof text !== "string") return { thinking: "", answer: text || "" };
|
|
22
51
|
const blocks = [];
|
|
@@ -34,6 +63,28 @@ export function stripThinking(text) {
|
|
|
34
63
|
return splitThinking(text).answer;
|
|
35
64
|
}
|
|
36
65
|
|
|
66
|
+
/**
|
|
67
|
+
* The answer, with untagged planning treated as thinking too.
|
|
68
|
+
*
|
|
69
|
+
* `stripThinking` only removes TAGGED blocks. A model that dumps its planning
|
|
70
|
+
* with no tags slips straight through, which is how a 668-token English
|
|
71
|
+
* chain-of-thought reached a user's phone instead of two sentences of Spanish.
|
|
72
|
+
*
|
|
73
|
+
* When the remaining answer still reads as raw planning, this returns "" — the
|
|
74
|
+
* caller decides what to do with an empty reply, which is a far better failure
|
|
75
|
+
* than shipping the model's notes to the user. Never guesses at salvaging a
|
|
76
|
+
* partial answer out of it.
|
|
77
|
+
*
|
|
78
|
+
* @returns {{ answer: string, leaked: boolean, thinking: string }}
|
|
79
|
+
*/
|
|
80
|
+
export function stripReasoning(text) {
|
|
81
|
+
const { thinking, answer } = splitThinking(text);
|
|
82
|
+
if (looksLikeUntaggedReasoning(answer)) {
|
|
83
|
+
return { answer: "", leaked: true, thinking: [thinking, answer].filter(Boolean).join("\n\n") };
|
|
84
|
+
}
|
|
85
|
+
return { answer, leaked: false, thinking };
|
|
86
|
+
}
|
|
87
|
+
|
|
37
88
|
export function formatForChannel(text, channel) {
|
|
38
89
|
const { thinking, answer } = splitThinking(text);
|
|
39
90
|
// Channels where reasoning would be noise to a human operator
|
package/src/core/vars/sources.js
CHANGED
|
@@ -13,16 +13,16 @@
|
|
|
13
13
|
//
|
|
14
14
|
// project wins over global when the same name exists in both.
|
|
15
15
|
|
|
16
|
-
import fs from "node:fs";
|
|
17
|
-
import os from "node:os";
|
|
18
16
|
import path from "node:path";
|
|
17
|
+
import { apxHome } from "#core/config/paths.js";
|
|
18
|
+
import { readJson, writeJson, SECRET_MODE } from "#core/util/json-file.js";
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
const
|
|
20
|
+
|
|
21
|
+
const globalVarsFile = () => path.join(apxHome(), "vars.json");
|
|
22
22
|
const PROJECT_VARS_FILENAME = "vars.json";
|
|
23
23
|
|
|
24
24
|
export function globalVarsPath() {
|
|
25
|
-
return
|
|
25
|
+
return globalVarsFile();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export function projectVarsPath(storagePath) {
|
|
@@ -30,32 +30,25 @@ export function projectVarsPath(storagePath) {
|
|
|
30
30
|
return path.join(storagePath, PROJECT_VARS_FILENAME);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// A vars file must be a plain object; anything else is treated as empty.
|
|
33
34
|
function readJsonSafe(absPath) {
|
|
34
|
-
if (!absPath
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return json && typeof json === "object" && !Array.isArray(json) ? json : {};
|
|
38
|
-
} catch {
|
|
39
|
-
return {};
|
|
40
|
-
}
|
|
35
|
+
if (!absPath) return {};
|
|
36
|
+
const json = readJson(absPath, {});
|
|
37
|
+
return json && typeof json === "object" && !Array.isArray(json) ? json : {};
|
|
41
38
|
}
|
|
42
39
|
|
|
40
|
+
// SECRET_MODE: these files hold tokens. The write is atomic, so a crash can no
|
|
41
|
+
// longer truncate the store.
|
|
43
42
|
function writeJsonSecure(absPath, obj) {
|
|
44
|
-
|
|
45
|
-
fs.writeFileSync(absPath, JSON.stringify(obj, null, 2) + "\n");
|
|
46
|
-
try {
|
|
47
|
-
fs.chmodSync(absPath, 0o600);
|
|
48
|
-
} catch {
|
|
49
|
-
// Best effort on non-POSIX filesystems.
|
|
50
|
-
}
|
|
43
|
+
writeJson(absPath, obj, { mode: SECRET_MODE });
|
|
51
44
|
}
|
|
52
45
|
|
|
53
46
|
export function readGlobalVars() {
|
|
54
|
-
return readJsonSafe(
|
|
47
|
+
return readJsonSafe(globalVarsFile());
|
|
55
48
|
}
|
|
56
49
|
|
|
57
50
|
export function writeGlobalVars(obj) {
|
|
58
|
-
writeJsonSecure(
|
|
51
|
+
writeJsonSecure(globalVarsFile(), obj);
|
|
59
52
|
}
|
|
60
53
|
|
|
61
54
|
export function readProjectVars(storagePath) {
|
package/src/core/voice/tts.js
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
//
|
|
6
6
|
// All audio files land under ~/.apx/tmp/tts/<uuid>.<ext>. Callers are
|
|
7
7
|
// responsible for cleaning up (Telegram plugin already uses similar temp
|
|
8
|
-
// files via /telegram/send_voice).
|
|
8
|
+
// files via /api/telegram/send_voice).
|
|
9
9
|
|
|
10
10
|
import fs from "node:fs";
|
|
11
|
-
import
|
|
12
|
-
|
|
11
|
+
import { TTS_TMP_DIR } from "#core/config/paths.js";
|
|
12
|
+
|
|
13
|
+
export { TTS_TMP_DIR };
|
|
13
14
|
import { readConfig } from "../config/index.js";
|
|
14
15
|
import {
|
|
15
16
|
selectTtsEngine,
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
} from "./engines/index.js";
|
|
20
21
|
import { emotionConfigFor, stripEmotionTags } from "./emotions.js";
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
|
|
23
24
|
|
|
24
25
|
export function ensureTtsTmpDir() {
|
|
25
26
|
fs.mkdirSync(TTS_TMP_DIR, { recursive: true });
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { readConfig, writeConfig } from "#core/config/index.js";
|
|
9
9
|
import { resolveAgentName } from "#core/identity/index.js";
|
|
10
10
|
import { setDottedKey, unsetDottedKey } from "../project-config.js";
|
|
11
|
-
import { PERMISSION_MODES
|
|
11
|
+
import { PERMISSION_MODES } from "#core/constants/permissions.js";
|
|
12
12
|
import {
|
|
13
13
|
redactConfig as redact,
|
|
14
14
|
isSecretMarker,
|
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
} from "#core/config/redact.js";
|
|
17
17
|
import { collectSecretValues, registerSecretValues } from "#core/config/secret-values.js";
|
|
18
18
|
|
|
19
|
-
export function register(
|
|
20
|
-
|
|
19
|
+
export function register(api, { config, scheduler, plugins }) {
|
|
20
|
+
api.get("/admin/config", (_req, res) => {
|
|
21
21
|
try {
|
|
22
22
|
const fresh = readConfig();
|
|
23
23
|
res.json({ config: redact(fresh) });
|
|
@@ -26,7 +26,7 @@ export function register(app, { config, scheduler, plugins }) {
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
api.patch("/admin/config", (req, res) => {
|
|
30
30
|
const { set, unset } = req.body || {};
|
|
31
31
|
let cfg;
|
|
32
32
|
try {
|
|
@@ -68,7 +68,7 @@ export function register(app, { config, scheduler, plugins }) {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
// Convenience: GET the resolved super_agent prompt (used by SettingsScreen)
|
|
71
|
-
|
|
71
|
+
api.get("/admin/super-agent", (_req, res) => {
|
|
72
72
|
try {
|
|
73
73
|
const fresh = readConfig();
|
|
74
74
|
const sa = fresh.super_agent || {};
|
|
@@ -8,11 +8,12 @@ import { execFile } from "node:child_process";
|
|
|
8
8
|
import fs from "node:fs";
|
|
9
9
|
import os from "node:os";
|
|
10
10
|
import path from "node:path";
|
|
11
|
+
import { LOG_DIR } from "#core/config/paths.js";
|
|
11
12
|
|
|
12
|
-
export function register(
|
|
13
|
+
export function register(api, { scheduler, plugins, config, registries }) {
|
|
13
14
|
// Daemon logs: errors.jsonl (structured) or apx.log (plain), newest first.
|
|
14
|
-
|
|
15
|
-
const dir =
|
|
15
|
+
api.get("/admin/logs", (req, res) => {
|
|
16
|
+
const dir = LOG_DIR;
|
|
16
17
|
const which = req.query.file === "apx" ? "apx.log" : "errors.jsonl";
|
|
17
18
|
const file = path.join(dir, which);
|
|
18
19
|
const limit = Math.min(parseInt(req.query.limit, 10) || 200, 2000);
|
|
@@ -26,7 +27,7 @@ export function register(app, { scheduler, plugins, config, registries }) {
|
|
|
26
27
|
res.json({ file: which, lines: tail });
|
|
27
28
|
});
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
api.post("/admin/reload", (_req, res) => {
|
|
30
31
|
try {
|
|
31
32
|
const fresh = readConfig();
|
|
32
33
|
// Mutate in place so every closure that captured `config` sees the new
|
|
@@ -46,7 +47,7 @@ export function register(app, { scheduler, plugins, config, registries }) {
|
|
|
46
47
|
}
|
|
47
48
|
});
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
api.post("/admin/shutdown", (_req, res) => {
|
|
50
51
|
res.json({ ok: true });
|
|
51
52
|
setTimeout(() => process.exit(0), 50);
|
|
52
53
|
});
|
|
@@ -56,7 +57,7 @@ export function register(app, { scheduler, plugins, config, registries }) {
|
|
|
56
57
|
// zenity (if present); Windows uses PowerShell's Shell.Application. If the
|
|
57
58
|
// platform lacks a usable picker — or none is installed — the endpoint
|
|
58
59
|
// returns 501 so the frontend can fall back to the inline directory list.
|
|
59
|
-
|
|
60
|
+
api.get("/admin/fs/pick-dir", (req, res) => {
|
|
60
61
|
// The prompt is attacker-controllable (query string). NEVER interpolate it
|
|
61
62
|
// into a shell string — use execFile (no shell) with an argv array, and
|
|
62
63
|
// pass the prompt out-of-band via an env var so it can't break out of any
|
|
@@ -109,7 +110,7 @@ export function register(app, { scheduler, plugins, config, registries }) {
|
|
|
109
110
|
});
|
|
110
111
|
});
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
api.get("/admin/fs/dirs", (req, res) => {
|
|
113
114
|
const requested = String(req.query.path || os.homedir());
|
|
114
115
|
const base = path.resolve(requested.replace(/^~(?=$|\/)/, os.homedir()));
|
|
115
116
|
try {
|
|
@@ -70,12 +70,12 @@ function normalizeAutonomy(v) {
|
|
|
70
70
|
return AUTONOMY_VALUES.has(v) ? v : undefined;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export function register(
|
|
73
|
+
export function register(api, { projects, project }) {
|
|
74
74
|
// Vault = global agent templates. Two-layer: bundled defaults shipped with
|
|
75
75
|
// APX (assets/agent-vault-defaults/) + user overrides/new ones in
|
|
76
76
|
// ~/.apx/agents/. The user layer wins per slug; tombstones in .removed.json
|
|
77
77
|
// hide bundled entries. GET merges both with `source` set per item.
|
|
78
|
-
|
|
78
|
+
api.get("/agents/vault", (req, res) => {
|
|
79
79
|
const includeRemoved = req.query?.include_removed === "1";
|
|
80
80
|
res.json(readVaultAgents({ includeRemoved }).map((a) => ({
|
|
81
81
|
...agentToResponse(a),
|
|
@@ -84,7 +84,7 @@ export function register(app, { projects, project }) {
|
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
// Create or replace a vault template (user layer / copy-on-write).
|
|
87
|
-
|
|
87
|
+
api.post("/agents/vault", (req, res) => {
|
|
88
88
|
const { slug, fields, body = "" } = req.body || {};
|
|
89
89
|
if (!slug || !/^[a-z][a-z0-9_-]*$/.test(slug)) {
|
|
90
90
|
return res.status(400).json({ error: "valid slug required" });
|
|
@@ -100,7 +100,7 @@ export function register(app, { projects, project }) {
|
|
|
100
100
|
|
|
101
101
|
// Patch a vault template. If the slug is bundled-only, copy it to the user
|
|
102
102
|
// layer first (the writer already does this), then apply the merged fields.
|
|
103
|
-
|
|
103
|
+
api.patch("/agents/vault/:slug", (req, res) => {
|
|
104
104
|
const { slug } = req.params;
|
|
105
105
|
const current = readVaultAgent(slug);
|
|
106
106
|
if (!current) return res.status(404).json({ error: `vault agent ${slug} not found` });
|
|
@@ -118,14 +118,14 @@ export function register(app, { projects, project }) {
|
|
|
118
118
|
|
|
119
119
|
// Delete a vault template. Tombstones bundled slugs so they stay hidden;
|
|
120
120
|
// deletes the user-layer file otherwise. POST .../restore lifts a tombstone.
|
|
121
|
-
|
|
121
|
+
api.delete("/agents/vault/:slug", (req, res) => {
|
|
122
122
|
const { slug } = req.params;
|
|
123
123
|
const out = removeVaultAgent(slug);
|
|
124
124
|
if (!out.removed) return res.status(404).json({ error: `vault agent ${slug} not found` });
|
|
125
125
|
res.json({ ok: true, ...out });
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
api.post("/agents/vault/:slug/restore", (req, res) => {
|
|
129
129
|
const { slug } = req.params;
|
|
130
130
|
const out = restoreVaultAgent(slug);
|
|
131
131
|
if (!out.restored) return res.status(404).json({ error: `slug ${slug} was not tombstoned` });
|
|
@@ -134,7 +134,7 @@ export function register(app, { projects, project }) {
|
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
// Import a vault template into a project (copies it to .apc/agents/<slug>.md).
|
|
137
|
-
|
|
137
|
+
api.post("/projects/:pid/agents/import", (req, res) => {
|
|
138
138
|
const p = project(req, res);
|
|
139
139
|
if (!p) return;
|
|
140
140
|
const { slug } = req.body || {};
|
|
@@ -154,7 +154,7 @@ export function register(app, { projects, project }) {
|
|
|
154
154
|
}
|
|
155
155
|
});
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
api.get("/projects/:pid/agents", (req, res) => {
|
|
158
158
|
const p = project(req, res);
|
|
159
159
|
if (!p) return;
|
|
160
160
|
const agents = readAgents(p.path).map(agentToResponse);
|
|
@@ -162,7 +162,7 @@ export function register(app, { projects, project }) {
|
|
|
162
162
|
res.json(agents);
|
|
163
163
|
});
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
api.get("/projects/:pid/agents/:slug", (req, res) => {
|
|
166
166
|
const p = project(req, res);
|
|
167
167
|
if (!p) return;
|
|
168
168
|
const agents = readAgents(p.path);
|
|
@@ -172,7 +172,7 @@ export function register(app, { projects, project }) {
|
|
|
172
172
|
res.json({ ...agentToResponse(a), memory, system: a.body || "" });
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
api.post("/projects/:pid/agents", (req, res) => {
|
|
176
176
|
const p = project(req, res);
|
|
177
177
|
if (!p) return;
|
|
178
178
|
const {
|
|
@@ -213,7 +213,7 @@ export function register(app, { projects, project }) {
|
|
|
213
213
|
|
|
214
214
|
// Edit an existing agent. Merges provided fields into the AGENT.md
|
|
215
215
|
// frontmatter; `system` rewrites the body (the agent's system prompt).
|
|
216
|
-
|
|
216
|
+
api.patch("/projects/:pid/agents/:slug", (req, res) => {
|
|
217
217
|
const p = project(req, res);
|
|
218
218
|
if (!p) return;
|
|
219
219
|
const slug = req.params.slug;
|
|
@@ -255,7 +255,7 @@ export function register(app, { projects, project }) {
|
|
|
255
255
|
});
|
|
256
256
|
|
|
257
257
|
// Delete an agent: removes .apc/agents/<slug>.md and runtime data dir.
|
|
258
|
-
|
|
258
|
+
api.delete("/projects/:pid/agents/:slug", (req, res) => {
|
|
259
259
|
const p = project(req, res);
|
|
260
260
|
if (!p) return;
|
|
261
261
|
const slug = req.params.slug;
|
|
@@ -276,7 +276,7 @@ export function register(app, { projects, project }) {
|
|
|
276
276
|
});
|
|
277
277
|
|
|
278
278
|
// ---- Project-level memory (.apc/memory.md) ----
|
|
279
|
-
|
|
279
|
+
api.get("/projects/:pid/memory", (req, res) => {
|
|
280
280
|
const p = project(req, res);
|
|
281
281
|
if (!p) return;
|
|
282
282
|
const memPath = apcMemoryFile(p.path);
|
|
@@ -284,7 +284,7 @@ export function register(app, { projects, project }) {
|
|
|
284
284
|
res.json({ body, path: memPath });
|
|
285
285
|
});
|
|
286
286
|
|
|
287
|
-
|
|
287
|
+
api.put("/projects/:pid/memory", (req, res) => {
|
|
288
288
|
const p = project(req, res);
|
|
289
289
|
if (!p) return;
|
|
290
290
|
const { body } = req.body || {};
|
|
@@ -298,7 +298,7 @@ export function register(app, { projects, project }) {
|
|
|
298
298
|
});
|
|
299
299
|
|
|
300
300
|
// ---- Per-agent memory ----
|
|
301
|
-
|
|
301
|
+
api.get("/projects/:pid/agents/:slug/memory", (req, res) => {
|
|
302
302
|
const p = project(req, res);
|
|
303
303
|
if (!p) return;
|
|
304
304
|
// Validate the agent exists — otherwise an unknown slug returned 200 with an
|
|
@@ -308,7 +308,7 @@ export function register(app, { projects, project }) {
|
|
|
308
308
|
res.json({ body: readAgentMemory(p, req.params.slug) });
|
|
309
309
|
});
|
|
310
310
|
|
|
311
|
-
|
|
311
|
+
api.put("/projects/:pid/agents/:slug/memory", (req, res) => {
|
|
312
312
|
const p = project(req, res);
|
|
313
313
|
if (!p) return;
|
|
314
314
|
if (!readAgents(p.path).some((a) => a.slug === req.params.slug))
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
import { previews } from "#core/artifacts/preview.js";
|
|
13
13
|
import { tunnels, detectProviders } from "#core/artifacts/tunnel.js";
|
|
14
14
|
|
|
15
|
-
export function register(
|
|
15
|
+
export function register(api, { project }) {
|
|
16
16
|
// Start (or reuse) an ephemeral preview server for an artifact.
|
|
17
|
-
|
|
17
|
+
api.post("/projects/:pid/artifacts/:name/preview", async (req, res) => {
|
|
18
18
|
const p = project(req, res);
|
|
19
19
|
if (!p) return;
|
|
20
20
|
const name = decodeURIComponent(req.params.name);
|
|
@@ -33,24 +33,24 @@ export function register(app, { project }) {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
// List preview servers scoped to a project.
|
|
36
|
-
|
|
36
|
+
api.get("/projects/:pid/previews", (req, res) => {
|
|
37
37
|
const p = project(req, res);
|
|
38
38
|
if (!p) return;
|
|
39
39
|
res.json(previews.list(p.id));
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
// List every live preview (all projects).
|
|
43
|
-
|
|
43
|
+
api.get("/previews", (_req, res) => {
|
|
44
44
|
res.json(previews.list());
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
// Which tunnel providers this host can use, best first.
|
|
48
|
-
|
|
48
|
+
api.get("/previews/tunnel-providers", (_req, res) => {
|
|
49
49
|
res.json({ providers: detectProviders() });
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
// Stop a preview server (also closes its tunnel).
|
|
53
|
-
|
|
53
|
+
api.delete("/previews/:id", async (req, res) => {
|
|
54
54
|
const rec = previews.get(req.params.id);
|
|
55
55
|
if (rec?.tunnel) tunnels.close(rec.tunnel.id);
|
|
56
56
|
const ok = await previews.stop(req.params.id);
|
|
@@ -58,7 +58,7 @@ export function register(app, { project }) {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
// Open a public tunnel to a preview's local port.
|
|
61
|
-
|
|
61
|
+
api.post("/previews/:id/tunnel", async (req, res) => {
|
|
62
62
|
const rec = previews.get(req.params.id);
|
|
63
63
|
if (!rec) return res.status(404).json({ error: "preview not found" });
|
|
64
64
|
if (rec.tunnel) return res.json(rec.tunnel); // already shared
|
|
@@ -72,7 +72,7 @@ export function register(app, { project }) {
|
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
// Close a preview's tunnel but keep the local server running.
|
|
75
|
-
|
|
75
|
+
api.delete("/previews/:id/tunnel", (req, res) => {
|
|
76
76
|
const rec = previews.get(req.params.id);
|
|
77
77
|
if (!rec || !rec.tunnel) return res.status(404).end();
|
|
78
78
|
tunnels.close(rec.tunnel.id);
|
|
@@ -89,14 +89,14 @@ function runArtifact({ absPath, cwd, args, timeoutMs = RUN_TIMEOUT_MS }) {
|
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
export function register(
|
|
93
|
-
|
|
92
|
+
export function register(api, { project }) {
|
|
93
|
+
api.get("/projects/:pid/artifacts", (req, res) => {
|
|
94
94
|
const p = project(req, res);
|
|
95
95
|
if (!p) return;
|
|
96
96
|
res.json(listArtifacts(p.storagePath));
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
api.post("/projects/:pid/artifacts", (req, res) => {
|
|
100
100
|
const p = project(req, res);
|
|
101
101
|
if (!p) return;
|
|
102
102
|
const { name, content = "" } = req.body || {};
|
|
@@ -109,7 +109,7 @@ export function register(app, { project }) {
|
|
|
109
109
|
}
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
api.get("/projects/:pid/artifacts/:name", (req, res) => {
|
|
113
113
|
const p = project(req, res);
|
|
114
114
|
if (!p) return;
|
|
115
115
|
try {
|
|
@@ -119,7 +119,7 @@ export function register(app, { project }) {
|
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
api.patch("/projects/:pid/artifacts/:name", (req, res) => {
|
|
123
123
|
const p = project(req, res);
|
|
124
124
|
if (!p) return;
|
|
125
125
|
const name = decodeURIComponent(req.params.name);
|
|
@@ -144,7 +144,7 @@ export function register(app, { project }) {
|
|
|
144
144
|
}
|
|
145
145
|
});
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
api.delete("/projects/:pid/artifacts/:name", (req, res) => {
|
|
148
148
|
const p = project(req, res);
|
|
149
149
|
if (!p) return;
|
|
150
150
|
const ok = removeArtifact(
|
|
@@ -158,7 +158,7 @@ export function register(app, { project }) {
|
|
|
158
158
|
// its own local spawn (stdio inherited) so it can run interactively. Output
|
|
159
159
|
// is captured up to MAX_CAPTURE_BYTES and the call is bounded by
|
|
160
160
|
// RUN_TIMEOUT_MS — anything longer should go through the terminal.
|
|
161
|
-
|
|
161
|
+
api.post("/projects/:pid/artifacts/:name/run", async (req, res) => {
|
|
162
162
|
const p = project(req, res);
|
|
163
163
|
if (!p) return;
|
|
164
164
|
const name = decodeURIComponent(req.params.name);
|
|
@@ -47,18 +47,18 @@ function modeGuidanceFor(mode) {
|
|
|
47
47
|
// codeSessionHistory() (transcript → engine messages) and makeTurnAccumulator()
|
|
48
48
|
// (stream events → persistable ChatParts) imported above.
|
|
49
49
|
|
|
50
|
-
export function register(
|
|
50
|
+
export function register(api, { projects, project, config, registries, plugins }) {
|
|
51
51
|
const findProject = (req, res) => project(req, res);
|
|
52
52
|
|
|
53
53
|
// ---- List ----------------------------------------------------------------
|
|
54
|
-
|
|
54
|
+
api.get("/projects/:pid/code/sessions", (req, res) => {
|
|
55
55
|
const p = findProject(req, res);
|
|
56
56
|
if (!p) return;
|
|
57
57
|
res.json({ sessions: listCodeSessions(p.storagePath) });
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
// ---- Create (captures git baseline) --------------------------------------
|
|
61
|
-
|
|
61
|
+
api.post("/projects/:pid/code/sessions", (req, res) => {
|
|
62
62
|
const p = findProject(req, res);
|
|
63
63
|
if (!p) return;
|
|
64
64
|
const { title, model, mode, agentSlug } = req.body || {};
|
|
@@ -86,7 +86,7 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
// ---- Get full transcript -------------------------------------------------
|
|
89
|
-
|
|
89
|
+
api.get("/projects/:pid/code/sessions/:sid", (req, res) => {
|
|
90
90
|
const p = findProject(req, res);
|
|
91
91
|
if (!p) return;
|
|
92
92
|
const session = getCodeSession(p.storagePath, req.params.sid);
|
|
@@ -95,7 +95,7 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
// ---- Patch (rename / model / mode) ---------------------------------------
|
|
98
|
-
|
|
98
|
+
api.patch("/projects/:pid/code/sessions/:sid", (req, res) => {
|
|
99
99
|
const p = findProject(req, res);
|
|
100
100
|
if (!p) return;
|
|
101
101
|
const session = updateCodeSession(p.storagePath, req.params.sid, req.body || {});
|
|
@@ -104,7 +104,7 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
// ---- Delete --------------------------------------------------------------
|
|
107
|
-
|
|
107
|
+
api.delete("/projects/:pid/code/sessions/:sid", (req, res) => {
|
|
108
108
|
const p = findProject(req, res);
|
|
109
109
|
if (!p) return;
|
|
110
110
|
const ok = removeCodeSession(p.storagePath, req.params.sid);
|
|
@@ -113,7 +113,7 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
// ---- Changes (diff vs baseline) ------------------------------------------
|
|
116
|
-
|
|
116
|
+
api.get("/projects/:pid/code/sessions/:sid/changes", (req, res) => {
|
|
117
117
|
const p = findProject(req, res);
|
|
118
118
|
if (!p) return;
|
|
119
119
|
const session = getCodeSession(p.storagePath, req.params.sid);
|
|
@@ -130,7 +130,7 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
130
130
|
});
|
|
131
131
|
|
|
132
132
|
// ---- Streaming turn ------------------------------------------------------
|
|
133
|
-
|
|
133
|
+
api.post("/projects/:pid/code/sessions/:sid/chat/stream", async (req, res) => {
|
|
134
134
|
const p = findProject(req, res);
|
|
135
135
|
if (!p) return;
|
|
136
136
|
const session = getCodeSession(p.storagePath, req.params.sid);
|