mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-16 03:39:29 +02:00
Phase 7 : outils web_search et run_shell avec validation
Backend : - tools.py : web_search (DuckDuckGo HTML sans clé, ou SearxNG via SEARX_URL) et run_shell (confiné au workspace, sortie bornée, timeout) - agent.py : run_shell sensible -> émet tool_confirm et ne s'exécute pas tant que l'utilisateur n'a pas validé (confirm_shell) - agent_config.py : web_search/run_shell désactivés par défaut, flag confirm_shell - routes/shell.py : POST /api/shell/run exécute une commande validée - routes/chat.py : relaie l'événement tool_confirm, passe confirm_shell Frontend : - streamChat : événement tool_confirm - store : pendingShell + approveShell/rejectShell (réinjecte le résultat à l'agent) - ChatPanel : carte de validation de commande (Approuver / Refuser) - SettingsView : toggles web_search/run_shell, marqueur sensible, switch confirm_shell - ToolCard : glyphes web_search/run_shell, statut 'à valider', aperçu d'argument Tests : run_shell confiné, gate de confirmation (commande dangereuse non exécutée), route shell, parser DuckDuckGo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SVay7z3y7q2gEe54ByAE6N
This commit is contained in:
1 parent
2db6beea5c
commit
de2befe31e
12 files changed
+398
-26
No files matched your search
@@ -4,11 +4,16 @@ import type { ToolCall } from "../api/client";
|
||||
export function ToolCard({ call }: { call: ToolCall }) {
|
||||
const running = call.status === "running";
|
||||
const error = call.status === "error";
|
||||
const pending = call.status === "pending";
|
||||
|
||||
// Argument principal affiché entre parenthèses (path le plus souvent).
|
||||
// Argument principal affiché entre parenthèses selon l'outil.
|
||||
const mainArg =
|
||||
(call.args?.path as string) ??
|
||||
(call.args?.query as string) ??
|
||||
(call.args?.command as string);
|
||||
const argPreview =
|
||||
typeof call.args?.path === "string"
|
||||
? `("${call.args.path}")`
|
||||
typeof mainArg === "string"
|
||||
? `("${mainArg.length > 48 ? mainArg.slice(0, 48) + "…" : mainArg}")`
|
||||
: Object.keys(call.args ?? {}).length
|
||||
? "(…)"
|
||||
: "()";
|
||||
@@ -32,6 +37,8 @@ export function ToolCard({ call }: { call: ToolCall }) {
|
||||
<span className="h-2.5 w-2.5 animate-spin rounded-full border-2 border-muted-3 border-t-accent" />
|
||||
en cours
|
||||
</span>
|
||||
) : pending ? (
|
||||
<span className="font-mono text-[11px] text-warn">⏸ à valider</span>
|
||||
) : (
|
||||
<span
|
||||
className={`flex items-center gap-1.5 font-mono text-[11px] ${
|
||||
@@ -74,6 +81,20 @@ function ToolGlyph({ name }: { name: string }) {
|
||||
<path d="M4 7h6l2 2h8v9H4z" />
|
||||
</svg>
|
||||
);
|
||||
if (name === "web_search")
|
||||
return (
|
||||
<svg {...common}>
|
||||
<circle cx="11" cy="11" r="7" />
|
||||
<path d="m21 21-4.3-4.3" />
|
||||
</svg>
|
||||
);
|
||||
if (name === "run_shell")
|
||||
return (
|
||||
<svg {...common}>
|
||||
<path d="m6 9 3 3-3 3M13 15h5" />
|
||||
<rect x="2" y="4" width="20" height="16" rx="2" />
|
||||
</svg>
|
||||
);
|
||||
// read_file (défaut)
|
||||
return (
|
||||
<svg {...common}>
|
||||
|
||||
Reference in new issue
Block a user