@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
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Shared helpers for the Routines screen + its components.
|
|
2
2
|
// Kept framework-free (pure functions + i18n) so list/detail/editor reuse them.
|
|
3
|
-
import { Bot, Crown, Heart, Send, Terminal } from "lucide-react";
|
|
3
|
+
import { Bot, Crown, Eye, Heart, Send, Terminal } from "lucide-react";
|
|
4
4
|
import type { RoutineEntry } from "../../lib/api";
|
|
5
5
|
import { t } from "../../i18n";
|
|
6
|
+
import { describeCron } from "../../lib/cron";
|
|
6
7
|
|
|
7
8
|
export type Kind = RoutineEntry["kind"];
|
|
8
9
|
|
|
@@ -17,6 +18,7 @@ export function kindMeta(): Record<Kind, { label: string; desc: string; icon: ty
|
|
|
17
18
|
super_agent: { label: t("agents_ui.kind_super_agent"), desc: t("agents_ui.kind_super_agent_desc"), icon: Crown },
|
|
18
19
|
telegram: { label: t("agents_ui.kind_telegram"), desc: t("agents_ui.kind_telegram_desc"), icon: Send },
|
|
19
20
|
shell: { label: t("agents_ui.kind_shell"), desc: t("agents_ui.kind_shell_desc"), icon: Terminal },
|
|
21
|
+
watch: { label: t("agents_ui.kind_watch"), desc: t("agents_ui.kind_watch_desc"), icon: Eye },
|
|
20
22
|
heartbeat: { label: t("agents_ui.kind_heartbeat"), desc: t("agents_ui.kind_heartbeat_desc"), icon: Heart },
|
|
21
23
|
};
|
|
22
24
|
}
|
|
@@ -49,16 +51,23 @@ export function scheduleHuman(s?: string): string {
|
|
|
49
51
|
return t("agents_ui.every_v", { v });
|
|
50
52
|
}
|
|
51
53
|
if (s.startsWith("once:")) return `once · ${new Date(s.slice(5)).toLocaleString()}`;
|
|
52
|
-
if (s.
|
|
53
|
-
|
|
54
|
+
if (s.trim().toLowerCase() === "manual") return t("agents_ui.sched_manual");
|
|
55
|
+
// Cron, read as a sentence. `cron · 0 9 * * *` was not a translation of
|
|
56
|
+
// anything — it just moved the expression behind a label. The leading "cron"
|
|
57
|
+
// word is tolerated because this editor used to write it.
|
|
58
|
+
const expr = s.replace(/^cron\s+/i, "");
|
|
59
|
+
return describeCron(expr, t as never) || expr;
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
export function schedPresets() {
|
|
57
63
|
return [
|
|
58
64
|
{ label: t("agents_ui.preset_every_10m"), value: "every:10m" },
|
|
59
65
|
{ label: t("agents_ui.preset_hourly"), value: "every:1h" },
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
// BARE cron, not `cron <expr>`: core parses the expression itself, and the
|
|
67
|
+
// labelled form used to come back invalid — so these two presets built
|
|
68
|
+
// routines that never ran.
|
|
69
|
+
{ label: t("agents_ui.preset_daily_9am"), value: "0 9 * * *" },
|
|
70
|
+
{ label: t("agents_ui.preset_weekdays_9am"), value: "0 9 * * 1-5" },
|
|
62
71
|
];
|
|
63
72
|
}
|
|
64
73
|
|
|
@@ -49,7 +49,7 @@ export function DesktopSettingsPanel() {
|
|
|
49
49
|
const position = cfgView.desktop?.position || "right";
|
|
50
50
|
|
|
51
51
|
const { data: autostart, mutate: mutateAutostart } = useSWR(
|
|
52
|
-
"/desktop/autostart",
|
|
52
|
+
"/api/desktop/autostart",
|
|
53
53
|
() => Desktop.autostartGet(),
|
|
54
54
|
);
|
|
55
55
|
|
|
@@ -48,7 +48,7 @@ export function MemoryPanel() {
|
|
|
48
48
|
const toast = useToast();
|
|
49
49
|
const { config, isLoading, patch } = useGlobalConfig();
|
|
50
50
|
const { data: providers, mutate: mutateProviders } = useSWR(
|
|
51
|
-
"/embeddings/providers",
|
|
51
|
+
"/api/embeddings/providers",
|
|
52
52
|
() => Embeddings.providers()
|
|
53
53
|
);
|
|
54
54
|
const [busy, setBusy] = useState(false);
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { ThumbsDown, ThumbsUp, Info } from "lucide-react";
|
|
3
|
+
import { Section } from "../Section";
|
|
4
|
+
import { Badge, Button, Empty, Field, Input, Loading, Switch } from "../ui";
|
|
5
|
+
import { useToast } from "../Toast";
|
|
6
|
+
import { useNudges, useNudgePolicy } from "../../hooks/useNudges";
|
|
7
|
+
import { NudgesApi, type NudgePolicy } from "../../lib/api/nudges";
|
|
8
|
+
import { t } from "../../i18n";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The interruption budget — how often APX may speak unprompted.
|
|
12
|
+
*
|
|
13
|
+
* Two halves that belong together: the rule, and the record of what the rule
|
|
14
|
+
* let through. Showing the ledger next to the dial is the point — someone
|
|
15
|
+
* deciding "is three a day too many?" needs to see the three.
|
|
16
|
+
*/
|
|
17
|
+
export function NudgePanel() {
|
|
18
|
+
const toast = useToast();
|
|
19
|
+
const { policy, source, isLoading, mutate } = useNudgePolicy();
|
|
20
|
+
const { entries, stats, mutate: mutateLedger } = useNudges(30);
|
|
21
|
+
|
|
22
|
+
const [draft, setDraft] = useState<NudgePolicy | null>(null);
|
|
23
|
+
const [busy, setBusy] = useState(false);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (policy) setDraft({ ...policy });
|
|
27
|
+
}, [policy]);
|
|
28
|
+
|
|
29
|
+
if (isLoading || !draft) return <Loading />;
|
|
30
|
+
|
|
31
|
+
const save = async () => {
|
|
32
|
+
setBusy(true);
|
|
33
|
+
try {
|
|
34
|
+
await NudgesApi.setPolicy(draft);
|
|
35
|
+
await mutate();
|
|
36
|
+
toast.success(t("settings.nudge.saved"));
|
|
37
|
+
} catch (e) {
|
|
38
|
+
toast.error((e as Error).message);
|
|
39
|
+
} finally {
|
|
40
|
+
setBusy(false);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const rate = async (id: string, useful: boolean) => {
|
|
45
|
+
try {
|
|
46
|
+
await NudgesApi.feedback(id, useful);
|
|
47
|
+
await mutateLedger();
|
|
48
|
+
} catch (e) {
|
|
49
|
+
toast.error((e as Error).message);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const num = (key: keyof NudgePolicy, label: string, hint?: string) => (
|
|
54
|
+
<Field label={label} hint={hint}>
|
|
55
|
+
<Input
|
|
56
|
+
type="number"
|
|
57
|
+
min={0}
|
|
58
|
+
value={String(draft[key] ?? 0)}
|
|
59
|
+
disabled={!draft.enabled}
|
|
60
|
+
onChange={(e) => setDraft({ ...draft, [key]: Number(e.target.value) || 0 })}
|
|
61
|
+
/>
|
|
62
|
+
</Field>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const left = draft.daily_max > 0 ? Math.max(0, draft.daily_max - (stats?.today ?? 0)) : "∞";
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className="flex flex-col gap-4" data-testid="nudge-panel">
|
|
69
|
+
<Section title={t("settings.nudge.title")} description={t("settings.nudge.subtitle")}>
|
|
70
|
+
<div className="mb-3 flex items-start gap-2 rounded-md border border-border bg-muted/40 p-3 text-sm">
|
|
71
|
+
<Info size={16} className="mt-0.5 shrink-0 opacity-70" />
|
|
72
|
+
<span>
|
|
73
|
+
{draft.enabled
|
|
74
|
+
? t("settings.nudge.on_hint")
|
|
75
|
+
.replace("{{sent}}", String(stats?.today ?? 0))
|
|
76
|
+
.replace("{{left}}", String(left))
|
|
77
|
+
: t("settings.nudge.off_hint")}
|
|
78
|
+
{source.length ? (
|
|
79
|
+
<span className="ml-1 opacity-60">
|
|
80
|
+
({t("settings.nudge.source")}: {source.join(" → ")})
|
|
81
|
+
</span>
|
|
82
|
+
) : null}
|
|
83
|
+
</span>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div className="mb-4">
|
|
87
|
+
<Switch
|
|
88
|
+
checked={draft.enabled}
|
|
89
|
+
onChange={(v) => setDraft({ ...draft, enabled: v })}
|
|
90
|
+
label={t("settings.nudge.enabled")}
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div className="grid gap-3 sm:grid-cols-2">
|
|
95
|
+
{num("daily_max", t("settings.nudge.daily_max"), t("settings.nudge.daily_max_hint"))}
|
|
96
|
+
<Field label={t("settings.nudge.quiet_hours")} hint={t("settings.nudge.quiet_hours_hint")}>
|
|
97
|
+
<Input
|
|
98
|
+
value={draft.quiet_hours ?? ""}
|
|
99
|
+
placeholder="22:00-07:30"
|
|
100
|
+
disabled={!draft.enabled}
|
|
101
|
+
onChange={(e) => setDraft({ ...draft, quiet_hours: e.target.value })}
|
|
102
|
+
/>
|
|
103
|
+
</Field>
|
|
104
|
+
{num("cooldown_minutes", t("settings.nudge.cooldown"))}
|
|
105
|
+
{num("project_cooldown_minutes", t("settings.nudge.project_cooldown"))}
|
|
106
|
+
{num("kind_cooldown_minutes", t("settings.nudge.kind_cooldown"))}
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div className="mt-3">
|
|
110
|
+
<Switch
|
|
111
|
+
checked={draft.critical_bypasses_budget}
|
|
112
|
+
onChange={(v) => setDraft({ ...draft, critical_bypasses_budget: v })}
|
|
113
|
+
label={t("settings.nudge.critical_bypass")}
|
|
114
|
+
disabled={!draft.enabled}
|
|
115
|
+
/>
|
|
116
|
+
<p className="mt-1 text-[11px] text-muted-foreground/70">
|
|
117
|
+
{t("settings.nudge.critical_bypass_hint")}
|
|
118
|
+
</p>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<div className="mt-4">
|
|
122
|
+
<Button variant="primary" loading={busy} onClick={save}>
|
|
123
|
+
{t("common.save")}
|
|
124
|
+
</Button>
|
|
125
|
+
</div>
|
|
126
|
+
</Section>
|
|
127
|
+
|
|
128
|
+
<Section title={t("settings.nudge.log_title")} description={t("settings.nudge.log_subtitle")}>
|
|
129
|
+
{!entries.length ? (
|
|
130
|
+
<Empty>{t("settings.nudge.log_empty")}</Empty>
|
|
131
|
+
) : (
|
|
132
|
+
<ul className="flex flex-col gap-2" data-testid="nudge-log">
|
|
133
|
+
{entries.map((e) => (
|
|
134
|
+
<li
|
|
135
|
+
key={e.id}
|
|
136
|
+
className="flex items-start gap-3 rounded-md border border-border bg-muted/20 p-2.5 text-sm"
|
|
137
|
+
>
|
|
138
|
+
<span className="min-w-0 flex-1">
|
|
139
|
+
<span className="flex flex-wrap items-center gap-2">
|
|
140
|
+
<Badge>{e.kind}</Badge>
|
|
141
|
+
<span className="text-xs opacity-55">
|
|
142
|
+
{String(e.at).replace("T", " ").slice(0, 16)}
|
|
143
|
+
</span>
|
|
144
|
+
{e.bypassed_budget ? (
|
|
145
|
+
<Badge tone="warning">{t("settings.nudge.bypass")}</Badge>
|
|
146
|
+
) : null}
|
|
147
|
+
</span>
|
|
148
|
+
<span className="mt-1 block line-clamp-2 opacity-80">{e.preview}</span>
|
|
149
|
+
</span>
|
|
150
|
+
|
|
151
|
+
{/* Rating is available for as long as the entry is on file, not
|
|
152
|
+
only in the chat where the buttons were. Retrospect is when
|
|
153
|
+
people actually notice a pattern was noise. */}
|
|
154
|
+
<span className="flex shrink-0 items-center gap-1">
|
|
155
|
+
<button
|
|
156
|
+
type="button"
|
|
157
|
+
aria-label={t("settings.nudge.useful")}
|
|
158
|
+
onClick={() => rate(e.id, true)}
|
|
159
|
+
className={`rounded p-1.5 transition hover:bg-muted ${
|
|
160
|
+
e.feedback?.useful === true ? "text-emerald-500" : "opacity-40"
|
|
161
|
+
}`}
|
|
162
|
+
>
|
|
163
|
+
<ThumbsUp size={14} />
|
|
164
|
+
</button>
|
|
165
|
+
<button
|
|
166
|
+
type="button"
|
|
167
|
+
aria-label={t("settings.nudge.noise")}
|
|
168
|
+
onClick={() => rate(e.id, false)}
|
|
169
|
+
className={`rounded p-1.5 transition hover:bg-muted ${
|
|
170
|
+
e.feedback?.useful === false ? "text-red-500" : "opacity-40"
|
|
171
|
+
}`}
|
|
172
|
+
>
|
|
173
|
+
<ThumbsDown size={14} />
|
|
174
|
+
</button>
|
|
175
|
+
</span>
|
|
176
|
+
</li>
|
|
177
|
+
))}
|
|
178
|
+
</ul>
|
|
179
|
+
)}
|
|
180
|
+
</Section>
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
import { AlertTriangle, CheckCircle2, Info } from "lucide-react";
|
|
3
3
|
import { Section } from "../Section";
|
|
4
|
-
import { Badge, Button, Dialog, Empty, Field, Input, Loading } from "../ui";
|
|
4
|
+
import { Badge, Button, Dialog, Empty, Field, Input, Loading, Switch } from "../ui";
|
|
5
5
|
import { UiSelect } from "../UiSelect";
|
|
6
6
|
import { useToast } from "../Toast";
|
|
7
7
|
import { useProfiles, useProfile, useProfileDoctor } from "../../hooks/useProfiles";
|
|
8
8
|
import { ProfilesApi, type ProfileSchemaProp } from "../../lib/api/profiles";
|
|
9
|
+
import { CronPicker } from "../cron/CronPicker";
|
|
9
10
|
import { t } from "../../i18n";
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -15,6 +16,11 @@ import { t } from "../../i18n";
|
|
|
15
16
|
* Identity), nor with configuration profiles. With none active, APX behaves
|
|
16
17
|
* exactly as it always has, and the panel says so rather than looking broken.
|
|
17
18
|
*/
|
|
19
|
+
/** Schema keys whose value is a five-field cron expression. */
|
|
20
|
+
function isCronKey(key: string): boolean {
|
|
21
|
+
return /(^|_)schedule$/.test(key) || /_cron$/.test(key);
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
export function ProfilePanel() {
|
|
19
25
|
const toast = useToast();
|
|
20
26
|
const { active, profiles, isLoading, mutate } = useProfiles();
|
|
@@ -143,16 +149,25 @@ export function ProfilePanel() {
|
|
|
143
149
|
)}
|
|
144
150
|
|
|
145
151
|
{profile ? (
|
|
146
|
-
<div className="mt-4 flex flex-wrap items-center gap-
|
|
147
|
-
{
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
<div className="mt-4 flex flex-wrap items-center gap-3">
|
|
153
|
+
{/* A switch, like every other on/off in Settings (Engines, Skills,
|
|
154
|
+
Desktop autostart). The red "Deactivate" button read as a
|
|
155
|
+
destructive action — deactivating a profile destroys nothing:
|
|
156
|
+
its settings survive and turning it back on restores them. */}
|
|
157
|
+
<Switch
|
|
158
|
+
checked={!!profile.active}
|
|
159
|
+
disabled={busy}
|
|
160
|
+
label={profile.active ? t("settings.profile.on") : t("settings.profile.off")}
|
|
161
|
+
onChange={(on) => {
|
|
162
|
+
if (on) activate(profile.id, !!active);
|
|
163
|
+
// Switching OFF still confirms: the profile's routines stop
|
|
164
|
+
// with it, and that is worth one deliberate tap.
|
|
165
|
+
else setConfirmOff(true);
|
|
166
|
+
}}
|
|
167
|
+
/>
|
|
168
|
+
{!profile.active && active ? (
|
|
169
|
+
<span className="text-xs opacity-60">{t("settings.profile.replaces_active")}</span>
|
|
170
|
+
) : null}
|
|
156
171
|
<span className="text-xs opacity-60">
|
|
157
172
|
{t("settings.profile.token_cost")}: ~{profile.tokens ?? 0}
|
|
158
173
|
{profile.budget ? ` / ${profile.budget}` : ""}
|
|
@@ -183,7 +198,16 @@ export function ProfilePanel() {
|
|
|
183
198
|
<div className="grid gap-3 sm:grid-cols-2">
|
|
184
199
|
{Object.entries(props).map(([key, def]) => (
|
|
185
200
|
<Field key={key} label={def.title || key} hint={def.description}>
|
|
186
|
-
{
|
|
201
|
+
{/* A schedule is a time and some days, not five
|
|
202
|
+
space-separated fields. Detected by key name because the
|
|
203
|
+
JSON-Schema subset has no "format" for cron. */}
|
|
204
|
+
{isCronKey(key) ? (
|
|
205
|
+
<CronPicker
|
|
206
|
+
value={draft[key] ?? String(def.default ?? "")}
|
|
207
|
+
onChange={(expr) => setDraft({ ...draft, [key]: expr })}
|
|
208
|
+
disabled={!canEdit}
|
|
209
|
+
/>
|
|
210
|
+
) : def.enum ? (
|
|
187
211
|
<UiSelect
|
|
188
212
|
value={draft[key] ?? String(def.default ?? "")}
|
|
189
213
|
onChange={(v) => setDraft({ ...draft, [key]: v })}
|
|
@@ -39,7 +39,7 @@ type NumericKnobs = {
|
|
|
39
39
|
|
|
40
40
|
export function SkillsInspectorPanel() {
|
|
41
41
|
const toast = useToast();
|
|
42
|
-
const { data, mutate, isLoading } = useSWR("/skills/inspector", () => Skills.inspector());
|
|
42
|
+
const { data, mutate, isLoading } = useSWR("/api/skills/inspector", () => Skills.inspector());
|
|
43
43
|
const [busy, setBusy] = useState(false);
|
|
44
44
|
const [probe, setProbe] = useState("");
|
|
45
45
|
const [probeResult, setProbeResult] = useState<InspectTrace | null>(null);
|
|
@@ -128,13 +128,13 @@ export function SkillsManager({ scope: fixedScope, selectable = false }: { scope
|
|
|
128
128
|
const [repoOpen, setRepoOpen] = useState(false);
|
|
129
129
|
const fileRef = useRef<HTMLInputElement>(null);
|
|
130
130
|
|
|
131
|
-
const { data: projects } = useSWR(selectable ? "/projects" : null, () => Projects.list());
|
|
131
|
+
const { data: projects } = useSWR(selectable ? "/api/projects" : null, () => Projects.list());
|
|
132
132
|
const scopeOptions = useMemo(() => [
|
|
133
133
|
{ value: SUPER, label: t("skills_page.scope_super_agent") },
|
|
134
134
|
...(projects ?? []).map((p) => ({ value: p.path, label: p.name || basename(p.path) })),
|
|
135
135
|
], [projects]);
|
|
136
136
|
|
|
137
|
-
const { data, mutate, isLoading } = useSWR(["/skills", scope], () => Skills.list(projectPath));
|
|
137
|
+
const { data, mutate, isLoading } = useSWR(["/api/skills", scope], () => Skills.list(projectPath));
|
|
138
138
|
const skills = useMemo(() => data?.skills ?? [], [data]);
|
|
139
139
|
const onCount = skills.filter((s) => s.enabled !== false).length;
|
|
140
140
|
|
|
@@ -32,7 +32,7 @@ export function TaskDetailPanel({
|
|
|
32
32
|
}) {
|
|
33
33
|
const toast = useToast();
|
|
34
34
|
const navigate = useNavigate();
|
|
35
|
-
const { data: task, isLoading, mutate } = useSWR(`/projects/${pid}/tasks/${taskId}`, () => Tasks.get(pid, taskId));
|
|
35
|
+
const { data: task, isLoading, mutate } = useSWR(`/api/projects/${pid}/tasks/${taskId}`, () => Tasks.get(pid, taskId));
|
|
36
36
|
const [body, setBody] = useState("");
|
|
37
37
|
const [busy, setBusy] = useState(false);
|
|
38
38
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One row of mutually-exclusive filters.
|
|
5
|
+
*
|
|
6
|
+
* Exists so every list page filters the same way and reads the same way.
|
|
7
|
+
* Labels are Capitalised: the chips used to render whatever the state value
|
|
8
|
+
* happened to be ("open", "in review"), which put raw storage vocabulary in
|
|
9
|
+
* the interface.
|
|
10
|
+
*/
|
|
11
|
+
export function FilterChips<T extends string>({
|
|
12
|
+
value,
|
|
13
|
+
options,
|
|
14
|
+
onChange,
|
|
15
|
+
label,
|
|
16
|
+
}: {
|
|
17
|
+
value: T;
|
|
18
|
+
options: { value: T; label: string }[];
|
|
19
|
+
onChange: (v: T) => void;
|
|
20
|
+
label?: string;
|
|
21
|
+
}) {
|
|
22
|
+
return (
|
|
23
|
+
<div className="flex flex-wrap items-center gap-1" role="group" aria-label={label}>
|
|
24
|
+
{options.map((o) => (
|
|
25
|
+
<button
|
|
26
|
+
key={o.value}
|
|
27
|
+
type="button"
|
|
28
|
+
aria-pressed={value === o.value}
|
|
29
|
+
onClick={() => onChange(o.value)}
|
|
30
|
+
className={cn(
|
|
31
|
+
"rounded-md px-2.5 py-1 text-xs font-medium transition-colors",
|
|
32
|
+
value === o.value
|
|
33
|
+
? "bg-accent text-accent-fg"
|
|
34
|
+
: "text-muted-fg hover:bg-muted/50 hover:text-foreground",
|
|
35
|
+
)}
|
|
36
|
+
>
|
|
37
|
+
{capitalise(o.label)}
|
|
38
|
+
</button>
|
|
39
|
+
))}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** First letter up, rest untouched — so "in review" keeps its lowercase w. */
|
|
45
|
+
function capitalise(s: string): string {
|
|
46
|
+
return s ? s.charAt(0).toUpperCase() + s.slice(1) : s;
|
|
47
|
+
}
|
|
@@ -15,6 +15,7 @@ import { Dialog as DialogRoot, DialogContent, DialogHeader, DialogTitle, DialogD
|
|
|
15
15
|
// Re-export the tooltip convenience wrapper so call sites can grab it from the
|
|
16
16
|
// same barrel as Button/Field/etc.: `import { Button, Tip } from "../ui"`.
|
|
17
17
|
export { Tip } from "./ui/tip";
|
|
18
|
+
export { FilterChips } from "./ui/filter-chips";
|
|
18
19
|
|
|
19
20
|
// ── Button ──────────────────────────────────────────────────────────────────
|
|
20
21
|
type Variant = "primary" | "secondary" | "ghost" | "destructive";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback, useRef, useState } from "react";
|
|
2
2
|
import { SuperAgent, Agents, Conversations } from "../lib/api";
|
|
3
|
-
import type { ChatStreamEvent, ChatUsage, ConversationMessage } from "../types/daemon";
|
|
3
|
+
import type { ChatStreamEvent, ChatUsage, ConversationMessage, ToolSummary } from "../types/daemon";
|
|
4
4
|
import { t } from "../i18n";
|
|
5
5
|
|
|
6
6
|
export type ToolStatus = "running" | "done" | "error" | "deduped";
|
|
@@ -37,6 +37,9 @@ export interface ChatMsg {
|
|
|
37
37
|
usage?: ChatUsage;
|
|
38
38
|
/** Operational notes (engine fallbacks, retries, suppressions). */
|
|
39
39
|
notes?: string[];
|
|
40
|
+
/** What a HISTORICAL turn did. Live turns render real ToolCall parts from
|
|
41
|
+
* the stream; replayed ones only have this, recorded at write time. */
|
|
42
|
+
toolSummary?: ToolSummary;
|
|
40
43
|
/** Skill Inspector decision for this turn (when the feature is on): which
|
|
41
44
|
* skills the per-turn RAG loaded inline vs merely hinted. */
|
|
42
45
|
inspector?: {
|
|
@@ -179,6 +182,7 @@ function threadToChatMsgs(messages: ConversationMessage[]): ChatMsg[] {
|
|
|
179
182
|
if (m.agent) turn.agentId = m.agent;
|
|
180
183
|
if (m.agent_name) turn.agent = m.agent_name;
|
|
181
184
|
if (m.model) turn.model = m.model;
|
|
185
|
+
if (m.tool_summary) turn.toolSummary = m.tool_summary;
|
|
182
186
|
if (m.usage) {
|
|
183
187
|
turn.usage = {
|
|
184
188
|
input_tokens: (turn.usage?.input_tokens || 0) + (m.usage.input_tokens || 0),
|
|
@@ -4,7 +4,7 @@ import type { GlobalConfig, SuperAgentConfig } from "../types/daemon";
|
|
|
4
4
|
|
|
5
5
|
export function useGlobalConfig() {
|
|
6
6
|
const { data, error, isLoading, mutate } = useSWR(
|
|
7
|
-
"/admin/config",
|
|
7
|
+
"/api/admin/config",
|
|
8
8
|
() => Admin.config.get(),
|
|
9
9
|
);
|
|
10
10
|
const patch = async (set?: Record<string, unknown>, unset?: string[]) => {
|
|
@@ -17,7 +17,7 @@ export function useGlobalConfig() {
|
|
|
17
17
|
|
|
18
18
|
export function useSuperAgentConfig() {
|
|
19
19
|
const { data, error, isLoading, mutate } = useSWR(
|
|
20
|
-
"/admin/super-agent",
|
|
20
|
+
"/api/admin/super-agent",
|
|
21
21
|
() => Admin.superAgent(),
|
|
22
22
|
);
|
|
23
23
|
return { superAgent: data as SuperAgentConfig | undefined, error, isLoading, mutate };
|
|
@@ -4,7 +4,7 @@ import type { Identity } from "../types/daemon";
|
|
|
4
4
|
|
|
5
5
|
export function useIdentity() {
|
|
6
6
|
const { data, error, isLoading, mutate } = useSWR<Identity>(
|
|
7
|
-
"/identity",
|
|
7
|
+
"/api/identity",
|
|
8
8
|
() => IdentityApi.get(),
|
|
9
9
|
);
|
|
10
10
|
const save = async (patch: Partial<Identity>) => {
|
|
@@ -4,7 +4,7 @@ import { Inbox, type InboxRow } from "../lib/api/inbox";
|
|
|
4
4
|
/** Every agent as a conversation, most recent first, super-agent pinned. */
|
|
5
5
|
export function useInbox(includeEmpty = false) {
|
|
6
6
|
const { data, error, isLoading, mutate } = useSWR<InboxRow[]>(
|
|
7
|
-
`/inbox?include_empty=${includeEmpty ? 1 : 0}`,
|
|
7
|
+
`/api/inbox?include_empty=${includeEmpty ? 1 : 0}`,
|
|
8
8
|
() => Inbox.list(includeEmpty),
|
|
9
9
|
{ refreshInterval: 15_000 },
|
|
10
10
|
);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import useSWR from "swr";
|
|
2
|
+
import { NudgesApi } from "../lib/api/nudges";
|
|
3
|
+
import type { NudgeEntry, NudgePolicy, NudgeStats } from "../lib/api/nudges";
|
|
4
|
+
|
|
5
|
+
/** The ledger of unrequested messages, plus what they add up to. */
|
|
6
|
+
export function useNudges(limit = 50) {
|
|
7
|
+
const { data, error, isLoading, mutate } = useSWR<{
|
|
8
|
+
data: NudgeEntry[];
|
|
9
|
+
meta: { total: number; stats: NudgeStats };
|
|
10
|
+
}>(`/api/nudges?limit=${limit}`, () => NudgesApi.list(limit));
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
entries: data?.data ?? [],
|
|
14
|
+
stats: data?.meta?.stats,
|
|
15
|
+
error,
|
|
16
|
+
isLoading,
|
|
17
|
+
mutate,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** The effective budget, and which layer set each part of it. */
|
|
22
|
+
export function useNudgePolicy() {
|
|
23
|
+
const { data, error, isLoading, mutate } = useSWR<{
|
|
24
|
+
policy: NudgePolicy;
|
|
25
|
+
source: string[];
|
|
26
|
+
defaults: NudgePolicy;
|
|
27
|
+
user_overrides: Partial<NudgePolicy>;
|
|
28
|
+
}>("/api/nudges/policy", () => NudgesApi.policy());
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
policy: data?.policy,
|
|
32
|
+
source: data?.source ?? [],
|
|
33
|
+
userOverrides: data?.user_overrides ?? {},
|
|
34
|
+
error,
|
|
35
|
+
isLoading,
|
|
36
|
+
mutate,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -7,7 +7,7 @@ export function useProfiles() {
|
|
|
7
7
|
const { data, error, isLoading, mutate } = useSWR<{
|
|
8
8
|
active: string | null;
|
|
9
9
|
profiles: ProfileSummary[];
|
|
10
|
-
}>("/profiles", () => ProfilesApi.list());
|
|
10
|
+
}>("/api/profiles", () => ProfilesApi.list());
|
|
11
11
|
|
|
12
12
|
return {
|
|
13
13
|
active: data?.active ?? null,
|
|
@@ -21,7 +21,7 @@ export function useProfiles() {
|
|
|
21
21
|
/** One profile, including its schema, settings and rendered prompt preview. */
|
|
22
22
|
export function useProfile(id: string | null) {
|
|
23
23
|
const { data, error, isLoading, mutate } = useSWR<ProfileDetail>(
|
|
24
|
-
id ? `/profiles/${id}` : null,
|
|
24
|
+
id ? `/api/profiles/${id}` : null,
|
|
25
25
|
() => ProfilesApi.get(id as string),
|
|
26
26
|
);
|
|
27
27
|
return { profile: data, error, isLoading, mutate };
|
|
@@ -30,7 +30,7 @@ export function useProfile(id: string | null) {
|
|
|
30
30
|
/** Health of the active profile (or a named one). */
|
|
31
31
|
export function useProfileDoctor(id: string | null) {
|
|
32
32
|
const { data, error, isLoading, mutate } = useSWR<ProfileDoctor>(
|
|
33
|
-
id ? `/profiles/doctor?id=${id}` : "/profiles/doctor",
|
|
33
|
+
id ? `/api/profiles/doctor?id=${id}` : "/api/profiles/doctor",
|
|
34
34
|
() => ProfilesApi.doctor(id || undefined),
|
|
35
35
|
);
|
|
36
36
|
return { doctor: data, error, isLoading, mutate };
|
|
@@ -6,7 +6,7 @@ import type { ProjectEntry } from "../types/daemon";
|
|
|
6
6
|
/** Project list, sorted so the default workspace (id=0) is first. */
|
|
7
7
|
export function useProjects() {
|
|
8
8
|
const { data, error, isLoading, mutate } = useSWR<ProjectEntry[]>(
|
|
9
|
-
"/projects",
|
|
9
|
+
"/api/projects",
|
|
10
10
|
() => Projects.list(),
|
|
11
11
|
{ refreshInterval: REFRESH.projects },
|
|
12
12
|
);
|
|
@@ -4,7 +4,7 @@ import { REFRESH } from "../constants";
|
|
|
4
4
|
|
|
5
5
|
export function useTelegramStatus() {
|
|
6
6
|
const { data, error, isLoading, mutate } = useSWR(
|
|
7
|
-
"/telegram/status",
|
|
7
|
+
"/api/telegram/status",
|
|
8
8
|
() => Telegram.status(),
|
|
9
9
|
{ refreshInterval: REFRESH.telegramStatus },
|
|
10
10
|
);
|
|
@@ -13,7 +13,7 @@ export function useTelegramStatus() {
|
|
|
13
13
|
|
|
14
14
|
export function useTelegramChannels() {
|
|
15
15
|
const { data, error, isLoading, mutate } = useSWR(
|
|
16
|
-
"/telegram/channels",
|
|
16
|
+
"/api/telegram/channels",
|
|
17
17
|
() => Telegram.channels.list(),
|
|
18
18
|
);
|
|
19
19
|
return { channels: data?.channels || [], error, isLoading, mutate };
|
|
@@ -21,7 +21,7 @@ export function useTelegramChannels() {
|
|
|
21
21
|
|
|
22
22
|
export function useTelegramContacts() {
|
|
23
23
|
const { data, error, isLoading, mutate } = useSWR(
|
|
24
|
-
"/telegram/contacts",
|
|
24
|
+
"/api/telegram/contacts",
|
|
25
25
|
() => Telegram.contacts.list(),
|
|
26
26
|
);
|
|
27
27
|
return {
|