@agentprojectcontext/apx 1.33.1 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/apx/SKILL.md +49 -61
- package/src/core/agent/a2a/reply.js +48 -0
- package/src/core/agent/build-agent-system.js +136 -59
- package/src/core/agent/channels/voice-context.js +98 -0
- package/src/core/agent/memory.js +2 -1
- package/src/core/agent/prompt-builder.js +178 -124
- package/src/core/agent/prompts/channels/code.md +12 -10
- package/src/core/agent/prompts/channels/desktop.md +5 -32
- package/src/core/agent/prompts/channels/telegram.md +4 -15
- package/src/core/agent/prompts/channels/web_code.md +11 -11
- package/src/core/agent/prompts/core/agent-base.md +24 -0
- package/src/core/agent/prompts/core/project-agent.md +11 -0
- package/src/core/agent/prompts/core/super-agent.md +21 -0
- package/src/core/agent/prompts/discipline/action.md +10 -0
- package/src/core/agent/prompts/discipline/single-segment.md +6 -0
- package/src/core/agent/prompts/discipline/two-segment.md +11 -0
- package/src/core/agent/prompts/modes/code-build.md +1 -0
- package/src/core/agent/prompts/modes/code-plan.md +1 -0
- package/src/core/agent/prompts/modes/index.js +28 -0
- package/src/core/agent/self-memory.js +43 -1
- package/src/core/agent/skills/index-store.js +307 -0
- package/src/core/agent/skills/index.js +15 -1
- package/src/core/agent/skills/inspector.js +317 -0
- package/src/core/agent/skills/loader.js +22 -18
- package/src/core/agent/stream/turn-accumulator.js +73 -0
- package/src/core/agent/suggestions.js +37 -0
- package/src/core/agent/super-agent.js +7 -1
- package/src/core/agent/tools/handlers/_git.js +50 -0
- package/src/core/agent/tools/handlers/add-project.js +5 -2
- package/src/core/agent/tools/handlers/call-runtime.js +3 -2
- package/src/core/agent/tools/handlers/git-diff.js +44 -0
- package/src/core/agent/tools/handlers/git-log.js +38 -0
- package/src/core/agent/tools/handlers/git-show.js +34 -0
- package/src/core/agent/tools/handlers/git-status.js +61 -0
- package/src/core/agent/tools/handlers/transcribe-audio.js +1 -1
- package/src/core/agent/tools/helpers.js +2 -2
- package/src/core/agent/tools/names.js +169 -0
- package/src/core/agent/tools/registry-bridge.js +6 -14
- package/src/core/agent/tools/registry.js +103 -69
- package/src/core/apc/context-copy.js +27 -0
- package/src/core/apc/notes.js +19 -0
- package/src/core/apc/parser.js +12 -5
- package/src/core/apc/paths.js +87 -0
- package/src/core/apc/scaffold.js +82 -76
- package/src/core/apc/skill-sync.js +10 -0
- package/src/{host/daemon/plugins → core/channels}/telegram/dispatch.js +38 -16
- package/src/core/config/index.js +24 -2
- package/src/core/config/redact.js +95 -0
- package/src/core/constants/channels.js +2 -0
- package/src/core/constants/code-modes.js +10 -0
- package/src/core/constants/index.js +1 -0
- package/src/core/deck/manifest.js +186 -0
- package/src/core/engines/catalog.js +83 -0
- package/src/core/{tools → http-tools}/browser.js +0 -1
- package/src/core/{tools → http-tools}/fetch.js +0 -1
- package/src/core/{tools → http-tools}/glob.js +0 -1
- package/src/core/{tools → http-tools}/grep.js +0 -1
- package/src/core/{tools → http-tools}/registry.js +0 -1
- package/src/core/{tools → http-tools}/search.js +0 -1
- package/src/core/i18n/en.js +9 -0
- package/src/core/i18n/es.js +12 -0
- package/src/core/i18n/index.js +54 -0
- package/src/core/i18n/pt.js +9 -0
- package/src/core/identity/telegram.js +2 -1
- package/src/core/mcp/runner.js +272 -14
- package/src/core/mcp/sources.js +3 -2
- package/src/core/routines/index.js +16 -0
- package/src/{host/daemon/routines.js → core/routines/runner.js} +36 -103
- package/src/core/runtime-skills/apc-context/SKILL.md +159 -0
- package/src/core/runtime-skills/apx/SKILL.md +83 -0
- package/src/core/runtime-skills/apx-agency-agents/SKILL.md +125 -0
- package/src/core/runtime-skills/apx-agent/SKILL.md +97 -0
- package/src/core/runtime-skills/apx-mcp/SKILL.md +111 -0
- package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +169 -0
- package/{skills → src/core/runtime-skills}/apx-project/SKILL.md +20 -29
- package/src/core/runtime-skills/apx-routine/SKILL.md +127 -0
- package/src/core/runtime-skills/apx-runtime/SKILL.md +99 -0
- package/src/core/runtime-skills/apx-sessions/SKILL.md +232 -0
- package/src/core/runtime-skills/apx-skill-builder/SKILL.md +129 -0
- package/{skills → src/core/runtime-skills}/apx-task/SKILL.md +18 -21
- package/src/core/runtime-skills/apx-telegram/SKILL.md +120 -0
- package/src/core/runtime-skills/apx-voice/SKILL.md +117 -0
- package/src/core/runtime-skills/{claude-code.md → claude-code/SKILL.md} +1 -0
- package/src/core/runtime-skills/{codex-cli.md → codex-cli/SKILL.md} +1 -0
- package/src/core/runtime-skills/{opencode-cli.md → opencode-cli/SKILL.md} +1 -0
- package/src/core/runtime-skills/{openrouter.md → openrouter/SKILL.md} +1 -0
- package/src/{host/daemon/env-detect.js → core/runtimes/detect.js} +1 -1
- package/src/core/stores/code-sessions.js +50 -2
- package/src/core/stores/routine-memory.js +1 -1
- package/src/core/stores/sessions-search.js +121 -0
- package/src/core/stores/sessions.js +38 -0
- package/src/core/vars/index.js +14 -0
- package/src/core/vars/interpolate.js +86 -0
- package/src/core/vars/sources.js +151 -0
- package/src/core/voice/audio-decode.js +38 -0
- package/src/core/voice/transcription.js +225 -0
- package/src/host/daemon/api/admin-config.js +5 -82
- package/src/host/daemon/api/agents.js +5 -5
- package/src/host/daemon/api/code.js +17 -169
- package/src/host/daemon/api/config.js +3 -4
- package/src/host/daemon/api/conversations.js +8 -29
- package/src/host/daemon/api/deck.js +37 -404
- package/src/host/daemon/api/engines.js +1 -80
- package/src/host/daemon/api/exec.js +1 -1
- package/src/host/daemon/api/mcps.js +32 -0
- package/src/host/daemon/api/routines.js +1 -1
- package/src/host/daemon/api/runtimes.js +4 -3
- package/src/host/daemon/api/sessions-search.js +24 -140
- package/src/host/daemon/api/sessions.js +12 -30
- package/src/host/daemon/api/shared.js +2 -1
- package/src/host/daemon/api/skills.js +140 -6
- package/src/host/daemon/api/super-agent.js +56 -1
- package/src/host/daemon/api/telegram.js +1 -11
- package/src/host/daemon/api/tools.js +6 -6
- package/src/host/daemon/api/transcribe.js +2 -2
- package/src/host/daemon/api/vars.js +137 -0
- package/src/host/daemon/api/voice.js +13 -290
- package/src/host/daemon/api.js +2 -0
- package/src/host/daemon/db.js +6 -6
- package/src/host/daemon/deck-exec.js +148 -0
- package/src/host/daemon/index.js +20 -3
- package/src/host/daemon/plugins/telegram/index.js +9 -9
- package/src/host/daemon/routines-scheduler.js +64 -0
- package/src/host/daemon/smoke.js +3 -2
- package/src/host/daemon/whisper-server.js +225 -0
- package/src/interfaces/cli/branding.js +53 -0
- package/src/interfaces/cli/commands/agent.js +3 -2
- package/src/interfaces/cli/commands/command.js +2 -3
- package/src/interfaces/cli/commands/messages.js +6 -2
- package/src/interfaces/cli/commands/pair.js +5 -4
- package/src/interfaces/cli/commands/search.js +1 -1
- package/src/interfaces/cli/commands/sessions.js +3 -2
- package/src/interfaces/cli/commands/skills.js +290 -55
- package/src/interfaces/cli/index.js +84 -2
- package/src/interfaces/web/dist/assets/index-C0fm31dY.js +618 -0
- package/src/interfaces/web/dist/assets/index-C0fm31dY.js.map +1 -0
- package/src/interfaces/web/dist/assets/index-UcAqlBO6.css +1 -0
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/package-lock.json +182 -182
- package/src/interfaces/web/src/components/ModelCombobox.tsx +2 -1
- package/src/interfaces/web/src/components/TelegramChannelDialog.tsx +1 -1
- package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +76 -0
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +37 -4
- package/src/interfaces/web/src/components/chat/MessageList.tsx +23 -1
- package/src/interfaces/web/src/components/chat/ModelPicker.tsx +3 -1
- package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +4 -4
- package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +1 -1
- package/src/interfaces/web/src/components/code/CodeFileTree.tsx +3 -2
- package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +3 -2
- package/src/interfaces/web/src/components/code/CodeTerminal.tsx +3 -2
- package/src/interfaces/web/src/components/config/GlobalConfigEditor.tsx +2 -1
- package/src/interfaces/web/src/components/deck/WidgetRow.tsx +2 -1
- package/src/interfaces/web/src/components/inputs/KeyValueList.tsx +93 -0
- package/src/interfaces/web/src/components/inputs/VarTokenInput.tsx +449 -0
- package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +2 -1
- package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +2 -2
- package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +73 -4
- package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +222 -0
- package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +3 -2
- package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +3 -2
- package/src/interfaces/web/src/components/ui/chat-input.tsx +5 -4
- package/src/interfaces/web/src/components/ui/sidebar.tsx +3 -2
- package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +2 -1
- package/src/interfaces/web/src/constants/index.ts +1 -1
- package/src/interfaces/web/src/hooks/useChat.ts +19 -0
- package/src/interfaces/web/src/i18n/en.ts +175 -7
- package/src/interfaces/web/src/i18n/es.ts +180 -15
- package/src/interfaces/web/src/lib/api/mcps.ts +25 -0
- package/src/interfaces/web/src/lib/api/skills.ts +70 -0
- package/src/interfaces/web/src/lib/api/vars.ts +38 -0
- package/src/interfaces/web/src/lib/api.ts +1 -0
- package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -31
- package/src/interfaces/web/src/screens/SettingsScreen.tsx +6 -2
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +4 -3
- package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +7 -6
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +4 -3
- package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/project/ConfigTab.tsx +132 -1
- package/src/interfaces/web/src/screens/project/McpsTab.tsx +549 -104
- package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +1 -1
- package/src/interfaces/web/src/screens/project/VarsTab.tsx +300 -0
- package/src/interfaces/web/src/types/daemon.ts +15 -0
- package/skills/apx-agency-agents/SKILL.md +0 -141
- package/skills/apx-agent/SKILL.md +0 -100
- package/skills/apx-mcp-builder/SKILL.md +0 -183
- package/skills/apx-routine/SKILL.md +0 -140
- package/skills/apx-runtime/SKILL.md +0 -117
- package/skills/apx-sessions/SKILL.md +0 -281
- package/skills/apx-skill-builder/SKILL.md +0 -153
- package/skills/apx-telegram/SKILL.md +0 -131
- package/skills/apx-voice/SKILL.md +0 -137
- package/src/core/agent/prompts/action-discipline.md +0 -24
- package/src/core/agent/prompts/super-agent-base.md +0 -42
- package/src/host/daemon/transcription.js +0 -538
- package/src/host/daemon/whisper-transcribe.py +0 -73
- package/src/interfaces/web/dist/assets/index-Aaiw8BZN.css +0 -1
- package/src/interfaces/web/dist/assets/index-DPqtjDjh.js +0 -602
- package/src/interfaces/web/dist/assets/index-DPqtjDjh.js.map +0 -1
- /package/src/{host/daemon → core/apc}/projects-helpers.js +0 -0
- /package/src/{host/daemon/plugins → core/channels}/telegram/ask.js +0 -0
- /package/src/{host/daemon/plugins → core/channels}/telegram/helpers.js +0 -0
- /package/src/{host/daemon/plugins → core/channels}/telegram/media.js +0 -0
- /package/src/core/{tools → http-tools}/index.js +0 -0
- /package/src/{host/daemon/compact.js → core/stores/conversations-compactor.js} +0 -0
- /package/src/{host/daemon → core/stores}/conversations.js +0 -0
- /package/src/{host/daemon → core/util}/thinking.js +0 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import useSWR from "swr";
|
|
3
|
+
import { Sparkles, RefreshCw, Wand2 } from "lucide-react";
|
|
4
|
+
import { Section } from "../Section";
|
|
5
|
+
import { Button, Field, Input, Loading, Badge, Switch } from "../ui";
|
|
6
|
+
import { useToast } from "../Toast";
|
|
7
|
+
import { Skills, type InspectTrace } from "../../lib/api/skills";
|
|
8
|
+
|
|
9
|
+
// Skill Inspector — per-turn skill RAG middleware. When ON, the static
|
|
10
|
+
// "available skills" slug-dump is removed from the agent's system prompt and a
|
|
11
|
+
// local RAG injects, per turn, only the skill(s) the user's message actually
|
|
12
|
+
// needs. This panel toggles the feature, tunes its thresholds, (re)builds the
|
|
13
|
+
// vector index, and offers a live dry-run so you can see what it would surface.
|
|
14
|
+
//
|
|
15
|
+
// Mirrors MemoryPanel (RAG embeddings): same Section/Field/Button idiom. Config
|
|
16
|
+
// persists under config.skills.inspector.* via the inspector PUT endpoint, so
|
|
17
|
+
// no separate global-config patch is needed.
|
|
18
|
+
|
|
19
|
+
// Numeric knobs with human labels + sane ranges. We keep them as plain number
|
|
20
|
+
// inputs (same idiom as the embeddings model fields) rather than sliders so the
|
|
21
|
+
// values are explicit and copy-pasteable.
|
|
22
|
+
const KNOBS: { key: keyof NumericKnobs; label: string; hint: string; step: number; min: number; max: number }[] = [
|
|
23
|
+
{ key: "load_threshold", label: "Umbral de carga", hint: "Similitud mínima para inyectar el CUERPO de la skill (alto = más estricto).", step: 0.01, min: 0, max: 1 },
|
|
24
|
+
{ key: "hint_threshold", label: "Umbral de sugerencia", hint: "Similitud mínima para solo SUGERIR la skill (que el agente la cargue si quiere).", step: 0.01, min: 0, max: 1 },
|
|
25
|
+
{ key: "margin", label: "Margen sobre el 2º", hint: "El top debe superar al segundo por este margen para cargar su cuerpo (evita empates flojos).", step: 0.01, min: 0, max: 1 },
|
|
26
|
+
{ key: "max_loaded", label: "Máx. cuerpos cargados", hint: "Cuántas skills se inyectan completas por turno.", step: 1, min: 0, max: 5 },
|
|
27
|
+
{ key: "max_hints", label: "Máx. sugerencias", hint: "Cuántas skills extra se nombran como sugerencia.", step: 1, min: 0, max: 8 },
|
|
28
|
+
{ key: "prompt_floor", label: "Largo mínimo del prompt", hint: "Mensajes más cortos que esto se ignoran (evita 'ok', 'hola').", step: 1, min: 0, max: 40 },
|
|
29
|
+
{ key: "body_char_cap", label: "Tope de chars del cuerpo", hint: "Recorta cuerpos de skill largos para no inflar el contexto.", step: 500, min: 500, max: 20000 },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
type NumericKnobs = {
|
|
33
|
+
load_threshold: number; hint_threshold: number; margin: number;
|
|
34
|
+
max_loaded: number; max_hints: number; prompt_floor: number; body_char_cap: number;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export function SkillsInspectorPanel() {
|
|
38
|
+
const toast = useToast();
|
|
39
|
+
const { data, mutate, isLoading } = useSWR("/skills/inspector", () => Skills.inspector());
|
|
40
|
+
const [busy, setBusy] = useState(false);
|
|
41
|
+
const [probe, setProbe] = useState("");
|
|
42
|
+
const [probeResult, setProbeResult] = useState<InspectTrace | null>(null);
|
|
43
|
+
|
|
44
|
+
if (isLoading || !data) return <Loading />;
|
|
45
|
+
|
|
46
|
+
const cfg = data.config;
|
|
47
|
+
const idx = data.index;
|
|
48
|
+
|
|
49
|
+
const apply = async (patch: Record<string, unknown>) => {
|
|
50
|
+
setBusy(true);
|
|
51
|
+
try {
|
|
52
|
+
await Skills.updateInspector(patch);
|
|
53
|
+
await mutate();
|
|
54
|
+
} catch (e) {
|
|
55
|
+
toast.error(`No se pudo guardar: ${(e as Error).message}`);
|
|
56
|
+
} finally {
|
|
57
|
+
setBusy(false);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const runIndex = async (force = false) => {
|
|
62
|
+
setBusy(true);
|
|
63
|
+
try {
|
|
64
|
+
const r = await Skills.index({ force });
|
|
65
|
+
toast.success(
|
|
66
|
+
`Indexado con ${r.embedder} (dim ${r.dim}): +${r.changed.added} ~${r.changed.refreshed} -${r.changed.removed}.`,
|
|
67
|
+
);
|
|
68
|
+
await mutate();
|
|
69
|
+
} catch (e) {
|
|
70
|
+
toast.error(`Falló el index: ${(e as Error).message}`);
|
|
71
|
+
} finally {
|
|
72
|
+
setBusy(false);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const runProbe = async () => {
|
|
77
|
+
if (!probe.trim()) return;
|
|
78
|
+
setBusy(true);
|
|
79
|
+
setProbeResult(null);
|
|
80
|
+
try {
|
|
81
|
+
const r = await Skills.inspect(probe.trim());
|
|
82
|
+
setProbeResult(r.trace);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
toast.error(`Falló el dry-run: ${(e as Error).message}`);
|
|
85
|
+
} finally {
|
|
86
|
+
setBusy(false);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div className="space-y-6">
|
|
92
|
+
<Section
|
|
93
|
+
title="Skill Inspector (RAG por turno)"
|
|
94
|
+
description="Función experimental. Cuando está activa, el agente NO recibe la lista completa de skills en su prompt; en cada mensaje un RAG local decide qué skill(s) cargar — el cuerpo completo si hay match fuerte, una sugerencia si hay match medio, nada si no aplica. Se reevalúa cada turno: una skill que dejó de ser relevante desaparece del contexto."
|
|
95
|
+
>
|
|
96
|
+
<div className="space-y-4">
|
|
97
|
+
<Field
|
|
98
|
+
label="Activar inspector"
|
|
99
|
+
hint="Apagado = comportamiento clásico (lista de slugs + sugerencia pasiva). Encendido = el RAG decide por turno."
|
|
100
|
+
>
|
|
101
|
+
<Switch
|
|
102
|
+
checked={cfg.enabled}
|
|
103
|
+
disabled={busy}
|
|
104
|
+
onChange={(v) => apply({ enabled: v })}
|
|
105
|
+
label={cfg.enabled ? "Encendido" : "Apagado"}
|
|
106
|
+
/>
|
|
107
|
+
</Field>
|
|
108
|
+
|
|
109
|
+
<div className="flex flex-wrap items-center gap-2 pt-1">
|
|
110
|
+
<Badge tone={idx.count > 0 ? "success" : "warning"}>
|
|
111
|
+
Índice: {idx.count} skills
|
|
112
|
+
</Badge>
|
|
113
|
+
<Badge tone="muted">{idx.embedder || "sin indexar"}</Badge>
|
|
114
|
+
{idx.dim ? <Badge tone="muted">dim {idx.dim}</Badge> : null}
|
|
115
|
+
{idx.updated_at ? (
|
|
116
|
+
<span className="text-xs text-muted-foreground">
|
|
117
|
+
actualizado {new Date(idx.updated_at).toLocaleString()}
|
|
118
|
+
</span>
|
|
119
|
+
) : null}
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div className="flex flex-wrap items-center gap-3 pt-1">
|
|
123
|
+
<Button variant="secondary" onClick={() => runIndex(false)} loading={busy}>
|
|
124
|
+
<RefreshCw size={14} /> Reindexar
|
|
125
|
+
</Button>
|
|
126
|
+
<Button variant="secondary" onClick={() => runIndex(true)} loading={busy}>
|
|
127
|
+
<RefreshCw size={14} /> Reindexar (forzado)
|
|
128
|
+
</Button>
|
|
129
|
+
<span className="text-xs text-muted-foreground">
|
|
130
|
+
El embedder sale de Memoria (RAG). Local con Ollama, u offline si no hay proveedor.
|
|
131
|
+
</span>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</Section>
|
|
135
|
+
|
|
136
|
+
<Section
|
|
137
|
+
title="Umbrales y límites"
|
|
138
|
+
description="Ajustá qué tan agresivo es el inspector. Subir los umbrales = menos falsos positivos pero más riesgo de perderse una skill; bajarlos = lo contrario."
|
|
139
|
+
>
|
|
140
|
+
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
141
|
+
{KNOBS.map((k) => (
|
|
142
|
+
<Field key={k.key} label={k.label} hint={k.hint}>
|
|
143
|
+
<Input
|
|
144
|
+
type="number"
|
|
145
|
+
step={k.step}
|
|
146
|
+
min={k.min}
|
|
147
|
+
max={k.max}
|
|
148
|
+
defaultValue={String(cfg[k.key])}
|
|
149
|
+
disabled={busy}
|
|
150
|
+
onBlur={(ev) => {
|
|
151
|
+
const n = Number(ev.target.value);
|
|
152
|
+
if (Number.isFinite(n) && n !== cfg[k.key]) apply({ [k.key]: n });
|
|
153
|
+
}}
|
|
154
|
+
className="max-w-[12rem]"
|
|
155
|
+
/>
|
|
156
|
+
</Field>
|
|
157
|
+
))}
|
|
158
|
+
</div>
|
|
159
|
+
</Section>
|
|
160
|
+
|
|
161
|
+
<Section
|
|
162
|
+
title="Probar (dry-run)"
|
|
163
|
+
description="Escribí un mensaje como lo haría un usuario y mirá qué skills cargaría/sugeriría el inspector — sin llamar al modelo. Fuerza el inspector activo aunque esté apagado arriba."
|
|
164
|
+
>
|
|
165
|
+
<div className="space-y-3">
|
|
166
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
167
|
+
<Input
|
|
168
|
+
value={probe}
|
|
169
|
+
placeholder="ej: necesito crear un video promocional con voz en off"
|
|
170
|
+
disabled={busy}
|
|
171
|
+
onChange={(ev) => setProbe(ev.target.value)}
|
|
172
|
+
onKeyDown={(ev) => { if (ev.key === "Enter") runProbe(); }}
|
|
173
|
+
className="max-w-xl flex-1"
|
|
174
|
+
/>
|
|
175
|
+
<Button variant="primary" onClick={runProbe} loading={busy}>
|
|
176
|
+
<Wand2 size={14} /> Probar
|
|
177
|
+
</Button>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
{probeResult && (
|
|
181
|
+
<div className="rounded-md border border-border/60 bg-muted/30 p-3 text-sm">
|
|
182
|
+
<div className="mb-2 flex flex-wrap items-center gap-2">
|
|
183
|
+
<Sparkles size={14} className="text-muted-foreground" />
|
|
184
|
+
<span className="text-muted-foreground">{probeResult.embedder || "—"}</span>
|
|
185
|
+
{probeResult.jit ? <Badge tone="warning">JIT (índice vacío)</Badge> : null}
|
|
186
|
+
{probeResult.reason && !probeResult.loaded?.length && !probeResult.hinted?.length ? (
|
|
187
|
+
<Badge tone="muted">{probeResult.reason}</Badge>
|
|
188
|
+
) : null}
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
{probeResult.loaded?.length ? (
|
|
192
|
+
<div className="mb-1">
|
|
193
|
+
<span className="text-muted-foreground">Cargadas: </span>
|
|
194
|
+
{probeResult.loaded.map((s) => (
|
|
195
|
+
<Badge key={s} tone="success" className="mr-1">{s}</Badge>
|
|
196
|
+
))}
|
|
197
|
+
</div>
|
|
198
|
+
) : null}
|
|
199
|
+
|
|
200
|
+
{probeResult.hinted?.length ? (
|
|
201
|
+
<div className="mb-1">
|
|
202
|
+
<span className="text-muted-foreground">Sugeridas: </span>
|
|
203
|
+
{probeResult.hinted.map((s) => (
|
|
204
|
+
<Badge key={s} tone="info" className="mr-1">{s}</Badge>
|
|
205
|
+
))}
|
|
206
|
+
</div>
|
|
207
|
+
) : null}
|
|
208
|
+
|
|
209
|
+
{probeResult.scored?.length ? (
|
|
210
|
+
<div className="mt-2 space-y-0.5 font-mono text-xs text-muted-foreground">
|
|
211
|
+
{probeResult.scored.map((s) => (
|
|
212
|
+
<div key={s.slug}>{s.sim.toFixed(3)} {s.slug}</div>
|
|
213
|
+
))}
|
|
214
|
+
</div>
|
|
215
|
+
) : null}
|
|
216
|
+
</div>
|
|
217
|
+
)}
|
|
218
|
+
</div>
|
|
219
|
+
</Section>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
@@ -4,6 +4,7 @@ import { Tip } from "../../ui/tip";
|
|
|
4
4
|
import { secretSuffix } from "../../../lib/secrets";
|
|
5
5
|
import { ENGINE_BADGES, ENGINE_GRADIENTS, ENGINE_ICONS, ENGINE_OPTIONS, engineStyle } from "./typeStyles";
|
|
6
6
|
import type { Provider } from "./types";
|
|
7
|
+
import { t } from "../../../i18n";
|
|
7
8
|
|
|
8
9
|
export function ProviderCard({
|
|
9
10
|
provider,
|
|
@@ -42,7 +43,7 @@ export function ProviderCard({
|
|
|
42
43
|
</span>
|
|
43
44
|
</div>
|
|
44
45
|
<div className="flex shrink-0 items-center gap-1">
|
|
45
|
-
<Tip content={active ? "
|
|
46
|
+
<Tip content={active ? t("providers_modal.toggle_active") : t("providers_modal.toggle_inactive")}>
|
|
46
47
|
<button
|
|
47
48
|
type="button"
|
|
48
49
|
onClick={(e) => { e.stopPropagation(); onToggle(); }}
|
|
@@ -57,7 +58,7 @@ export function ProviderCard({
|
|
|
57
58
|
{active ? "Active" : "Off"}
|
|
58
59
|
</button>
|
|
59
60
|
</Tip>
|
|
60
|
-
<Tip content="
|
|
61
|
+
<Tip content={t("providers_modal.delete")}>
|
|
61
62
|
<button
|
|
62
63
|
type="button"
|
|
63
64
|
onClick={(e) => { e.stopPropagation(); onDelete(); }}
|
|
@@ -7,6 +7,7 @@ import { Engines } from "../../../lib/api";
|
|
|
7
7
|
import { isSecretMarker, secretSuffix } from "../../../lib/secrets";
|
|
8
8
|
import { ENGINE_ICONS, ENGINE_OPTIONS, ENGINE_PRESETS, type EngineType } from "./typeStyles";
|
|
9
9
|
import type { Provider } from "./types";
|
|
10
|
+
import { t } from "../../../i18n";
|
|
10
11
|
|
|
11
12
|
export interface ProviderSaveResult {
|
|
12
13
|
provider: Provider;
|
|
@@ -269,7 +270,7 @@ export function ProviderModal({ open, initial, existingSlugs, onClose, onSave }:
|
|
|
269
270
|
<Dialog
|
|
270
271
|
open={open}
|
|
271
272
|
onClose={onClose}
|
|
272
|
-
title={isEdit ?
|
|
273
|
+
title={isEdit ? t("providers_modal.edit_title", { name: initial?.name || initial?.slug || "" }) : t("providers_modal.new_title")}
|
|
273
274
|
description="Proveedor LLM. El motor (engine) define qué adapter usa (openai, ollama, …)."
|
|
274
275
|
size="lg"
|
|
275
276
|
footer={
|
|
@@ -362,7 +363,7 @@ export function ProviderModal({ open, initial, existingSlugs, onClose, onSave }:
|
|
|
362
363
|
options={modelOptions}
|
|
363
364
|
className="flex-1"
|
|
364
365
|
/>
|
|
365
|
-
<Button size="sm" variant="secondary" onClick={loadModels} disabled={loadingModels} title="
|
|
366
|
+
<Button size="sm" variant="secondary" onClick={loadModels} disabled={loadingModels} title={t("providers_modal.list_models_hint")} aria-label={t("providers_modal.list_models_hint")}>
|
|
366
367
|
{loadingModels ? <Loader2 className="size-3.5 animate-spin" /> : <RefreshCw className="size-3.5" />}
|
|
367
368
|
Cargar modelos
|
|
368
369
|
</Button>
|
|
@@ -5,6 +5,7 @@ import { ArrowUp, Square } from "lucide-react"
|
|
|
5
5
|
|
|
6
6
|
import { cn } from "@/lib/utils"
|
|
7
7
|
import { Button } from "@/components/ui/button"
|
|
8
|
+
import { t } from "@/i18n"
|
|
8
9
|
|
|
9
10
|
interface ChatInputProps {
|
|
10
11
|
value: string
|
|
@@ -109,8 +110,8 @@ export function ChatInput({
|
|
|
109
110
|
size="icon-sm"
|
|
110
111
|
variant="destructive"
|
|
111
112
|
onClick={onStop}
|
|
112
|
-
aria-label="
|
|
113
|
-
title="
|
|
113
|
+
aria-label={t("chat_ui.stop")}
|
|
114
|
+
title={t("chat_ui.stop")}
|
|
114
115
|
>
|
|
115
116
|
<Square className="size-3.5" fill="currentColor" />
|
|
116
117
|
</Button>
|
|
@@ -121,8 +122,8 @@ export function ChatInput({
|
|
|
121
122
|
variant="default"
|
|
122
123
|
onClick={onSubmit}
|
|
123
124
|
disabled={!canSend}
|
|
124
|
-
aria-label="
|
|
125
|
-
title="
|
|
125
|
+
aria-label={t("chat_ui.send")}
|
|
126
|
+
title={t("chat_ui.send")}
|
|
126
127
|
>
|
|
127
128
|
<ArrowUp className="size-4" />
|
|
128
129
|
</Button>
|
|
@@ -9,6 +9,7 @@ import { useIsMobile } from "@/hooks/use-mobile"
|
|
|
9
9
|
import { cn } from "@/lib/utils"
|
|
10
10
|
import { Button } from "@/components/ui/button"
|
|
11
11
|
import { Input } from "@/components/ui/input"
|
|
12
|
+
import { t } from "@/i18n"
|
|
12
13
|
import { Separator } from "@/components/ui/separator"
|
|
13
14
|
import {
|
|
14
15
|
Sheet,
|
|
@@ -284,10 +285,10 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
|
|
|
284
285
|
<button
|
|
285
286
|
data-sidebar="rail"
|
|
286
287
|
data-slot="sidebar-rail"
|
|
287
|
-
aria-label="
|
|
288
|
+
aria-label={t("sidebar_ui.toggle")}
|
|
288
289
|
tabIndex={-1}
|
|
289
290
|
onClick={toggleSidebar}
|
|
290
|
-
title="
|
|
291
|
+
title={t("sidebar_ui.toggle")}
|
|
291
292
|
className={cn(
|
|
292
293
|
"absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2",
|
|
293
294
|
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
type OpenAiTtsConfig,
|
|
14
14
|
type PiperConfig,
|
|
15
15
|
} from "../../lib/api/voice";
|
|
16
|
+
import { t } from "../../i18n";
|
|
16
17
|
|
|
17
18
|
// Per-provider settings. Saved as dotted-key patches under voice.tts.<id>.
|
|
18
19
|
// Secrets (api_key) follow the EnginesPanel convention: a blank field keeps
|
|
@@ -124,7 +125,7 @@ export function VoiceProviderModal({ open, providerId, config, onClose, onSave }
|
|
|
124
125
|
<Dialog
|
|
125
126
|
open={open}
|
|
126
127
|
onClose={onClose}
|
|
127
|
-
title={
|
|
128
|
+
title={t("voice_screen.configure_provider", { name: meta?.name || providerId || "" })}
|
|
128
129
|
description={meta?.note}
|
|
129
130
|
size="md"
|
|
130
131
|
footer={
|
|
@@ -58,7 +58,7 @@ export const ENGINE_ORDER = [
|
|
|
58
58
|
export const PERMISSION_MODES = ["total", "automatico", "permiso"] as const;
|
|
59
59
|
export type PermissionMode = (typeof PERMISSION_MODES)[number];
|
|
60
60
|
|
|
61
|
-
/** Routine kinds — must match src/
|
|
61
|
+
/** Routine kinds — must match src/core/routines/runner.js. */
|
|
62
62
|
export const ROUTINE_KINDS = [
|
|
63
63
|
"heartbeat",
|
|
64
64
|
"exec_agent",
|
|
@@ -32,6 +32,13 @@ export interface ChatMsg {
|
|
|
32
32
|
usage?: ChatUsage;
|
|
33
33
|
/** Operational notes (engine fallbacks, retries, suppressions). */
|
|
34
34
|
notes?: string[];
|
|
35
|
+
/** Skill Inspector decision for this turn (when the feature is on): which
|
|
36
|
+
* skills the per-turn RAG loaded inline vs merely hinted. */
|
|
37
|
+
inspector?: {
|
|
38
|
+
embedder?: string;
|
|
39
|
+
loaded?: string[];
|
|
40
|
+
hinted?: string[];
|
|
41
|
+
};
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
export interface SendOptions {
|
|
@@ -138,6 +145,18 @@ export function applyStreamEvent(turn: ChatMsg, ev: ChatStreamEvent): ChatMsg {
|
|
|
138
145
|
return withNote(`retry (${ev.reason || "?"})`);
|
|
139
146
|
case "tools_suppressed":
|
|
140
147
|
return withNote(`tools suppressed: ${(ev.tools || []).join(", ")}`);
|
|
148
|
+
case "skill_inspector": {
|
|
149
|
+
const insp = ev.inspector;
|
|
150
|
+
if (!insp || (!insp.loaded?.length && !insp.hinted?.length)) return turn;
|
|
151
|
+
return {
|
|
152
|
+
...turn,
|
|
153
|
+
inspector: {
|
|
154
|
+
embedder: insp.embedder,
|
|
155
|
+
loaded: insp.loaded || [],
|
|
156
|
+
hinted: insp.hinted || [],
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
141
160
|
case "assistant_text":
|
|
142
161
|
return ev.text ? { ...turn, parts: [...turn.parts, { kind: "text", text: ev.text }] } : turn;
|
|
143
162
|
case "tool_start":
|
|
@@ -253,6 +253,18 @@ export const en = {
|
|
|
253
253
|
unregistered: "Unregistered.",
|
|
254
254
|
base_subtitle: "General workspace · super-agent",
|
|
255
255
|
|
|
256
|
+
danger: {
|
|
257
|
+
title: "Danger zone",
|
|
258
|
+
subtitle: "Actions that affect APX's project registry. They do not touch repo files.",
|
|
259
|
+
rebuild_desc: "Re-scans .apc/, MCPs and agents and regenerates the super-agent context for this project.",
|
|
260
|
+
unregister_desc: "Removes the project from APX's registry. The folder on disk stays intact.",
|
|
261
|
+
rebuild_confirm_title: "Rebuild context",
|
|
262
|
+
rebuild_confirm_desc: "Regenerate context for {label}.",
|
|
263
|
+
rebuild_long: "Re-reads APC config, lists available MCPs and agents, and rebuilds the super-agent system prompt. Safe to run — nothing is deleted. Use it after editing .apc/ by hand or if changes are not being picked up.",
|
|
264
|
+
unregister_confirm_title: "Unregister project",
|
|
265
|
+
unregister_long: "The project disappears from `apx`. Files on disk (.apc/, code, everything) stay. You can re-register it with `apx project register <path>`.",
|
|
266
|
+
},
|
|
267
|
+
|
|
256
268
|
nav: {
|
|
257
269
|
overview: "Overview",
|
|
258
270
|
chat: "Chat",
|
|
@@ -262,6 +274,7 @@ export const en = {
|
|
|
262
274
|
routines: "Routines",
|
|
263
275
|
tasks: "Tasks",
|
|
264
276
|
mcps: "MCPs",
|
|
277
|
+
vars: "Variables",
|
|
265
278
|
threads: "Chats",
|
|
266
279
|
logs: "Logs",
|
|
267
280
|
memories: "Memories",
|
|
@@ -486,17 +499,17 @@ export const en = {
|
|
|
486
499
|
conflicts: "⚠ Conflicts: {names}",
|
|
487
500
|
new_title: "New MCP",
|
|
488
501
|
new_desc: "POST /projects/:pid/mcps?scope=…",
|
|
489
|
-
scope_label: "
|
|
490
|
-
transport_label: "
|
|
491
|
-
name_label: "
|
|
502
|
+
scope_label: "Scope",
|
|
503
|
+
transport_label: "Transport",
|
|
504
|
+
name_label: "Name",
|
|
492
505
|
name_ph: "filesystem",
|
|
493
|
-
cmd_label: "
|
|
506
|
+
cmd_label: "Command",
|
|
494
507
|
cmd_ph: "npx",
|
|
495
|
-
args_label: "
|
|
508
|
+
args_label: "Args",
|
|
496
509
|
args_hint: "space-separated",
|
|
497
510
|
args_ph: "-y @modelcontextprotocol/server-filesystem /tmp",
|
|
498
|
-
env_label: "
|
|
499
|
-
url_label: "
|
|
511
|
+
env_label: "Env (JSON, optional)",
|
|
512
|
+
url_label: "URL",
|
|
500
513
|
url_ph: "https://example.com/mcp",
|
|
501
514
|
enabled_label: "Enabled",
|
|
502
515
|
add_btn: "Add",
|
|
@@ -504,6 +517,77 @@ export const en = {
|
|
|
504
517
|
env_invalid: "env must be valid JSON",
|
|
505
518
|
removed: "removed",
|
|
506
519
|
added: "MCP added.",
|
|
520
|
+
updated: "MCP updated.",
|
|
521
|
+
edit_title: "Edit MCP",
|
|
522
|
+
save_btn: "Save",
|
|
523
|
+
add_arg: "Add arg",
|
|
524
|
+
edit_btn: "Edit",
|
|
525
|
+
test_btn: "Test",
|
|
526
|
+
logs_btn: "Logs",
|
|
527
|
+
testing: "Testing…",
|
|
528
|
+
test_ok: "OK · {n} tools available",
|
|
529
|
+
logs_title: "Logs · {name}",
|
|
530
|
+
logs_empty: "No logs yet. Start the MCP by calling a tool or running Test.",
|
|
531
|
+
logs_events: "Recent events",
|
|
532
|
+
logs_stderr: "stderr (last 4KB)",
|
|
533
|
+
logs_panel_title: "Live logs",
|
|
534
|
+
logs_panel_pick: "pick an MCP",
|
|
535
|
+
logs_panel_hint: "Click an MCP in the list to see what's happening live.",
|
|
536
|
+
logs_panel_idle: "No activity. Hit Test to spin it up.",
|
|
537
|
+
scope_runtime: "Runtime",
|
|
538
|
+
scope_shared: "Shared",
|
|
539
|
+
scope_global: "Global",
|
|
540
|
+
scope_runtime_desc: "This project only · with secrets · not committed (~/.apx/projects/<id>/mcps.json)",
|
|
541
|
+
scope_shared_desc: "This project only · committeable · no secrets (.apc/mcps.json)",
|
|
542
|
+
scope_global_desc: "All projects on this machine (~/.apx/mcps.json)",
|
|
543
|
+
transport_stdio: "stdio",
|
|
544
|
+
transport_http: "HTTP",
|
|
545
|
+
transport_stdio_desc: "Local process — `command` + args",
|
|
546
|
+
transport_http_desc: "Remote endpoint — URL + headers",
|
|
547
|
+
args_hint_tokens: "One entry per arg. Use the + button to insert a variable.",
|
|
548
|
+
env_hint_tokens: "Key/value pairs. Values accept ${var.NAME} (+ button on the right).",
|
|
549
|
+
env_empty: "No env vars.",
|
|
550
|
+
headers_label: "Headers",
|
|
551
|
+
headers_hint: "Key/value pairs — typically Authorization: Bearer ${var.TOKEN}.",
|
|
552
|
+
headers_empty: "No headers.",
|
|
553
|
+
},
|
|
554
|
+
|
|
555
|
+
vars: {
|
|
556
|
+
title: "Variables",
|
|
557
|
+
subtitle_project: "Replace ${var.NAME} when loading MCPs and templates. Project vars beat globals. Stored outside the repo (~/.apx/, chmod 0600).",
|
|
558
|
+
subtitle_base: "Global variables — available to every project. Stored in ~/.apx/vars.json (chmod 0600).",
|
|
559
|
+
empty: "No variables yet.",
|
|
560
|
+
new: "Variable",
|
|
561
|
+
new_title: "New variable",
|
|
562
|
+
edit_title: "Edit variable",
|
|
563
|
+
new_desc: "Referenced as ${var.NAME} in any field that supports interpolation.",
|
|
564
|
+
reveal_all: "Show values",
|
|
565
|
+
reveal: "Show",
|
|
566
|
+
hide: "Hide",
|
|
567
|
+
filter_label: "Show:",
|
|
568
|
+
filter_all: "All",
|
|
569
|
+
filter_project: "Project only",
|
|
570
|
+
filter_global: "Globals only",
|
|
571
|
+
scope_label: "Scope",
|
|
572
|
+
scope_project: "project",
|
|
573
|
+
scope_project_desc: "This project only. Beats the global with the same name.",
|
|
574
|
+
scope_global: "global",
|
|
575
|
+
scope_global_desc: "Available to every project.",
|
|
576
|
+
name_label: "Name",
|
|
577
|
+
name_hint: "Uppercase, digits and _. E.g. MY_API_KEY, GITHUB_TOKEN.",
|
|
578
|
+
value_label: "Value",
|
|
579
|
+
value_hint: "Stored on disk with 0600 perms. Never committed.",
|
|
580
|
+
value_edit_ph: "(leave empty to keep current… not yet supported, paste the value again)",
|
|
581
|
+
add_btn: "Add",
|
|
582
|
+
save_btn: "Save",
|
|
583
|
+
edit_btn: "Edit",
|
|
584
|
+
delete_btn: "Delete",
|
|
585
|
+
delete_confirm: "Delete {name} ({scope})?",
|
|
586
|
+
removed: "Variable removed.",
|
|
587
|
+
added: "Variable added.",
|
|
588
|
+
updated: "Variable updated.",
|
|
589
|
+
name_required: "Name required.",
|
|
590
|
+
value_required: "Value required.",
|
|
507
591
|
},
|
|
508
592
|
|
|
509
593
|
threads: {
|
|
@@ -783,5 +867,89 @@ export const en = {
|
|
|
783
867
|
changes_no_git: "Changes need a git repository. This project isn't one.",
|
|
784
868
|
changes_files: "{n} file(s) changed",
|
|
785
869
|
stopped: "[stopped]",
|
|
870
|
+
close: "Close",
|
|
871
|
+
reload: "Reload",
|
|
872
|
+
discard_changes: "Discard changes",
|
|
873
|
+
save_shortcut_hint: "Save (Cmd/Ctrl+S)",
|
|
874
|
+
artifacts_rename: "Rename",
|
|
875
|
+
artifacts_view: "View contents",
|
|
876
|
+
artifacts_edit: "Edit contents",
|
|
877
|
+
tree_collapse_all: "Collapse all",
|
|
878
|
+
terminal_clear: "Clear",
|
|
879
|
+
terminal_close: "Close terminal",
|
|
880
|
+
},
|
|
881
|
+
|
|
882
|
+
desktop_screen: {
|
|
883
|
+
status_title: "Status",
|
|
884
|
+
autostart_title: "Auto-start",
|
|
885
|
+
shortcut_title: "Keyboard shortcut",
|
|
886
|
+
appearance_title: "Appearance",
|
|
887
|
+
activation_title: "Activation + transcription",
|
|
888
|
+
last_conv_title: "Last conversation",
|
|
889
|
+
},
|
|
890
|
+
|
|
891
|
+
voice_screen: {
|
|
892
|
+
providers_title: "Voice providers (TTS)",
|
|
893
|
+
test_title: "Test voice",
|
|
894
|
+
stt_title: "Transcription (STT)",
|
|
895
|
+
configure_provider: "Configure {name}",
|
|
896
|
+
},
|
|
897
|
+
|
|
898
|
+
deck_screen: {
|
|
899
|
+
widgets_title: "Widgets",
|
|
900
|
+
context_title: "APX context",
|
|
901
|
+
reload_manifest: "Reload manifest",
|
|
902
|
+
widget_native: "Native APX widget",
|
|
903
|
+
widget_external: "External widget",
|
|
904
|
+
},
|
|
905
|
+
|
|
906
|
+
memory_panel: {
|
|
907
|
+
embeddings_title: "Embeddings (RAG)",
|
|
908
|
+
ollama_title: "Ollama (local)",
|
|
909
|
+
openai_title: "OpenAI",
|
|
910
|
+
gemini_title: "Gemini",
|
|
911
|
+
compaction_title: "History compaction",
|
|
912
|
+
},
|
|
913
|
+
|
|
914
|
+
router_panel: {
|
|
915
|
+
title: "Model router",
|
|
916
|
+
},
|
|
917
|
+
|
|
918
|
+
engines_panel: {
|
|
919
|
+
title: "Providers",
|
|
920
|
+
new_btn: "New provider",
|
|
921
|
+
},
|
|
922
|
+
|
|
923
|
+
providers_modal: {
|
|
924
|
+
new_title: "New provider",
|
|
925
|
+
edit_title: "Edit {name}",
|
|
926
|
+
list_models_hint: "List the provider's actual models",
|
|
927
|
+
toggle_active: "Active · click to deactivate",
|
|
928
|
+
toggle_inactive: "Inactive · click to activate",
|
|
929
|
+
delete: "Delete",
|
|
930
|
+
},
|
|
931
|
+
|
|
932
|
+
chat_ui: {
|
|
933
|
+
copy: "Copy",
|
|
934
|
+
stop: "Stop",
|
|
935
|
+
send: "Send",
|
|
936
|
+
pick_model: "Pick model (or Auto)",
|
|
937
|
+
insert_variable: "Insert variable",
|
|
938
|
+
},
|
|
939
|
+
|
|
940
|
+
sidebar_ui: {
|
|
941
|
+
toggle: "Toggle sidebar",
|
|
942
|
+
},
|
|
943
|
+
|
|
944
|
+
models_ui: {
|
|
945
|
+
invalid_hint: "Model/provider unavailable",
|
|
946
|
+
},
|
|
947
|
+
|
|
948
|
+
global_config: {
|
|
949
|
+
title: "APX config",
|
|
950
|
+
},
|
|
951
|
+
|
|
952
|
+
agent_detail_extra: {
|
|
953
|
+
skills_title: "Skills & tools",
|
|
786
954
|
},
|
|
787
955
|
} as const;
|