@agentprojectcontext/apx 1.31.2 → 1.32.2
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/constants.js +5 -0
- 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 +17 -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 +5 -0
- 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 +66 -36
- 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/core/agent/tools/handlers/ask-questions.js +115 -0
- 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} +3 -7
- 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/text-similarity.js +52 -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 +118 -1
- package/src/host/daemon/api/code.js +60 -16
- 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 +3 -3
- 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} +45 -6
- package/src/host/daemon/plugins/index.js +2 -2
- package/src/host/daemon/plugins/telegram/ask.js +309 -0
- package/src/host/daemon/plugins/{telegram.js → telegram/index.js} +390 -191
- 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/artifact.js +99 -0
- 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 +8 -4
- package/src/interfaces/cli/postinstall.js +2 -2
- package/src/interfaces/cli/terminal-chat/renderer.js +22 -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-34U_Mp1M.css +1 -0
- package/src/interfaces/web/dist/assets/index-BkybwwRn.js +570 -0
- package/src/interfaces/web/dist/assets/index-BkybwwRn.js.map +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/package-lock.json +9 -9
- package/src/interfaces/web/src/App.tsx +51 -32
- package/src/interfaces/web/src/components/RobyBubble.tsx +12 -6
- package/src/interfaces/web/src/components/UiSelect.tsx +1 -1
- package/src/interfaces/web/src/components/chat/AskQuestionsCard.tsx +72 -0
- package/src/interfaces/web/src/components/chat/InlineAskPanel.tsx +399 -0
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +16 -3
- package/src/interfaces/web/src/components/chat/MessageList.tsx +2 -1
- package/src/interfaces/web/src/components/chat/SkillPicker.tsx +77 -0
- package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +230 -0
- package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +1 -1
- package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +40 -17
- package/src/interfaces/web/src/components/common/TabLayout.tsx +9 -5
- 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/hooks/useChat.ts +47 -2
- package/src/interfaces/web/src/hooks/useNavCollapseCtx.tsx +59 -0
- package/src/interfaces/web/src/hooks/usePersonaName.ts +11 -0
- package/src/interfaces/web/src/i18n/en.ts +27 -7
- package/src/interfaces/web/src/i18n/es.ts +27 -7
- package/src/interfaces/web/src/lib/api/artifacts.ts +47 -0
- package/src/interfaces/web/src/lib/api/skills.ts +25 -0
- package/src/interfaces/web/src/lib/api.ts +2 -0
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +41 -20
- 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 +27 -9
- 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/super-agent-tools/tools/ask-questions.js +0 -32
- package/src/host/daemon/tool-call-parser.js +0 -2
- package/src/interfaces/web/dist/assets/index-BDUsA6L6.css +0 -1
- package/src/interfaces/web/dist/assets/index-BV615I9p.js +0 -548
- package/src/interfaces/web/dist/assets/index-BV615I9p.js.map +0 -1
- /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
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import useSWR from "swr";
|
|
3
|
+
import { ChevronRight, Copy, RefreshCw, Trash2, FileCode2, Play } from "lucide-react";
|
|
4
|
+
import { cn } from "../../lib/cn";
|
|
5
|
+
import { t } from "../../i18n";
|
|
6
|
+
import { Empty, Spinner } from "../ui";
|
|
7
|
+
import { Artifacts, type ArtifactEntry, type ArtifactRunResult } from "../../lib/api/artifacts";
|
|
8
|
+
import { useToast } from "../Toast";
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
pid: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function ArtifactRow({
|
|
15
|
+
pid,
|
|
16
|
+
entry,
|
|
17
|
+
onDeleted,
|
|
18
|
+
}: {
|
|
19
|
+
pid: string;
|
|
20
|
+
entry: ArtifactEntry;
|
|
21
|
+
onDeleted: () => void;
|
|
22
|
+
}) {
|
|
23
|
+
const [open, setOpen] = useState(false);
|
|
24
|
+
const [running, setRunning] = useState(false);
|
|
25
|
+
const [runResult, setRunResult] = useState<ArtifactRunResult | null>(null);
|
|
26
|
+
const toast = useToast();
|
|
27
|
+
const detail = useSWR(open ? ["artifact", pid, entry.name] : null, () =>
|
|
28
|
+
Artifacts.read(pid, entry.name),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// Daemon-side detection: a file is runnable if it has the exec bit OR
|
|
32
|
+
// starts with a shebang. Locally we can only check the shebang from the
|
|
33
|
+
// fetched content; if it's missing we still show Run (the daemon will
|
|
34
|
+
// 400 cleanly and the toast surfaces the reason).
|
|
35
|
+
const looksRunnable = !detail.data?.content || detail.data.content.startsWith("#!");
|
|
36
|
+
|
|
37
|
+
const copy = async (text: string) => {
|
|
38
|
+
try {
|
|
39
|
+
await navigator.clipboard.writeText(text);
|
|
40
|
+
toast.info("Copiado.");
|
|
41
|
+
} catch {
|
|
42
|
+
/* ignore */
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const run = async () => {
|
|
47
|
+
setRunning(true);
|
|
48
|
+
setRunResult(null);
|
|
49
|
+
try {
|
|
50
|
+
const r = await Artifacts.run(pid, entry.name);
|
|
51
|
+
setRunResult(r);
|
|
52
|
+
if (r.ok) toast.info(`exit 0 — ${r.durationMs}ms`);
|
|
53
|
+
else toast.error(`exit ${r.exitCode ?? r.signal ?? "?"}${r.timedOut ? " (timeout)" : ""}`);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
toast.error((e as Error).message);
|
|
56
|
+
} finally {
|
|
57
|
+
setRunning(false);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const remove = async () => {
|
|
62
|
+
if (!window.confirm(t("code_module.artifacts_delete_confirm"))) return;
|
|
63
|
+
try {
|
|
64
|
+
await Artifacts.remove(pid, entry.name);
|
|
65
|
+
onDeleted();
|
|
66
|
+
} catch (e) {
|
|
67
|
+
toast.error((e as Error).message);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<li className="rounded-md border border-border">
|
|
73
|
+
<button
|
|
74
|
+
type="button"
|
|
75
|
+
onClick={() => setOpen((v) => !v)}
|
|
76
|
+
className="flex w-full items-center gap-2 px-2 py-1.5 text-left text-xs hover:bg-accent/40"
|
|
77
|
+
>
|
|
78
|
+
<ChevronRight
|
|
79
|
+
className={cn(
|
|
80
|
+
"size-3 shrink-0 transition-transform",
|
|
81
|
+
open && "rotate-90",
|
|
82
|
+
)}
|
|
83
|
+
/>
|
|
84
|
+
<FileCode2 className="size-3.5 shrink-0 text-emerald-600 dark:text-emerald-400" />
|
|
85
|
+
<span className="min-w-0 flex-1 truncate font-mono">{entry.name}</span>
|
|
86
|
+
<span className="shrink-0 font-mono text-[10px] text-muted-foreground">
|
|
87
|
+
{entry.size}b
|
|
88
|
+
</span>
|
|
89
|
+
</button>
|
|
90
|
+
{open && (
|
|
91
|
+
<div className="space-y-2 border-t border-border p-2">
|
|
92
|
+
<div className="flex flex-wrap items-center gap-1">
|
|
93
|
+
<code className="min-w-0 flex-1 truncate rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground">
|
|
94
|
+
{entry.path}
|
|
95
|
+
</code>
|
|
96
|
+
{looksRunnable && (
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
onClick={() => void run()}
|
|
100
|
+
disabled={running}
|
|
101
|
+
title={t("code_module.artifacts_run")}
|
|
102
|
+
className={cn(
|
|
103
|
+
"inline-flex items-center gap-1 rounded px-1.5 py-1 text-[10px] font-medium",
|
|
104
|
+
running
|
|
105
|
+
? "bg-muted text-muted-foreground"
|
|
106
|
+
: "bg-emerald-500/15 text-emerald-700 hover:bg-emerald-500/25 dark:text-emerald-300",
|
|
107
|
+
)}
|
|
108
|
+
>
|
|
109
|
+
{running ? <Spinner size={10} /> : <Play className="size-3" />}
|
|
110
|
+
{t("code_module.artifacts_run")}
|
|
111
|
+
</button>
|
|
112
|
+
)}
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
onClick={() => void copy(entry.path)}
|
|
116
|
+
title={t("code_module.artifacts_copy_path")}
|
|
117
|
+
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
118
|
+
>
|
|
119
|
+
<Copy className="size-3" />
|
|
120
|
+
</button>
|
|
121
|
+
<button
|
|
122
|
+
type="button"
|
|
123
|
+
onClick={() => void remove()}
|
|
124
|
+
title={t("code_module.artifacts_delete")}
|
|
125
|
+
className="rounded p-1 text-rose-600 hover:bg-rose-50 dark:text-rose-400 dark:hover:bg-rose-950"
|
|
126
|
+
>
|
|
127
|
+
<Trash2 className="size-3" />
|
|
128
|
+
</button>
|
|
129
|
+
</div>
|
|
130
|
+
<div className="text-[10px] text-muted-foreground">
|
|
131
|
+
{t("code_module.artifacts_run_hint")}{" "}
|
|
132
|
+
<code className="rounded bg-muted px-1 font-mono">
|
|
133
|
+
apx artifact run {entry.name}
|
|
134
|
+
</code>
|
|
135
|
+
</div>
|
|
136
|
+
{runResult && (
|
|
137
|
+
<div className="space-y-1">
|
|
138
|
+
<div className="flex items-center gap-2 text-[10px]">
|
|
139
|
+
<span
|
|
140
|
+
className={cn(
|
|
141
|
+
"rounded px-1.5 py-0.5 font-mono",
|
|
142
|
+
runResult.ok
|
|
143
|
+
? "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300"
|
|
144
|
+
: "bg-rose-500/15 text-rose-700 dark:text-rose-300",
|
|
145
|
+
)}
|
|
146
|
+
>
|
|
147
|
+
exit {runResult.exitCode ?? runResult.signal ?? "?"}
|
|
148
|
+
</span>
|
|
149
|
+
{runResult.timedOut && (
|
|
150
|
+
<span className="rounded bg-amber-500/15 px-1.5 py-0.5 font-mono text-amber-700 dark:text-amber-300">
|
|
151
|
+
timeout
|
|
152
|
+
</span>
|
|
153
|
+
)}
|
|
154
|
+
{runResult.truncated && (
|
|
155
|
+
<span className="rounded bg-amber-500/15 px-1.5 py-0.5 font-mono text-amber-700 dark:text-amber-300">
|
|
156
|
+
truncated
|
|
157
|
+
</span>
|
|
158
|
+
)}
|
|
159
|
+
<span className="font-mono text-muted-foreground">
|
|
160
|
+
{runResult.durationMs}ms
|
|
161
|
+
</span>
|
|
162
|
+
</div>
|
|
163
|
+
{runResult.stdout && (
|
|
164
|
+
<pre className="max-h-32 overflow-auto rounded bg-background/60 p-2 text-[10px] leading-tight">
|
|
165
|
+
{runResult.stdout}
|
|
166
|
+
</pre>
|
|
167
|
+
)}
|
|
168
|
+
{runResult.stderr && (
|
|
169
|
+
<pre className="max-h-32 overflow-auto rounded bg-rose-500/5 p-2 text-[10px] leading-tight text-rose-700 dark:text-rose-300">
|
|
170
|
+
{runResult.stderr}
|
|
171
|
+
</pre>
|
|
172
|
+
)}
|
|
173
|
+
</div>
|
|
174
|
+
)}
|
|
175
|
+
{detail.isLoading ? (
|
|
176
|
+
<div className="flex justify-center py-2">
|
|
177
|
+
<Spinner size={12} />
|
|
178
|
+
</div>
|
|
179
|
+
) : detail.data?.content ? (
|
|
180
|
+
<pre className="max-h-64 overflow-auto rounded bg-muted/50 p-2 text-[10px] leading-tight">
|
|
181
|
+
{detail.data.content}
|
|
182
|
+
</pre>
|
|
183
|
+
) : null}
|
|
184
|
+
</div>
|
|
185
|
+
)}
|
|
186
|
+
</li>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Artifacts tab: managed files stored under <project>/artifacts/. The agent
|
|
191
|
+
// puts reusable scripts here so the user can run them from a terminal.
|
|
192
|
+
export function CodeArtifactsTab({ pid }: Props) {
|
|
193
|
+
const list = useSWR(pid ? ["artifacts", pid] : null, () => Artifacts.list(pid));
|
|
194
|
+
const entries = list.data || [];
|
|
195
|
+
return (
|
|
196
|
+
<div className="flex h-full flex-col" data-testid="code-artifacts-tab">
|
|
197
|
+
<div className="flex shrink-0 items-center justify-between px-3 py-2">
|
|
198
|
+
<span className="text-[11px] text-muted-foreground">
|
|
199
|
+
{entries.length > 0
|
|
200
|
+
? t("code_module.artifacts_count", { n: entries.length })
|
|
201
|
+
: ""}
|
|
202
|
+
</span>
|
|
203
|
+
<button
|
|
204
|
+
type="button"
|
|
205
|
+
onClick={() => void list.mutate()}
|
|
206
|
+
title="↻"
|
|
207
|
+
className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
208
|
+
>
|
|
209
|
+
{list.isLoading ? <Spinner size={12} /> : <RefreshCw className="size-3" />}
|
|
210
|
+
</button>
|
|
211
|
+
</div>
|
|
212
|
+
<div className="min-h-0 flex-1 overflow-y-auto px-3 pb-3">
|
|
213
|
+
{entries.length === 0 ? (
|
|
214
|
+
<Empty>{t("code_module.artifacts_none")}</Empty>
|
|
215
|
+
) : (
|
|
216
|
+
<ul className="space-y-1.5">
|
|
217
|
+
{entries.map((a) => (
|
|
218
|
+
<ArtifactRow
|
|
219
|
+
key={a.name}
|
|
220
|
+
pid={pid}
|
|
221
|
+
entry={a}
|
|
222
|
+
onDeleted={() => void list.mutate()}
|
|
223
|
+
/>
|
|
224
|
+
))}
|
|
225
|
+
</ul>
|
|
226
|
+
)}
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
);
|
|
230
|
+
}
|
|
@@ -26,7 +26,7 @@ export function CodeProjectPicker({ projects, value, onChange, disabled }: Props
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
|
-
<div className="w-
|
|
29
|
+
<div className="w-full" data-testid="code-project-select">
|
|
30
30
|
<UiSelect
|
|
31
31
|
value={value}
|
|
32
32
|
onChange={onChange}
|
|
@@ -1,36 +1,56 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { Gauge, GitCompare, Package } from "lucide-react";
|
|
2
3
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from "../ui/tabs";
|
|
3
4
|
import { t } from "../../i18n";
|
|
4
5
|
import { CodeContextTab } from "./CodeContextTab";
|
|
5
6
|
import { CodeChangesTab } from "./CodeChangesTab";
|
|
7
|
+
import { CodeArtifactsTab } from "./CodeArtifactsTab";
|
|
6
8
|
import type { CodeChanges, CodeTurn } from "../../lib/api/code";
|
|
7
9
|
|
|
8
10
|
interface Props {
|
|
11
|
+
pid: string;
|
|
9
12
|
turns: CodeTurn[];
|
|
10
13
|
changes: CodeChanges | undefined;
|
|
11
14
|
changesLoading: boolean;
|
|
12
15
|
onRefreshChanges: () => void;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const TABS = [
|
|
19
|
+
{ value: "context", icon: Gauge, label: "tab_context" },
|
|
20
|
+
{ value: "changes", icon: GitCompare, label: "tab_changes" },
|
|
21
|
+
{ value: "artifacts", icon: Package, label: "tab_artifacts" },
|
|
22
|
+
] as const;
|
|
23
|
+
|
|
24
|
+
export function CodeSidePanel({ pid, turns, changes, changesLoading, onRefreshChanges }: Props) {
|
|
25
|
+
const [active, setActive] = useState<string>("context");
|
|
18
26
|
const changeCount = changes?.files.length || 0;
|
|
27
|
+
|
|
19
28
|
return (
|
|
20
|
-
<Tabs
|
|
21
|
-
<div className="shrink-0 border-b border-border px-
|
|
29
|
+
<Tabs value={active} onValueChange={setActive} className="flex h-full flex-col gap-0" data-testid="code-side-panel">
|
|
30
|
+
<div className="shrink-0 border-b border-border px-2 py-2">
|
|
22
31
|
<TabsList variant="line" className="w-full">
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
{TABS.map(({ value, icon: Icon, label }) => {
|
|
33
|
+
const isActive = active === value;
|
|
34
|
+
const fullLabel = t(`code_module.${label}` as never);
|
|
35
|
+
return (
|
|
36
|
+
<TabsTrigger
|
|
37
|
+
key={value}
|
|
38
|
+
value={value}
|
|
39
|
+
title={fullLabel}
|
|
40
|
+
className={isActive ? "flex-1 min-w-0" : "w-8 shrink-0"}
|
|
41
|
+
>
|
|
42
|
+
<Icon className="size-3.5 shrink-0" />
|
|
43
|
+
{isActive && (
|
|
44
|
+
<span className="truncate text-xs">{fullLabel}</span>
|
|
45
|
+
)}
|
|
46
|
+
{value === "changes" && changeCount > 0 && (
|
|
47
|
+
<span className="ml-0.5 rounded-full bg-muted px-1 text-[10px] text-muted-foreground leading-none py-0.5">
|
|
48
|
+
{changeCount}
|
|
49
|
+
</span>
|
|
50
|
+
)}
|
|
51
|
+
</TabsTrigger>
|
|
52
|
+
);
|
|
53
|
+
})}
|
|
34
54
|
</TabsList>
|
|
35
55
|
</div>
|
|
36
56
|
<TabsContent value="context" className="min-h-0 flex-1 overflow-y-auto">
|
|
@@ -39,6 +59,9 @@ export function CodeSidePanel({ turns, changes, changesLoading, onRefreshChanges
|
|
|
39
59
|
<TabsContent value="changes" className="min-h-0 flex-1 overflow-hidden">
|
|
40
60
|
<CodeChangesTab changes={changes} loading={changesLoading} onRefresh={onRefreshChanges} />
|
|
41
61
|
</TabsContent>
|
|
62
|
+
<TabsContent value="artifacts" className="min-h-0 flex-1 overflow-hidden">
|
|
63
|
+
<CodeArtifactsTab pid={pid} />
|
|
64
|
+
</TabsContent>
|
|
42
65
|
</Tabs>
|
|
43
66
|
);
|
|
44
67
|
}
|
|
@@ -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,14 +30,17 @@ 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
38
|
<div className="flex min-w-0 flex-1 flex-col overflow-y-auto">
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
{actions ? (
|
|
40
|
+
<div className="flex items-center justify-end gap-2 px-6 pt-3">
|
|
41
|
+
{actions}
|
|
42
|
+
</div>
|
|
43
|
+
) : null}
|
|
40
44
|
<div className={cn(contentClassName)} data-testid={testId}>
|
|
41
45
|
{children}
|
|
42
46
|
</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,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) => [
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
// ── Combined provider (one wrapper in Shell) ──────────────────────────────────
|
|
16
|
+
|
|
17
|
+
export function NavCollapseProvider({ children }: { children: ReactNode }) {
|
|
18
|
+
const [collapse, setCollapse] = useState<CollapseState>(null);
|
|
19
|
+
const [label, setLabel] = useState("");
|
|
20
|
+
return (
|
|
21
|
+
<CollapseSetCtx.Provider value={setCollapse}>
|
|
22
|
+
<CollapseReadCtx.Provider value={collapse}>
|
|
23
|
+
<LabelSetCtx.Provider value={setLabel}>
|
|
24
|
+
<LabelReadCtx.Provider value={label}>
|
|
25
|
+
{children}
|
|
26
|
+
</LabelReadCtx.Provider>
|
|
27
|
+
</LabelSetCtx.Provider>
|
|
28
|
+
</CollapseReadCtx.Provider>
|
|
29
|
+
</CollapseSetCtx.Provider>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ── Nav collapse hooks ────────────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
export function useNavCollapseCtx() {
|
|
36
|
+
return useContext(CollapseReadCtx);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function useRegisterNavCollapse(collapsed: boolean, toggle: () => void) {
|
|
40
|
+
const setState = useContext(CollapseSetCtx);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
setState?.({ collapsed, toggle });
|
|
43
|
+
return () => setState?.(null);
|
|
44
|
+
}, [collapsed, toggle, setState]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ── Page label hooks ──────────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
export function usePageLabel() {
|
|
50
|
+
return useContext(LabelReadCtx);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function useSetPageLabel(label: string) {
|
|
54
|
+
const set = useContext(LabelSetCtx);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
set?.(label);
|
|
57
|
+
return () => set?.("");
|
|
58
|
+
}, [label, set]);
|
|
59
|
+
}
|
|
@@ -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
|
},
|
|
@@ -726,6 +726,18 @@ export const en = {
|
|
|
726
726
|
message: "That route does not exist.",
|
|
727
727
|
},
|
|
728
728
|
|
|
729
|
+
ask_panel: {
|
|
730
|
+
answers_header: "Answers",
|
|
731
|
+
other: "Other",
|
|
732
|
+
other_placeholder: "Write your own answer here",
|
|
733
|
+
text_placeholder: "Type your answer…",
|
|
734
|
+
back: "Back",
|
|
735
|
+
skip: "Skip",
|
|
736
|
+
next: "Next",
|
|
737
|
+
submit: "Send",
|
|
738
|
+
status_waiting: "Waiting for your answer…",
|
|
739
|
+
status_received: "Answers received",
|
|
740
|
+
},
|
|
729
741
|
code_module: {
|
|
730
742
|
title: "Code",
|
|
731
743
|
badge: "super-agent",
|
|
@@ -747,6 +759,14 @@ export const en = {
|
|
|
747
759
|
mode_plan_hint: "Plan — read-only, proposes changes without touching files",
|
|
748
760
|
tab_context: "Context",
|
|
749
761
|
tab_changes: "Changes",
|
|
762
|
+
tab_artifacts: "Artifacts",
|
|
763
|
+
artifacts_none: "No artifacts yet. Ask the agent to create a script under `artifacts/<name>`.",
|
|
764
|
+
artifacts_count: "{n} artifact(s)",
|
|
765
|
+
artifacts_copy_path: "Copy path",
|
|
766
|
+
artifacts_run: "Run",
|
|
767
|
+
artifacts_run_hint: "Run it from your terminal:",
|
|
768
|
+
artifacts_delete: "Delete",
|
|
769
|
+
artifacts_delete_confirm: "Delete this artifact? The file will be removed from disk.",
|
|
750
770
|
ctx_model: "Model",
|
|
751
771
|
ctx_tokens: "Tokens",
|
|
752
772
|
ctx_input: "Input",
|