mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
feat: add permission decision options, tool allowlisting, and refactored chat UI components
This commit is contained in:
@@ -37,13 +37,18 @@ export const AgentStateSchema = z.object({
|
||||
tool: z.string(),
|
||||
arguments: z.unknown(),
|
||||
createdAt: z.number().nullish()
|
||||
})).nullish(),
|
||||
}).passthrough()).nullish(),
|
||||
completedRequests: z.record(z.string(), z.object({
|
||||
tool: z.string(),
|
||||
arguments: z.unknown(),
|
||||
createdAt: z.number().nullish(),
|
||||
completedAt: z.number().nullish(),
|
||||
status: z.enum(['canceled', 'denied', 'approved']),
|
||||
mode: z.string().nullish()
|
||||
})).nullish()
|
||||
reason: z.string().optional(),
|
||||
mode: z.string().optional(),
|
||||
decision: z.enum(['approved', 'approved_for_session', 'denied', 'abort']).optional(),
|
||||
allowTools: z.array(z.string()).optional()
|
||||
}).passthrough()).nullish()
|
||||
}).passthrough()
|
||||
|
||||
export type AgentState = z.infer<typeof AgentStateSchema>
|
||||
@@ -558,19 +563,28 @@ export class SyncEngine {
|
||||
async approvePermission(
|
||||
sessionId: string,
|
||||
requestId: string,
|
||||
mode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan'
|
||||
mode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan',
|
||||
allowTools?: string[],
|
||||
decision?: 'approved' | 'approved_for_session' | 'denied' | 'abort'
|
||||
): Promise<void> {
|
||||
await this.sessionRpc(sessionId, 'permission', {
|
||||
id: requestId,
|
||||
approved: true,
|
||||
mode
|
||||
mode,
|
||||
allowTools,
|
||||
decision
|
||||
})
|
||||
}
|
||||
|
||||
async denyPermission(sessionId: string, requestId: string): Promise<void> {
|
||||
async denyPermission(
|
||||
sessionId: string,
|
||||
requestId: string,
|
||||
decision?: 'approved' | 'approved_for_session' | 'denied' | 'abort'
|
||||
): Promise<void> {
|
||||
await this.sessionRpc(sessionId, 'permission', {
|
||||
id: requestId,
|
||||
approved: false
|
||||
approved: false,
|
||||
decision
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,16 @@ import type { SyncEngine } from '../../sync/syncEngine'
|
||||
import type { WebAppEnv } from '../middleware/auth'
|
||||
import { requireSessionFromParam, requireSyncEngine } from './guards'
|
||||
|
||||
const decisionSchema = z.enum(['approved', 'approved_for_session', 'denied', 'abort'])
|
||||
|
||||
const approveBodySchema = z.object({
|
||||
mode: z.enum(['default', 'acceptEdits', 'bypassPermissions']).optional()
|
||||
mode: z.enum(['default', 'acceptEdits', 'bypassPermissions', 'plan']).optional(),
|
||||
allowTools: z.array(z.string()).optional(),
|
||||
decision: decisionSchema.optional()
|
||||
})
|
||||
|
||||
const denyBodySchema = z.object({
|
||||
decision: decisionSchema.optional()
|
||||
})
|
||||
|
||||
export function createPermissionsRoutes(getSyncEngine: () => SyncEngine | null): Hono<WebAppEnv> {
|
||||
@@ -26,7 +34,7 @@ export function createPermissionsRoutes(getSyncEngine: () => SyncEngine | null):
|
||||
const { sessionId, session } = sessionResult
|
||||
|
||||
const json = await c.req.json().catch(() => null)
|
||||
const parsed = approveBodySchema.safeParse(json)
|
||||
const parsed = approveBodySchema.safeParse(json ?? {})
|
||||
if (!parsed.success) {
|
||||
return c.json({ error: 'Invalid body' }, 400)
|
||||
}
|
||||
@@ -37,7 +45,9 @@ export function createPermissionsRoutes(getSyncEngine: () => SyncEngine | null):
|
||||
}
|
||||
|
||||
const mode = parsed.data.mode
|
||||
await engine.approvePermission(sessionId, requestId, mode)
|
||||
const allowTools = parsed.data.allowTools
|
||||
const decision = parsed.data.decision
|
||||
await engine.approvePermission(sessionId, requestId, mode, allowTools, decision)
|
||||
return c.json({ ok: true })
|
||||
})
|
||||
|
||||
@@ -60,7 +70,13 @@ export function createPermissionsRoutes(getSyncEngine: () => SyncEngine | null):
|
||||
return c.json({ error: 'Request not found' }, 404)
|
||||
}
|
||||
|
||||
await engine.denyPermission(sessionId, requestId)
|
||||
const json = await c.req.json().catch(() => null)
|
||||
const parsed = denyBodySchema.safeParse(json ?? {})
|
||||
if (!parsed.success) {
|
||||
return c.json({ error: 'Invalid body' }, 400)
|
||||
}
|
||||
|
||||
await engine.denyPermission(sessionId, requestId, parsed.data.decision)
|
||||
return c.json({ ok: true })
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user