@agentprojectcontext/apx 1.32.0 → 1.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -1
- package/skills/apc-context/SKILL.md +5 -2
- package/skills/apx/SKILL.md +3 -3
- package/skills/apx-agency-agents/SKILL.md +5 -5
- package/skills/apx-agent/SKILL.md +7 -7
- package/skills/apx-mcp/SKILL.md +6 -4
- package/skills/apx-mcp-builder/SKILL.md +4 -7
- package/skills/apx-project/SKILL.md +4 -5
- package/skills/apx-routine/SKILL.md +14 -12
- package/skills/apx-runtime/SKILL.md +5 -3
- package/skills/apx-sessions/SKILL.md +5 -5
- package/skills/apx-skill-builder/SKILL.md +10 -6
- package/skills/apx-task/SKILL.md +8 -8
- package/skills/apx-telegram/SKILL.md +23 -7
- package/skills/apx-voice/SKILL.md +8 -6
- package/src/core/{agent-system.js → agent/build-agent-system.js} +10 -12
- package/src/core/agent/index.js +0 -2
- package/src/core/{agent-memory.js → agent/memory.js} +2 -2
- package/src/core/agent/model-router.js +21 -43
- package/src/core/agent/prompt-builder.js +17 -63
- package/src/core/agent/prompts/action-discipline.md +24 -0
- package/src/core/agent/prompts/channels/code.md +8 -12
- package/src/core/agent/prompts/channels/desktop.md +6 -4
- package/src/core/agent/prompts/channels/routine.md +10 -1
- package/src/core/agent/prompts/channels/telegram.md +10 -1
- package/src/core/agent/prompts/channels/web_code.md +20 -0
- package/src/core/agent/prompts/modes/voice.md +2 -2
- package/src/core/agent/prompts/super-agent-base.md +2 -2
- package/src/core/agent/run-agent.js +37 -35
- package/src/core/agent/runtime-bridge.js +42 -0
- package/src/core/agent/self-memory.js +19 -9
- package/src/core/agent/skills/catalog.js +65 -0
- package/src/core/agent/skills/index.js +6 -0
- package/src/{host/daemon/skills-loader.js → core/agent/skills/loader.js} +3 -3
- package/src/core/agent/skills/rag.js +91 -0
- package/src/core/agent/skills/trigger.js +71 -0
- package/src/{host/daemon → core/agent}/super-agent.js +5 -5
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/add-project.js +3 -4
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-agent.js +2 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-mcp.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-runtime.js +10 -11
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/create-task.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/discover-tools.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/edit-file.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/import-agent.js +4 -5
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-agents.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-skills.js +7 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-tasks.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-vault-agents.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/load-skill.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-agent-memory.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-self-memory.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/remember.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/run-shell.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-messages.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-sessions.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/send-telegram.js +0 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/set-identity.js +1 -3
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/set-permission-mode.js +1 -3
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/tail-messages.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/transcribe-audio.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/write-file.js +1 -2
- package/src/core/agent/tools/helpers.js +74 -0
- package/src/{host/daemon/super-agent-tools → core/agent/tools}/registry-bridge.js +3 -3
- package/src/{host/daemon/super-agent-tools/index.js → core/agent/tools/registry.js} +31 -32
- package/src/core/apc/agents-vault.js +37 -0
- package/src/core/{scaffold.js → apc/scaffold.js} +4 -5
- package/src/core/{config.js → config/index.js} +21 -27
- package/src/core/config/paths.js +32 -0
- package/src/core/constants/actors.js +8 -0
- package/src/core/constants/channels.js +19 -0
- package/src/core/constants/index.js +5 -0
- package/src/core/constants/permissions.js +17 -0
- package/src/core/constants/roles.js +9 -0
- package/src/core/engines/_streaming.js +63 -0
- package/src/core/engines/anthropic.js +11 -22
- package/src/core/engines/ollama.js +7 -16
- package/src/core/identity/index.js +8 -0
- package/src/core/{identity.js → identity/self.js} +5 -5
- package/src/core/{telegram-identity.js → identity/telegram.js} +1 -1
- package/src/core/logging.js +1 -1
- package/src/core/mascot.js +1 -1
- package/src/core/memory/active-threads.js +10 -10
- package/src/core/memory/broker.js +9 -9
- package/src/core/memory/compactor.js +2 -2
- package/src/core/memory/index.js +2 -2
- package/src/core/memory/indexer.js +1 -1
- package/src/core/{code-sessions-store.js → stores/code-sessions.js} +7 -8
- package/src/core/{messages-store.js → stores/messages.js} +6 -4
- package/src/core/stores/routine-memory.js +71 -0
- package/src/core/{routines-store.js → stores/routines.js} +1 -3
- package/src/core/stores/runtime-sessions.js +99 -0
- package/src/core/{tasks-store.js → stores/tasks.js} +3 -8
- package/src/core/update-check.js +1 -1
- package/src/core/util/ids.js +14 -0
- package/src/core/util/index.js +2 -0
- package/src/core/util/time.js +9 -0
- package/src/core/voice/tts.js +1 -1
- package/src/host/daemon/api/admin-config.js +4 -3
- package/src/host/daemon/api/admin.js +1 -1
- package/src/host/daemon/api/agents.js +4 -25
- package/src/host/daemon/api/artifacts.js +26 -1
- package/src/host/daemon/api/code.js +62 -17
- package/src/host/daemon/api/confirm.js +1 -1
- package/src/host/daemon/api/connections.js +2 -2
- package/src/host/daemon/api/conversations.js +2 -2
- package/src/host/daemon/api/deck.js +1 -1
- package/src/host/daemon/api/desktop.js +1 -1
- package/src/host/daemon/api/embeddings.js +4 -4
- package/src/host/daemon/api/engines.js +2 -2
- package/src/host/daemon/api/exec.js +20 -5
- package/src/host/daemon/api/identity.js +1 -1
- package/src/host/daemon/api/mcps.js +1 -1
- package/src/host/daemon/api/messages.js +1 -1
- package/src/host/daemon/api/runtimes.js +9 -8
- package/src/host/daemon/api/sessions-search.js +1 -1
- package/src/host/daemon/api/sessions.js +2 -2
- package/src/host/daemon/api/shared.js +5 -4
- package/src/host/daemon/api/skills.js +30 -0
- package/src/host/daemon/api/super-agent.js +29 -9
- package/src/host/daemon/api/tasks.js +2 -2
- package/src/host/daemon/api/telegram.js +1 -1
- package/src/host/daemon/api/tools.js +6 -6
- package/src/host/daemon/api/tts.js +2 -2
- package/src/host/daemon/api/voice.js +14 -12
- package/src/host/daemon/api.js +2 -0
- package/src/host/daemon/compact.js +1 -1
- package/src/host/daemon/db.js +4 -4
- package/src/host/daemon/desktop-ws.js +1 -1
- package/src/host/daemon/index.js +4 -4
- package/src/host/daemon/plugins/{desktop.js → desktop/index.js} +11 -6
- package/src/host/daemon/plugins/index.js +2 -2
- package/src/host/daemon/plugins/{telegram.js → telegram/index.js} +52 -193
- package/src/host/daemon/plugins/telegram/media.js +162 -0
- package/src/host/daemon/projects-helpers.js +54 -0
- package/src/host/daemon/routines.js +28 -12
- package/src/host/daemon/smoke.js +2 -2
- package/src/host/daemon/token-store.js +1 -1
- package/src/host/daemon/transcription.js +2 -2
- package/src/host/daemon/wakeup.js +2 -2
- package/src/interfaces/cli/commands/agent.js +3 -3
- package/src/interfaces/cli/commands/command.js +1 -1
- package/src/interfaces/cli/commands/config.js +3 -2
- package/src/interfaces/cli/commands/desktop.js +1 -1
- package/src/interfaces/cli/commands/exec.js +2 -1
- package/src/interfaces/cli/commands/identity.js +2 -2
- package/src/interfaces/cli/commands/init.js +1 -1
- package/src/interfaces/cli/commands/mcp.js +1 -1
- package/src/interfaces/cli/commands/memory.js +2 -2
- package/src/interfaces/cli/commands/model.js +16 -6
- package/src/interfaces/cli/commands/project.js +1 -1
- package/src/interfaces/cli/commands/routine.js +58 -0
- package/src/interfaces/cli/commands/search.js +1 -1
- package/src/interfaces/cli/commands/session.js +4 -4
- package/src/interfaces/cli/commands/setup.js +4 -3
- package/src/interfaces/cli/commands/skills.js +25 -4
- package/src/interfaces/cli/commands/status.js +1 -1
- package/src/interfaces/cli/commands/sys.js +11 -4
- package/src/interfaces/cli/commands/update.js +1 -1
- package/src/interfaces/cli/index.js +4 -4
- package/src/interfaces/cli/postinstall.js +2 -2
- package/src/interfaces/mcp-server/index.js +1 -1
- package/src/interfaces/tui/component/prompt/index.tsx +3 -1
- package/src/interfaces/tui/context/sdk-apx.tsx +47 -7
- package/src/interfaces/tui/context/sync-apx.tsx +20 -2
- package/src/interfaces/tui/context/sync.tsx +2 -1
- package/src/interfaces/tui/routes/session/index.tsx +151 -136
- package/src/interfaces/tui/routes/session/sidebar-apx.tsx +37 -15
- package/src/interfaces/tui/run.ts +2 -0
- package/src/interfaces/web/dist/assets/index-7dVT2O1S.css +1 -0
- package/src/interfaces/web/dist/assets/index-DWsE_8Nz.js +602 -0
- package/src/interfaces/web/dist/assets/index-DWsE_8Nz.js.map +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/package-lock.json +6 -6
- package/src/interfaces/web/src/App.tsx +53 -32
- package/src/interfaces/web/src/components/RobyBubble.tsx +12 -6
- package/src/interfaces/web/src/components/UiSelect.tsx +13 -3
- package/src/interfaces/web/src/components/chat/SkillPicker.tsx +77 -0
- package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +253 -111
- package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +10 -8
- package/src/interfaces/web/src/components/code/CodeComposer.tsx +20 -17
- package/src/interfaces/web/src/components/code/CodeContextTab.tsx +43 -18
- package/src/interfaces/web/src/components/code/CodeFileTree.tsx +212 -0
- package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +121 -0
- package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +1 -1
- package/src/interfaces/web/src/components/code/CodeSessionList.tsx +30 -26
- package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +40 -21
- package/src/interfaces/web/src/components/code/CodeTerminal.tsx +140 -0
- package/src/interfaces/web/src/components/common/TabLayout.tsx +11 -7
- package/src/interfaces/web/src/components/common/TabNav.tsx +3 -3
- package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +4 -2
- package/src/interfaces/web/src/components/ui/chat-input.tsx +17 -6
- package/src/interfaces/web/src/hooks/useChat.ts +48 -2
- package/src/interfaces/web/src/hooks/useNavCollapseCtx.tsx +83 -0
- package/src/interfaces/web/src/hooks/usePersonaName.ts +11 -0
- package/src/interfaces/web/src/i18n/en.ts +7 -7
- package/src/interfaces/web/src/i18n/es.ts +8 -8
- package/src/interfaces/web/src/lib/api/agents.ts +1 -1
- package/src/interfaces/web/src/lib/api/artifacts.ts +10 -0
- package/src/interfaces/web/src/lib/api/code.ts +4 -2
- package/src/interfaces/web/src/lib/api/skills.ts +25 -0
- package/src/interfaces/web/src/lib/api.ts +1 -0
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +430 -86
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +5 -18
- package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +1 -8
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +39 -40
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +16 -16
- package/src/skills/apc-context/SKILL.md +159 -0
- package/src/core/agent/ghost-guard.js +0 -24
- package/src/core/agent/prompts/channels/terminal.md +0 -16
- package/src/host/daemon/apc-runtime-context.js +0 -124
- package/src/host/daemon/super-agent-tools/helpers.js +0 -124
- package/src/host/daemon/tool-call-parser.js +0 -2
- package/src/interfaces/web/dist/assets/index-63P_ji1a.js +0 -571
- package/src/interfaces/web/dist/assets/index-63P_ji1a.js.map +0 -1
- package/src/interfaces/web/dist/assets/index-DLWy6dYz.css +0 -1
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/ask-questions.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-files.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-mcps.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-projects.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-file.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-files.js +0 -0
- /package/src/core/agent/{pseudo-tools.js → tools/pseudo-tools.js} +0 -0
- /package/src/core/agent/{tool-call-parser.js → tools/tool-call-parser.js} +0 -0
- /package/src/core/{parser.js → apc/parser.js} +0 -0
- /package/src/core/{apc-skill-sync.js → apc/skill-sync.js} +0 -0
- /package/src/core/{artifacts-store.js → stores/artifacts.js} +0 -0
- /package/src/{host/daemon → core/stores}/engine-sessions.js +0 -0
- /package/src/core/{session-store.js → stores/sessions.js} +0 -0
- /package/src/host/daemon/plugins/{telegram-ask.js → telegram/ask.js} +0 -0
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
// stateful: the turn handler rebuilds `previousMessages` from the stored
|
|
13
13
|
// transcript, runs the super-agent on the `code` channel (with plan/build mode
|
|
14
14
|
// + per-mode tool gating), then persists the rich assistant turn.
|
|
15
|
-
import { runSuperAgent } from "
|
|
15
|
+
import { runSuperAgent } from "#core/agent/super-agent.js";
|
|
16
16
|
import { appendSuperAgentErrorTrace } from "./shared.js";
|
|
17
|
-
import { createWebConfirmAdapter } from "
|
|
17
|
+
import { createWebConfirmAdapter } from "#core/confirmation/adapters/web.js";
|
|
18
|
+
import { CHANNELS } from "#core/constants/channels.js";
|
|
18
19
|
import {
|
|
19
20
|
listCodeSessions,
|
|
20
21
|
getCodeSession,
|
|
@@ -22,9 +23,10 @@ import {
|
|
|
22
23
|
updateCodeSession,
|
|
23
24
|
removeCodeSession,
|
|
24
25
|
appendTurn,
|
|
25
|
-
} from "
|
|
26
|
-
import { captureBaseline, diffAgainstBaseline, initGitRepo } from "
|
|
27
|
-
import { loggerFor } from "
|
|
26
|
+
} from "#core/stores/code-sessions.js";
|
|
27
|
+
import { captureBaseline, diffAgainstBaseline, initGitRepo } from "#core/git-baseline.js";
|
|
28
|
+
import { loggerFor } from "#core/logging.js";
|
|
29
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
28
30
|
|
|
29
31
|
const log = loggerFor("code");
|
|
30
32
|
|
|
@@ -80,20 +82,51 @@ function modeGuidanceFor(mode) {
|
|
|
80
82
|
"for choices. Prefer 2–4 mutually-exclusive options when a question has a",
|
|
81
83
|
"natural shortlist (yes/no, which-of-these, …); leave options empty for",
|
|
82
84
|
"open-ended answers (API keys, names, free-form ideas).",
|
|
85
|
+
"If the previous assistant turn already asked these same questions and the",
|
|
86
|
+
"current user message is the compiled answers, DO NOT call ask_questions",
|
|
87
|
+
"again — process the answers and proceed with the task.",
|
|
83
88
|
].join(" ");
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
// Build the [{role, content}] history the super-agent expects from the stored
|
|
87
|
-
// rich transcript: flatten each turn's text parts
|
|
92
|
+
// rich transcript: flatten each turn's text parts. Tool parts are normally
|
|
93
|
+
// internal, but ask_questions is special — without surfacing it the model
|
|
94
|
+
// loses track that it ALREADY asked, sees the user's compiled-answer reply
|
|
95
|
+
// as a fresh request, and asks again forever. We render a one-line synthetic
|
|
96
|
+
// summary of each ask_questions call so the next turn's context shows
|
|
97
|
+
// "I asked X, the user replied Y" naturally.
|
|
98
|
+
function summarizeAskQuestionsPart(part) {
|
|
99
|
+
const raw = part?.args?.questions;
|
|
100
|
+
if (!Array.isArray(raw) || raw.length === 0) return null;
|
|
101
|
+
const lines = raw
|
|
102
|
+
.map((q) => {
|
|
103
|
+
if (typeof q === "string") return `- ${q}`;
|
|
104
|
+
if (!q || typeof q !== "object" || typeof q.question !== "string") return null;
|
|
105
|
+
const opts = Array.isArray(q.options) ? q.options : [];
|
|
106
|
+
const optStr = opts
|
|
107
|
+
.map((o) => (typeof o === "string" ? o : (o && typeof o.label === "string" ? o.label : "")))
|
|
108
|
+
.filter(Boolean)
|
|
109
|
+
.join(", ");
|
|
110
|
+
return optStr ? `- ${q.question} (opciones: ${optStr})` : `- ${q.question}`;
|
|
111
|
+
})
|
|
112
|
+
.filter(Boolean);
|
|
113
|
+
if (lines.length === 0) return null;
|
|
114
|
+
return `[ask_questions]\n${lines.join("\n")}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
88
117
|
function historyFrom(session) {
|
|
89
|
-
return (session.messages || []).map((m) =>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
.
|
|
95
|
-
|
|
96
|
-
|
|
118
|
+
return (session.messages || []).map((m) => {
|
|
119
|
+
const chunks = [];
|
|
120
|
+
for (const p of m.parts || []) {
|
|
121
|
+
if (!p) continue;
|
|
122
|
+
if (p.kind === "text" && p.text) chunks.push(p.text);
|
|
123
|
+
else if (p.kind === "tool" && p.tool === "ask_questions") {
|
|
124
|
+
const summary = summarizeAskQuestionsPart(p);
|
|
125
|
+
if (summary) chunks.push(summary);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return { role: m.role, content: chunks.join("\n\n").trim() };
|
|
129
|
+
});
|
|
97
130
|
}
|
|
98
131
|
|
|
99
132
|
// Accumulate stream events into the rich ChatPart shape so the persisted
|
|
@@ -180,7 +213,7 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
180
213
|
app.post("/projects/:pid/code/sessions", (req, res) => {
|
|
181
214
|
const p = findProject(req, res);
|
|
182
215
|
if (!p) return;
|
|
183
|
-
const { title, model, mode } = req.body || {};
|
|
216
|
+
const { title, model, mode, agentSlug } = req.body || {};
|
|
184
217
|
let git = captureBaseline(p.path);
|
|
185
218
|
// No baseline because the project isn't a git repo yet. For real projects
|
|
186
219
|
// (not the default apx home, id 0) init one so the "changes" diff works —
|
|
@@ -198,6 +231,7 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
198
231
|
title,
|
|
199
232
|
model,
|
|
200
233
|
mode,
|
|
234
|
+
agentSlug: agentSlug || null,
|
|
201
235
|
git,
|
|
202
236
|
});
|
|
203
237
|
res.status(201).json(session);
|
|
@@ -259,6 +293,15 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
259
293
|
const mode = session.mode === "plan" ? "plan" : "build";
|
|
260
294
|
const previousMessages = historyFrom(session);
|
|
261
295
|
|
|
296
|
+
// If a project agent is selected, inject its system prompt as a suffix so
|
|
297
|
+
// the super-agent's tool loop runs with the agent's personality/context.
|
|
298
|
+
let agentSystemSuffix = "";
|
|
299
|
+
if (session.agentSlug) {
|
|
300
|
+
const agents = readAgents(p.path);
|
|
301
|
+
const agent = agents.find((a) => a.slug === session.agentSlug);
|
|
302
|
+
if (agent?.body) agentSystemSuffix = `\n\n## Agente seleccionado: ${session.agentSlug}\n${agent.body}`;
|
|
303
|
+
}
|
|
304
|
+
|
|
262
305
|
// Persist the user turn immediately so a crash mid-stream still records it.
|
|
263
306
|
appendTurn(p.storagePath, session.id, {
|
|
264
307
|
role: "user",
|
|
@@ -285,15 +328,17 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
285
328
|
plugins,
|
|
286
329
|
registries,
|
|
287
330
|
prompt,
|
|
288
|
-
channel:
|
|
331
|
+
channel: CHANNELS.WEB_CODE,
|
|
289
332
|
channelMeta: {
|
|
290
333
|
projectId: String(p.id),
|
|
291
334
|
projectName: p.name,
|
|
292
335
|
projectPath: p.path,
|
|
293
336
|
mode,
|
|
294
337
|
modeGuidance: modeGuidanceFor(mode),
|
|
338
|
+
agentSlug: session.agentSlug || null,
|
|
295
339
|
},
|
|
296
340
|
previousMessages,
|
|
341
|
+
systemSuffix: agentSystemSuffix,
|
|
297
342
|
overrideModel: session.model || undefined,
|
|
298
343
|
allowedTools: mode === "plan" ? PLAN_TOOLS : "*",
|
|
299
344
|
// Coding tasks are multi-step: give the loop a high safety ceiling so it
|
|
@@ -349,7 +394,7 @@ export function register(app, { projects, project, config, registries, plugins }
|
|
|
349
394
|
});
|
|
350
395
|
appendSuperAgentErrorTrace(req, e, {
|
|
351
396
|
prompt,
|
|
352
|
-
channel:
|
|
397
|
+
channel: CHANNELS.WEB_CODE,
|
|
353
398
|
previousMessages,
|
|
354
399
|
model: session.model,
|
|
355
400
|
stream: true,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// Promise in the agent loop, unblocking it to continue with confirmed: true
|
|
9
9
|
// or to return a cancelled error.
|
|
10
10
|
|
|
11
|
-
import { getConfirmationStore } from "
|
|
11
|
+
import { getConfirmationStore } from "#core/confirmation/pending-store.js";
|
|
12
12
|
|
|
13
13
|
export function register(app) {
|
|
14
14
|
app.post("/super-agent/confirm/:correlationId", async (req, res) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// GET /projects/:pid/agents/:slug/connections
|
|
2
2
|
// Builds a per-peer summary of an agent's a2a traffic from the messages store.
|
|
3
|
-
import { readAgents } from "
|
|
4
|
-
import { readProjectMessages } from "
|
|
3
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
4
|
+
import { readProjectMessages } from "#core/stores/messages.js";
|
|
5
5
|
|
|
6
6
|
export function register(app, { project }) {
|
|
7
7
|
app.get("/projects/:pid/agents/:slug/connections", (req, res) => {
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
// POST /projects/:pid/send (agent-to-agent)
|
|
7
7
|
import fs from "node:fs";
|
|
8
8
|
import path from "node:path";
|
|
9
|
-
import { readAgents } from "
|
|
10
|
-
import { callEngine } from "
|
|
9
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
10
|
+
import { callEngine } from "#core/engines/index.js";
|
|
11
11
|
import { listConversations, readConversation } from "../conversations.js";
|
|
12
12
|
import { compactConversation } from "../compact.js";
|
|
13
13
|
import { nowIso } from "./shared.js";
|
|
@@ -226,7 +226,7 @@ export function register(app, ctx) {
|
|
|
226
226
|
// the override we're about to set; we mutate ONLY the override and
|
|
227
227
|
// leave everything else intact.
|
|
228
228
|
try {
|
|
229
|
-
const { readConfig, writeConfig } = await import("
|
|
229
|
+
const { readConfig, writeConfig } = await import("#core/config/index.js");
|
|
230
230
|
const fresh = readConfig();
|
|
231
231
|
fresh.deck = fresh.deck && typeof fresh.deck === "object" ? fresh.deck : {};
|
|
232
232
|
fresh.deck.widget_overrides =
|
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
// POST /embeddings/reindex → { ok, cleared, indexed } (rebuild the vector
|
|
9
9
|
// store under the current embedder — needed
|
|
10
10
|
// after switching provider/model)
|
|
11
|
-
import { readConfig } from "
|
|
11
|
+
import { readConfig } from "#core/config/index.js";
|
|
12
12
|
import {
|
|
13
13
|
listAvailableEmbedEngines,
|
|
14
14
|
embeddingsConfig,
|
|
15
15
|
resolveMode,
|
|
16
16
|
resolveChainOrder,
|
|
17
|
-
} from "
|
|
18
|
-
import { embedOne } from "
|
|
19
|
-
import { reindexMemory } from "
|
|
17
|
+
} from "#core/memory/embed-engines/index.js";
|
|
18
|
+
import { embedOne } from "#core/memory/embeddings.js";
|
|
19
|
+
import { reindexMemory } from "#core/memory/index.js";
|
|
20
20
|
|
|
21
21
|
export function register(app) {
|
|
22
22
|
app.get("/embeddings/providers", async (_req, res) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// GET /engines — list engine adapter ids known to core/engines.
|
|
2
2
|
// POST /engines/models — live model catalog from a provider.
|
|
3
3
|
// GET /engines/models — legacy (Ollama only, no auth).
|
|
4
|
-
import { ENGINE_IDS } from "
|
|
5
|
-
import { fetchJsonWithTimeout } from "
|
|
4
|
+
import { ENGINE_IDS } from "#core/engines/index.js";
|
|
5
|
+
import { fetchJsonWithTimeout } from "#core/engines/_health.js";
|
|
6
6
|
|
|
7
7
|
const DEFAULT_BASE = {
|
|
8
8
|
openai: "https://api.openai.com/v1",
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
//
|
|
5
5
|
// POST /projects/:pid/agents/:slug/exec one-shot, no history
|
|
6
6
|
// POST /projects/:pid/agents/:slug/chat append to (or start) a conversation
|
|
7
|
-
import { callEngine } from "
|
|
8
|
-
import { readAgents } from "
|
|
9
|
-
import { buildAgentSystem } from "
|
|
7
|
+
import { callEngine } from "#core/engines/index.js";
|
|
8
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
9
|
+
import { buildAgentSystem } from "#core/agent/build-agent-system.js";
|
|
10
|
+
import { resolveActiveModel } from "#core/agent/model-router.js";
|
|
10
11
|
import {
|
|
11
12
|
startConversation,
|
|
12
13
|
appendTurn,
|
|
@@ -14,6 +15,20 @@ import {
|
|
|
14
15
|
setStatus,
|
|
15
16
|
} from "../conversations.js";
|
|
16
17
|
|
|
18
|
+
// Pick a model for a direct agent chat: explicit override → agent's own model →
|
|
19
|
+
// super-agent default (resolved via the same router the super-agent uses, so
|
|
20
|
+
// it walks the fallback chain when the primary is empty/unhealthy).
|
|
21
|
+
async function pickAgentModel({ modelOverride, agent, config }) {
|
|
22
|
+
if (modelOverride) return modelOverride;
|
|
23
|
+
if (agent.fields?.Model) return agent.fields.Model;
|
|
24
|
+
try {
|
|
25
|
+
const routing = await resolveActiveModel(config);
|
|
26
|
+
return routing?.modelId || null;
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
17
32
|
export function register(app, { projects, project, config }) {
|
|
18
33
|
app.post("/projects/:pid/agents/:slug/exec", async (req, res) => {
|
|
19
34
|
const p = project(req, res);
|
|
@@ -28,7 +43,7 @@ export function register(app, { projects, project, config }) {
|
|
|
28
43
|
const agents = readAgents(p.path);
|
|
29
44
|
const agent = agents.find((a) => a.slug === req.params.slug);
|
|
30
45
|
if (!agent) return res.status(404).json({ error: "agent not found" });
|
|
31
|
-
const modelId = modelOverride
|
|
46
|
+
const modelId = await pickAgentModel({ modelOverride, agent, config });
|
|
32
47
|
if (!modelId)
|
|
33
48
|
return res
|
|
34
49
|
.status(400)
|
|
@@ -106,7 +121,7 @@ export function register(app, { projects, project, config }) {
|
|
|
106
121
|
const agents = readAgents(p.path);
|
|
107
122
|
const agent = agents.find((a) => a.slug === req.params.slug);
|
|
108
123
|
if (!agent) return res.status(404).json({ error: "agent not found" });
|
|
109
|
-
const modelId = modelOverride
|
|
124
|
+
const modelId = await pickAgentModel({ modelOverride, agent, config });
|
|
110
125
|
if (!modelId)
|
|
111
126
|
return res
|
|
112
127
|
.status(400)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// GET /identity full identity.json
|
|
2
2
|
// PATCH /identity { agent_name?, owner_name?, personality?, owner_context?, language?, timezone? }
|
|
3
|
-
import { readIdentity, writeIdentity } from "
|
|
3
|
+
import { readIdentity, writeIdentity } from "#core/identity/index.js";
|
|
4
4
|
|
|
5
5
|
const ALLOWED_KEYS = new Set([
|
|
6
6
|
"agent_name",
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
readGlobalMessages,
|
|
10
10
|
readProjectMessages,
|
|
11
11
|
searchProjectMessages,
|
|
12
|
-
} from "
|
|
12
|
+
} from "#core/stores/messages.js";
|
|
13
13
|
|
|
14
14
|
export function register(app, { project }) {
|
|
15
15
|
app.get("/projects/:pid/messages", (req, res) => {
|
|
@@ -7,18 +7,19 @@
|
|
|
7
7
|
// GET /projects/:pid/sessions/:id/resume?summarize=true
|
|
8
8
|
import fs from "node:fs";
|
|
9
9
|
import path from "node:path";
|
|
10
|
-
import { readAgents } from "
|
|
11
|
-
import { readSessionFrontmatter } from "
|
|
12
|
-
import { buildAgentSystem } from "
|
|
10
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
11
|
+
import { readSessionFrontmatter } from "#core/stores/sessions.js";
|
|
12
|
+
import { buildAgentSystem } from "#core/agent/build-agent-system.js";
|
|
13
|
+
import { CHANNELS } from "#core/constants/channels.js";
|
|
13
14
|
import { getRuntime, RUNTIME_IDS } from "../runtimes/index.js";
|
|
14
15
|
import { detectAll } from "../env-detect.js";
|
|
16
|
+
import { buildRuntimeBridgeHint as buildApfHint } from "#core/agent/runtime-bridge.js";
|
|
15
17
|
import {
|
|
16
|
-
buildApfHint,
|
|
17
18
|
createRuntimeSession,
|
|
18
19
|
closeRuntimeSession,
|
|
19
|
-
extractApfResult,
|
|
20
|
-
} from "
|
|
21
|
-
import { runSuperAgent, isSuperAgentEnabled } from "
|
|
20
|
+
extractRuntimeResult as extractApfResult,
|
|
21
|
+
} from "#core/stores/runtime-sessions.js";
|
|
22
|
+
import { runSuperAgent, isSuperAgentEnabled } from "#core/agent/super-agent.js";
|
|
22
23
|
|
|
23
24
|
export function register(app, { projects, registries, plugins, project, config }) {
|
|
24
25
|
app.get("/runtimes", (_req, res) =>
|
|
@@ -205,7 +206,7 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
205
206
|
plugins,
|
|
206
207
|
registries,
|
|
207
208
|
prompt,
|
|
208
|
-
channel:
|
|
209
|
+
channel: CHANNELS.API,
|
|
209
210
|
contextNote: `Resume request for session ${id}.`,
|
|
210
211
|
});
|
|
211
212
|
out.summary = sa.text;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// then delegates to compactConversation.
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
|
-
import { readAgents } from "
|
|
7
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
8
8
|
import { compactConversation } from "../compact.js";
|
|
9
9
|
|
|
10
10
|
export function register(app, { projects, config }) {
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// GET /projects/:pid/sessions/:sid by filename (cross-agent lookup)
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
|
-
import { parseSessionFrontmatter, readAgents } from "
|
|
8
|
-
import { collectAllSessions } from "
|
|
7
|
+
import { parseSessionFrontmatter, readAgents } from "#core/apc/parser.js";
|
|
8
|
+
import { collectAllSessions } from "#interfaces/cli/commands/sessions.js";
|
|
9
9
|
import { nowIso } from "./shared.js";
|
|
10
10
|
|
|
11
11
|
export function register(app, { projects, project }) {
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
|
-
import { appendErrorTrace, previewText } from "
|
|
9
|
-
import { readAgents } from "
|
|
10
|
-
import { agentMemoryPath } from "
|
|
8
|
+
import { appendErrorTrace, previewText } from "#core/logging.js";
|
|
9
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
10
|
+
import { agentMemoryPath } from "#core/agent/memory.js";
|
|
11
|
+
import { CHANNELS } from "#core/constants/channels.js";
|
|
11
12
|
|
|
12
13
|
export const nowIso = () =>
|
|
13
14
|
new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
@@ -141,7 +142,7 @@ export function resolveSuperAgentContext(req, project) {
|
|
|
141
142
|
};
|
|
142
143
|
}
|
|
143
144
|
return {
|
|
144
|
-
channel:
|
|
145
|
+
channel: CHANNELS.API,
|
|
145
146
|
channelMeta: {
|
|
146
147
|
projectId: String(project.id),
|
|
147
148
|
projectName: project.name,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Lightweight `/skills` listing for UI surfaces (web composer picker,
|
|
2
|
+
// future palettes). Same data backing `list_skills` tool, but here without
|
|
3
|
+
// auth-binding to a project — anyone with a valid daemon token can ask
|
|
4
|
+
// "which skills are around right now?".
|
|
5
|
+
//
|
|
6
|
+
// Returns the catalog already condensed (slug + first-sentence description)
|
|
7
|
+
// so the picker doesn't have to repeat the cleanup work.
|
|
8
|
+
import { listSkills } from "#core/agent/skills/loader.js";
|
|
9
|
+
import { condenseSkillDescription } from "#core/agent/skills/catalog.js";
|
|
10
|
+
|
|
11
|
+
export function register(app /*, ctx */) {
|
|
12
|
+
app.get("/skills", (req, res) => {
|
|
13
|
+
const projectPath = typeof req.query?.project_path === "string"
|
|
14
|
+
? req.query.project_path
|
|
15
|
+
: undefined;
|
|
16
|
+
try {
|
|
17
|
+
const skills = listSkills({ projectPath });
|
|
18
|
+
res.json({
|
|
19
|
+
count: skills.length,
|
|
20
|
+
skills: skills.map(({ slug, source, description }) => ({
|
|
21
|
+
slug,
|
|
22
|
+
source,
|
|
23
|
+
description: condenseSkillDescription(description),
|
|
24
|
+
})),
|
|
25
|
+
});
|
|
26
|
+
} catch (e) {
|
|
27
|
+
res.status(500).json({ error: e.message });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -5,14 +5,17 @@
|
|
|
5
5
|
//
|
|
6
6
|
// POST /projects/:pid/super-agent/chat/stream NDJSON event stream
|
|
7
7
|
// POST /projects/:pid/super-agent/chat blocking JSON response
|
|
8
|
-
import { runSuperAgent } from "
|
|
8
|
+
import { runSuperAgent } from "#core/agent/super-agent.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveSuperAgentContext,
|
|
11
11
|
appendSuperAgentErrorTrace,
|
|
12
12
|
} from "./shared.js";
|
|
13
|
-
import { loggerFor } from "
|
|
14
|
-
import { appendGlobalMessage } from "
|
|
15
|
-
import { createWebConfirmAdapter } from "
|
|
13
|
+
import { loggerFor } from "#core/logging.js";
|
|
14
|
+
import { appendGlobalMessage } from "#core/stores/messages.js";
|
|
15
|
+
import { createWebConfirmAdapter } from "#core/confirmation/adapters/web.js";
|
|
16
|
+
import { tryResolveSkillCommand } from "#core/agent/skills/trigger.js";
|
|
17
|
+
import { suggestSkillForPrompt } from "#core/agent/skills/rag.js";
|
|
18
|
+
import { CHANNELS } from "#core/constants/channels.js";
|
|
16
19
|
|
|
17
20
|
const log = loggerFor("super-agent");
|
|
18
21
|
|
|
@@ -20,7 +23,7 @@ const log = loggerFor("super-agent");
|
|
|
20
23
|
// RAG index, search_messages, and the "active threads" awareness block. Only
|
|
21
24
|
// the human surfaces (web big chat + sidebar) — not generic "api"/automation
|
|
22
25
|
// callers. Best-effort: a logging failure never breaks the reply.
|
|
23
|
-
const WEB_LOGGED_CHANNELS = new Set([
|
|
26
|
+
const WEB_LOGGED_CHANNELS = new Set([CHANNELS.WEB, CHANNELS.WEB_SIDEBAR]);
|
|
24
27
|
function logWebTurn(channel, { prompt, replyText }) {
|
|
25
28
|
if (!WEB_LOGGED_CHANNELS.has(channel)) return;
|
|
26
29
|
try {
|
|
@@ -66,11 +69,24 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
66
69
|
// Optional coding-surface knobs: the terminal Code TUI (apx code, Build
|
|
67
70
|
// mode) sends these so it runs to completion exactly like the web Code
|
|
68
71
|
// module. Plain chat callers omit them and keep the lightweight defaults.
|
|
69
|
-
const { prompt, previousMessages, model, maxIters, maxTokens, completionContract } =
|
|
72
|
+
const { prompt: rawPrompt, previousMessages, model, maxIters, maxTokens, completionContract } =
|
|
70
73
|
req.body || {};
|
|
71
|
-
if (!
|
|
74
|
+
if (!rawPrompt) return res.status(400).json({ error: "prompt required" });
|
|
72
75
|
const ctx = resolveSuperAgentContext(req, p);
|
|
73
76
|
|
|
77
|
+
// `/slug ...` shortcut: load the matching skill body into contextNote and
|
|
78
|
+
// strip the prefix from the user prompt. Falls through unchanged when the
|
|
79
|
+
// slug is unknown.
|
|
80
|
+
const slashed = tryResolveSkillCommand(rawPrompt, { projectPath: p.path });
|
|
81
|
+
const prompt = slashed.handled ? slashed.prompt : rawPrompt;
|
|
82
|
+
if (slashed.handled) {
|
|
83
|
+
ctx.contextNote = [ctx.contextNote, slashed.contextNote].filter(Boolean).join("\n\n");
|
|
84
|
+
} else {
|
|
85
|
+
// Semantic skill nudge — only when there was no explicit /slug.
|
|
86
|
+
const hint = await suggestSkillForPrompt(prompt, { projectPath: p.path });
|
|
87
|
+
if (hint) ctx.contextNote = [ctx.contextNote, hint].filter(Boolean).join("\n\n");
|
|
88
|
+
}
|
|
89
|
+
|
|
74
90
|
res.setHeader("content-type", "application/x-ndjson; charset=utf-8");
|
|
75
91
|
res.setHeader("cache-control", "no-cache, no-transform");
|
|
76
92
|
res.setHeader("x-accel-buffering", "no");
|
|
@@ -151,7 +167,7 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
151
167
|
registries,
|
|
152
168
|
prompt,
|
|
153
169
|
contextNote,
|
|
154
|
-
channel:
|
|
170
|
+
channel: CHANNELS.API,
|
|
155
171
|
overrideModel: model,
|
|
156
172
|
maxTokens:
|
|
157
173
|
max_tokens && Number.isFinite(Number(max_tokens))
|
|
@@ -174,7 +190,8 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
174
190
|
app.post("/projects/:pid/super-agent/chat", async (req, res) => {
|
|
175
191
|
const p = project(req, res);
|
|
176
192
|
if (!p) return;
|
|
177
|
-
const { prompt, previousMessages, model
|
|
193
|
+
const { prompt, previousMessages, model, maxIters, maxTokens, completionContract } =
|
|
194
|
+
req.body || {};
|
|
178
195
|
if (!prompt) return res.status(400).json({ error: "prompt required" });
|
|
179
196
|
const ctx = resolveSuperAgentContext(req, p);
|
|
180
197
|
try {
|
|
@@ -189,6 +206,9 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
189
206
|
contextNote: ctx.contextNote,
|
|
190
207
|
previousMessages: previousMessages || [],
|
|
191
208
|
overrideModel: model,
|
|
209
|
+
...(Number.isFinite(Number(maxIters)) ? { maxIters: Number(maxIters) } : {}),
|
|
210
|
+
...(Number.isFinite(Number(maxTokens)) ? { maxTokens: Number(maxTokens) } : {}),
|
|
211
|
+
...(completionContract ? { completionContract: true } : {}),
|
|
192
212
|
onEvent: wrapOnEventForLog(null, {
|
|
193
213
|
trace_id: req.apxTraceId,
|
|
194
214
|
channel: ctx.channel,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Per-project tasks (TODOs). Backed by core/tasks
|
|
1
|
+
// Per-project tasks (TODOs). Backed by core/stores/tasks.js (JSONL event log).
|
|
2
2
|
// GET /projects/:pid/tasks ?state=open|done|dropped|all&tag=X&agent=Y&due_before=ISO&limit=N
|
|
3
3
|
// POST /projects/:pid/tasks { title, body?, tags?, due?, agent?, source?, meta? }
|
|
4
4
|
// GET /projects/:pid/tasks/:id (id or prefix)
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
dropTask,
|
|
16
16
|
reopenTask,
|
|
17
17
|
countTasks,
|
|
18
|
-
} from "
|
|
18
|
+
} from "#core/stores/tasks.js";
|
|
19
19
|
|
|
20
20
|
export function register(app, { project, projects }) {
|
|
21
21
|
// Global tasks across every project.
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
// search / glob / grep → filesystem-bounded
|
|
5
5
|
// registry → /:name wildcard, MOUNT LAST so it
|
|
6
6
|
// doesn't shadow the specific paths
|
|
7
|
-
import { buildBrowserRouter } from "
|
|
8
|
-
import { buildFetchRouter } from "
|
|
9
|
-
import { buildSearchRouter } from "
|
|
10
|
-
import { buildRegistryRouter } from "
|
|
11
|
-
import { buildGlobRouter } from "
|
|
12
|
-
import { buildGrepRouter } from "
|
|
7
|
+
import { buildBrowserRouter } from "#core/tools/browser.js";
|
|
8
|
+
import { buildFetchRouter } from "#core/tools/fetch.js";
|
|
9
|
+
import { buildSearchRouter } from "#core/tools/search.js";
|
|
10
|
+
import { buildRegistryRouter } from "#core/tools/registry.js";
|
|
11
|
+
import { buildGlobRouter } from "#core/tools/glob.js";
|
|
12
|
+
import { buildGrepRouter } from "#core/tools/grep.js";
|
|
13
13
|
|
|
14
14
|
export function register(app, { express, projects, registries }) {
|
|
15
15
|
app.use("/tools/fetch", buildFetchRouter(express));
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
//
|
|
9
9
|
// Audio files land under ~/.apx/tmp/tts/<uuid>.<ext>. The caller (CLI,
|
|
10
10
|
// Telegram plugin, overlay) is responsible for picking them up.
|
|
11
|
-
import { synthesize, listProviders } from "
|
|
12
|
-
import { readConfig } from "
|
|
11
|
+
import { synthesize, listProviders } from "#core/voice/tts.js";
|
|
12
|
+
import { readConfig } from "#core/config/index.js";
|
|
13
13
|
|
|
14
14
|
export function register(app) {
|
|
15
15
|
app.post("/tts/say", async (req, res) => {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// eslint-disable-next-line -- import below
|
|
2
|
+
import { CHANNELS } from "#core/constants/channels.js";
|
|
1
3
|
// Daemon HTTP routes for the unified "voice" channel.
|
|
2
4
|
//
|
|
3
5
|
// POST /voice/turn { audio?: <base64 or path>, format?, text?, agent?,
|
|
@@ -19,12 +21,12 @@ import fs from "node:fs";
|
|
|
19
21
|
import path from "node:path";
|
|
20
22
|
import os from "node:os";
|
|
21
23
|
import { randomUUID } from "node:crypto";
|
|
22
|
-
import { readConfig } from "
|
|
23
|
-
import { synthesize } from "
|
|
24
|
+
import { readConfig } from "#core/config/index.js";
|
|
25
|
+
import { synthesize } from "#core/voice/tts.js";
|
|
24
26
|
import { transcribe } from "../transcription.js";
|
|
25
|
-
import { runSuperAgent, isSuperAgentEnabled } from "
|
|
26
|
-
import { appendGlobalMessage } from "
|
|
27
|
-
import { appendErrorTrace, previewText } from "
|
|
27
|
+
import { runSuperAgent, isSuperAgentEnabled } from "#core/agent/super-agent.js";
|
|
28
|
+
import { appendGlobalMessage } from "#core/stores/messages.js";
|
|
29
|
+
import { appendErrorTrace, previewText } from "#core/logging.js";
|
|
28
30
|
|
|
29
31
|
// ── Channel-aware pre-processor ────────────────────────────────────
|
|
30
32
|
//
|
|
@@ -84,14 +86,14 @@ function buildChannelContext(channel, { projectId, language = "es" } = {}) {
|
|
|
84
86
|
const dynamicNote = `${langDirective}${projectHint}`;
|
|
85
87
|
switch (channel) {
|
|
86
88
|
case "voice":
|
|
87
|
-
return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel:
|
|
89
|
+
return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel: CHANNELS.DECK, channelMeta: { voice: true } };
|
|
88
90
|
case "deck":
|
|
89
|
-
return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel:
|
|
91
|
+
return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel: CHANNELS.DECK, channelMeta: {} };
|
|
90
92
|
case "desktop":
|
|
91
|
-
return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel:
|
|
93
|
+
return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel: CHANNELS.DESKTOP, channelMeta: { voice: true } };
|
|
92
94
|
case "telegram":
|
|
93
95
|
// Format rules live in channels/telegram.md; keep only the dynamic note.
|
|
94
|
-
return { ...base, contextNote: dynamicNote, channel:
|
|
96
|
+
return { ...base, contextNote: dynamicNote, channel: CHANNELS.TELEGRAM, channelMeta: {} };
|
|
95
97
|
default:
|
|
96
98
|
return { ...base, contextNote: dynamicNote, channel: channel || "api", channelMeta: {} };
|
|
97
99
|
}
|
|
@@ -232,7 +234,7 @@ async function tryVoiceTaskIntent({ projects, userText, hintProjectId }) {
|
|
|
232
234
|
};
|
|
233
235
|
}
|
|
234
236
|
try {
|
|
235
|
-
const { createTask } = await import("
|
|
237
|
+
const { createTask } = await import("#core/stores/tasks.js");
|
|
236
238
|
const task = createTask(project.storagePath, {
|
|
237
239
|
title,
|
|
238
240
|
source: "voice",
|
|
@@ -511,8 +513,8 @@ export function register(app, { projects, plugins, registries }) {
|
|
|
511
513
|
}
|
|
512
514
|
|
|
513
515
|
// Note for plugin authors:
|
|
514
|
-
// Desktop (src/host/daemon/plugins/desktop.js) and Telegram
|
|
515
|
-
// (src/host/daemon/plugins/telegram.js) currently implement their own
|
|
516
|
+
// Desktop (src/host/daemon/plugins/desktop/index.js) and Telegram
|
|
517
|
+
// (src/host/daemon/plugins/telegram/index.js) currently implement their own
|
|
516
518
|
// STT → agent → render pipelines. To get spoken replies via APX they can
|
|
517
519
|
// POST to /voice/turn (or call `synthesize()` directly) instead of
|
|
518
520
|
// re-implementing TTS. This module intentionally does NOT migrate them —
|