@agentprojectcontext/apx 1.37.0 → 1.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/package.json +1 -1
- package/src/core/mascot.js +80 -80
- package/src/interfaces/web/dist/assets/index-CQc_5t8F.js +629 -0
- package/src/interfaces/web/dist/assets/index-CQc_5t8F.js.map +1 -0
- package/src/interfaces/web/dist/assets/{index-B6sYFQFa.css → index-hwxuTPcK.css} +1 -1
- package/src/interfaces/web/dist/index.html +2 -2
- package/src/interfaces/web/src/App.tsx +15 -24
- package/src/interfaces/web/src/components/ModelCombobox.tsx +1 -1
- package/src/interfaces/web/src/components/Roby.tsx +96 -0
- package/src/interfaces/web/src/components/TelegramChannelDialog.tsx +11 -11
- package/src/interfaces/web/src/components/TelegramSendDialog.tsx +5 -5
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +2 -2
- package/src/interfaces/web/src/components/chat/ModelPicker.tsx +5 -5
- package/src/interfaces/web/src/components/chat/ToolCall.tsx +23 -19
- package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +10 -10
- package/src/interfaces/web/src/components/code/CodeContextTab.tsx +7 -7
- package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +3 -2
- package/src/interfaces/web/src/components/common/TabNav.tsx +3 -2
- package/src/interfaces/web/src/components/config/ConfigTabsEditor.tsx +3 -2
- package/src/interfaces/web/src/components/config/GlobalConfigEditor.tsx +2 -2
- package/src/interfaces/web/src/components/config/global-config-sections.ts +9 -9
- package/src/interfaces/web/src/components/config/project-config-sections.ts +61 -54
- package/src/interfaces/web/src/components/deck/DaemonCard.tsx +6 -5
- package/src/interfaces/web/src/components/inputs/KeyValueList.tsx +5 -4
- package/src/interfaces/web/src/components/inputs/VarTokenInput.tsx +3 -3
- package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +22 -9
- package/src/interfaces/web/src/components/settings/AdvancedPanel.tsx +1 -1
- package/src/interfaces/web/src/components/settings/AppearancePanel.tsx +1 -1
- package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +14 -14
- package/src/interfaces/web/src/components/settings/DevicesPanel.tsx +3 -3
- package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +7 -7
- package/src/interfaces/web/src/components/settings/IdentityPanel.tsx +2 -2
- package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +37 -37
- package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +44 -35
- package/src/interfaces/web/src/components/settings/SuperAgentPanel.tsx +5 -5
- package/src/interfaces/web/src/components/settings/TelegramChannelsPanel.tsx +3 -3
- package/src/interfaces/web/src/components/settings/TelegramContactsPanel.tsx +1 -1
- package/src/interfaces/web/src/components/settings/TelegramGlobalPanel.tsx +3 -3
- package/src/interfaces/web/src/components/settings/TelegramRolesPanel.tsx +1 -1
- package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +6 -6
- package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +36 -36
- package/src/interfaces/web/src/components/voice/VoiceProviderList.tsx +15 -14
- package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +22 -22
- package/src/interfaces/web/src/components/voice/VoiceSttCard.tsx +18 -17
- package/src/interfaces/web/src/components/voice/VoiceTestCard.tsx +19 -18
- package/src/interfaces/web/src/hooks/useChat.ts +6 -5
- package/src/interfaces/web/src/i18n/en.ts +517 -1
- package/src/interfaces/web/src/i18n/es.ts +517 -1
- package/src/interfaces/web/src/i18n/index.ts +1 -1
- package/src/interfaces/web/src/lib/api/voice.ts +5 -5
- package/src/interfaces/web/src/screens/ProjectScreen.tsx +14 -1
- package/src/interfaces/web/src/screens/SettingsScreen.tsx +1 -1
- package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +8 -8
- package/src/interfaces/web/src/screens/base/ComingSoon.tsx +3 -2
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +12 -12
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +15 -15
- package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +37 -37
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +8 -8
- package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +16 -10
- package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +25 -24
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +2 -2
- package/src/interfaces/web/src/screens/project/ConfigTab.tsx +3 -3
- package/src/interfaces/web/src/screens/project/McpsTab.tsx +6 -9
- package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +66 -52
- package/src/interfaces/web/src/screens/project/TelegramTab.tsx +1 -1
- package/src/interfaces/web/dist/assets/index-DsADpObh.js +0 -633
- package/src/interfaces/web/dist/assets/index-DsADpObh.js.map +0 -1
|
@@ -15,17 +15,17 @@ import { t } from "../../i18n";
|
|
|
15
15
|
// provider/model changes the embedder space, so a "Reindexar" action rebuilds
|
|
16
16
|
// the vector store under the new embedder.
|
|
17
17
|
|
|
18
|
-
const
|
|
19
|
-
{ value: "auto", label: "
|
|
20
|
-
{ value: "ollama", label: "
|
|
21
|
-
{ value: "gemini", label: "
|
|
22
|
-
{ value: "openai", label: "
|
|
23
|
-
{ value: "tf", label: "
|
|
18
|
+
const providerOptions = () => [
|
|
19
|
+
{ value: "auto", label: t("memory_panel.provider_auto") },
|
|
20
|
+
{ value: "ollama", label: t("memory_panel.provider_ollama") },
|
|
21
|
+
{ value: "gemini", label: t("memory_panel.provider_gemini") },
|
|
22
|
+
{ value: "openai", label: t("memory_panel.provider_openai") },
|
|
23
|
+
{ value: "tf", label: t("memory_panel.provider_tf") },
|
|
24
24
|
];
|
|
25
25
|
|
|
26
|
-
const
|
|
27
|
-
{ value: "chain", label: "
|
|
28
|
-
{ value: "single", label: "
|
|
26
|
+
const modeOptions = () => [
|
|
27
|
+
{ value: "chain", label: t("memory_panel.mode_chain") },
|
|
28
|
+
{ value: "single", label: t("memory_panel.mode_single") },
|
|
29
29
|
];
|
|
30
30
|
|
|
31
31
|
interface MemoryCfg {
|
|
@@ -68,7 +68,7 @@ export function MemoryPanel() {
|
|
|
68
68
|
await patch(set);
|
|
69
69
|
await mutateProviders();
|
|
70
70
|
} catch (e) {
|
|
71
|
-
toast.error(
|
|
71
|
+
toast.error(t("memory_panel.save_failed", { msg: (e as Error).message }));
|
|
72
72
|
} finally {
|
|
73
73
|
setBusy(false);
|
|
74
74
|
}
|
|
@@ -80,9 +80,9 @@ export function MemoryPanel() {
|
|
|
80
80
|
try {
|
|
81
81
|
const r = await Embeddings.test({});
|
|
82
82
|
setTestResult(`${r.embedder} · dim ${r.dim} · ${r.ms}ms`);
|
|
83
|
-
toast.success(
|
|
83
|
+
toast.success(t("memory_panel.test_ok", { embedder: r.embedder }));
|
|
84
84
|
} catch (e) {
|
|
85
|
-
toast.error(
|
|
85
|
+
toast.error(t("memory_panel.test_failed", { msg: (e as Error).message }));
|
|
86
86
|
} finally {
|
|
87
87
|
setBusy(false);
|
|
88
88
|
}
|
|
@@ -92,9 +92,9 @@ export function MemoryPanel() {
|
|
|
92
92
|
setBusy(true);
|
|
93
93
|
try {
|
|
94
94
|
const r = await Embeddings.reindex();
|
|
95
|
-
toast.success(
|
|
95
|
+
toast.success(t("memory_panel.reindexed", { indexed: r.indexed, cleared: r.cleared }));
|
|
96
96
|
} catch (e) {
|
|
97
|
-
toast.error(
|
|
97
|
+
toast.error(t("memory_panel.reindex_failed", { msg: (e as Error).message }));
|
|
98
98
|
} finally {
|
|
99
99
|
setBusy(false);
|
|
100
100
|
}
|
|
@@ -104,24 +104,24 @@ export function MemoryPanel() {
|
|
|
104
104
|
<div className="grid gap-6 xl:grid-cols-2 xl:items-start">
|
|
105
105
|
<Section
|
|
106
106
|
title={t("memory_panel.embeddings_title")}
|
|
107
|
-
description="
|
|
107
|
+
description={t("memory_panel.embeddings_desc")}
|
|
108
108
|
>
|
|
109
109
|
<div className="space-y-3">
|
|
110
|
-
<Field label="
|
|
110
|
+
<Field label={t("memory_panel.provider_label")} hint={t("memory_panel.provider_hint")}>
|
|
111
111
|
<UiSelect
|
|
112
112
|
value={provider}
|
|
113
113
|
onChange={(v) => apply({ "memory.embeddings.provider": v })}
|
|
114
|
-
options={
|
|
114
|
+
options={providerOptions()}
|
|
115
115
|
disabled={busy}
|
|
116
116
|
className="max-w-xl"
|
|
117
117
|
/>
|
|
118
118
|
</Field>
|
|
119
119
|
|
|
120
|
-
<Field label="
|
|
120
|
+
<Field label={t("memory_panel.mode_label")} hint={t("memory_panel.mode_hint")}>
|
|
121
121
|
<UiSelect
|
|
122
122
|
value={mode}
|
|
123
123
|
onChange={(v) => apply({ "memory.embeddings.mode": v })}
|
|
124
|
-
options={
|
|
124
|
+
options={modeOptions()}
|
|
125
125
|
disabled={busy}
|
|
126
126
|
className="max-w-md"
|
|
127
127
|
/>
|
|
@@ -130,25 +130,25 @@ export function MemoryPanel() {
|
|
|
130
130
|
<div className="flex flex-wrap items-center gap-2 pt-1">
|
|
131
131
|
{engines.map((e) => (
|
|
132
132
|
<Badge key={e.id} tone={e.available ? "success" : "muted"}>
|
|
133
|
-
{e.id}: {e.available ? "
|
|
133
|
+
{e.id}: {e.available ? t("memory_panel.available") : t("memory_panel.unavailable")}
|
|
134
134
|
</Badge>
|
|
135
135
|
))}
|
|
136
136
|
</div>
|
|
137
137
|
|
|
138
138
|
<div className="flex flex-wrap items-center gap-3 pt-1">
|
|
139
139
|
<Button variant="secondary" onClick={runTest} loading={busy}>
|
|
140
|
-
<Sparkles size={14} />
|
|
140
|
+
<Sparkles size={14} /> {t("memory_panel.test_btn")}
|
|
141
141
|
</Button>
|
|
142
142
|
<Button variant="secondary" onClick={runReindex} loading={busy}>
|
|
143
|
-
<Database size={14} />
|
|
143
|
+
<Database size={14} /> {t("memory_panel.reindex_btn")}
|
|
144
144
|
</Button>
|
|
145
145
|
{testResult && <span className="text-sm text-muted-foreground">{testResult}</span>}
|
|
146
146
|
</div>
|
|
147
147
|
</div>
|
|
148
148
|
</Section>
|
|
149
149
|
|
|
150
|
-
<Section title={t("memory_panel.ollama_title")} description="
|
|
151
|
-
<Field label="
|
|
150
|
+
<Section title={t("memory_panel.ollama_title")} description={t("memory_panel.ollama_desc")}>
|
|
151
|
+
<Field label={t("memory_panel.model_label")}>
|
|
152
152
|
<Input
|
|
153
153
|
defaultValue={emb.ollama?.model || "nomic-embed-text"}
|
|
154
154
|
placeholder="nomic-embed-text"
|
|
@@ -160,7 +160,7 @@ export function MemoryPanel() {
|
|
|
160
160
|
className="max-w-md"
|
|
161
161
|
/>
|
|
162
162
|
</Field>
|
|
163
|
-
<Field label="
|
|
163
|
+
<Field label={t("memory_panel.base_url_label")} hint={t("memory_panel.ollama_base_url_hint")}>
|
|
164
164
|
<Input
|
|
165
165
|
defaultValue={emb.ollama?.base_url || ""}
|
|
166
166
|
placeholder="http://localhost:11434"
|
|
@@ -171,8 +171,8 @@ export function MemoryPanel() {
|
|
|
171
171
|
</Field>
|
|
172
172
|
</Section>
|
|
173
173
|
|
|
174
|
-
<Section title={t("memory_panel.openai_title")} description="
|
|
175
|
-
<Field label="
|
|
174
|
+
<Section title={t("memory_panel.openai_title")} description={t("memory_panel.openai_desc")}>
|
|
175
|
+
<Field label={t("memory_panel.model_label")}>
|
|
176
176
|
<Input
|
|
177
177
|
defaultValue={emb.openai?.model || "text-embedding-3-small"}
|
|
178
178
|
placeholder="text-embedding-3-small"
|
|
@@ -184,7 +184,7 @@ export function MemoryPanel() {
|
|
|
184
184
|
className="max-w-md"
|
|
185
185
|
/>
|
|
186
186
|
</Field>
|
|
187
|
-
<Field label="
|
|
187
|
+
<Field label={t("memory_panel.api_key_label")} hint={t("memory_panel.openai_key_hint")}>
|
|
188
188
|
<Input
|
|
189
189
|
type="password"
|
|
190
190
|
defaultValue={emb.openai?.api_key || ""}
|
|
@@ -199,8 +199,8 @@ export function MemoryPanel() {
|
|
|
199
199
|
</Field>
|
|
200
200
|
</Section>
|
|
201
201
|
|
|
202
|
-
<Section title={t("memory_panel.gemini_title")} description="
|
|
203
|
-
<Field label="
|
|
202
|
+
<Section title={t("memory_panel.gemini_title")} description={t("memory_panel.gemini_desc")}>
|
|
203
|
+
<Field label={t("memory_panel.model_label")}>
|
|
204
204
|
<Input
|
|
205
205
|
defaultValue={emb.gemini?.model || "text-embedding-004"}
|
|
206
206
|
placeholder="text-embedding-004"
|
|
@@ -212,7 +212,7 @@ export function MemoryPanel() {
|
|
|
212
212
|
className="max-w-md"
|
|
213
213
|
/>
|
|
214
214
|
</Field>
|
|
215
|
-
<Field label="
|
|
215
|
+
<Field label={t("memory_panel.api_key_label")} hint={t("memory_panel.gemini_key_hint")}>
|
|
216
216
|
<Input
|
|
217
217
|
type="password"
|
|
218
218
|
defaultValue={emb.gemini?.api_key || ""}
|
|
@@ -229,10 +229,10 @@ export function MemoryPanel() {
|
|
|
229
229
|
|
|
230
230
|
<Section
|
|
231
231
|
title={t("memory_panel.compaction_title")}
|
|
232
|
-
description="
|
|
232
|
+
description={t("memory_panel.compaction_desc")}
|
|
233
233
|
>
|
|
234
234
|
<div className="grid gap-3 sm:grid-cols-2">
|
|
235
|
-
<Field label="
|
|
235
|
+
<Field label={t("memory_panel.threshold_label")} hint={t("memory_panel.threshold_hint")}>
|
|
236
236
|
<Input
|
|
237
237
|
type="number"
|
|
238
238
|
min={1}
|
|
@@ -248,7 +248,7 @@ export function MemoryPanel() {
|
|
|
248
248
|
className="max-w-[10rem]"
|
|
249
249
|
/>
|
|
250
250
|
</Field>
|
|
251
|
-
<Field label="
|
|
251
|
+
<Field label={t("memory_panel.keep_recent_label")} hint={t("memory_panel.keep_recent_hint")}>
|
|
252
252
|
<Input
|
|
253
253
|
type="number"
|
|
254
254
|
min={1}
|
|
@@ -265,7 +265,7 @@ export function MemoryPanel() {
|
|
|
265
265
|
/>
|
|
266
266
|
</Field>
|
|
267
267
|
</div>
|
|
268
|
-
<Field label="
|
|
268
|
+
<Field label={t("memory_panel.compact_model_label")} hint={t("memory_panel.compact_model_hint")}>
|
|
269
269
|
<Input
|
|
270
270
|
defaultValue={mem.compact_model || "ollama:gemma4:31b-cloud"}
|
|
271
271
|
placeholder="ollama:gemma4:31b-cloud"
|
|
@@ -277,10 +277,10 @@ export function MemoryPanel() {
|
|
|
277
277
|
className="max-w-md"
|
|
278
278
|
/>
|
|
279
279
|
</Field>
|
|
280
|
-
<Field label="
|
|
280
|
+
<Field label={t("memory_panel.compact_fallback_label")} hint={t("memory_panel.compact_fallback_hint")}>
|
|
281
281
|
<Input
|
|
282
282
|
defaultValue={mem.compact_fallback_model || ""}
|
|
283
|
-
placeholder="
|
|
283
|
+
placeholder={t("memory_panel.compact_fallback_ph")}
|
|
284
284
|
disabled={busy}
|
|
285
285
|
onBlur={(ev) => {
|
|
286
286
|
const v = ev.target.value.trim();
|
|
@@ -5,6 +5,7 @@ import { Section } from "../Section";
|
|
|
5
5
|
import { Button, Field, Input, Loading, Badge, Switch } from "../ui";
|
|
6
6
|
import { useToast } from "../Toast";
|
|
7
7
|
import { Skills, type InspectTrace } from "../../lib/api/skills";
|
|
8
|
+
import { t } from "../../i18n";
|
|
8
9
|
|
|
9
10
|
// Skill Inspector — per-turn skill RAG middleware. When ON, the static
|
|
10
11
|
// "available skills" slug-dump is removed from the agent's system prompt and a
|
|
@@ -19,15 +20,17 @@ import { Skills, type InspectTrace } from "../../lib/api/skills";
|
|
|
19
20
|
// Numeric knobs with human labels + sane ranges. We keep them as plain number
|
|
20
21
|
// inputs (same idiom as the embeddings model fields) rather than sliders so the
|
|
21
22
|
// values are explicit and copy-pasteable.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
function knobs(): { key: keyof NumericKnobs; label: string; hint: string; step: number; min: number; max: number }[] {
|
|
24
|
+
return [
|
|
25
|
+
{ key: "load_threshold", label: t("settings_ui.knob_load_threshold"), hint: t("settings_ui.knob_load_threshold_hint"), step: 0.01, min: 0, max: 1 },
|
|
26
|
+
{ key: "hint_threshold", label: t("settings_ui.knob_hint_threshold"), hint: t("settings_ui.knob_hint_threshold_hint"), step: 0.01, min: 0, max: 1 },
|
|
27
|
+
{ key: "margin", label: t("settings_ui.knob_margin"), hint: t("settings_ui.knob_margin_hint"), step: 0.01, min: 0, max: 1 },
|
|
28
|
+
{ key: "max_loaded", label: t("settings_ui.knob_max_loaded"), hint: t("settings_ui.knob_max_loaded_hint"), step: 1, min: 0, max: 5 },
|
|
29
|
+
{ key: "max_hints", label: t("settings_ui.knob_max_hints"), hint: t("settings_ui.knob_max_hints_hint"), step: 1, min: 0, max: 8 },
|
|
30
|
+
{ key: "prompt_floor", label: t("settings_ui.knob_prompt_floor"), hint: t("settings_ui.knob_prompt_floor_hint"), step: 1, min: 0, max: 40 },
|
|
31
|
+
{ key: "body_char_cap", label: t("settings_ui.knob_body_char_cap"), hint: t("settings_ui.knob_body_char_cap_hint"), step: 500, min: 500, max: 20000 },
|
|
32
|
+
];
|
|
33
|
+
}
|
|
31
34
|
|
|
32
35
|
type NumericKnobs = {
|
|
33
36
|
load_threshold: number; hint_threshold: number; margin: number;
|
|
@@ -52,7 +55,7 @@ export function SkillsInspectorPanel() {
|
|
|
52
55
|
await Skills.updateInspector(patch);
|
|
53
56
|
await mutate();
|
|
54
57
|
} catch (e) {
|
|
55
|
-
toast.error(
|
|
58
|
+
toast.error(t("settings_ui.could_not_save", { msg: (e as Error).message }));
|
|
56
59
|
} finally {
|
|
57
60
|
setBusy(false);
|
|
58
61
|
}
|
|
@@ -63,11 +66,17 @@ export function SkillsInspectorPanel() {
|
|
|
63
66
|
try {
|
|
64
67
|
const r = await Skills.index({ force });
|
|
65
68
|
toast.success(
|
|
66
|
-
|
|
69
|
+
t("settings_ui.indexed_with", {
|
|
70
|
+
embedder: r.embedder,
|
|
71
|
+
dim: r.dim,
|
|
72
|
+
added: r.changed.added,
|
|
73
|
+
refreshed: r.changed.refreshed,
|
|
74
|
+
removed: r.changed.removed,
|
|
75
|
+
}),
|
|
67
76
|
);
|
|
68
77
|
await mutate();
|
|
69
78
|
} catch (e) {
|
|
70
|
-
toast.error(
|
|
79
|
+
toast.error(t("settings_ui.index_failed", { msg: (e as Error).message }));
|
|
71
80
|
} finally {
|
|
72
81
|
setBusy(false);
|
|
73
82
|
}
|
|
@@ -81,7 +90,7 @@ export function SkillsInspectorPanel() {
|
|
|
81
90
|
const r = await Skills.inspect(probe.trim());
|
|
82
91
|
setProbeResult(r.trace);
|
|
83
92
|
} catch (e) {
|
|
84
|
-
toast.error(
|
|
93
|
+
toast.error(t("settings_ui.dry_run_failed", { msg: (e as Error).message }));
|
|
85
94
|
} finally {
|
|
86
95
|
setBusy(false);
|
|
87
96
|
}
|
|
@@ -90,55 +99,55 @@ export function SkillsInspectorPanel() {
|
|
|
90
99
|
return (
|
|
91
100
|
<div className="grid gap-6 xl:grid-cols-2 xl:items-start">
|
|
92
101
|
<Section
|
|
93
|
-
title="
|
|
94
|
-
description="
|
|
102
|
+
title={t("settings_ui.inspector_title")}
|
|
103
|
+
description={t("settings_ui.inspector_desc")}
|
|
95
104
|
>
|
|
96
105
|
<div className="space-y-4">
|
|
97
106
|
<Field
|
|
98
|
-
label="
|
|
99
|
-
hint="
|
|
107
|
+
label={t("settings_ui.enable_inspector")}
|
|
108
|
+
hint={t("settings_ui.enable_inspector_hint")}
|
|
100
109
|
>
|
|
101
110
|
<Switch
|
|
102
111
|
checked={cfg.enabled}
|
|
103
112
|
disabled={busy}
|
|
104
113
|
onChange={(v) => apply({ enabled: v })}
|
|
105
|
-
label={cfg.enabled ? "
|
|
114
|
+
label={cfg.enabled ? t("settings_ui.on") : t("settings_ui.off")}
|
|
106
115
|
/>
|
|
107
116
|
</Field>
|
|
108
117
|
|
|
109
118
|
<div className="flex flex-wrap items-center gap-2 pt-1">
|
|
110
119
|
<Badge tone={idx.count > 0 ? "success" : "warning"}>
|
|
111
|
-
|
|
120
|
+
{t("settings_ui.index_count", { n: idx.count })}
|
|
112
121
|
</Badge>
|
|
113
|
-
<Badge tone="muted">{idx.embedder || "
|
|
114
|
-
{idx.dim ? <Badge tone="muted">dim {idx.dim}</Badge> : null}
|
|
122
|
+
<Badge tone="muted">{idx.embedder || t("settings_ui.not_indexed")}</Badge>
|
|
123
|
+
{idx.dim ? <Badge tone="muted">{t("settings_ui.dim", { dim: idx.dim })}</Badge> : null}
|
|
115
124
|
{idx.updated_at ? (
|
|
116
125
|
<span className="text-xs text-muted-foreground">
|
|
117
|
-
|
|
126
|
+
{t("settings_ui.updated_at", { date: new Date(idx.updated_at).toLocaleString() })}
|
|
118
127
|
</span>
|
|
119
128
|
) : null}
|
|
120
129
|
</div>
|
|
121
130
|
|
|
122
131
|
<div className="flex flex-wrap items-center gap-3 pt-1">
|
|
123
132
|
<Button variant="secondary" onClick={() => runIndex(false)} loading={busy}>
|
|
124
|
-
<RefreshCw size={14} />
|
|
133
|
+
<RefreshCw size={14} /> {t("settings_ui.reindex")}
|
|
125
134
|
</Button>
|
|
126
135
|
<Button variant="secondary" onClick={() => runIndex(true)} loading={busy}>
|
|
127
|
-
<RefreshCw size={14} />
|
|
136
|
+
<RefreshCw size={14} /> {t("settings_ui.reindex_forced")}
|
|
128
137
|
</Button>
|
|
129
138
|
<span className="text-xs text-muted-foreground">
|
|
130
|
-
|
|
139
|
+
{t("settings_ui.embedder_source")}
|
|
131
140
|
</span>
|
|
132
141
|
</div>
|
|
133
142
|
</div>
|
|
134
143
|
</Section>
|
|
135
144
|
|
|
136
145
|
<Section
|
|
137
|
-
title="
|
|
138
|
-
description="
|
|
146
|
+
title={t("settings_ui.thresholds_title")}
|
|
147
|
+
description={t("settings_ui.thresholds_desc")}
|
|
139
148
|
>
|
|
140
149
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
141
|
-
{
|
|
150
|
+
{knobs().map((k) => (
|
|
142
151
|
<Field key={k.key} label={k.label} hint={k.hint}>
|
|
143
152
|
<Input
|
|
144
153
|
type="number"
|
|
@@ -159,21 +168,21 @@ export function SkillsInspectorPanel() {
|
|
|
159
168
|
</Section>
|
|
160
169
|
|
|
161
170
|
<Section
|
|
162
|
-
title="
|
|
163
|
-
description="
|
|
171
|
+
title={t("settings_ui.test_title")}
|
|
172
|
+
description={t("settings_ui.test_desc")}
|
|
164
173
|
>
|
|
165
174
|
<div className="space-y-3">
|
|
166
175
|
<div className="flex flex-wrap items-center gap-2">
|
|
167
176
|
<Input
|
|
168
177
|
value={probe}
|
|
169
|
-
placeholder="
|
|
178
|
+
placeholder={t("settings_ui.test_placeholder")}
|
|
170
179
|
disabled={busy}
|
|
171
180
|
onChange={(ev) => setProbe(ev.target.value)}
|
|
172
181
|
onKeyDown={(ev) => { if (ev.key === "Enter") runProbe(); }}
|
|
173
182
|
className="max-w-xl flex-1"
|
|
174
183
|
/>
|
|
175
184
|
<Button variant="primary" onClick={runProbe} loading={busy}>
|
|
176
|
-
<Wand2 size={14} />
|
|
185
|
+
<Wand2 size={14} /> {t("settings_ui.test_btn")}
|
|
177
186
|
</Button>
|
|
178
187
|
</div>
|
|
179
188
|
|
|
@@ -182,7 +191,7 @@ export function SkillsInspectorPanel() {
|
|
|
182
191
|
<div className="mb-2 flex flex-wrap items-center gap-2">
|
|
183
192
|
<Sparkles size={14} className="text-muted-foreground" />
|
|
184
193
|
<span className="text-muted-foreground">{probeResult.embedder || "—"}</span>
|
|
185
|
-
{probeResult.jit ? <Badge tone="warning">
|
|
194
|
+
{probeResult.jit ? <Badge tone="warning">{t("settings_ui.jit_empty_index")}</Badge> : null}
|
|
186
195
|
{probeResult.reason && !probeResult.loaded?.length && !probeResult.hinted?.length ? (
|
|
187
196
|
<Badge tone="muted">{probeResult.reason}</Badge>
|
|
188
197
|
) : null}
|
|
@@ -190,7 +199,7 @@ export function SkillsInspectorPanel() {
|
|
|
190
199
|
|
|
191
200
|
{probeResult.loaded?.length ? (
|
|
192
201
|
<div className="mb-1">
|
|
193
|
-
<span className="text-muted-foreground">
|
|
202
|
+
<span className="text-muted-foreground">{t("settings_ui.loaded_label")} </span>
|
|
194
203
|
{probeResult.loaded.map((s) => (
|
|
195
204
|
<Badge key={s} tone="success" className="mr-1">{s}</Badge>
|
|
196
205
|
))}
|
|
@@ -199,7 +208,7 @@ export function SkillsInspectorPanel() {
|
|
|
199
208
|
|
|
200
209
|
{probeResult.hinted?.length ? (
|
|
201
210
|
<div className="mb-1">
|
|
202
|
-
<span className="text-muted-foreground">
|
|
211
|
+
<span className="text-muted-foreground">{t("settings_ui.suggested_label")} </span>
|
|
203
212
|
{probeResult.hinted.map((s) => (
|
|
204
213
|
<Badge key={s} tone="info" className="mr-1">{s}</Badge>
|
|
205
214
|
))}
|
|
@@ -53,20 +53,20 @@ export function SuperAgentPanel() {
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
return (
|
|
56
|
-
<Section title={t("settings.super_agent.title")} description="
|
|
56
|
+
<Section title={t("settings.super_agent.title")} description={t("settings.super_agent.behavior_subtitle")}>
|
|
57
57
|
<div className="space-y-4">
|
|
58
58
|
<div className="flex items-center gap-3">
|
|
59
|
-
<Switch checked={enabled} onChange={setEnabled} label="
|
|
59
|
+
<Switch checked={enabled} onChange={setEnabled} label={t("settings.super_agent.enabled_label")} />
|
|
60
60
|
</div>
|
|
61
61
|
|
|
62
62
|
{/* Model lives in the Router now — single source of truth. */}
|
|
63
63
|
<div className="flex items-center justify-between rounded-lg border border-border bg-muted/20 p-3">
|
|
64
64
|
<div className="min-w-0">
|
|
65
|
-
<div className="text-sm font-medium">
|
|
65
|
+
<div className="text-sm font-medium">{t("settings.super_agent.model_active")}</div>
|
|
66
66
|
<div className="truncate font-mono text-xs text-muted-fg">{superAgent.model || "—"}</div>
|
|
67
67
|
</div>
|
|
68
68
|
<Button size="sm" variant="secondary" onClick={() => navigate("/p/0/models")}>
|
|
69
|
-
<Cpu size={13} />
|
|
69
|
+
<Cpu size={13} /> {t("settings.super_agent.model_configure")}
|
|
70
70
|
</Button>
|
|
71
71
|
</div>
|
|
72
72
|
|
|
@@ -82,7 +82,7 @@ export function SuperAgentPanel() {
|
|
|
82
82
|
className="font-mono text-xs"
|
|
83
83
|
value={system}
|
|
84
84
|
onChange={(e) => setSystem(e.target.value)}
|
|
85
|
-
placeholder="
|
|
85
|
+
placeholder={t("settings.super_agent.system_ph")}
|
|
86
86
|
/>
|
|
87
87
|
</Field>
|
|
88
88
|
|
|
@@ -49,7 +49,7 @@ export function TelegramChannelsPanel() {
|
|
|
49
49
|
<ul className="space-y-2 text-sm">
|
|
50
50
|
{channels.map((c) => {
|
|
51
51
|
const ownerLabel = c.owner_user_id != null
|
|
52
|
-
? (nameByUserId.get(String(c.owner_user_id)) ||
|
|
52
|
+
? (nameByUserId.get(String(c.owner_user_id)) || t("telegram_ui.user_id_fallback", { id: c.owner_user_id }))
|
|
53
53
|
: t("telegram_channels.no_owner");
|
|
54
54
|
return (
|
|
55
55
|
<li key={c.name} className="rounded-md border border-border bg-muted/30 px-3 py-2">
|
|
@@ -67,8 +67,8 @@ export function TelegramChannelsPanel() {
|
|
|
67
67
|
<div className="mt-1 grid grid-cols-2 gap-2 text-xs text-muted-fg">
|
|
68
68
|
<span>chat_id: {c.chat_id || "—"}</span>
|
|
69
69
|
<span>bot_token: {c.bot_token ? `…${secretSuffix(c.bot_token) ?? ""}` : "—"}</span>
|
|
70
|
-
<span>route_to_agent: {c.route_to_agent || "
|
|
71
|
-
<span>engine: {c.respond_with_engine ? "
|
|
70
|
+
<span>route_to_agent: {c.route_to_agent || t("telegram_ui.default_apx")}</span>
|
|
71
|
+
<span>engine: {c.respond_with_engine ? t("telegram_ui.yes") : t("telegram_ui.no")}</span>
|
|
72
72
|
<span className="col-span-2">{t("telegram_channels.owner_label")} {ownerLabel}</span>
|
|
73
73
|
</div>
|
|
74
74
|
</li>
|
|
@@ -28,7 +28,7 @@ export function TelegramContactsPanel({ bare = false }: Props) {
|
|
|
28
28
|
const setRole = async (c: TelegramContact, role: string) => {
|
|
29
29
|
try {
|
|
30
30
|
await Telegram.contacts.patch(c.user_id, { role });
|
|
31
|
-
toast.success(
|
|
31
|
+
toast.success(t("telegram_ui.role_assigned", { name: c.name || c.user_id, role }));
|
|
32
32
|
mutate();
|
|
33
33
|
} catch (e) { toast.error((e as Error).message); }
|
|
34
34
|
};
|
|
@@ -76,14 +76,14 @@ export function TelegramGlobalPanel() {
|
|
|
76
76
|
<Field
|
|
77
77
|
label={t("settings.telegram_global.bot_token")}
|
|
78
78
|
hint={channel?.bot_token
|
|
79
|
-
? `…${secretSuffix(channel.bot_token) ?? ""} (
|
|
80
|
-
: "
|
|
79
|
+
? `…${secretSuffix(channel.bot_token) ?? ""} ${t("telegram_ui.secret_set_replace")}`
|
|
80
|
+
: t("telegram_ui.bot_token_hint_short")}
|
|
81
81
|
>
|
|
82
82
|
<Input
|
|
83
83
|
type="password"
|
|
84
84
|
value={botToken}
|
|
85
85
|
onChange={(e) => setBotToken(e.target.value)}
|
|
86
|
-
placeholder={channel?.bot_token ? `…${secretSuffix(channel.bot_token) ?? ""} (
|
|
86
|
+
placeholder={channel?.bot_token ? `…${secretSuffix(channel.bot_token) ?? ""} ${t("telegram_ui.secret_already_set")}` : ""}
|
|
87
87
|
/>
|
|
88
88
|
</Field>
|
|
89
89
|
<Field label={t("settings.telegram_global.chat_id")}>
|
|
@@ -71,7 +71,7 @@ export function TelegramRolesPanel() {
|
|
|
71
71
|
<Button size="sm" variant="destructive" onClick={() => remove(n)}>{t("telegram_roles.delete_btn")}</Button>
|
|
72
72
|
)}
|
|
73
73
|
</div>
|
|
74
|
-
<div className="mt-1 text-xs text-muted-fg">
|
|
74
|
+
<div className="mt-1 text-xs text-muted-fg">{t("telegram_contacts.tools_label")} {toolsLabel}</div>
|
|
75
75
|
</li>
|
|
76
76
|
);
|
|
77
77
|
})}
|
|
@@ -55,7 +55,7 @@ export function ProviderCard({
|
|
|
55
55
|
)}
|
|
56
56
|
>
|
|
57
57
|
<span className={cn("size-1.5 rounded-full", active ? "bg-emerald-400" : "bg-muted-fg/40")} />
|
|
58
|
-
{active ? "
|
|
58
|
+
{active ? t("providers_card.active") : t("providers_card.off")}
|
|
59
59
|
</button>
|
|
60
60
|
</Tip>
|
|
61
61
|
<Tip content={t("providers_modal.delete")}>
|
|
@@ -72,14 +72,14 @@ export function ProviderCard({
|
|
|
72
72
|
|
|
73
73
|
{/* Body */}
|
|
74
74
|
<div className="mt-auto space-y-1 text-xs">
|
|
75
|
-
<Row label="
|
|
76
|
-
{provider.base_url && <Row label="
|
|
77
|
-
<Row label="
|
|
75
|
+
<Row label={t("providers_card.model")} value={provider.default_model || "—"} mono />
|
|
76
|
+
{provider.base_url && <Row label={t("providers_card.base_url")} value={provider.base_url} mono truncate />}
|
|
77
|
+
<Row label={t("providers_card.api_key")} value={hasKey ? (keySuffix ? `…${keySuffix}` : t("providers_card.key_set")) : "—"} mono={!!keySuffix} />
|
|
78
78
|
{provider.default_temperature !== undefined && (
|
|
79
|
-
<Row label="
|
|
79
|
+
<Row label={t("providers_card.temp")} value={provider.default_temperature.toFixed(1)} />
|
|
80
80
|
)}
|
|
81
81
|
{provider.pricing?.input_per_million !== undefined && (
|
|
82
|
-
<Row label="
|
|
82
|
+
<Row label={t("providers_card.price_io")} value={`${provider.pricing.input_per_million ?? 0} / ${provider.pricing.output_per_million ?? 0}`} />
|
|
83
83
|
)}
|
|
84
84
|
</div>
|
|
85
85
|
</div>
|