@agentprojectcontext/apx 1.33.1 → 1.35.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 +1 -1
- package/skills/apx/SKILL.md +49 -61
- package/src/core/agent/a2a/reply.js +48 -0
- package/src/core/agent/build-agent-system.js +136 -59
- package/src/core/agent/channels/voice-context.js +98 -0
- package/src/core/agent/memory.js +2 -1
- package/src/core/agent/prompt-builder.js +178 -124
- package/src/core/agent/prompts/channels/code.md +12 -10
- package/src/core/agent/prompts/channels/desktop.md +5 -32
- package/src/core/agent/prompts/channels/telegram.md +4 -15
- package/src/core/agent/prompts/channels/web_code.md +11 -11
- package/src/core/agent/prompts/core/agent-base.md +24 -0
- package/src/core/agent/prompts/core/project-agent.md +11 -0
- package/src/core/agent/prompts/core/super-agent.md +21 -0
- package/src/core/agent/prompts/discipline/action.md +10 -0
- package/src/core/agent/prompts/discipline/single-segment.md +6 -0
- package/src/core/agent/prompts/discipline/two-segment.md +11 -0
- package/src/core/agent/prompts/modes/code-build.md +1 -0
- package/src/core/agent/prompts/modes/code-plan.md +1 -0
- package/src/core/agent/prompts/modes/index.js +28 -0
- package/src/core/agent/self-memory.js +43 -1
- package/src/core/agent/skills/index-store.js +307 -0
- package/src/core/agent/skills/index.js +15 -1
- package/src/core/agent/skills/inspector.js +317 -0
- package/src/core/agent/skills/loader.js +22 -18
- package/src/core/agent/stream/turn-accumulator.js +73 -0
- package/src/core/agent/suggestions.js +37 -0
- package/src/core/agent/super-agent.js +7 -1
- package/src/core/agent/tools/handlers/_git.js +50 -0
- package/src/core/agent/tools/handlers/add-project.js +5 -2
- package/src/core/agent/tools/handlers/call-runtime.js +3 -2
- package/src/core/agent/tools/handlers/git-diff.js +44 -0
- package/src/core/agent/tools/handlers/git-log.js +38 -0
- package/src/core/agent/tools/handlers/git-show.js +34 -0
- package/src/core/agent/tools/handlers/git-status.js +61 -0
- package/src/core/agent/tools/handlers/transcribe-audio.js +1 -1
- package/src/core/agent/tools/helpers.js +2 -2
- package/src/core/agent/tools/names.js +169 -0
- package/src/core/agent/tools/registry-bridge.js +6 -14
- package/src/core/agent/tools/registry.js +103 -69
- package/src/core/apc/context-copy.js +27 -0
- package/src/core/apc/notes.js +19 -0
- package/src/core/apc/parser.js +12 -5
- package/src/core/apc/paths.js +87 -0
- package/src/core/apc/scaffold.js +82 -76
- package/src/core/apc/skill-sync.js +10 -0
- package/src/{host/daemon/plugins → core/channels}/telegram/dispatch.js +38 -16
- package/src/core/config/index.js +24 -2
- package/src/core/config/redact.js +95 -0
- package/src/core/constants/channels.js +2 -0
- package/src/core/constants/code-modes.js +10 -0
- package/src/core/constants/index.js +1 -0
- package/src/core/deck/manifest.js +186 -0
- package/src/core/engines/catalog.js +83 -0
- package/src/core/{tools → http-tools}/browser.js +0 -1
- package/src/core/{tools → http-tools}/fetch.js +0 -1
- package/src/core/{tools → http-tools}/glob.js +0 -1
- package/src/core/{tools → http-tools}/grep.js +0 -1
- package/src/core/{tools → http-tools}/registry.js +0 -1
- package/src/core/{tools → http-tools}/search.js +0 -1
- package/src/core/i18n/en.js +9 -0
- package/src/core/i18n/es.js +12 -0
- package/src/core/i18n/index.js +54 -0
- package/src/core/i18n/pt.js +9 -0
- package/src/core/identity/telegram.js +2 -1
- package/src/core/mcp/runner.js +272 -14
- package/src/core/mcp/sources.js +3 -2
- package/src/core/routines/index.js +16 -0
- package/src/{host/daemon/routines.js → core/routines/runner.js} +36 -103
- package/src/core/runtime-skills/apc-context/SKILL.md +159 -0
- package/src/core/runtime-skills/apx/SKILL.md +83 -0
- package/src/core/runtime-skills/apx-agency-agents/SKILL.md +125 -0
- package/src/core/runtime-skills/apx-agent/SKILL.md +97 -0
- package/src/core/runtime-skills/apx-mcp/SKILL.md +111 -0
- package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +169 -0
- package/{skills → src/core/runtime-skills}/apx-project/SKILL.md +20 -29
- package/src/core/runtime-skills/apx-routine/SKILL.md +127 -0
- package/src/core/runtime-skills/apx-runtime/SKILL.md +99 -0
- package/src/core/runtime-skills/apx-sessions/SKILL.md +232 -0
- package/src/core/runtime-skills/apx-skill-builder/SKILL.md +129 -0
- package/{skills → src/core/runtime-skills}/apx-task/SKILL.md +18 -21
- package/src/core/runtime-skills/apx-telegram/SKILL.md +120 -0
- package/src/core/runtime-skills/apx-voice/SKILL.md +117 -0
- package/src/core/runtime-skills/{claude-code.md → claude-code/SKILL.md} +1 -0
- package/src/core/runtime-skills/{codex-cli.md → codex-cli/SKILL.md} +1 -0
- package/src/core/runtime-skills/{opencode-cli.md → opencode-cli/SKILL.md} +1 -0
- package/src/core/runtime-skills/{openrouter.md → openrouter/SKILL.md} +1 -0
- package/src/{host/daemon/env-detect.js → core/runtimes/detect.js} +1 -1
- package/src/core/stores/code-sessions.js +50 -2
- package/src/core/stores/routine-memory.js +1 -1
- package/src/core/stores/sessions-search.js +121 -0
- package/src/core/stores/sessions.js +38 -0
- package/src/core/vars/index.js +14 -0
- package/src/core/vars/interpolate.js +86 -0
- package/src/core/vars/sources.js +151 -0
- package/src/core/voice/audio-decode.js +38 -0
- package/src/core/voice/transcription.js +225 -0
- package/src/host/daemon/api/admin-config.js +5 -82
- package/src/host/daemon/api/agents.js +5 -5
- package/src/host/daemon/api/code.js +17 -169
- package/src/host/daemon/api/config.js +3 -4
- package/src/host/daemon/api/conversations.js +8 -29
- package/src/host/daemon/api/deck.js +37 -404
- package/src/host/daemon/api/engines.js +1 -80
- package/src/host/daemon/api/exec.js +1 -1
- package/src/host/daemon/api/mcps.js +32 -0
- package/src/host/daemon/api/routines.js +1 -1
- package/src/host/daemon/api/runtimes.js +4 -3
- package/src/host/daemon/api/sessions-search.js +24 -140
- package/src/host/daemon/api/sessions.js +12 -30
- package/src/host/daemon/api/shared.js +2 -1
- package/src/host/daemon/api/skills.js +140 -6
- package/src/host/daemon/api/super-agent.js +56 -1
- package/src/host/daemon/api/telegram.js +1 -11
- package/src/host/daemon/api/tools.js +6 -6
- package/src/host/daemon/api/transcribe.js +2 -2
- package/src/host/daemon/api/vars.js +137 -0
- package/src/host/daemon/api/voice.js +13 -290
- package/src/host/daemon/api.js +2 -0
- package/src/host/daemon/db.js +6 -6
- package/src/host/daemon/deck-exec.js +148 -0
- package/src/host/daemon/index.js +20 -3
- package/src/host/daemon/plugins/telegram/index.js +9 -9
- package/src/host/daemon/routines-scheduler.js +64 -0
- package/src/host/daemon/smoke.js +3 -2
- package/src/host/daemon/whisper-server.js +225 -0
- package/src/interfaces/cli/branding.js +53 -0
- package/src/interfaces/cli/commands/agent.js +3 -2
- package/src/interfaces/cli/commands/command.js +2 -3
- package/src/interfaces/cli/commands/messages.js +6 -2
- package/src/interfaces/cli/commands/pair.js +5 -4
- package/src/interfaces/cli/commands/search.js +1 -1
- package/src/interfaces/cli/commands/sessions.js +3 -2
- package/src/interfaces/cli/commands/skills.js +290 -55
- package/src/interfaces/cli/index.js +84 -2
- package/src/interfaces/web/dist/assets/index-C0fm31dY.js +618 -0
- package/src/interfaces/web/dist/assets/index-C0fm31dY.js.map +1 -0
- package/src/interfaces/web/dist/assets/index-UcAqlBO6.css +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/package-lock.json +182 -182
- package/src/interfaces/web/src/components/ModelCombobox.tsx +2 -1
- package/src/interfaces/web/src/components/TelegramChannelDialog.tsx +1 -1
- package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +76 -0
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +37 -4
- package/src/interfaces/web/src/components/chat/MessageList.tsx +23 -1
- package/src/interfaces/web/src/components/chat/ModelPicker.tsx +3 -1
- package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +4 -4
- package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +1 -1
- package/src/interfaces/web/src/components/code/CodeFileTree.tsx +3 -2
- package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +3 -2
- package/src/interfaces/web/src/components/code/CodeTerminal.tsx +3 -2
- package/src/interfaces/web/src/components/config/GlobalConfigEditor.tsx +2 -1
- package/src/interfaces/web/src/components/deck/WidgetRow.tsx +2 -1
- package/src/interfaces/web/src/components/inputs/KeyValueList.tsx +93 -0
- package/src/interfaces/web/src/components/inputs/VarTokenInput.tsx +449 -0
- package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +2 -1
- package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +2 -2
- package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +73 -4
- package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +222 -0
- package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +3 -2
- package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +3 -2
- package/src/interfaces/web/src/components/ui/chat-input.tsx +5 -4
- package/src/interfaces/web/src/components/ui/sidebar.tsx +3 -2
- package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +2 -1
- package/src/interfaces/web/src/constants/index.ts +1 -1
- package/src/interfaces/web/src/hooks/useChat.ts +19 -0
- package/src/interfaces/web/src/i18n/en.ts +175 -7
- package/src/interfaces/web/src/i18n/es.ts +180 -15
- package/src/interfaces/web/src/lib/api/mcps.ts +25 -0
- package/src/interfaces/web/src/lib/api/skills.ts +70 -0
- package/src/interfaces/web/src/lib/api/vars.ts +38 -0
- package/src/interfaces/web/src/lib/api.ts +1 -0
- package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -31
- package/src/interfaces/web/src/screens/SettingsScreen.tsx +6 -2
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +4 -3
- package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +7 -6
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +4 -3
- package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/project/ConfigTab.tsx +132 -1
- package/src/interfaces/web/src/screens/project/McpsTab.tsx +549 -104
- package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +1 -1
- package/src/interfaces/web/src/screens/project/VarsTab.tsx +300 -0
- package/src/interfaces/web/src/types/daemon.ts +15 -0
- package/skills/apx-agency-agents/SKILL.md +0 -141
- package/skills/apx-agent/SKILL.md +0 -100
- package/skills/apx-mcp-builder/SKILL.md +0 -183
- package/skills/apx-routine/SKILL.md +0 -140
- package/skills/apx-runtime/SKILL.md +0 -117
- package/skills/apx-sessions/SKILL.md +0 -281
- package/skills/apx-skill-builder/SKILL.md +0 -153
- package/skills/apx-telegram/SKILL.md +0 -131
- package/skills/apx-voice/SKILL.md +0 -137
- package/src/core/agent/prompts/action-discipline.md +0 -24
- package/src/core/agent/prompts/super-agent-base.md +0 -42
- package/src/host/daemon/transcription.js +0 -538
- package/src/host/daemon/whisper-transcribe.py +0 -73
- package/src/interfaces/web/dist/assets/index-Aaiw8BZN.css +0 -1
- package/src/interfaces/web/dist/assets/index-DPqtjDjh.js +0 -602
- package/src/interfaces/web/dist/assets/index-DPqtjDjh.js.map +0 -1
- /package/src/{host/daemon → core/apc}/projects-helpers.js +0 -0
- /package/src/{host/daemon/plugins → core/channels}/telegram/ask.js +0 -0
- /package/src/{host/daemon/plugins → core/channels}/telegram/helpers.js +0 -0
- /package/src/{host/daemon/plugins → core/channels}/telegram/media.js +0 -0
- /package/src/core/{tools → http-tools}/index.js +0 -0
- /package/src/{host/daemon/compact.js → core/stores/conversations-compactor.js} +0 -0
- /package/src/{host/daemon → core/stores}/conversations.js +0 -0
- /package/src/{host/daemon → core/util}/thinking.js +0 -0
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
deleteRoutine,
|
|
16
16
|
setEnabled as setRoutineEnabled,
|
|
17
17
|
runRoutineNow,
|
|
18
|
-
} from "
|
|
18
|
+
} from "#core/routines/index.js";
|
|
19
19
|
|
|
20
20
|
export function register(app, { projects, registries, plugins, project, config }) {
|
|
21
21
|
app.get("/projects/:pid/routines", (req, res) => {
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
import fs from "node:fs";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { readAgents } from "#core/apc/parser.js";
|
|
11
|
+
import { apcProjectFile, apcAgentsDir } from "#core/apc/paths.js";
|
|
11
12
|
import { readSessionFrontmatter } from "#core/stores/sessions.js";
|
|
12
13
|
import { buildAgentSystem } from "#core/agent/build-agent-system.js";
|
|
13
14
|
import { CHANNELS } from "#core/constants/channels.js";
|
|
14
15
|
import { getRuntime, RUNTIME_IDS } from "../runtimes/index.js";
|
|
15
|
-
import { detectAll } from "
|
|
16
|
+
import { detectAll } from "#core/runtimes/detect.js";
|
|
16
17
|
import { buildRuntimeBridgeHint as buildApfHint } from "#core/agent/runtime-bridge.js";
|
|
17
18
|
import {
|
|
18
19
|
createRuntimeSession,
|
|
@@ -52,7 +53,7 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
52
53
|
let projectName = path.basename(p.path);
|
|
53
54
|
try {
|
|
54
55
|
const meta = JSON.parse(
|
|
55
|
-
fs.readFileSync(
|
|
56
|
+
fs.readFileSync(apcProjectFile(p.path), "utf8")
|
|
56
57
|
);
|
|
57
58
|
if (meta.name) projectName = meta.name;
|
|
58
59
|
} catch {}
|
|
@@ -152,7 +153,7 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
152
153
|
|
|
153
154
|
const sessionRoots = [
|
|
154
155
|
path.join(p.storagePath || p.path, "agents"),
|
|
155
|
-
|
|
156
|
+
apcAgentsDir(p.path),
|
|
156
157
|
];
|
|
157
158
|
let sessionFile = null;
|
|
158
159
|
let agentSlug = null;
|
|
@@ -2,169 +2,53 @@
|
|
|
2
2
|
// GET /sessions/search?q=…&project=…&limit=20
|
|
3
3
|
// POST /sessions/:id/compact resolves which project/agent owns the file
|
|
4
4
|
// then delegates to compactConversation.
|
|
5
|
-
import fs from "node:fs";
|
|
6
5
|
import path from "node:path";
|
|
7
6
|
import { readAgents } from "#core/apc/parser.js";
|
|
8
|
-
import { compactConversation } from "
|
|
7
|
+
import { compactConversation } from "#core/stores/conversations-compactor.js";
|
|
8
|
+
import { searchSessions, findSessionFile } from "#core/stores/sessions-search.js";
|
|
9
|
+
|
|
10
|
+
function resolveProjects(projects, projectRef) {
|
|
11
|
+
const all = projects.list();
|
|
12
|
+
if (projectRef != null) {
|
|
13
|
+
const ref = String(projectRef);
|
|
14
|
+
const found = all.find((p) => String(p.id) === ref || p.path === path.resolve(ref));
|
|
15
|
+
return found ? [projects.get(found.id)] : [];
|
|
16
|
+
}
|
|
17
|
+
return all.map((p) => projects.get(p.id)).filter(Boolean);
|
|
18
|
+
}
|
|
9
19
|
|
|
10
20
|
export function register(app, { projects, config }) {
|
|
11
21
|
app.get("/sessions/search", (req, res) => {
|
|
12
22
|
const { q, project: projectRef, limit = "20" } = req.query;
|
|
13
23
|
if (!q) return res.status(400).json({ error: "q required" });
|
|
14
24
|
const lim = Math.min(parseInt(limit, 10) || 20, 200);
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const targetProjects = (() => {
|
|
19
|
-
if (projectRef != null) {
|
|
20
|
-
const ref = String(projectRef);
|
|
21
|
-
const found = allProjects.find(
|
|
22
|
-
(p) => String(p.id) === ref || p.path === path.resolve(ref)
|
|
23
|
-
);
|
|
24
|
-
return found ? [projects.get(found.id)] : [];
|
|
25
|
-
}
|
|
26
|
-
return allProjects.map((p) => projects.get(p.id)).filter(Boolean);
|
|
27
|
-
})();
|
|
28
|
-
|
|
29
|
-
const matches = [];
|
|
30
|
-
|
|
31
|
-
for (const p of targetProjects) {
|
|
32
|
-
if (!p) continue;
|
|
33
|
-
|
|
34
|
-
// 1) Legacy session files in the repo (.apc/agents/<slug>/sessions/)
|
|
35
|
-
const sessionAgentsDir = path.join(p.path, ".apc", "agents");
|
|
36
|
-
if (fs.existsSync(sessionAgentsDir)) {
|
|
37
|
-
for (const slug of fs.readdirSync(sessionAgentsDir)) {
|
|
38
|
-
const sessionsDir = path.join(sessionAgentsDir, slug, "sessions");
|
|
39
|
-
if (!fs.existsSync(sessionsDir)) continue;
|
|
40
|
-
for (const f of fs
|
|
41
|
-
.readdirSync(sessionsDir)
|
|
42
|
-
.filter((x) => x.endsWith(".md"))) {
|
|
43
|
-
const filePath = path.join(sessionsDir, f);
|
|
44
|
-
try {
|
|
45
|
-
const text = fs.readFileSync(filePath, "utf8");
|
|
46
|
-
if (text.toLowerCase().includes(needle)) {
|
|
47
|
-
const lines = text.split("\n");
|
|
48
|
-
const matchLine = lines.findIndex((l) =>
|
|
49
|
-
l.toLowerCase().includes(needle)
|
|
50
|
-
);
|
|
51
|
-
const excerpt = lines
|
|
52
|
-
.slice(Math.max(0, matchLine - 1), matchLine + 3)
|
|
53
|
-
.join("\n");
|
|
54
|
-
matches.push({
|
|
55
|
-
type: "session",
|
|
56
|
-
project: p.id,
|
|
57
|
-
agent: slug,
|
|
58
|
-
filename: f,
|
|
59
|
-
path: filePath,
|
|
60
|
-
excerpt: excerpt.slice(0, 300),
|
|
61
|
-
});
|
|
62
|
-
if (matches.length >= lim) break;
|
|
63
|
-
}
|
|
64
|
-
} catch {}
|
|
65
|
-
}
|
|
66
|
-
if (matches.length >= lim) break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (matches.length >= lim) break;
|
|
71
|
-
|
|
72
|
-
// 2) Conversation files in daemon storage (~/.apx/…/conversations/)
|
|
73
|
-
const convAgentsDir = path.join(p.storagePath, "agents");
|
|
74
|
-
if (fs.existsSync(convAgentsDir)) {
|
|
75
|
-
for (const slug of fs.readdirSync(convAgentsDir)) {
|
|
76
|
-
const convDir = path.join(convAgentsDir, slug, "conversations");
|
|
77
|
-
if (!fs.existsSync(convDir)) continue;
|
|
78
|
-
for (const f of fs
|
|
79
|
-
.readdirSync(convDir)
|
|
80
|
-
.filter((x) => x.endsWith(".md"))) {
|
|
81
|
-
const filePath = path.join(convDir, f);
|
|
82
|
-
try {
|
|
83
|
-
const text = fs.readFileSync(filePath, "utf8");
|
|
84
|
-
if (text.toLowerCase().includes(needle)) {
|
|
85
|
-
const lines = text.split("\n");
|
|
86
|
-
const matchLine = lines.findIndex((l) =>
|
|
87
|
-
l.toLowerCase().includes(needle)
|
|
88
|
-
);
|
|
89
|
-
const excerpt = lines
|
|
90
|
-
.slice(Math.max(0, matchLine - 1), matchLine + 3)
|
|
91
|
-
.join("\n");
|
|
92
|
-
matches.push({
|
|
93
|
-
type: "conversation",
|
|
94
|
-
project: p.id,
|
|
95
|
-
agent: slug,
|
|
96
|
-
filename: f,
|
|
97
|
-
path: filePath,
|
|
98
|
-
excerpt: excerpt.slice(0, 300),
|
|
99
|
-
});
|
|
100
|
-
if (matches.length >= lim) break;
|
|
101
|
-
}
|
|
102
|
-
} catch {}
|
|
103
|
-
}
|
|
104
|
-
if (matches.length >= lim) break;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (matches.length >= lim) break;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
res.json({ q, count: matches.length, results: matches });
|
|
25
|
+
const targets = resolveProjects(projects, projectRef);
|
|
26
|
+
const results = searchSessions(targets, q, lim);
|
|
27
|
+
res.json({ q, count: results.length, results });
|
|
112
28
|
});
|
|
113
29
|
|
|
114
30
|
app.post("/sessions/:id/compact", async (req, res) => {
|
|
115
31
|
const { id } = req.params;
|
|
116
32
|
const { model: modelOverride, project: projectRef } = req.body || {};
|
|
117
|
-
|
|
118
|
-
const candidates
|
|
119
|
-
projectRef != null
|
|
120
|
-
? (() => {
|
|
121
|
-
const ref = String(projectRef);
|
|
122
|
-
const found = projects
|
|
123
|
-
.list()
|
|
124
|
-
.find(
|
|
125
|
-
(p) => String(p.id) === ref || p.path === path.resolve(ref)
|
|
126
|
-
);
|
|
127
|
-
return found ? [projects.get(found.id)] : [];
|
|
128
|
-
})()
|
|
129
|
-
: projects.list().map((p) => projects.get(p.id)).filter(Boolean);
|
|
130
|
-
|
|
131
|
-
let found = null;
|
|
132
|
-
const filename = id.endsWith(".md") ? id : `${id}.md`;
|
|
133
|
-
|
|
134
|
-
for (const p of candidates) {
|
|
135
|
-
if (!p) continue;
|
|
136
|
-
const agentsDir = path.join(p.storagePath, "agents");
|
|
137
|
-
if (fs.existsSync(agentsDir)) {
|
|
138
|
-
for (const slug of fs.readdirSync(agentsDir)) {
|
|
139
|
-
const f = path.join(agentsDir, slug, "conversations", filename);
|
|
140
|
-
if (fs.existsSync(f)) {
|
|
141
|
-
found = { p, slug };
|
|
142
|
-
break;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
if (found) break;
|
|
147
|
-
}
|
|
33
|
+
const candidates = resolveProjects(projects, projectRef);
|
|
34
|
+
const found = findSessionFile(candidates, id);
|
|
148
35
|
|
|
149
36
|
if (!found) {
|
|
150
|
-
return res
|
|
151
|
-
.status(404)
|
|
152
|
-
.json({ error: `session/conversation "${id}" not found` });
|
|
37
|
+
return res.status(404).json({ error: `session/conversation "${id}" not found` });
|
|
153
38
|
}
|
|
154
39
|
|
|
155
|
-
const { p,
|
|
40
|
+
const { project: p, agentSlug, filename } = found;
|
|
156
41
|
const agents = readAgents(p.path);
|
|
157
|
-
const agent = agents.find((a) => a.slug ===
|
|
42
|
+
const agent = agents.find((a) => a.slug === agentSlug);
|
|
158
43
|
const modelId = modelOverride || agent?.fields?.Model;
|
|
159
|
-
if (!modelId)
|
|
160
|
-
return res
|
|
161
|
-
|
|
162
|
-
.json({ error: "agent has no model; pass model in body" });
|
|
44
|
+
if (!modelId) {
|
|
45
|
+
return res.status(400).json({ error: "agent has no model; pass model in body" });
|
|
46
|
+
}
|
|
163
47
|
|
|
164
48
|
try {
|
|
165
49
|
const result = await compactConversation({
|
|
166
50
|
storagePath: p.storagePath,
|
|
167
|
-
agentSlug
|
|
51
|
+
agentSlug,
|
|
168
52
|
filename,
|
|
169
53
|
modelId,
|
|
170
54
|
config: p.config || config,
|
|
@@ -4,9 +4,15 @@
|
|
|
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 {
|
|
7
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
8
|
+
import {
|
|
9
|
+
parseSessionFrontmatter,
|
|
10
|
+
} from "#core/apc/parser.js";
|
|
11
|
+
import {
|
|
12
|
+
agentSessionsDir,
|
|
13
|
+
createAgentSessionFile,
|
|
14
|
+
} from "#core/stores/sessions.js";
|
|
8
15
|
import { collectAllSessions } from "#interfaces/cli/commands/sessions.js";
|
|
9
|
-
import { nowIso } from "./shared.js";
|
|
10
16
|
|
|
11
17
|
export function register(app, { projects, project }) {
|
|
12
18
|
// Cross-engine sessions (apx · claude · codex), newest first.
|
|
@@ -29,12 +35,7 @@ export function register(app, { projects, project }) {
|
|
|
29
35
|
const agents = readAgents(p.path);
|
|
30
36
|
if (!agents.find((a) => a.slug === req.params.slug))
|
|
31
37
|
return res.status(404).json({ error: "agent not found" });
|
|
32
|
-
const sessionsDir =
|
|
33
|
-
p.storagePath,
|
|
34
|
-
"agents",
|
|
35
|
-
req.params.slug,
|
|
36
|
-
"sessions"
|
|
37
|
-
);
|
|
38
|
+
const sessionsDir = agentSessionsDir(p.storagePath, req.params.slug);
|
|
38
39
|
if (!fs.existsSync(sessionsDir)) return res.json([]);
|
|
39
40
|
const sessions = fs
|
|
40
41
|
.readdirSync(sessionsDir)
|
|
@@ -62,32 +63,13 @@ export function register(app, { projects, project }) {
|
|
|
62
63
|
if (!p) return;
|
|
63
64
|
const { title, body = "" } = req.body || {};
|
|
64
65
|
if (!title) return res.status(400).json({ error: "title required" });
|
|
65
|
-
const
|
|
66
|
+
const { filename, path: filePath } = createAgentSessionFile(
|
|
66
67
|
p.storagePath,
|
|
67
|
-
"agents",
|
|
68
68
|
req.params.slug,
|
|
69
|
-
|
|
69
|
+
{ title, body }
|
|
70
70
|
);
|
|
71
|
-
fs.mkdirSync(sessionsDir, { recursive: true });
|
|
72
|
-
const titleSlug =
|
|
73
|
-
title
|
|
74
|
-
.toLowerCase()
|
|
75
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
76
|
-
.replace(/^-|-$/g, "") || "session";
|
|
77
|
-
const today = new Date().toISOString().slice(0, 10);
|
|
78
|
-
let candidate = path.join(sessionsDir, `${today}-${titleSlug}.md`);
|
|
79
|
-
let n = 2;
|
|
80
|
-
while (fs.existsSync(candidate)) {
|
|
81
|
-
candidate = path.join(sessionsDir, `${today}-${titleSlug}-${n}.md`);
|
|
82
|
-
n++;
|
|
83
|
-
}
|
|
84
|
-
const started = nowIso();
|
|
85
|
-
const content = `---\ntitle: ${title}\nstarted: ${started}\n---\n\n# ${title}\n\n${body}\n`;
|
|
86
|
-
fs.writeFileSync(candidate, content);
|
|
87
71
|
projects.rebuild(p.id);
|
|
88
|
-
res
|
|
89
|
-
.status(201)
|
|
90
|
-
.json({ filename: path.basename(candidate), path: candidate });
|
|
72
|
+
res.status(201).json({ filename, path: filePath });
|
|
91
73
|
});
|
|
92
74
|
|
|
93
75
|
// GET session by filename (sid may include or omit the .md extension)
|
|
@@ -8,6 +8,7 @@ import { randomUUID } from "node:crypto";
|
|
|
8
8
|
import { appendErrorTrace, previewText } from "#core/logging.js";
|
|
9
9
|
import { readAgents } from "#core/apc/parser.js";
|
|
10
10
|
import { agentMemoryPath } from "#core/agent/memory.js";
|
|
11
|
+
import { apcMemoryFile } from "#core/apc/paths.js";
|
|
11
12
|
import { CHANNELS } from "#core/constants/channels.js";
|
|
12
13
|
|
|
13
14
|
export const nowIso = () =>
|
|
@@ -117,7 +118,7 @@ export function makeTopProjectResolver(projects) {
|
|
|
117
118
|
export function resolveMemoryPath(p) {
|
|
118
119
|
const firstAgent = readAgents(p.path)[0];
|
|
119
120
|
if (firstAgent) return agentMemoryPath(p, firstAgent.slug);
|
|
120
|
-
return
|
|
121
|
+
return apcMemoryFile(p.path);
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
// Channel context passed to the super-agent loop. `api` is the default when
|
|
@@ -1,12 +1,42 @@
|
|
|
1
|
-
//
|
|
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?".
|
|
1
|
+
// `/skills` listing + Skill Inspector control surface for UI clients.
|
|
5
2
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// GET /skills catalog (slug + condensed description)
|
|
4
|
+
// GET /skills/inspector inspector config + index status
|
|
5
|
+
// PUT /skills/inspector toggle / tune inspector config
|
|
6
|
+
// POST /skills/index (re)build the inspector vector index
|
|
7
|
+
// POST /skills/inspect dry-run the inspector for a prompt
|
|
8
|
+
//
|
|
9
|
+
// The listing is the same data backing `list_skills` (no auth-binding to a
|
|
10
|
+
// project). The inspector routes mirror /embeddings/* so the web admin can
|
|
11
|
+
// configure the skill RAG exactly like it configures the memory RAG.
|
|
8
12
|
import { listSkills } from "#core/agent/skills/loader.js";
|
|
9
13
|
import { condenseSkillDescription } from "#core/agent/skills/catalog.js";
|
|
14
|
+
import {
|
|
15
|
+
inspectPromptForSkills,
|
|
16
|
+
INSPECTOR_DEFAULTS,
|
|
17
|
+
} from "#core/agent/skills/inspector.js";
|
|
18
|
+
import {
|
|
19
|
+
ensureIndex,
|
|
20
|
+
planIndex,
|
|
21
|
+
readIndex,
|
|
22
|
+
} from "#core/agent/skills/index-store.js";
|
|
23
|
+
import { readConfig, writeConfig } from "#core/config/index.js";
|
|
24
|
+
|
|
25
|
+
const KNOWN_KEYS = Object.keys(INSPECTOR_DEFAULTS);
|
|
26
|
+
|
|
27
|
+
function mergedInspectorConfig(cfg) {
|
|
28
|
+
return { ...INSPECTOR_DEFAULTS, ...(cfg?.skills?.inspector || {}) };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function indexStatus() {
|
|
32
|
+
const idx = readIndex();
|
|
33
|
+
return {
|
|
34
|
+
count: Object.keys(idx.items || {}).length,
|
|
35
|
+
embedder: idx.embedder || null,
|
|
36
|
+
dim: idx.dim || null,
|
|
37
|
+
updated_at: idx.updated_at || null,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
10
40
|
|
|
11
41
|
export function register(app /*, ctx */) {
|
|
12
42
|
app.get("/skills", (req, res) => {
|
|
@@ -27,4 +57,108 @@ export function register(app /*, ctx */) {
|
|
|
27
57
|
res.status(500).json({ error: e.message });
|
|
28
58
|
}
|
|
29
59
|
});
|
|
60
|
+
|
|
61
|
+
// ---- Inspector config + status -----------------------------------------
|
|
62
|
+
|
|
63
|
+
app.get("/skills/inspector", (_req, res) => {
|
|
64
|
+
try {
|
|
65
|
+
const cfg = readConfig();
|
|
66
|
+
res.json({
|
|
67
|
+
config: mergedInspectorConfig(cfg),
|
|
68
|
+
defaults: INSPECTOR_DEFAULTS,
|
|
69
|
+
keys: KNOWN_KEYS,
|
|
70
|
+
index: indexStatus(),
|
|
71
|
+
});
|
|
72
|
+
} catch (e) {
|
|
73
|
+
res.status(500).json({ error: e.message });
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
app.put("/skills/inspector", (req, res) => {
|
|
78
|
+
try {
|
|
79
|
+
const patch = req.body || {};
|
|
80
|
+
const cfg = readConfig();
|
|
81
|
+
cfg.skills = cfg.skills || {};
|
|
82
|
+
const current = mergedInspectorConfig(cfg);
|
|
83
|
+
const next = { ...current };
|
|
84
|
+
|
|
85
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
86
|
+
if (!KNOWN_KEYS.includes(k)) continue;
|
|
87
|
+
const def = INSPECTOR_DEFAULTS[k];
|
|
88
|
+
if (typeof def === "boolean") next[k] = !!v;
|
|
89
|
+
else if (typeof def === "number") {
|
|
90
|
+
const n = Number(v);
|
|
91
|
+
if (Number.isFinite(n)) next[k] = n;
|
|
92
|
+
} else {
|
|
93
|
+
next[k] = v;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
cfg.skills.inspector = next;
|
|
98
|
+
writeConfig(cfg);
|
|
99
|
+
res.json({ ok: true, config: next, index: indexStatus() });
|
|
100
|
+
} catch (e) {
|
|
101
|
+
res.status(500).json({ error: e.message });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// ---- Index build --------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
app.post("/skills/index", async (req, res) => {
|
|
108
|
+
try {
|
|
109
|
+
const { project_path, force } = req.body || {};
|
|
110
|
+
const cfg = readConfig();
|
|
111
|
+
const plan = planIndex({ projectPath: project_path });
|
|
112
|
+
const out = await ensureIndex({
|
|
113
|
+
projectPath: project_path,
|
|
114
|
+
embedOpts: { globalConfig: cfg },
|
|
115
|
+
force: !!force,
|
|
116
|
+
});
|
|
117
|
+
res.json({
|
|
118
|
+
ok: true,
|
|
119
|
+
embedder: out.embedder,
|
|
120
|
+
dim: out.dim,
|
|
121
|
+
planned: {
|
|
122
|
+
missing: plan.missing.length,
|
|
123
|
+
stale: plan.stale.length,
|
|
124
|
+
gone: plan.gone.length,
|
|
125
|
+
total: plan.total,
|
|
126
|
+
},
|
|
127
|
+
changed: {
|
|
128
|
+
added: out.changed.added.length,
|
|
129
|
+
refreshed: out.changed.refreshed.length,
|
|
130
|
+
removed: out.changed.removed.length,
|
|
131
|
+
kept: out.changed.kept.length,
|
|
132
|
+
},
|
|
133
|
+
index: indexStatus(),
|
|
134
|
+
});
|
|
135
|
+
} catch (e) {
|
|
136
|
+
res.status(500).json({ error: e.message });
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// ---- Dry-run ------------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
app.post("/skills/inspect", async (req, res) => {
|
|
143
|
+
try {
|
|
144
|
+
const { prompt, project_path } = req.body || {};
|
|
145
|
+
if (!prompt || typeof prompt !== "string") {
|
|
146
|
+
return res.status(400).json({ error: "prompt required" });
|
|
147
|
+
}
|
|
148
|
+
const cfg = readConfig();
|
|
149
|
+
// Force enabled for the dry-run so the operator sees what it WOULD do
|
|
150
|
+
// even when the feature is currently off.
|
|
151
|
+
const probed = structuredClone(cfg);
|
|
152
|
+
probed.skills = probed.skills || {};
|
|
153
|
+
probed.skills.inspector = { ...mergedInspectorConfig(cfg), enabled: true };
|
|
154
|
+
const out = await inspectPromptForSkills({
|
|
155
|
+
prompt,
|
|
156
|
+
projectPath: project_path,
|
|
157
|
+
globalConfig: probed,
|
|
158
|
+
});
|
|
159
|
+
res.json({ trace: out.trace, contextNote: out.contextNote });
|
|
160
|
+
} catch (e) {
|
|
161
|
+
res.status(500).json({ error: e.message });
|
|
162
|
+
}
|
|
163
|
+
});
|
|
30
164
|
}
|
|
@@ -15,10 +15,30 @@ import { appendGlobalMessage } from "#core/stores/messages.js";
|
|
|
15
15
|
import { createWebConfirmAdapter } from "#core/confirmation/adapters/web.js";
|
|
16
16
|
import { tryResolveSkillCommand } from "#core/agent/skills/trigger.js";
|
|
17
17
|
import { suggestSkillForPrompt } from "#core/agent/skills/rag.js";
|
|
18
|
+
import { inspectPromptForSkills, isInspectorEnabled, summarizeTrace } from "#core/agent/skills/inspector.js";
|
|
18
19
|
import { CHANNELS } from "#core/constants/channels.js";
|
|
19
20
|
|
|
20
21
|
const log = loggerFor("super-agent");
|
|
21
22
|
|
|
23
|
+
// Emit a single, readable line so `apx log -f` shows exactly what the skill
|
|
24
|
+
// inspector decided this turn (which skills it loaded/hinted, the embedder, and
|
|
25
|
+
// the top similarity). Best-effort: logging must never break a reply.
|
|
26
|
+
function logInspectorDecision(trace, { trace_id, channel } = {}) {
|
|
27
|
+
if (!trace) return;
|
|
28
|
+
try {
|
|
29
|
+
const top = trace.scored?.[0];
|
|
30
|
+
const topStr = top ? ` top=${top.slug}@${top.sim}` : "";
|
|
31
|
+
log.info(`skill inspector: ${summarizeTrace(trace)} [${trace.embedder || "?"}]${topStr}`, {
|
|
32
|
+
trace_id,
|
|
33
|
+
channel,
|
|
34
|
+
loaded: trace.loaded || [],
|
|
35
|
+
hinted: trace.hinted || [],
|
|
36
|
+
});
|
|
37
|
+
} catch {
|
|
38
|
+
/* logging is best-effort */
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
22
42
|
// Persist human web turns to the cross-channel message store so they feed the
|
|
23
43
|
// RAG index, search_messages, and the "active threads" awareness block. Only
|
|
24
44
|
// the human surfaces (web big chat + sidebar) — not generic "api"/automation
|
|
@@ -79,10 +99,25 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
79
99
|
// slug is unknown.
|
|
80
100
|
const slashed = tryResolveSkillCommand(rawPrompt, { projectPath: p.path });
|
|
81
101
|
const prompt = slashed.handled ? slashed.prompt : rawPrompt;
|
|
102
|
+
const inspectorOn = isInspectorEnabled(config);
|
|
103
|
+
let inspectorTrace = null;
|
|
82
104
|
if (slashed.handled) {
|
|
83
105
|
ctx.contextNote = [ctx.contextNote, slashed.contextNote].filter(Boolean).join("\n\n");
|
|
106
|
+
} else if (inspectorOn) {
|
|
107
|
+
// Inspector middleware: per-turn semantic RAG. Replaces both the passive
|
|
108
|
+
// suggestSkillForPrompt nudge AND the static slug-dump in the system
|
|
109
|
+
// prompt — see runSuperAgent({ skipSkillsHint }).
|
|
110
|
+
const out = await inspectPromptForSkills({
|
|
111
|
+
prompt,
|
|
112
|
+
projectPath: p.path,
|
|
113
|
+
globalConfig: config,
|
|
114
|
+
});
|
|
115
|
+
inspectorTrace = out.trace;
|
|
116
|
+
if (out.contextNote) {
|
|
117
|
+
ctx.contextNote = [ctx.contextNote, out.contextNote].filter(Boolean).join("\n\n");
|
|
118
|
+
}
|
|
84
119
|
} else {
|
|
85
|
-
//
|
|
120
|
+
// Legacy path — passive nudge, still works when inspector is off.
|
|
86
121
|
const hint = await suggestSkillForPrompt(prompt, { projectPath: p.path });
|
|
87
122
|
if (hint) ctx.contextNote = [ctx.contextNote, hint].filter(Boolean).join("\n\n");
|
|
88
123
|
}
|
|
@@ -101,6 +136,14 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
101
136
|
channel: ctx.channel,
|
|
102
137
|
});
|
|
103
138
|
|
|
139
|
+
// Surface the inspector decision to clients before model_start so the web
|
|
140
|
+
// debug panel / TUI can render "loaded: X" the moment the turn begins.
|
|
141
|
+
if (inspectorTrace) {
|
|
142
|
+
try { onEvent({ type: "skill_inspector", inspector: inspectorTrace }); }
|
|
143
|
+
catch { /* trace is best-effort */ }
|
|
144
|
+
logInspectorDecision(inspectorTrace, { trace_id: req.apxTraceId, channel: ctx.channel });
|
|
145
|
+
}
|
|
146
|
+
|
|
104
147
|
// Web/TUI channels receive a "confirmation_required" SSE event and respond
|
|
105
148
|
// via POST /super-agent/confirm/:correlationId (see api/confirm.js).
|
|
106
149
|
const requestConfirmation = createWebConfirmAdapter({ onEvent });
|
|
@@ -122,6 +165,7 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
122
165
|
...(completionContract ? { completionContract: true } : {}),
|
|
123
166
|
onEvent,
|
|
124
167
|
requestConfirmation,
|
|
168
|
+
skipSkillsHint: inspectorOn,
|
|
125
169
|
});
|
|
126
170
|
projects.rebuild(p.id);
|
|
127
171
|
logWebTurn(ctx.channel, { prompt, replyText: saResult.text });
|
|
@@ -194,6 +238,16 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
194
238
|
req.body || {};
|
|
195
239
|
if (!prompt) return res.status(400).json({ error: "prompt required" });
|
|
196
240
|
const ctx = resolveSuperAgentContext(req, p);
|
|
241
|
+
const inspectorOn = isInspectorEnabled(config);
|
|
242
|
+
if (inspectorOn) {
|
|
243
|
+
try {
|
|
244
|
+
const out = await inspectPromptForSkills({ prompt, projectPath: p.path, globalConfig: config });
|
|
245
|
+
if (out.contextNote) {
|
|
246
|
+
ctx.contextNote = [ctx.contextNote, out.contextNote].filter(Boolean).join("\n\n");
|
|
247
|
+
}
|
|
248
|
+
logInspectorDecision(out.trace, { trace_id: req.apxTraceId, channel: ctx.channel });
|
|
249
|
+
} catch { /* inspector failure must not block the turn */ }
|
|
250
|
+
}
|
|
197
251
|
try {
|
|
198
252
|
const saResult = await runSuperAgent({
|
|
199
253
|
globalConfig: config,
|
|
@@ -213,6 +267,7 @@ export function register(app, { projects, registries, plugins, project, config }
|
|
|
213
267
|
trace_id: req.apxTraceId,
|
|
214
268
|
channel: ctx.channel,
|
|
215
269
|
}),
|
|
270
|
+
skipSkillsHint: inspectorOn,
|
|
216
271
|
});
|
|
217
272
|
projects.rebuild(p.id);
|
|
218
273
|
logWebTurn(ctx.channel, { prompt, replyText: saResult.text });
|
|
@@ -39,17 +39,7 @@ import {
|
|
|
39
39
|
removeRole,
|
|
40
40
|
} from "#core/config/index.js";
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
if (!channel?.bot_token) return channel;
|
|
44
|
-
return {
|
|
45
|
-
...channel,
|
|
46
|
-
bot_token: `*** set *** (...${String(channel.bot_token).slice(-5)})`,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function isSecretMarker(value) {
|
|
51
|
-
return typeof value === "string" && value.startsWith("*** set ***");
|
|
52
|
-
}
|
|
42
|
+
import { redactChannel, isSecretMarker } from "#core/config/redact.js";
|
|
53
43
|
|
|
54
44
|
export function register(app, { telegram }) {
|
|
55
45
|
app.get("/telegram/status", (_req, res) => {
|
|
@@ -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 "#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";
|
|
7
|
+
import { buildBrowserRouter } from "#core/http-tools/browser.js";
|
|
8
|
+
import { buildFetchRouter } from "#core/http-tools/fetch.js";
|
|
9
|
+
import { buildSearchRouter } from "#core/http-tools/search.js";
|
|
10
|
+
import { buildRegistryRouter } from "#core/http-tools/registry.js";
|
|
11
|
+
import { buildGlobRouter } from "#core/http-tools/glob.js";
|
|
12
|
+
import { buildGrepRouter } from "#core/http-tools/grep.js";
|
|
13
13
|
|
|
14
14
|
export function register(app, { express, projects, registries }) {
|
|
15
15
|
app.use("/tools/fetch", buildFetchRouter(express));
|
|
@@ -11,7 +11,7 @@ export function register(app) {
|
|
|
11
11
|
// the first real utterance doesn't pay the cold-load cost.
|
|
12
12
|
app.get("/transcribe/warmup", async (_req, res) => {
|
|
13
13
|
try {
|
|
14
|
-
const { warmupWhisper } = await import("../
|
|
14
|
+
const { warmupWhisper } = await import("../whisper-server.js");
|
|
15
15
|
res.json(await warmupWhisper());
|
|
16
16
|
} catch (e) {
|
|
17
17
|
res.status(500).json({ ok: false, error: e.message });
|
|
@@ -29,7 +29,7 @@ export function register(app) {
|
|
|
29
29
|
const language = req.headers["x-language"] || "auto";
|
|
30
30
|
const provider = req.headers["x-provider"];
|
|
31
31
|
try {
|
|
32
|
-
const { transcribeBuffer } = await import("
|
|
32
|
+
const { transcribeBuffer } = await import("#core/voice/transcription.js");
|
|
33
33
|
const result = await transcribeBuffer(buf, format, {
|
|
34
34
|
language: language === "auto" ? undefined : language,
|
|
35
35
|
beam_size: 3,
|