11import type { ToolCall } from "@intx/types/runtime" ;
22import { isAbsolute , resolve } from "node:path" ;
3- import { randomUUID } from "node:crypto" ;
43import type {
54 Approval ,
65 ApprovalOutcome ,
@@ -43,17 +42,25 @@ import { NOOP_APPROVAL_LOG, type ApprovalLog, type ApprovalOutcomeKind } from ".
4342// Closes out an operator prompt: ends the wait span and records the outcome.
4443// buildRequests yields at most one request per tool call, and the two prompt
4544// sites below are mutually exclusive, so this runs once per prompt shown.
45+ function finishApprovalWait (
46+ telemetry : Telemetry ,
47+ waitSpanId : string ,
48+ tool : string ,
49+ outcome : ApprovalOutcome | undefined ,
50+ ) : void {
51+ const decision = outcome !== undefined && outcome . allow ? "allow" : "deny" ;
52+ end ( waitSpanId , outcome !== undefined ? { decision } : undefined ) ;
53+ telemetry . capture ( "permission_prompt" , {
54+ decision,
55+ permission_kind : classifyPermissionKind ( tool ) ,
56+ } ) ;
57+ }
58+
4659// Classifies a settled ApprovalOutcome into the approval-log taxonomy.
4760// gate-wire.ts's timeout/abort auto-denies carry a fixed message text (see
4861// autoDeny in gate-wire.ts and the timeout branch in tui/request-approval.ts's
4962// finish() usage); anything else that denies is a plain operator/unavailable
5063// decision.
51- function withRequestId ( request : PermissionRequest ) : PermissionRequest {
52- return request . id !== undefined && request . id . length > 0
53- ? request
54- : { ...request , id : randomUUID ( ) } ;
55- }
56-
5764function classifyOutcome ( outcome : ApprovalOutcome | undefined ) : ApprovalOutcomeKind {
5865 if ( outcome === undefined ) return "deny" ;
5966 if ( ! outcome . allow ) {
@@ -65,20 +72,6 @@ function classifyOutcome(outcome: ApprovalOutcome | undefined): ApprovalOutcomeK
6572 return outcome . persist !== undefined ? "allow-with-scope" : "allow-once" ;
6673}
6774
68- function finishApprovalWait (
69- telemetry : Telemetry ,
70- waitSpanId : string ,
71- tool : string ,
72- outcome : ApprovalOutcome | undefined ,
73- ) : void {
74- const decision = outcome !== undefined && outcome . allow ? "allow" : "deny" ;
75- end ( waitSpanId , outcome !== undefined ? { decision } : undefined ) ;
76- telemetry . capture ( "permission_prompt" , {
77- decision,
78- permission_kind : classifyPermissionKind ( tool ) ,
79- } ) ;
80- }
81-
8275export type GateVerdict = { allowed : true } | { allowed : false ; reason : string } ;
8376
8477// One shell segment's forced-ask guard: a secret-path reference or a
@@ -653,7 +646,7 @@ export function createPermissionGate(options: PermissionGateOptions): Permission
653646 const requestForOperator = anySecret ? { ...request , scopes : [ ] } : request ;
654647 return {
655648 kind : "ask" ,
656- request : withRequestId ( requestForOperator ) ,
649+ request : requestForOperator ,
657650 anySecret,
658651 segmentCount : segments . length ,
659652 } ;
@@ -681,7 +674,7 @@ export function createPermissionGate(options: PermissionGateOptions): Permission
681674 } ;
682675 }
683676
684- return { kind : "ask" , request : withRequestId ( request ) , anySecret : false , segmentCount : 0 } ;
677+ return { kind : "ask" , request, anySecret : false , segmentCount : 0 } ;
685678 }
686679 return { kind : "allow" } ;
687680 } ;
0 commit comments