@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,10 +1,14 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
|
+
import { Plus } from "lucide-react";
|
|
2
3
|
import { useNavigate } from "react-router-dom";
|
|
3
4
|
import { Tasks } from "../../lib/api";
|
|
4
5
|
import type { TaskStatus } from "../../types/daemon";
|
|
5
6
|
import { Section } from "../../components/Section";
|
|
6
7
|
import { PagedList, usePagedQuery } from "../../components/Pager";
|
|
7
|
-
import { Badge, Button, Empty, Loading } from "../../components/ui";
|
|
8
|
+
import { Badge, Button, Dialog, Empty, Field, FilterChips, Input, Loading } from "../../components/ui";
|
|
9
|
+
import { UiSelect } from "../../components/UiSelect";
|
|
10
|
+
import { useProjects } from "../../hooks/useProjects";
|
|
11
|
+
import { useToast } from "../../components/Toast";
|
|
8
12
|
import { t } from "../../i18n";
|
|
9
13
|
|
|
10
14
|
// All projects' tasks, aggregated (GET /tasks), server-paginated.
|
|
@@ -15,38 +19,79 @@ export function GlobalTasksTab() {
|
|
|
15
19
|
// right now" is not "what is open". Only meaningful for open tasks.
|
|
16
20
|
const [status, setStatus] = useState<TaskStatus | "">("");
|
|
17
21
|
const effectiveStatus = state === "open" ? status : "";
|
|
22
|
+
// The per-project Tasks screen has always had an inline add form; this one
|
|
23
|
+
// did not, so on the base workspace the only way to file a task was to ask
|
|
24
|
+
// the agent. A picker is the price of the cross-project view.
|
|
25
|
+
const [adding, setAdding] = useState(false);
|
|
26
|
+
const [title, setTitle] = useState("");
|
|
27
|
+
const [target, setTarget] = useState("");
|
|
28
|
+
const [due, setDue] = useState("");
|
|
29
|
+
const [busy, setBusy] = useState(false);
|
|
30
|
+
const { projects } = useProjects();
|
|
31
|
+
const toast = useToast();
|
|
32
|
+
|
|
18
33
|
const paged = usePagedQuery({
|
|
19
|
-
key: `/tasks?state=${state}&status=${effectiveStatus}`,
|
|
34
|
+
key: `/api/tasks?state=${state}&status=${effectiveStatus}`,
|
|
20
35
|
fetchPage: (limit, offset) => Tasks.globalPage({ state, limit, offset, status: effectiveStatus }),
|
|
21
36
|
resetKey: `${state}|${effectiveStatus}`,
|
|
22
37
|
});
|
|
23
38
|
|
|
39
|
+
const create = async () => {
|
|
40
|
+
if (!title.trim() || !target) return;
|
|
41
|
+
setBusy(true);
|
|
42
|
+
try {
|
|
43
|
+
await Tasks.add(String(target), { title: title.trim(), due: due || null });
|
|
44
|
+
await paged.mutate();
|
|
45
|
+
setAdding(false);
|
|
46
|
+
setTitle(""); setDue("");
|
|
47
|
+
} catch (e) {
|
|
48
|
+
toast.error((e as Error).message);
|
|
49
|
+
} finally {
|
|
50
|
+
setBusy(false);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
24
54
|
return (
|
|
25
55
|
<Section
|
|
26
56
|
fullHeight
|
|
27
57
|
title={t("project.global_tasks.title")}
|
|
28
58
|
description={t("project.global_tasks.subtitle")}
|
|
29
59
|
action={
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
))}
|
|
34
|
-
|
|
60
|
+
<Button
|
|
61
|
+
size="sm"
|
|
62
|
+
variant="primary"
|
|
63
|
+
onClick={() => { setTarget(String(projects[0]?.id ?? "")); setAdding(true); }}
|
|
64
|
+
>
|
|
65
|
+
<Plus size={14} /> {t("project.global_tasks.add")}
|
|
66
|
+
</Button>
|
|
67
|
+
}
|
|
68
|
+
filters={
|
|
69
|
+
<>
|
|
70
|
+
<FilterChips
|
|
71
|
+
value={state}
|
|
72
|
+
onChange={setState}
|
|
73
|
+
label={t("project.global_tasks.title")}
|
|
74
|
+
options={(["open", "done", "dropped", "all"] as const).map((s) => ({ value: s, label: s }))}
|
|
75
|
+
/>
|
|
76
|
+
{state === "open" ? (
|
|
77
|
+
<>
|
|
78
|
+
<span className="mx-1 h-4 w-px bg-border" aria-hidden />
|
|
79
|
+
<FilterChips
|
|
80
|
+
value={status}
|
|
81
|
+
onChange={setStatus}
|
|
82
|
+
label={t("project.global_tasks.any_status")}
|
|
83
|
+
options={[
|
|
84
|
+
{ value: "" as const, label: t("project.global_tasks.any_status") },
|
|
85
|
+
...(["pending", "running", "in_review", "blocked"] as const).map((s) => ({
|
|
86
|
+
value: s, label: s.replace("_", " "),
|
|
87
|
+
})),
|
|
88
|
+
]}
|
|
89
|
+
/>
|
|
90
|
+
</>
|
|
91
|
+
) : null}
|
|
92
|
+
</>
|
|
35
93
|
}
|
|
36
94
|
>
|
|
37
|
-
{state === "open" ? (
|
|
38
|
-
<div className="mb-3 flex flex-wrap gap-1">
|
|
39
|
-
<Button size="sm" variant={status === "" ? "primary" : "ghost"} onClick={() => setStatus("")}>
|
|
40
|
-
{t("project.global_tasks.any_status")}
|
|
41
|
-
</Button>
|
|
42
|
-
{(["pending", "running", "in_review", "blocked"] as const).map((s) => (
|
|
43
|
-
<Button key={s} size="sm" variant={status === s ? "primary" : "ghost"} onClick={() => setStatus(s)}>
|
|
44
|
-
{s.replace("_", " ")}
|
|
45
|
-
</Button>
|
|
46
|
-
))}
|
|
47
|
-
</div>
|
|
48
|
-
) : null}
|
|
49
|
-
|
|
50
95
|
{paged.isLoading && <Loading />}
|
|
51
96
|
{!paged.isLoading && paged.total === 0 && <Empty>{t("project.global_tasks.empty")}</Empty>}
|
|
52
97
|
<PagedList paged={paged} fullHeight>
|
|
@@ -73,6 +118,44 @@ export function GlobalTasksTab() {
|
|
|
73
118
|
))}
|
|
74
119
|
</ul>
|
|
75
120
|
</PagedList>
|
|
121
|
+
|
|
122
|
+
<Dialog
|
|
123
|
+
open={adding}
|
|
124
|
+
onClose={() => setAdding(false)}
|
|
125
|
+
title={t("project.global_tasks.add_title")}
|
|
126
|
+
footer={
|
|
127
|
+
<>
|
|
128
|
+
<Button onClick={() => setAdding(false)}>{t("common.cancel")}</Button>
|
|
129
|
+
<Button variant="primary" loading={busy} disabled={!title.trim() || !target} onClick={create}>
|
|
130
|
+
{t("project.global_tasks.add")}
|
|
131
|
+
</Button>
|
|
132
|
+
</>
|
|
133
|
+
}
|
|
134
|
+
>
|
|
135
|
+
<div className="flex flex-col gap-3 p-5">
|
|
136
|
+
<Field label={t("project.global_tasks.field_title")}>
|
|
137
|
+
<Input
|
|
138
|
+
value={title}
|
|
139
|
+
onChange={(e) => setTitle(e.target.value)}
|
|
140
|
+
autoFocus
|
|
141
|
+
onKeyDown={(e) => { if (e.key === "Enter" && title.trim() && target) create(); }}
|
|
142
|
+
/>
|
|
143
|
+
</Field>
|
|
144
|
+
{/* Required, unlike the per-project screen: a cross-project view has
|
|
145
|
+
no "here" to default to, and guessing one would file the task
|
|
146
|
+
somewhere the user did not look. */}
|
|
147
|
+
<Field label={t("project.global_tasks.field_project")}>
|
|
148
|
+
<UiSelect
|
|
149
|
+
value={String(target)}
|
|
150
|
+
onChange={setTarget}
|
|
151
|
+
options={projects.map((p) => ({ value: String(p.id), label: p.name || p.path }))}
|
|
152
|
+
/>
|
|
153
|
+
</Field>
|
|
154
|
+
<Field label={t("project.global_tasks.field_due")}>
|
|
155
|
+
<Input type="date" value={due} onChange={(e) => setDue(e.target.value)} />
|
|
156
|
+
</Field>
|
|
157
|
+
</div>
|
|
158
|
+
</Dialog>
|
|
76
159
|
</Section>
|
|
77
160
|
);
|
|
78
161
|
}
|
|
@@ -23,6 +23,16 @@ function actorLabel(m: MessageEntry): string {
|
|
|
23
23
|
return m.agent_slug || m.actor_id || m.author || m.actor_kind || "—";
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/** Structured lifecycle events APX records as they happen (a routine created,
|
|
27
|
+
* a routine updated). Returns the label to badge, or null for ordinary rows. */
|
|
28
|
+
function lifecycleEvent(m: MessageEntry): string | null {
|
|
29
|
+
const e = m.meta?.event;
|
|
30
|
+
if (typeof e !== "string") return null;
|
|
31
|
+
if (e === "routine_created") return t("logs.event_routine_created");
|
|
32
|
+
if (e === "routine_updated") return t("logs.event_routine_updated");
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
/** Model that produced this record — persisted in meta by every channel that
|
|
27
37
|
* runs an agent turn. Absent on user/system rows and on pre-1.74 history. */
|
|
28
38
|
function modelOf(m: MessageEntry): string | null {
|
|
@@ -56,6 +66,11 @@ function LogRow({ m }: { m: MessageEntry }) {
|
|
|
56
66
|
<span className="font-mono">{fmtTs(m.ts)}</span>
|
|
57
67
|
<Badge tone="info">{m.channel}</Badge>
|
|
58
68
|
{m.type && <Badge>{m.type}</Badge>}
|
|
69
|
+
{/* Lifecycle events get their own chip rather than blending into the
|
|
70
|
+
body text. "A routine now exists" is the kind of thing people
|
|
71
|
+
scroll back looking for, and a green badge is findable in a way a
|
|
72
|
+
sentence in a log line is not. */}
|
|
73
|
+
{lifecycleEvent(m) && <Badge tone="success">{lifecycleEvent(m)}</Badge>}
|
|
59
74
|
<span className="font-medium text-foreground">{actorLabel(m)}</span>
|
|
60
75
|
{model && <span className="font-mono text-[11px] text-sky-400/90">{model}</span>}
|
|
61
76
|
{tokens !== null && <span className="font-mono text-[11px]">{tokens} tok</span>}
|
|
@@ -79,7 +94,7 @@ function LogRow({ m }: { m: MessageEntry }) {
|
|
|
79
94
|
|
|
80
95
|
function DaemonErrors() {
|
|
81
96
|
const [open, setOpen] = useState(false);
|
|
82
|
-
const logs = useSWR(open ? "/admin/logs?errors" : null, () => Admin.logs("errors", 200));
|
|
97
|
+
const logs = useSWR(open ? "/api/admin/logs?errors" : null, () => Admin.logs("errors", 200));
|
|
83
98
|
const entries = logs.data?.entries || [];
|
|
84
99
|
return (
|
|
85
100
|
<details className="mb-3 rounded-lg border border-border bg-muted/20" onToggle={(e) => setOpen((e.target as HTMLDetailsElement).open)}>
|
|
@@ -116,8 +131,8 @@ export function LogsTab({ pid }: { pid?: string }) {
|
|
|
116
131
|
const ch = channel.trim() || undefined;
|
|
117
132
|
|
|
118
133
|
const key = isGlobal
|
|
119
|
-
? `/messages/global?channel=${ch ?? ""}`
|
|
120
|
-
: `/projects/${pid}/messages?channel=${ch ?? ""}`;
|
|
134
|
+
? `/api/messages/global?channel=${ch ?? ""}`
|
|
135
|
+
: `/api/projects/${pid}/messages?channel=${ch ?? ""}`;
|
|
121
136
|
const list = useSWR<MessageEntry[]>(key, () =>
|
|
122
137
|
isGlobal
|
|
123
138
|
? Messages.global({ channel: ch, limit: 300 })
|
|
@@ -34,7 +34,7 @@ export function SessionsTab({ pid }: { pid?: string } = {}) {
|
|
|
34
34
|
}, [input]);
|
|
35
35
|
|
|
36
36
|
const paged = usePagedQuery<SessionRow>({
|
|
37
|
-
key: `/sessions?engine=${engine}&q=${query}&deep=${deep ? 1 : 0}&cwd=${cwd || ""}`,
|
|
37
|
+
key: `/api/sessions?engine=${engine}&q=${query}&deep=${deep ? 1 : 0}&cwd=${cwd || ""}`,
|
|
38
38
|
fetchPage: (limit, offset) =>
|
|
39
39
|
Sessions.page({ engine: engine || undefined, q: query || undefined, deep, cwd, limit, offset }),
|
|
40
40
|
resetKey: `${engine}|${query}|${deep ? 1 : 0}|${cwd || ""}`,
|
|
@@ -50,7 +50,7 @@ function ResizeHandleH() {
|
|
|
50
50
|
// what the session changed vs its git baseline.
|
|
51
51
|
export function CodeScreen() {
|
|
52
52
|
const toast = useToast();
|
|
53
|
-
const projects = useSWR("/projects", () => Projects.list());
|
|
53
|
+
const projects = useSWR("/api/projects", () => Projects.list());
|
|
54
54
|
const projectList = useMemo(() => projects.data || [], [projects.data]);
|
|
55
55
|
|
|
56
56
|
const [pid, setPid] = useState<string>("");
|
|
@@ -12,7 +12,7 @@ import { t } from "../../i18n";
|
|
|
12
12
|
// shortcut, appearance, activation) live in Settings → Desktop.
|
|
13
13
|
export function DesktopScreen() {
|
|
14
14
|
const { data: msgs, isLoading: msgsLoading, mutate: mutateMsgs } = useSWR(
|
|
15
|
-
"/messages/global?channel=desktop",
|
|
15
|
+
"/api/messages/global?channel=desktop",
|
|
16
16
|
() => fetchDesktopMessages(40),
|
|
17
17
|
{ refreshInterval: 8000 },
|
|
18
18
|
);
|
|
@@ -23,7 +23,7 @@ export function VoiceScreen() {
|
|
|
23
23
|
isLoading: provLoading,
|
|
24
24
|
error: provError,
|
|
25
25
|
mutate: mutateProviders,
|
|
26
|
-
} = useSWR("/tts/providers", () => Voice.providers());
|
|
26
|
+
} = useSWR("/api/tts/providers", () => Voice.providers());
|
|
27
27
|
|
|
28
28
|
// editing holds the engine id being configured. "__new__" opens the modal in
|
|
29
29
|
// "create custom provider" mode.
|
|
@@ -61,12 +61,12 @@ export function AgentDetailScreen({ pid }: { pid: string }) {
|
|
|
61
61
|
const [tab, setTab] = useState<TabKey>("overview");
|
|
62
62
|
const TABS = buildTabs();
|
|
63
63
|
|
|
64
|
-
const detail = useSWR(`/projects/${pid}/agents/${slug}`, () => Agents.get(pid, slug));
|
|
65
|
-
const agents = useSWR(`/projects/${pid}/agents`, () => Agents.list(pid));
|
|
66
|
-
const routines = useSWR(`/projects/${pid}/routines`, () => Routines.list(pid));
|
|
67
|
-
const records = useSWR(`/projects/${pid}/messages?agent=${slug}`, () => Messages.project(pid, { agent: slug, limit: 200 }));
|
|
68
|
-
const threads = useSWR(`/projects/${pid}/agents/${slug}/conversations`, () => Conversations.list(pid, slug));
|
|
69
|
-
const tasks = useSWR(`/projects/${pid}/tasks?all`, () => Tasks.list(pid, "all"));
|
|
64
|
+
const detail = useSWR(`/api/projects/${pid}/agents/${slug}`, () => Agents.get(pid, slug));
|
|
65
|
+
const agents = useSWR(`/api/projects/${pid}/agents`, () => Agents.list(pid));
|
|
66
|
+
const routines = useSWR(`/api/projects/${pid}/routines`, () => Routines.list(pid));
|
|
67
|
+
const records = useSWR(`/api/projects/${pid}/messages?agent=${slug}`, () => Messages.project(pid, { agent: slug, limit: 200 }));
|
|
68
|
+
const threads = useSWR(`/api/projects/${pid}/agents/${slug}/conversations`, () => Conversations.list(pid, slug));
|
|
69
|
+
const tasks = useSWR(`/api/projects/${pid}/tasks?all`, () => Tasks.list(pid, "all"));
|
|
70
70
|
|
|
71
71
|
const a = detail.data;
|
|
72
72
|
const myRoutines = routinesForAgent(routines.data || [], slug);
|
|
@@ -318,7 +318,7 @@ function Stat({ label, value, icon: I }: { label: string; value: number; icon: t
|
|
|
318
318
|
// bare textarea.
|
|
319
319
|
function MemoryEditor({ pid, slug, onSaved }: { pid: string; slug: string; onSaved: () => void }) {
|
|
320
320
|
const toast = useToast();
|
|
321
|
-
const body = useSWR(`/memory/${pid}/agent:${slug}`, () => Agents.memory.get(pid, slug).then((r) => r.body));
|
|
321
|
+
const body = useSWR(`/api/memory/${pid}/agent:${slug}`, () => Agents.memory.get(pid, slug).then((r) => r.body));
|
|
322
322
|
|
|
323
323
|
const file = useMemo<FileContent | null>(() => {
|
|
324
324
|
if (body.data === undefined) return null;
|
|
@@ -425,7 +425,7 @@ function Field2({ label, value }: { label: string; value: string }) {
|
|
|
425
425
|
}
|
|
426
426
|
|
|
427
427
|
function ToolsPicker({ value, onChange }: { value: string; onChange: (v: string) => void }) {
|
|
428
|
-
const cat = useSWR("/tools", () => Tools.list());
|
|
428
|
+
const cat = useSWR("/api/tools", () => Tools.list());
|
|
429
429
|
const selected = csv(value);
|
|
430
430
|
const catalog = cat.data || [];
|
|
431
431
|
const toggle = (name: string) => {
|
|
@@ -89,7 +89,7 @@ function buildTree(agents: AgentEntry[]) {
|
|
|
89
89
|
export function AgentsTab({ pid }: { pid: string }) {
|
|
90
90
|
const navigate = useNavigate();
|
|
91
91
|
const toast = useToast();
|
|
92
|
-
const list = useSWR(`/projects/${pid}/agents?stats=1`, () => Agents.list(pid, { stats: true }));
|
|
92
|
+
const list = useSWR(`/api/projects/${pid}/agents?stats=1`, () => Agents.list(pid, { stats: true }));
|
|
93
93
|
const [view, setView] = useState<"hierarchy" | "list">("hierarchy");
|
|
94
94
|
const [creating, setCreating] = useState(false);
|
|
95
95
|
|
|
@@ -154,7 +154,7 @@ function ImportVaultDialog({
|
|
|
154
154
|
open, onClose, onImported, pid, existing,
|
|
155
155
|
}: { open: boolean; onClose: () => void; onImported: () => void; pid: string; existing: string[] }) {
|
|
156
156
|
const toast = useToast();
|
|
157
|
-
const vault = useSWR(open ? "/agents/vault" : null, () => Agents.vault());
|
|
157
|
+
const vault = useSWR(open ? "/api/agents/vault" : null, () => Agents.vault());
|
|
158
158
|
const [busy, setBusy] = useState("");
|
|
159
159
|
const items = vault.data || [];
|
|
160
160
|
|
|
@@ -20,10 +20,24 @@ import type { AgentEntry } from "../../types/daemon";
|
|
|
20
20
|
// with a real APC agent slug (which must match /^[a-z][a-z0-9_-]*$/).
|
|
21
21
|
const ROBY_SLUG = "__super_agent__";
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* `hideSidebar` lets another screen (the agent inbox) supply its own
|
|
25
|
+
* conversation list and embed just the thread. The chat surface is not forked
|
|
26
|
+
* — one implementation, two frames around it.
|
|
27
|
+
*/
|
|
28
|
+
export function ChatTab({
|
|
29
|
+
pid,
|
|
30
|
+
hideSidebar = false,
|
|
31
|
+
initialSelection,
|
|
32
|
+
}: {
|
|
33
|
+
pid: string;
|
|
34
|
+
hideSidebar?: boolean;
|
|
35
|
+
/** Open a specific conversation on mount instead of a fresh live session. */
|
|
36
|
+
initialSelection?: ChatKey;
|
|
37
|
+
}) {
|
|
24
38
|
const toast = useToast();
|
|
25
39
|
const [params, setSearchParams] = useSearchParams();
|
|
26
|
-
const agents = useSWR(`/projects/${pid}/agents`, () => Agents.list(pid));
|
|
40
|
+
const agents = useSWR(`/api/projects/${pid}/agents`, () => Agents.list(pid));
|
|
27
41
|
const [creating, setCreating] = useState(false);
|
|
28
42
|
const [model, setModel] = useState("");
|
|
29
43
|
const [dismissedAskKey, setDismissedAskKey] = useState<string | null>(null);
|
|
@@ -36,6 +50,10 @@ export function ChatTab({ pid }: { pid: string }) {
|
|
|
36
50
|
// defaulting to a live session with the super-agent so the chat works even on
|
|
37
51
|
// a brand-new project with zero agents and zero conversations.
|
|
38
52
|
const [selected, setSelected] = useState<ChatKey>(() => {
|
|
53
|
+
// An embedding screen that already knows which conversation the user
|
|
54
|
+
// picked wins over the URL — otherwise clicking a row in the inbox opens
|
|
55
|
+
// an empty new session and the message you clicked on is nowhere.
|
|
56
|
+
if (initialSelection) return initialSelection;
|
|
39
57
|
const agent = params.get("agent");
|
|
40
58
|
const conv = params.get("conv");
|
|
41
59
|
const channel = params.get("channel");
|
|
@@ -147,10 +165,10 @@ export function ChatTab({ pid }: { pid: string }) {
|
|
|
147
165
|
try {
|
|
148
166
|
if (selected.kind === "conv") {
|
|
149
167
|
await Conversations.remove(pid, selected.agentSlug, selected.convId);
|
|
150
|
-
void mutate(`/projects/${pid}/agents/${selected.agentSlug}/conversations`);
|
|
168
|
+
void mutate(`/api/projects/${pid}/agents/${selected.agentSlug}/conversations`);
|
|
151
169
|
} else if (selected.kind === "thread") {
|
|
152
170
|
await Conversations.removeThread(pid, selected.channel, selected.threadId);
|
|
153
|
-
void mutate(`/projects/${pid}/super-agent/threads`);
|
|
171
|
+
void mutate(`/api/projects/${pid}/super-agent/threads`);
|
|
154
172
|
}
|
|
155
173
|
toast.success(t("project.chat.deleted"));
|
|
156
174
|
setConfirmDelete(false);
|
|
@@ -183,7 +201,7 @@ export function ChatTab({ pid }: { pid: string }) {
|
|
|
183
201
|
|
|
184
202
|
return (
|
|
185
203
|
<div className="flex h-full overflow-hidden rounded-xl border border-border bg-card/40">
|
|
186
|
-
<ChatList
|
|
204
|
+
{hideSidebar ? null : <ChatList
|
|
187
205
|
pid={pid}
|
|
188
206
|
agents={agentList}
|
|
189
207
|
superAgentSlug={ROBY_SLUG}
|
|
@@ -191,7 +209,7 @@ export function ChatTab({ pid }: { pid: string }) {
|
|
|
191
209
|
selected={selected}
|
|
192
210
|
onSelect={selectChat}
|
|
193
211
|
onNewChat={onNewChat}
|
|
194
|
-
/>
|
|
212
|
+
/>}
|
|
195
213
|
|
|
196
214
|
<section className="flex min-w-0 flex-1 flex-col">
|
|
197
215
|
<header className="flex shrink-0 items-center justify-between gap-3 border-b border-border px-4 py-3">
|
|
@@ -19,7 +19,7 @@ export function ConfigTab({ pid }: { pid: string }) {
|
|
|
19
19
|
const toast = useToast();
|
|
20
20
|
const navigate = useNavigate();
|
|
21
21
|
const { project, mutate: mutateProject } = useProject(pid);
|
|
22
|
-
const cfg = useSWR(`/projects/${pid}/config`, () => Projects.config.show(pid));
|
|
22
|
+
const cfg = useSWR(`/api/projects/${pid}/config`, () => Projects.config.show(pid));
|
|
23
23
|
const isBase = String(pid) === "0";
|
|
24
24
|
|
|
25
25
|
if (cfg.isLoading) return <Loading />;
|
|
@@ -73,9 +73,9 @@ function sourceLabel(source: string): string {
|
|
|
73
73
|
|
|
74
74
|
export function McpsTab({ pid }: { pid: string }) {
|
|
75
75
|
const toast = useToast();
|
|
76
|
-
const list = useSWR(`/projects/${pid}/mcps`, () => Mcps.list(pid));
|
|
77
|
-
const conflicts = useSWR(`/projects/${pid}/mcps/check`, () => Mcps.check(pid));
|
|
78
|
-
const vars = useSWR<VarsList>(`/projects/${pid}/vars`, () => Vars.list(pid));
|
|
76
|
+
const list = useSWR(`/api/projects/${pid}/mcps`, () => Mcps.list(pid));
|
|
77
|
+
const conflicts = useSWR(`/api/projects/${pid}/mcps/check`, () => Mcps.check(pid));
|
|
78
|
+
const vars = useSWR<VarsList>(`/api/projects/${pid}/vars`, () => Vars.list(pid));
|
|
79
79
|
const [dialog, setDialog] = useState<DialogMode>(null);
|
|
80
80
|
const [activeMcp, setActiveMcp] = useState<string | null>(null);
|
|
81
81
|
const [results, setResults] = useState<Record<string, McpResult>>({});
|
|
@@ -14,12 +14,12 @@ import type { AgentEntry, RoutineEntry, TaskEntry } from "../../types/daemon";
|
|
|
14
14
|
// automation), what's in flight (task workflow), and what just happened.
|
|
15
15
|
export function Overview({ pid }: { pid: string }) {
|
|
16
16
|
const navigate = useNavigate();
|
|
17
|
-
const tasks = useSWR(`/projects/${pid}/tasks?state=open`, () => Tasks.list(pid), { refreshInterval: 20_000 });
|
|
18
|
-
const summary = useSWR(`/projects/${pid}/tasks-summary`, () => Tasks.summary(pid), { refreshInterval: 20_000 });
|
|
19
|
-
const routines = useSWR(`/projects/${pid}/routines`, () => Routines.list(pid));
|
|
20
|
-
const agents = useSWR(`/projects/${pid}/agents`, () => Agents.list(pid));
|
|
21
|
-
const mcps = useSWR(`/projects/${pid}/mcps`, () => Mcps.list(pid));
|
|
22
|
-
const artifacts = useSWR(`/projects/${pid}/artifacts`, () => Artifacts.list(pid));
|
|
17
|
+
const tasks = useSWR(`/api/projects/${pid}/tasks?state=open`, () => Tasks.list(pid), { refreshInterval: 20_000 });
|
|
18
|
+
const summary = useSWR(`/api/projects/${pid}/tasks-summary`, () => Tasks.summary(pid), { refreshInterval: 20_000 });
|
|
19
|
+
const routines = useSWR(`/api/projects/${pid}/routines`, () => Routines.list(pid));
|
|
20
|
+
const agents = useSWR(`/api/projects/${pid}/agents`, () => Agents.list(pid));
|
|
21
|
+
const mcps = useSWR(`/api/projects/${pid}/mcps`, () => Mcps.list(pid));
|
|
22
|
+
const artifacts = useSWR(`/api/projects/${pid}/artifacts`, () => Artifacts.list(pid));
|
|
23
23
|
|
|
24
24
|
const agentList = agents.data ?? [];
|
|
25
25
|
const orchestrators = agentList.filter((a) => a.is_master || a.type === "orchestrator");
|
|
@@ -5,6 +5,7 @@ import { Plus } from "lucide-react";
|
|
|
5
5
|
import { Routines, type RoutineEntry } from "../../lib/api";
|
|
6
6
|
import { Button, Dialog, Empty, Loading } from "../../components/ui";
|
|
7
7
|
import { useToast } from "../../components/Toast";
|
|
8
|
+
import { Section } from "../../components/Section";
|
|
8
9
|
import { t } from "../../i18n";
|
|
9
10
|
import { RoutineList } from "../../components/routines/RoutineList";
|
|
10
11
|
import { RoutineDetail } from "../../components/routines/RoutineDetail";
|
|
@@ -15,7 +16,7 @@ import { RoutineEditor } from "../../components/routines/RoutineEditor";
|
|
|
15
16
|
// editing is behind a button, delete uses the shared <Dialog>.
|
|
16
17
|
export function RoutinesTab({ pid }: { pid: string }) {
|
|
17
18
|
const toast = useToast();
|
|
18
|
-
const list = useSWR(`/projects/${pid}/routines`, () => Routines.list(pid));
|
|
19
|
+
const list = useSWR(`/api/projects/${pid}/routines`, () => Routines.list(pid));
|
|
19
20
|
const [params, setParams] = useSearchParams();
|
|
20
21
|
const [editing, setEditing] = useState<Partial<RoutineEntry> | null>(null);
|
|
21
22
|
const [confirmDelete, setConfirmDelete] = useState<RoutineEntry | null>(null);
|
|
@@ -56,7 +57,7 @@ export function RoutinesTab({ pid }: { pid: string }) {
|
|
|
56
57
|
// Refresh the routine list (last status) and its executions list.
|
|
57
58
|
await Promise.all([
|
|
58
59
|
list.mutate(),
|
|
59
|
-
globalMutate(`/projects/${pid}/routines/${r.name}/runs`),
|
|
60
|
+
globalMutate(`/api/projects/${pid}/routines/${r.name}/runs`),
|
|
60
61
|
]);
|
|
61
62
|
} catch (e: any) { toast.error(e?.message || t("project.routines.run_error")); }
|
|
62
63
|
finally { setRunning(null); }
|
|
@@ -75,23 +76,24 @@ export function RoutinesTab({ pid }: { pid: string }) {
|
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
return (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
// Same frame as every other list page. This one used to draw its own
|
|
80
|
+
// header outside a card while Tasks and Commitments sat inside one, so
|
|
81
|
+
// moving between them the whole page shifted.
|
|
82
|
+
<Section
|
|
83
|
+
fullHeight
|
|
84
|
+
title={t("project.routines.title")}
|
|
85
|
+
description={t("project.routines.subtitle")}
|
|
86
|
+
action={
|
|
85
87
|
<Button size="sm" variant="primary" onClick={() => setEditing({ kind: "super_agent", schedule: "every:10m", enabled: true })}>
|
|
86
88
|
<Plus size={14} /> {t("project.routines.new_btn")}
|
|
87
89
|
</Button>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
}
|
|
91
|
+
>
|
|
90
92
|
{list.isLoading && <Loading />}
|
|
91
93
|
{!list.isLoading && rows.length === 0 && <Empty>{t("project.routines.empty")}</Empty>}
|
|
92
94
|
|
|
93
95
|
{rows.length > 0 && (
|
|
94
|
-
<div className="grid min-h-0 flex-1 grid-rows-[minmax(0,1fr)] grid-cols-[minmax(200px,260px)_1fr] overflow-hidden rounded-
|
|
96
|
+
<div className="grid min-h-0 flex-1 grid-rows-[minmax(0,1fr)] grid-cols-[minmax(200px,260px)_1fr] overflow-hidden rounded-lg border border-border">
|
|
95
97
|
<RoutineList routines={rows} selectedName={selected?.name ?? null} onSelect={selectRoutine} />
|
|
96
98
|
<div className="min-h-0 min-w-0 overflow-hidden">
|
|
97
99
|
{selected
|
|
@@ -148,6 +150,6 @@ export function RoutinesTab({ pid }: { pid: string }) {
|
|
|
148
150
|
>
|
|
149
151
|
<p className="text-sm text-muted-fg">{t("project.routines.run_confirm_body")}</p>
|
|
150
152
|
</Dialog>
|
|
151
|
-
</
|
|
153
|
+
</Section>
|
|
152
154
|
);
|
|
153
155
|
}
|
|
@@ -12,7 +12,7 @@ import type { OrgArea, OrgRole } from "../../types/daemon";
|
|
|
12
12
|
|
|
13
13
|
export function StructureTab({ pid }: { pid: string }) {
|
|
14
14
|
const toast = useToast();
|
|
15
|
-
const org = useSWR(`/projects/${pid}/organization`, () => Org.get(pid));
|
|
15
|
+
const org = useSWR(`/api/projects/${pid}/organization`, () => Org.get(pid));
|
|
16
16
|
|
|
17
17
|
const [areaDialog, setAreaDialog] = useState<{ editing?: OrgArea | null } | null>(null);
|
|
18
18
|
const [roleDialog, setRoleDialog] = useState<{ editing?: OrgRole | null; presetArea?: string | null } | null>(null);
|
|
@@ -18,7 +18,7 @@ export function TasksTab({ pid }: { pid: string }) {
|
|
|
18
18
|
// dedupingInterval:0 so switching the state filter always revalidates the
|
|
19
19
|
// target page instead of showing the stale cached one from a prior switch.
|
|
20
20
|
const paged = usePagedQuery({
|
|
21
|
-
key: `/projects/${pid}/tasks?state=${state}`,
|
|
21
|
+
key: `/api/projects/${pid}/tasks?state=${state}`,
|
|
22
22
|
fetchPage: (limit, offset) => Tasks.listPage(pid, { state, limit, offset }),
|
|
23
23
|
resetKey: state,
|
|
24
24
|
swr: { dedupingInterval: 0, revalidateOnFocus: true },
|
|
@@ -23,7 +23,7 @@ export function VarsTab({ pid }: { pid: string }) {
|
|
|
23
23
|
);
|
|
24
24
|
const [revealAll, setRevealAll] = useState(false);
|
|
25
25
|
const list = useSWR<VarsList>(
|
|
26
|
-
`/projects/${pid}/vars?reveal=${revealAll ? 1 : 0}`,
|
|
26
|
+
`/api/projects/${pid}/vars?reveal=${revealAll ? 1 : 0}`,
|
|
27
27
|
() => Vars.list(pid, { reveal: revealAll }),
|
|
28
28
|
);
|
|
29
29
|
const [openCreate, setOpenCreate] = useState<{ name?: string; value?: string; scope?: VarScope } | null>(null);
|
|
@@ -55,7 +55,7 @@ export interface AgentDetail extends AgentEntry {
|
|
|
55
55
|
|
|
56
56
|
export interface RoutineEntry {
|
|
57
57
|
name: string;
|
|
58
|
-
kind: "heartbeat" | "exec_agent" | "super_agent" | "telegram" | "shell";
|
|
58
|
+
kind: "heartbeat" | "exec_agent" | "super_agent" | "telegram" | "shell" | "watch";
|
|
59
59
|
schedule: string;
|
|
60
60
|
spec: Record<string, unknown>;
|
|
61
61
|
enabled: boolean;
|
|
@@ -228,6 +228,15 @@ export interface ConversationMessage {
|
|
|
228
228
|
actor_kind?: string;
|
|
229
229
|
model?: string;
|
|
230
230
|
usage?: ChatUsage;
|
|
231
|
+
/** Compact record of what the turn did, written at the time (the live tool
|
|
232
|
+
* events are long gone by the time a thread is read back). */
|
|
233
|
+
tool_summary?: ToolSummary;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface ToolSummary {
|
|
237
|
+
total: number;
|
|
238
|
+
failed: number;
|
|
239
|
+
tools: { name: string; count: number; failed: number }[];
|
|
231
240
|
}
|
|
232
241
|
|
|
233
242
|
export interface ConversationDetail {
|
|
@@ -6,28 +6,23 @@ import path from "node:path";
|
|
|
6
6
|
// Vite config for the APX admin panel.
|
|
7
7
|
//
|
|
8
8
|
// - Single SPA, no SSR (this is a local admin tool).
|
|
9
|
-
// - During `vite dev`,
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
9
|
+
// - During `vite dev`, /api is proxied to the running daemon so we develop the
|
|
10
|
+
// UI with hot reload against REAL data. Frontend routes (/, /settings,
|
|
11
|
+
// /p/:id) live outside /api, so vite serves index.html for them (SPA
|
|
12
|
+
// routing). `ws: true` also carries the /api/desktop/ws upgrade through.
|
|
13
13
|
// - `vite build` emits to ./dist; the daemon serves that folder when present.
|
|
14
|
+
//
|
|
15
|
+
// This used to be a hand-maintained list of every daemon prefix, kept in sync
|
|
16
|
+
// by hand with two other copies (the SPA fallback and the auth allowlist) —
|
|
17
|
+
// and it drifted. Now the daemon mounts everything under /api
|
|
18
|
+
// (src/host/daemon/api/prefix.js), so one entry covers the whole surface and
|
|
19
|
+
// a new route can never be missed here.
|
|
14
20
|
|
|
15
21
|
const DAEMON_TARGET = process.env.APX_DAEMON_URL || "http://127.0.0.1:7430";
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// (e.g. an empty /pair/list).
|
|
21
|
-
const API_PREFIXES = [
|
|
22
|
-
"/health", "/admin", "/projects", "/telegram", "/engines", "/runtimes",
|
|
23
|
-
"/messages", "/sessions", "/tools", "/mcp", "/voice", "/tts", "/desktop", "/overlay",
|
|
24
|
-
"/transcribe", "/run", "/files", "/memory", "/env", "/pair", "/deck",
|
|
25
|
-
"/super-agent", "/identity", "/agents", "/tasks", "/code",
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
const proxy = Object.fromEntries(
|
|
29
|
-
API_PREFIXES.map((p) => [p, { target: DAEMON_TARGET, changeOrigin: false, ws: true }])
|
|
30
|
-
);
|
|
23
|
+
const proxy = {
|
|
24
|
+
"/api": { target: DAEMON_TARGET, changeOrigin: false, ws: true },
|
|
25
|
+
};
|
|
31
26
|
|
|
32
27
|
export default defineConfig({
|
|
33
28
|
plugins: [react(), tailwindcss()],
|