feat: vendor permission system source

This commit is contained in:
云服务部-叶林立
2026-08-19 14:35:19 +08:00
parent 198584daf8
commit 410c50a3e5
809 changed files with 157793 additions and 139 deletions
@@ -0,0 +1,90 @@
/**
* Centralized construction for `permissions:ui_prompt` payloads.
*
* The single builder `buildUiPrompt` handles both direct and forwarded asks, so
* the public contract's shape — including the normalized `surface`/`value`
* projection and the `forwarding` context — lives in exactly one place and
* cannot drift by source.
*
* This module is a leaf: it owns narrow input types that each call site's
* domain object satisfies structurally, so it imports nothing from the
* prompter or forwarding modules (no import cycles, correct layering).
*/
import type { PromptPayload } from "#src/presentation/prompt-payload";
import type {
ForwardedPromptContext,
PermissionUiPromptEvent,
} from "./permission-events";
/** Input for a direct (non-forwarded) tool or skill prompt. */
export interface DirectPromptInput {
requestId: string;
source: "tool_call" | "skill_input" | "skill_read";
agentName: string | null;
/** The ask's complete payload; the event carries its invariant core alone. */
payload: PromptPayload;
toolName?: string;
skillName?: string;
path?: string;
command?: string;
target?: string;
}
/**
* Input for any UI prompt — direct or forwarded.
*
* A direct prompt supplies only the `DirectPromptInput` fields and lets
* `surface`/`value` derive and `forwarding` default to `null`; a forwarded ask
* supplies the child's original `surface`/`value` projection explicitly and a
* populated `forwarding` context, so the parent's broadcast stays non-degraded
* (the #292 contract hardening).
*/
export interface UiPromptInput extends DirectPromptInput {
/** Explicit display surface; falls back to the derived projection when omitted. */
surface?: string | null;
/** Explicit display value; falls back to the derived projection when omitted. */
value?: string | null;
/** Forwarding context for a forwarded subagent ask; `null`/omitted for a direct prompt. */
forwarding?: ForwardedPromptContext | null;
}
/**
* Build a `permissions:ui_prompt` event from either a direct or a forwarded ask.
*
* `surface`/`value` use the explicit override when the caller sets them (an
* explicit `null` is honored, not treated as "derive"); otherwise they fall
* back to the direct-prompt projection. `forwarding` passes through, defaulting
* to `null`.
*/
export function buildUiPrompt(input: UiPromptInput): PermissionUiPromptEvent {
return {
requestId: input.requestId,
source: input.source,
surface: input.surface !== undefined ? input.surface : directSurface(input),
value: input.value !== undefined ? input.value : directValue(input),
agentName: input.agentName,
request: input.payload.request,
forwarding: input.forwarding ?? null,
};
}
/** Normalized display surface for a direct prompt. */
function directSurface(input: DirectPromptInput): string | null {
if (input.source === "skill_input" || input.source === "skill_read") {
return "skill";
}
return input.toolName ?? null;
}
/** Normalized display value for a direct prompt. */
function directValue(input: DirectPromptInput): string | null {
return (
input.command ??
input.path ??
input.target ??
input.skillName ??
input.toolName ??
null
);
}