BeforeTool-hook + kort-vy (strukturerade godkännanden) + release på master-push
Feature: strukturerade verktygsgodkännanden
- shared: protokoll för approval (daemon:approval, server:approval[-resolved],
web:approval-decision, server:approval-decision)
- daemon: hook-läge ('agent-helm hook' — samma binär), lokal 127.0.0.1-endpoint
som hooken POST:ar till, long-poll tills beslut; graceful default (allow) när
ingen UI; timeout-fallback; skickar AGENT_HELM_HOOK_PORT till agentens env
- server: routar daemon:approval -> prenumeranter, beslut -> daemon + döljer kort
- web: reaktiv approvals-lista + kort-overlay (Tillåt/Neka), mobilanpassad
CI:
- release.yaml triggar nu även på master-push -> rullande 'latest'-release
(versionerade releaser kvar på v*-taggar); install.sh hämtar 'latest'
Docs: hook-konfig (gemini settings.json) + hook-env i .env.example + DEPLOY.md.
Säkerhet: hook-endpoint binder endast 127.0.0.1; inga hemligheter i repot.
Verifierat lokalt: hook->daemon->server->kort->beslut->hook ger {"decision":"allow"};
alla paket typecheckar; web bygger.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -37,7 +37,15 @@ export interface DaemonExit {
|
||||
code: number;
|
||||
}
|
||||
|
||||
export type DaemonMessage = DaemonHello | DaemonOutput | DaemonExit;
|
||||
/** Agenten vill köra ett verktyg (via BeforeTool-hooken) och vill ha godkännande. */
|
||||
export interface DaemonApproval {
|
||||
type: "daemon:approval";
|
||||
approvalId: string;
|
||||
toolName: string;
|
||||
toolInput: unknown;
|
||||
}
|
||||
|
||||
export type DaemonMessage = DaemonHello | DaemonOutput | DaemonExit | DaemonApproval;
|
||||
|
||||
/* ----------------------------- Server -> Daemon ---------------------------- */
|
||||
|
||||
@@ -47,7 +55,15 @@ export interface ServerInput {
|
||||
data: string;
|
||||
}
|
||||
|
||||
export type ServerToDaemon = ServerInput;
|
||||
/** Beslut på en hook-förfrågan, vidarebefordrat till daemonen som äger sessionen. */
|
||||
export interface ServerApprovalDecision {
|
||||
type: "server:approval-decision";
|
||||
approvalId: string;
|
||||
decision: "allow" | "deny";
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export type ServerToDaemon = ServerInput | ServerApprovalDecision;
|
||||
|
||||
/* ---------------------------- Frontend -> Server --------------------------- */
|
||||
|
||||
@@ -68,7 +84,16 @@ export interface WebInput {
|
||||
data: string;
|
||||
}
|
||||
|
||||
export type WebMessage = WebHello | WebSubscribe | WebInput;
|
||||
/** Användarens svar på ett godkännande-kort. */
|
||||
export interface WebApprovalDecision {
|
||||
type: "web:approval-decision";
|
||||
sessionId: string;
|
||||
approvalId: string;
|
||||
decision: "allow" | "deny";
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export type WebMessage = WebHello | WebSubscribe | WebInput | WebApprovalDecision;
|
||||
|
||||
/* ---------------------------- Server -> Frontend --------------------------- */
|
||||
|
||||
@@ -106,13 +131,32 @@ export interface ServerError {
|
||||
message: string;
|
||||
}
|
||||
|
||||
/** Strukturerad godkännande-förfrågan (från en BeforeTool-hook) -> visas som kort. */
|
||||
export interface ServerApproval {
|
||||
type: "server:approval";
|
||||
sessionId: string;
|
||||
approvalId: string;
|
||||
toolName: string;
|
||||
toolInput: unknown;
|
||||
}
|
||||
|
||||
/** En förfrågan har besvarats (av dig eller en annan klient) -> dölj kortet. */
|
||||
export interface ServerApprovalResolved {
|
||||
type: "server:approval-resolved";
|
||||
sessionId: string;
|
||||
approvalId: string;
|
||||
decision: "allow" | "deny";
|
||||
}
|
||||
|
||||
export type ServerToWeb =
|
||||
| ServerWelcome
|
||||
| ServerSessions
|
||||
| ServerSnapshot
|
||||
| ServerOutput
|
||||
| ServerSessionExit
|
||||
| ServerError;
|
||||
| ServerError
|
||||
| ServerApproval
|
||||
| ServerApprovalResolved;
|
||||
|
||||
/* --------------------------------- Helpers --------------------------------- */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user