refactor: extract execution permission policy
This commit is contained in:
104
src/lib/execution/permission-policy.ts
Normal file
104
src/lib/execution/permission-policy.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { listExecutionTools, type ExecutionToolName } from "@/lib/execution/tool-registry";
|
||||
|
||||
type CollaborationMode = "development" | "approval_required";
|
||||
|
||||
type ApprovalState = "not_required" | "pending_agent" | "pending_user" | "approved" | "rejected";
|
||||
|
||||
type PermissionPolicyProject = {
|
||||
id: string;
|
||||
isGroup: boolean;
|
||||
collaborationMode: CollaborationMode;
|
||||
approvalState: ApprovalState;
|
||||
};
|
||||
|
||||
type ToolPolicy = {
|
||||
allowedTools: ExecutionToolName[];
|
||||
deniedTools: ExecutionToolName[];
|
||||
};
|
||||
|
||||
type CollaborationPolicy = {
|
||||
mode: CollaborationMode;
|
||||
canDispatchDirectly: boolean;
|
||||
canCrossThreadTalk: boolean;
|
||||
};
|
||||
|
||||
type PermissionPolicyResult = {
|
||||
allowed: boolean;
|
||||
requiresApproval: boolean;
|
||||
reason?: string;
|
||||
toolPolicy: ToolPolicy;
|
||||
collaborationPolicy: CollaborationPolicy;
|
||||
};
|
||||
|
||||
const DEFAULT_APPROVAL_REQUIRED_REASON =
|
||||
"当前还有一条主 Agent 推荐等待确认,请先确认或拒绝后再继续发送新指令。";
|
||||
|
||||
const EMPTY_TOOL_POLICY: ToolPolicy = {
|
||||
allowedTools: [],
|
||||
deniedTools: [],
|
||||
};
|
||||
|
||||
function listDefaultAllowedTools(): ExecutionToolName[] {
|
||||
return listExecutionTools()
|
||||
.filter((tool) => tool.kind === "execution")
|
||||
.map((tool) => tool.name);
|
||||
}
|
||||
|
||||
function buildCollaborationPolicy(mode: CollaborationMode): CollaborationPolicy {
|
||||
return {
|
||||
mode,
|
||||
canDispatchDirectly: mode === "development",
|
||||
canCrossThreadTalk: mode === "development",
|
||||
};
|
||||
}
|
||||
|
||||
function buildAllowedPolicy(mode: CollaborationMode, requiresApproval: boolean): PermissionPolicyResult {
|
||||
return {
|
||||
allowed: true,
|
||||
requiresApproval,
|
||||
toolPolicy: {
|
||||
allowedTools:
|
||||
mode === "approval_required"
|
||||
? ["group_dispatch_plan"]
|
||||
: listDefaultAllowedTools(),
|
||||
deniedTools: [],
|
||||
},
|
||||
collaborationPolicy: buildCollaborationPolicy(mode),
|
||||
};
|
||||
}
|
||||
|
||||
export function evaluatePermissionPolicy(input: {
|
||||
project?: PermissionPolicyProject;
|
||||
hasPendingDispatchPlan?: boolean;
|
||||
}): PermissionPolicyResult {
|
||||
const project = input.project;
|
||||
|
||||
if (!project) {
|
||||
return {
|
||||
allowed: true,
|
||||
requiresApproval: false,
|
||||
toolPolicy: EMPTY_TOOL_POLICY,
|
||||
collaborationPolicy: buildCollaborationPolicy("development"),
|
||||
};
|
||||
}
|
||||
|
||||
if (project.isGroup && project.collaborationMode === "approval_required" && input.hasPendingDispatchPlan) {
|
||||
return {
|
||||
allowed: false,
|
||||
requiresApproval: true,
|
||||
reason: DEFAULT_APPROVAL_REQUIRED_REASON,
|
||||
toolPolicy: {
|
||||
allowedTools: ["group_dispatch_plan"],
|
||||
deniedTools: ["dispatch_execution"],
|
||||
},
|
||||
collaborationPolicy: buildCollaborationPolicy("approval_required"),
|
||||
};
|
||||
}
|
||||
|
||||
return buildAllowedPolicy(
|
||||
project.collaborationMode,
|
||||
project.isGroup && project.collaborationMode === "approval_required",
|
||||
);
|
||||
}
|
||||
|
||||
export const evaluatePermissionPolicyForTesting = evaluatePermissionPolicy;
|
||||
23
src/lib/execution/tool-registry.ts
Normal file
23
src/lib/execution/tool-registry.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
export type ExecutionToolKind = "execution" | "analysis";
|
||||
|
||||
export type ExecutionToolName =
|
||||
| "conversation_reply"
|
||||
| "group_dispatch_plan"
|
||||
| "dispatch_execution"
|
||||
| "attachment_analysis";
|
||||
|
||||
export interface ExecutionToolDefinition {
|
||||
name: ExecutionToolName;
|
||||
kind: ExecutionToolKind;
|
||||
}
|
||||
|
||||
const EXECUTION_TOOLS: readonly ExecutionToolDefinition[] = [
|
||||
{ name: "conversation_reply", kind: "execution" },
|
||||
{ name: "group_dispatch_plan", kind: "execution" },
|
||||
{ name: "dispatch_execution", kind: "execution" },
|
||||
{ name: "attachment_analysis", kind: "analysis" },
|
||||
] as const;
|
||||
|
||||
export function listExecutionTools() {
|
||||
return EXECUTION_TOOLS;
|
||||
}
|
||||
Reference in New Issue
Block a user