@agentprojectcontext/apx 1.32.0 → 1.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -1
- package/skills/apc-context/SKILL.md +5 -2
- package/skills/apx/SKILL.md +3 -3
- package/skills/apx-agency-agents/SKILL.md +5 -5
- package/skills/apx-agent/SKILL.md +7 -7
- package/skills/apx-mcp/SKILL.md +6 -4
- package/skills/apx-mcp-builder/SKILL.md +4 -7
- package/skills/apx-project/SKILL.md +4 -5
- package/skills/apx-routine/SKILL.md +14 -12
- package/skills/apx-runtime/SKILL.md +5 -3
- package/skills/apx-sessions/SKILL.md +5 -5
- package/skills/apx-skill-builder/SKILL.md +10 -6
- package/skills/apx-task/SKILL.md +8 -8
- package/skills/apx-telegram/SKILL.md +23 -7
- package/skills/apx-voice/SKILL.md +8 -6
- package/src/core/{agent-system.js → agent/build-agent-system.js} +10 -12
- package/src/core/agent/index.js +0 -2
- package/src/core/{agent-memory.js → agent/memory.js} +2 -2
- package/src/core/agent/model-router.js +21 -43
- package/src/core/agent/prompt-builder.js +17 -63
- package/src/core/agent/prompts/action-discipline.md +24 -0
- package/src/core/agent/prompts/channels/code.md +8 -12
- package/src/core/agent/prompts/channels/desktop.md +6 -4
- package/src/core/agent/prompts/channels/routine.md +10 -1
- package/src/core/agent/prompts/channels/telegram.md +10 -1
- package/src/core/agent/prompts/channels/web_code.md +20 -0
- package/src/core/agent/prompts/modes/voice.md +2 -2
- package/src/core/agent/prompts/super-agent-base.md +2 -2
- package/src/core/agent/run-agent.js +37 -35
- package/src/core/agent/runtime-bridge.js +42 -0
- package/src/core/agent/self-memory.js +19 -9
- package/src/core/agent/skills/catalog.js +65 -0
- package/src/core/agent/skills/index.js +6 -0
- package/src/{host/daemon/skills-loader.js → core/agent/skills/loader.js} +3 -3
- package/src/core/agent/skills/rag.js +91 -0
- package/src/core/agent/skills/trigger.js +71 -0
- package/src/{host/daemon → core/agent}/super-agent.js +5 -5
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/add-project.js +3 -4
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-agent.js +2 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-mcp.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/call-runtime.js +10 -11
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/create-task.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/discover-tools.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/edit-file.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/import-agent.js +4 -5
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-agents.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-skills.js +7 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-tasks.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-vault-agents.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/load-skill.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-agent-memory.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-self-memory.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/remember.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/run-shell.js +1 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-messages.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-sessions.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/send-telegram.js +0 -2
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/set-identity.js +1 -3
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/set-permission-mode.js +1 -3
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/tail-messages.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/transcribe-audio.js +1 -1
- package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/write-file.js +1 -2
- package/src/core/agent/tools/helpers.js +74 -0
- package/src/{host/daemon/super-agent-tools → core/agent/tools}/registry-bridge.js +3 -3
- package/src/{host/daemon/super-agent-tools/index.js → core/agent/tools/registry.js} +31 -32
- package/src/core/apc/agents-vault.js +37 -0
- package/src/core/{scaffold.js → apc/scaffold.js} +4 -5
- package/src/core/{config.js → config/index.js} +21 -27
- package/src/core/config/paths.js +32 -0
- package/src/core/constants/actors.js +8 -0
- package/src/core/constants/channels.js +19 -0
- package/src/core/constants/index.js +5 -0
- package/src/core/constants/permissions.js +17 -0
- package/src/core/constants/roles.js +9 -0
- package/src/core/engines/_streaming.js +63 -0
- package/src/core/engines/anthropic.js +11 -22
- package/src/core/engines/ollama.js +7 -16
- package/src/core/identity/index.js +8 -0
- package/src/core/{identity.js → identity/self.js} +5 -5
- package/src/core/{telegram-identity.js → identity/telegram.js} +1 -1
- package/src/core/logging.js +1 -1
- package/src/core/mascot.js +1 -1
- package/src/core/memory/active-threads.js +10 -10
- package/src/core/memory/broker.js +9 -9
- package/src/core/memory/compactor.js +2 -2
- package/src/core/memory/index.js +2 -2
- package/src/core/memory/indexer.js +1 -1
- package/src/core/{code-sessions-store.js → stores/code-sessions.js} +7 -8
- package/src/core/{messages-store.js → stores/messages.js} +6 -4
- package/src/core/stores/routine-memory.js +71 -0
- package/src/core/{routines-store.js → stores/routines.js} +1 -3
- package/src/core/stores/runtime-sessions.js +99 -0
- package/src/core/{tasks-store.js → stores/tasks.js} +3 -8
- package/src/core/update-check.js +1 -1
- package/src/core/util/ids.js +14 -0
- package/src/core/util/index.js +2 -0
- package/src/core/util/time.js +9 -0
- package/src/core/voice/tts.js +1 -1
- package/src/host/daemon/api/admin-config.js +4 -3
- package/src/host/daemon/api/admin.js +1 -1
- package/src/host/daemon/api/agents.js +4 -25
- package/src/host/daemon/api/artifacts.js +26 -1
- package/src/host/daemon/api/code.js +62 -17
- package/src/host/daemon/api/confirm.js +1 -1
- package/src/host/daemon/api/connections.js +2 -2
- package/src/host/daemon/api/conversations.js +2 -2
- package/src/host/daemon/api/deck.js +1 -1
- package/src/host/daemon/api/desktop.js +1 -1
- package/src/host/daemon/api/embeddings.js +4 -4
- package/src/host/daemon/api/engines.js +2 -2
- package/src/host/daemon/api/exec.js +20 -5
- package/src/host/daemon/api/identity.js +1 -1
- package/src/host/daemon/api/mcps.js +1 -1
- package/src/host/daemon/api/messages.js +1 -1
- package/src/host/daemon/api/runtimes.js +9 -8
- package/src/host/daemon/api/sessions-search.js +1 -1
- package/src/host/daemon/api/sessions.js +2 -2
- package/src/host/daemon/api/shared.js +5 -4
- package/src/host/daemon/api/skills.js +30 -0
- package/src/host/daemon/api/super-agent.js +29 -9
- package/src/host/daemon/api/tasks.js +2 -2
- package/src/host/daemon/api/telegram.js +1 -1
- package/src/host/daemon/api/tools.js +6 -6
- package/src/host/daemon/api/tts.js +2 -2
- package/src/host/daemon/api/voice.js +14 -12
- package/src/host/daemon/api.js +2 -0
- package/src/host/daemon/compact.js +1 -1
- package/src/host/daemon/db.js +4 -4
- package/src/host/daemon/desktop-ws.js +1 -1
- package/src/host/daemon/index.js +4 -4
- package/src/host/daemon/plugins/{desktop.js → desktop/index.js} +11 -6
- package/src/host/daemon/plugins/index.js +2 -2
- package/src/host/daemon/plugins/{telegram.js → telegram/index.js} +52 -193
- package/src/host/daemon/plugins/telegram/media.js +162 -0
- package/src/host/daemon/projects-helpers.js +54 -0
- package/src/host/daemon/routines.js +28 -12
- package/src/host/daemon/smoke.js +2 -2
- package/src/host/daemon/token-store.js +1 -1
- package/src/host/daemon/transcription.js +2 -2
- package/src/host/daemon/wakeup.js +2 -2
- package/src/interfaces/cli/commands/agent.js +3 -3
- package/src/interfaces/cli/commands/command.js +1 -1
- package/src/interfaces/cli/commands/config.js +3 -2
- package/src/interfaces/cli/commands/desktop.js +1 -1
- package/src/interfaces/cli/commands/exec.js +2 -1
- package/src/interfaces/cli/commands/identity.js +2 -2
- package/src/interfaces/cli/commands/init.js +1 -1
- package/src/interfaces/cli/commands/mcp.js +1 -1
- package/src/interfaces/cli/commands/memory.js +2 -2
- package/src/interfaces/cli/commands/model.js +16 -6
- package/src/interfaces/cli/commands/project.js +1 -1
- package/src/interfaces/cli/commands/routine.js +58 -0
- package/src/interfaces/cli/commands/search.js +1 -1
- package/src/interfaces/cli/commands/session.js +4 -4
- package/src/interfaces/cli/commands/setup.js +4 -3
- package/src/interfaces/cli/commands/skills.js +25 -4
- package/src/interfaces/cli/commands/status.js +1 -1
- package/src/interfaces/cli/commands/sys.js +11 -4
- package/src/interfaces/cli/commands/update.js +1 -1
- package/src/interfaces/cli/index.js +4 -4
- package/src/interfaces/cli/postinstall.js +2 -2
- package/src/interfaces/mcp-server/index.js +1 -1
- package/src/interfaces/tui/component/prompt/index.tsx +3 -1
- package/src/interfaces/tui/context/sdk-apx.tsx +47 -7
- package/src/interfaces/tui/context/sync-apx.tsx +20 -2
- package/src/interfaces/tui/context/sync.tsx +2 -1
- package/src/interfaces/tui/routes/session/index.tsx +151 -136
- package/src/interfaces/tui/routes/session/sidebar-apx.tsx +37 -15
- package/src/interfaces/tui/run.ts +2 -0
- package/src/interfaces/web/dist/assets/index-7dVT2O1S.css +1 -0
- package/src/interfaces/web/dist/assets/index-DWsE_8Nz.js +602 -0
- package/src/interfaces/web/dist/assets/index-DWsE_8Nz.js.map +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/package-lock.json +6 -6
- package/src/interfaces/web/src/App.tsx +53 -32
- package/src/interfaces/web/src/components/RobyBubble.tsx +12 -6
- package/src/interfaces/web/src/components/UiSelect.tsx +13 -3
- package/src/interfaces/web/src/components/chat/SkillPicker.tsx +77 -0
- package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +253 -111
- package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +10 -8
- package/src/interfaces/web/src/components/code/CodeComposer.tsx +20 -17
- package/src/interfaces/web/src/components/code/CodeContextTab.tsx +43 -18
- package/src/interfaces/web/src/components/code/CodeFileTree.tsx +212 -0
- package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +121 -0
- package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +1 -1
- package/src/interfaces/web/src/components/code/CodeSessionList.tsx +30 -26
- package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +40 -21
- package/src/interfaces/web/src/components/code/CodeTerminal.tsx +140 -0
- package/src/interfaces/web/src/components/common/TabLayout.tsx +11 -7
- package/src/interfaces/web/src/components/common/TabNav.tsx +3 -3
- package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +4 -2
- package/src/interfaces/web/src/components/ui/chat-input.tsx +17 -6
- package/src/interfaces/web/src/hooks/useChat.ts +48 -2
- package/src/interfaces/web/src/hooks/useNavCollapseCtx.tsx +83 -0
- package/src/interfaces/web/src/hooks/usePersonaName.ts +11 -0
- package/src/interfaces/web/src/i18n/en.ts +7 -7
- package/src/interfaces/web/src/i18n/es.ts +8 -8
- package/src/interfaces/web/src/lib/api/agents.ts +1 -1
- package/src/interfaces/web/src/lib/api/artifacts.ts +10 -0
- package/src/interfaces/web/src/lib/api/code.ts +4 -2
- package/src/interfaces/web/src/lib/api/skills.ts +25 -0
- package/src/interfaces/web/src/lib/api.ts +1 -0
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +430 -86
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +5 -18
- package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +1 -8
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +39 -40
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +16 -16
- package/src/skills/apc-context/SKILL.md +159 -0
- package/src/core/agent/ghost-guard.js +0 -24
- package/src/core/agent/prompts/channels/terminal.md +0 -16
- package/src/host/daemon/apc-runtime-context.js +0 -124
- package/src/host/daemon/super-agent-tools/helpers.js +0 -124
- package/src/host/daemon/tool-call-parser.js +0 -2
- package/src/interfaces/web/dist/assets/index-63P_ji1a.js +0 -571
- package/src/interfaces/web/dist/assets/index-63P_ji1a.js.map +0 -1
- package/src/interfaces/web/dist/assets/index-DLWy6dYz.css +0 -1
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/ask-questions.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-files.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-mcps.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/list-projects.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/read-file.js +0 -0
- /package/src/{host/daemon/super-agent-tools/tools → core/agent/tools/handlers}/search-files.js +0 -0
- /package/src/core/agent/{pseudo-tools.js → tools/pseudo-tools.js} +0 -0
- /package/src/core/agent/{tool-call-parser.js → tools/tool-call-parser.js} +0 -0
- /package/src/core/{parser.js → apc/parser.js} +0 -0
- /package/src/core/{apc-skill-sync.js → apc/skill-sync.js} +0 -0
- /package/src/core/{artifacts-store.js → stores/artifacts.js} +0 -0
- /package/src/{host/daemon → core/stores}/engine-sessions.js +0 -0
- /package/src/core/{session-store.js → stores/sessions.js} +0 -0
- /package/src/host/daemon/plugins/{telegram-ask.js → telegram/ask.js} +0 -0
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
// collapse toggle (and optional page actions) followed by the routed content.
|
|
4
4
|
// The page title/subtitle live in the top breadcrumb now, not here.
|
|
5
5
|
import { type ReactNode } from "react";
|
|
6
|
-
import { TabNav,
|
|
6
|
+
import { TabNav, type TabSection } from "./TabNav";
|
|
7
7
|
import { cn } from "../../lib/cn";
|
|
8
|
+
import { useRegisterNavCollapse } from "../../hooks/useNavCollapseCtx";
|
|
8
9
|
|
|
9
10
|
interface Props {
|
|
10
11
|
sections: TabSection[];
|
|
@@ -29,15 +30,18 @@ export function TabLayout({
|
|
|
29
30
|
testId,
|
|
30
31
|
children,
|
|
31
32
|
}: Props) {
|
|
33
|
+
useRegisterNavCollapse(collapsed, onToggleCollapse);
|
|
34
|
+
|
|
32
35
|
return (
|
|
33
36
|
<div className="flex h-full">
|
|
34
37
|
<TabNav sections={sections} active={active} onChange={onChange} collapsed={collapsed} />
|
|
35
|
-
<div className="flex min-w-0 flex-1 flex-col overflow-
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
<div className="flex min-w-0 flex-1 flex-col overflow-hidden">
|
|
39
|
+
{actions ? (
|
|
40
|
+
<div className="flex shrink-0 items-center justify-end gap-2 px-6 pt-3">
|
|
41
|
+
{actions}
|
|
42
|
+
</div>
|
|
43
|
+
) : null}
|
|
44
|
+
<div className={cn("flex-1 min-h-0 overflow-y-auto", contentClassName)} data-testid={testId}>
|
|
41
45
|
{children}
|
|
42
46
|
</div>
|
|
43
47
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Left-rail tab nav used inside Settings + per-project screens. Mirrors
|
|
2
2
|
// the panda.project sectioned-nav pattern: optional section title above
|
|
3
3
|
// each group, icon + label rows, active state in the section's tone.
|
|
4
|
-
import { useState, useEffect, Fragment, type ElementType } from "react";
|
|
4
|
+
import { useState, useEffect, useCallback, Fragment, type ElementType } from "react";
|
|
5
5
|
import { PanelLeft } from "lucide-react";
|
|
6
6
|
import { cn } from "../../lib/cn";
|
|
7
7
|
import { Tip } from "../ui/tip";
|
|
@@ -34,12 +34,12 @@ export function useNavCollapse(storageKey: string) {
|
|
|
34
34
|
try { setCollapsed(localStorage.getItem(storageKey) === "true"); } catch { /* ignore */ }
|
|
35
35
|
}, [storageKey]);
|
|
36
36
|
|
|
37
|
-
const toggle = () =>
|
|
37
|
+
const toggle = useCallback(() =>
|
|
38
38
|
setCollapsed((v) => {
|
|
39
39
|
const next = !v;
|
|
40
40
|
try { localStorage.setItem(storageKey, String(next)); } catch { /* quota */ }
|
|
41
41
|
return next;
|
|
42
|
-
});
|
|
42
|
+
}), [storageKey]);
|
|
43
43
|
|
|
44
44
|
return { collapsed, toggle };
|
|
45
45
|
}
|
|
@@ -9,6 +9,7 @@ import { ProjectAvatar } from "./ProjectAvatar";
|
|
|
9
9
|
import { Tip } from "../ui/tip";
|
|
10
10
|
import { useProjects } from "../../hooks/useProjects";
|
|
11
11
|
import { t } from "../../i18n";
|
|
12
|
+
import { usePersonaName } from "../../hooks/usePersonaName";
|
|
12
13
|
|
|
13
14
|
interface Props {
|
|
14
15
|
onSelect: (href: string) => void;
|
|
@@ -37,6 +38,7 @@ export function ProjectSidebar({ onSelect, onOpenRoby }: Props) {
|
|
|
37
38
|
const { projects, isLoading } = useProjects();
|
|
38
39
|
const location = useLocation();
|
|
39
40
|
const MODULES = buildModules();
|
|
41
|
+
const persona = usePersonaName();
|
|
40
42
|
|
|
41
43
|
const isActive = (href: string) =>
|
|
42
44
|
location.pathname === href || location.pathname.startsWith(`${href}/`);
|
|
@@ -122,12 +124,12 @@ export function ProjectSidebar({ onSelect, onOpenRoby }: Props) {
|
|
|
122
124
|
/>
|
|
123
125
|
{/* Roby launcher — subtle (not a loud floating bubble), pinned under the
|
|
124
126
|
gear so it doesn't overlap the chat composer. */}
|
|
125
|
-
<Tip content={t("
|
|
127
|
+
<Tip content={t("superagent.talk", { persona })} side="right">
|
|
126
128
|
<button
|
|
127
129
|
type="button"
|
|
128
130
|
onClick={onOpenRoby}
|
|
129
131
|
data-testid="nav-roby"
|
|
130
|
-
aria-label={t("
|
|
132
|
+
aria-label={t("superagent.talk", { persona })}
|
|
131
133
|
className="mt-1 flex size-10 items-center justify-center rounded-xl border border-border/60 bg-muted/30 text-muted-fg transition-colors hover:bg-accent hover:text-foreground"
|
|
132
134
|
>
|
|
133
135
|
<Bot size={18} />
|
|
@@ -49,12 +49,23 @@ export function ChatInput({
|
|
|
49
49
|
React.useLayoutEffect(() => {
|
|
50
50
|
const el = ref.current
|
|
51
51
|
if (!el) return
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
const resize = () => {
|
|
53
|
+
el.style.height = "auto"
|
|
54
|
+
// Force a reflow before reading scrollHeight so the "auto" reset takes
|
|
55
|
+
// effect — without this, scrollHeight can return the stale prior height.
|
|
56
|
+
void el.offsetHeight
|
|
57
|
+
const lineHeight = parseFloat(getComputedStyle(el).lineHeight) || 20
|
|
58
|
+
const min = lineHeight * minRows
|
|
59
|
+
const max = lineHeight * maxRows
|
|
60
|
+
el.style.height = `${Math.min(Math.max(el.scrollHeight, min), max)}px`
|
|
61
|
+
el.style.overflowY = el.scrollHeight > max ? "auto" : "hidden"
|
|
62
|
+
}
|
|
63
|
+
resize()
|
|
64
|
+
// Re-run after the next paint to catch cases where the parent layout
|
|
65
|
+
// wasn't ready on the initial sync pass (e.g. inside a resizable panel
|
|
66
|
+
// that's just been mounted).
|
|
67
|
+
const raf = requestAnimationFrame(resize)
|
|
68
|
+
return () => cancelAnimationFrame(raf)
|
|
58
69
|
}, [value, minRows, maxRows])
|
|
59
70
|
|
|
60
71
|
const canSend = value.trim().length > 0 && !disabled
|
|
@@ -49,7 +49,7 @@ export interface UseChatResult {
|
|
|
49
49
|
streaming: boolean;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/** Concatenate the text parts of a message (for clipboard
|
|
52
|
+
/** Concatenate the text parts of a message (for clipboard). */
|
|
53
53
|
export function textOf(msg: ChatMsg): string {
|
|
54
54
|
return msg.parts
|
|
55
55
|
.filter((p): p is TextPart => p.kind === "text")
|
|
@@ -58,6 +58,51 @@ export function textOf(msg: ChatMsg): string {
|
|
|
58
58
|
.trim();
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/** Compact line summarising an ask_questions tool call. Surfaced into the
|
|
62
|
+
* history string we send to the super-agent so the model can see it ALREADY
|
|
63
|
+
* asked and not re-ask the same questions on the next turn. Without this,
|
|
64
|
+
* ask_questions calls are invisible in history and the model loops. */
|
|
65
|
+
function summarizeAskQuestions(part: ToolPart): string | null {
|
|
66
|
+
const raw = (part.args as { questions?: unknown } | undefined)?.questions;
|
|
67
|
+
if (!Array.isArray(raw) || raw.length === 0) return null;
|
|
68
|
+
const lines = raw
|
|
69
|
+
.map((q) => {
|
|
70
|
+
if (typeof q === "string") return `- ${q}`;
|
|
71
|
+
if (!q || typeof q !== "object") return null;
|
|
72
|
+
const qq = q as { question?: unknown; options?: unknown };
|
|
73
|
+
if (typeof qq.question !== "string") return null;
|
|
74
|
+
const opts = Array.isArray(qq.options) ? qq.options : [];
|
|
75
|
+
const optStr = opts
|
|
76
|
+
.map((o) =>
|
|
77
|
+
typeof o === "string"
|
|
78
|
+
? o
|
|
79
|
+
: o && typeof o === "object" && typeof (o as { label?: unknown }).label === "string"
|
|
80
|
+
? ((o as { label: string }).label)
|
|
81
|
+
: "",
|
|
82
|
+
)
|
|
83
|
+
.filter((s) => s)
|
|
84
|
+
.join(", ");
|
|
85
|
+
return optStr ? `- ${qq.question} (opciones: ${optStr})` : `- ${qq.question}`;
|
|
86
|
+
})
|
|
87
|
+
.filter((s): s is string => !!s);
|
|
88
|
+
if (lines.length === 0) return null;
|
|
89
|
+
return `[ask_questions]\n${lines.join("\n")}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** History view of a message — text parts plus ask_questions summaries.
|
|
93
|
+
* Used when sending `previousMessages` to the super-agent. */
|
|
94
|
+
export function historyTextOf(msg: ChatMsg): string {
|
|
95
|
+
const chunks: string[] = [];
|
|
96
|
+
for (const p of msg.parts) {
|
|
97
|
+
if (p.kind === "text" && p.text) chunks.push(p.text);
|
|
98
|
+
else if (p.kind === "tool" && p.tool === "ask_questions") {
|
|
99
|
+
const s = summarizeAskQuestions(p);
|
|
100
|
+
if (s) chunks.push(s);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return chunks.join("\n\n").trim();
|
|
104
|
+
}
|
|
105
|
+
|
|
61
106
|
const userPart = (text: string): ChatPart[] => [{ kind: "text", text }];
|
|
62
107
|
|
|
63
108
|
function isErrorResult(result: unknown): boolean {
|
|
@@ -202,7 +247,7 @@ export function useChat(pid: string, onError?: (msg: string) => void): UseChatRe
|
|
|
202
247
|
const nowIso = () => new Date().toISOString();
|
|
203
248
|
const history: ConversationMessage[] = msgs.map((m) => ({
|
|
204
249
|
role: m.role,
|
|
205
|
-
content:
|
|
250
|
+
content: historyTextOf(m),
|
|
206
251
|
}));
|
|
207
252
|
|
|
208
253
|
setMsgs((curr) => [
|
|
@@ -218,6 +263,7 @@ export function useChat(pid: string, onError?: (msg: string) => void): UseChatRe
|
|
|
218
263
|
const out = await Agents.chat(pid, opts.agentSlug, {
|
|
219
264
|
prompt: trimmed,
|
|
220
265
|
conversation_id: convoRef.current,
|
|
266
|
+
model: opts.model || undefined,
|
|
221
267
|
});
|
|
222
268
|
convoRef.current = out.conversation_id;
|
|
223
269
|
patchLast((m) => ({
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createContext, useContext, useState, useEffect, type ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
// ── Nav collapse ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
type CollapseState = { collapsed: boolean; toggle: () => void } | null;
|
|
6
|
+
|
|
7
|
+
const CollapseReadCtx = createContext<CollapseState>(null);
|
|
8
|
+
const CollapseSetCtx = createContext<((s: CollapseState) => void) | null>(null);
|
|
9
|
+
|
|
10
|
+
// ── Page label (extra breadcrumb segment pushed by leaf screens) ──────────────
|
|
11
|
+
|
|
12
|
+
const LabelReadCtx = createContext<string>("");
|
|
13
|
+
const LabelSetCtx = createContext<((s: string) => void) | null>(null);
|
|
14
|
+
|
|
15
|
+
// ── Page actions (buttons screens can inject into the TopBar) ─────────────────
|
|
16
|
+
|
|
17
|
+
const ActionsReadCtx = createContext<ReactNode>(null);
|
|
18
|
+
const ActionsSetCtx = createContext<((a: ReactNode) => void) | null>(null);
|
|
19
|
+
|
|
20
|
+
// ── Combined provider (one wrapper in Shell) ──────────────────────────────────
|
|
21
|
+
|
|
22
|
+
export function NavCollapseProvider({ children }: { children: ReactNode }) {
|
|
23
|
+
const [collapse, setCollapse] = useState<CollapseState>(null);
|
|
24
|
+
const [label, setLabel] = useState("");
|
|
25
|
+
const [actions, setActions] = useState<ReactNode>(null);
|
|
26
|
+
return (
|
|
27
|
+
<CollapseSetCtx.Provider value={setCollapse}>
|
|
28
|
+
<CollapseReadCtx.Provider value={collapse}>
|
|
29
|
+
<LabelSetCtx.Provider value={setLabel}>
|
|
30
|
+
<LabelReadCtx.Provider value={label}>
|
|
31
|
+
<ActionsSetCtx.Provider value={setActions}>
|
|
32
|
+
<ActionsReadCtx.Provider value={actions}>
|
|
33
|
+
{children}
|
|
34
|
+
</ActionsReadCtx.Provider>
|
|
35
|
+
</ActionsSetCtx.Provider>
|
|
36
|
+
</LabelReadCtx.Provider>
|
|
37
|
+
</LabelSetCtx.Provider>
|
|
38
|
+
</CollapseReadCtx.Provider>
|
|
39
|
+
</CollapseSetCtx.Provider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ── Nav collapse hooks ────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
export function useNavCollapseCtx() {
|
|
46
|
+
return useContext(CollapseReadCtx);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function useRegisterNavCollapse(collapsed: boolean, toggle: () => void) {
|
|
50
|
+
const setState = useContext(CollapseSetCtx);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
setState?.({ collapsed, toggle });
|
|
53
|
+
return () => setState?.(null);
|
|
54
|
+
}, [collapsed, toggle, setState]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── Page label hooks ──────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
export function usePageLabel() {
|
|
60
|
+
return useContext(LabelReadCtx);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function useSetPageLabel(label: string) {
|
|
64
|
+
const set = useContext(LabelSetCtx);
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
set?.(label);
|
|
67
|
+
return () => set?.("");
|
|
68
|
+
}, [label, set]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ── Page actions hooks ────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
export function usePageActions() {
|
|
74
|
+
return useContext(ActionsReadCtx);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function useSetPageActions(actions: ReactNode) {
|
|
78
|
+
const set = useContext(ActionsSetCtx);
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
set?.(actions);
|
|
81
|
+
return () => set?.(null);
|
|
82
|
+
}, [actions, set]);
|
|
83
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Resolve the super-agent display name (the persona shown to the user).
|
|
2
|
+
// Reads identity.json via useIdentity(); falls back to "APX" while loading
|
|
3
|
+
// or when identity is empty. UI strings should always interpolate this hook
|
|
4
|
+
// instead of hardcoding a persona name (it would otherwise drift from what
|
|
5
|
+
// the daemon-side resolveAgentName() reports across CLI / Telegram / etc.).
|
|
6
|
+
import { useIdentity } from "./useIdentity";
|
|
7
|
+
|
|
8
|
+
export function usePersonaName(): string {
|
|
9
|
+
const { identity } = useIdentity();
|
|
10
|
+
return (identity as { agent_name?: string })?.agent_name?.trim() || "APX";
|
|
11
|
+
}
|
|
@@ -286,8 +286,8 @@ export const en = {
|
|
|
286
286
|
chat: {
|
|
287
287
|
title: "Chat with agent",
|
|
288
288
|
subtitle: "Direct conversations with project agents. The super-agent does not intervene.",
|
|
289
|
-
|
|
290
|
-
|
|
289
|
+
superagent_title: "Chat with {persona}",
|
|
290
|
+
superagent_subtitle: "Chat with {persona} — the APX super-agent. Can use tools (projects, tasks, mcps, agents).",
|
|
291
291
|
empty: "Send a message to start the conversation.",
|
|
292
292
|
placeholder: "Type something and press enter to send (shift+enter = new line)",
|
|
293
293
|
send: "Send",
|
|
@@ -710,13 +710,13 @@ export const en = {
|
|
|
710
710
|
delete_btn: "Delete",
|
|
711
711
|
},
|
|
712
712
|
|
|
713
|
-
|
|
714
|
-
title: "
|
|
713
|
+
superagent: {
|
|
714
|
+
title: "{persona}",
|
|
715
715
|
badge: "super-agent · APX",
|
|
716
716
|
desc: "Quick chat with your super-agent. Has access to tools (projects, tasks, mcps, agents); for a longer persistent thread, open Chats.",
|
|
717
|
-
empty: "Send
|
|
718
|
-
thinking: "
|
|
719
|
-
talk: "Talk to
|
|
717
|
+
empty: "Send {persona} a message to get started.",
|
|
718
|
+
thinking: "{persona} is thinking…",
|
|
719
|
+
talk: "Talk to {persona}",
|
|
720
720
|
new_chat: "New chat",
|
|
721
721
|
placeholder: "Type and press enter to send (shift+enter = new line)…",
|
|
722
722
|
},
|
|
@@ -286,9 +286,9 @@ export const es = {
|
|
|
286
286
|
|
|
287
287
|
chat: {
|
|
288
288
|
title: "Chat con agente",
|
|
289
|
-
subtitle: "
|
|
290
|
-
|
|
291
|
-
|
|
289
|
+
subtitle: "Chat directo con el agente del proyecto.",
|
|
290
|
+
superagent_title: "Chat con {persona}",
|
|
291
|
+
superagent_subtitle: "Chat con {persona} — el super-agente APX. Puede usar tools (proyectos, tasks, mcps, agentes).",
|
|
292
292
|
empty: "Mandá un mensaje para arrancar la conversación.",
|
|
293
293
|
placeholder: "Escribí algo y enter para enviar (shift+enter = nueva línea)",
|
|
294
294
|
send: "Enviar",
|
|
@@ -711,13 +711,13 @@ export const es = {
|
|
|
711
711
|
delete_btn: "Borrar",
|
|
712
712
|
},
|
|
713
713
|
|
|
714
|
-
|
|
715
|
-
title: "
|
|
714
|
+
superagent: {
|
|
715
|
+
title: "{persona}",
|
|
716
716
|
badge: "super-agent · APX",
|
|
717
717
|
desc: "Conversación rápida con tu super-agente. Tiene acceso a tools (proyectos, tasks, mcps, agentes); para un hilo más largo y persistente, abrí Chats.",
|
|
718
|
-
empty: "Mandale un mensaje a
|
|
719
|
-
thinking: "
|
|
720
|
-
talk: "Hablar con
|
|
718
|
+
empty: "Mandale un mensaje a {persona} para arrancar.",
|
|
719
|
+
thinking: "{persona} está pensando…",
|
|
720
|
+
talk: "Hablar con {persona}",
|
|
721
721
|
new_chat: "Nuevo chat",
|
|
722
722
|
placeholder: "Escribí y enter para enviar (shift+enter = nueva línea)…",
|
|
723
723
|
},
|
|
@@ -10,7 +10,7 @@ export const Agents = {
|
|
|
10
10
|
http.patch<AgentEntry>(`/projects/${pid}/agents/${encodeURIComponent(slug)}`, body),
|
|
11
11
|
remove: (pid: string, slug: string) =>
|
|
12
12
|
http.del<{ ok: boolean }>(`/projects/${pid}/agents/${encodeURIComponent(slug)}`),
|
|
13
|
-
chat: (pid: string, slug: string, body: { prompt: string; conversation_id?: string }) =>
|
|
13
|
+
chat: (pid: string, slug: string, body: { prompt: string; conversation_id?: string; model?: string }) =>
|
|
14
14
|
http.post<{ conversation_id: string; text: string; usage?: unknown; engine: string }>(
|
|
15
15
|
`/projects/${pid}/agents/${encodeURIComponent(slug)}/chat`,
|
|
16
16
|
body,
|
|
@@ -44,4 +44,14 @@ export const Artifacts = {
|
|
|
44
44
|
http.del<void>(
|
|
45
45
|
`/projects/${encodeURIComponent(pid)}/artifacts/${encodeURIComponent(name)}`,
|
|
46
46
|
),
|
|
47
|
+
write: (pid: string, name: string, content: string) =>
|
|
48
|
+
http.patch<{ ok: boolean; name: string }>(
|
|
49
|
+
`/projects/${encodeURIComponent(pid)}/artifacts/${encodeURIComponent(name)}`,
|
|
50
|
+
{ content },
|
|
51
|
+
),
|
|
52
|
+
rename: (pid: string, name: string, newName: string) =>
|
|
53
|
+
http.patch<{ ok: boolean; name: string }>(
|
|
54
|
+
`/projects/${encodeURIComponent(pid)}/artifacts/${encodeURIComponent(name)}`,
|
|
55
|
+
{ newName },
|
|
56
|
+
),
|
|
47
57
|
};
|
|
@@ -39,6 +39,7 @@ export interface CodeSessionRow {
|
|
|
39
39
|
title: string;
|
|
40
40
|
mode: CodeMode;
|
|
41
41
|
model: string | null;
|
|
42
|
+
agentSlug: string | null;
|
|
42
43
|
createdAt: string;
|
|
43
44
|
updatedAt: string;
|
|
44
45
|
messageCount: number;
|
|
@@ -53,6 +54,7 @@ export interface CodeSession {
|
|
|
53
54
|
createdAt: string;
|
|
54
55
|
updatedAt: string;
|
|
55
56
|
model: string | null;
|
|
57
|
+
agentSlug: string | null;
|
|
56
58
|
mode: CodeMode;
|
|
57
59
|
git: { baselineCommit: string | null; baselineTree: string } | null;
|
|
58
60
|
messages: CodeTurn[];
|
|
@@ -89,13 +91,13 @@ export const Code = {
|
|
|
89
91
|
|
|
90
92
|
create: (
|
|
91
93
|
pid: string | number,
|
|
92
|
-
body: { title?: string; model?: string | null; mode?: CodeMode } = {},
|
|
94
|
+
body: { title?: string; model?: string | null; mode?: CodeMode; agentSlug?: string | null } = {},
|
|
93
95
|
) => http.post<CodeSession>(base(pid), body),
|
|
94
96
|
|
|
95
97
|
update: (
|
|
96
98
|
pid: string | number,
|
|
97
99
|
sid: string,
|
|
98
|
-
patch: { title?: string; model?: string | null; mode?: CodeMode },
|
|
100
|
+
patch: { title?: string; model?: string | null; mode?: CodeMode; agentSlug?: string | null },
|
|
99
101
|
) => http.patch<CodeSession>(`${base(pid)}/${sid}`, patch),
|
|
100
102
|
|
|
101
103
|
remove: (pid: string | number, sid: string) =>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { http } from "../http";
|
|
2
|
+
|
|
3
|
+
export type SkillEntry = {
|
|
4
|
+
slug: string;
|
|
5
|
+
source: "bundled" | "user" | "project" | string;
|
|
6
|
+
description: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type SkillsList = {
|
|
10
|
+
count: number;
|
|
11
|
+
skills: SkillEntry[];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const Skills = {
|
|
15
|
+
/**
|
|
16
|
+
* List installed skills (bundled + user + optional project-scoped). The
|
|
17
|
+
* description is already condensed for one-line rendering.
|
|
18
|
+
*/
|
|
19
|
+
list: (projectPath?: string) =>
|
|
20
|
+
http.get<SkillsList>(
|
|
21
|
+
projectPath
|
|
22
|
+
? `/skills?project_path=${encodeURIComponent(projectPath)}`
|
|
23
|
+
: "/skills",
|
|
24
|
+
),
|
|
25
|
+
};
|