Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline (Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/* packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
95 lines
3.2 KiB
TypeScript
95 lines
3.2 KiB
TypeScript
import type { MessageBlock } from "@rakazo/contracts";
|
|
import { redactSecrets } from "@rakazo/core";
|
|
|
|
const MAX_APPROVAL_SUMMARY_LENGTH = 500;
|
|
const MAX_APPROVAL_DETAIL_LENGTH = 4_000;
|
|
|
|
export function buildApprovalAskBlock(
|
|
effectId: string,
|
|
toolName: string,
|
|
args: Record<string, unknown>,
|
|
secrets: string[],
|
|
options?: { reviewReason?: string },
|
|
): MessageBlock {
|
|
const summary = describeApprovalAction(toolName, args);
|
|
const detail = formatApprovalDetail(toolName, args, options?.reviewReason);
|
|
const safeDetail = detail ? redactSecrets(detail, secrets) : undefined;
|
|
return {
|
|
kind: "ask",
|
|
approvalEffectId: effectId,
|
|
text: truncate(
|
|
redactSecrets(
|
|
toolName === "create_space" ? `${summary}?` : `Review before ${summary}`,
|
|
secrets,
|
|
),
|
|
MAX_APPROVAL_SUMMARY_LENGTH,
|
|
),
|
|
detail: safeDetail ? truncate(safeDetail, MAX_APPROVAL_DETAIL_LENGTH) : undefined,
|
|
status: "pending",
|
|
actions:
|
|
toolName === "create_space"
|
|
? [
|
|
{ id: "allow", label: "Create space", outcome: "created" },
|
|
{ id: "deny", label: "Cancel", outcome: "cancelled" },
|
|
]
|
|
: [
|
|
{ id: "allow", label: "Allow once" },
|
|
{ id: "always", label: "Always allow this tool" },
|
|
{ id: "deny", label: "Deny" },
|
|
],
|
|
};
|
|
}
|
|
|
|
function describeApprovalAction(toolName: string, args: Record<string, unknown>): string {
|
|
if (toolName === "destination.write") {
|
|
const collection = args.collection ? String(args.collection) : "records";
|
|
const title = args.title ? ` "${String(args.title)}"` : "";
|
|
return `writing${title} to ${collection}`;
|
|
}
|
|
if (toolName === "delete_bot" || toolName === "archive_bot") {
|
|
const name = args.confirm_name ?? args.confirmName;
|
|
return name ? `${toolName.replace("_", " ")} (${String(name)})` : toolName.replace("_", " ");
|
|
}
|
|
if (toolName === "create_space") {
|
|
const name = args.name ? String(args.name) : "Untitled";
|
|
return `Create space “${name}”`;
|
|
}
|
|
const target = pickScopeLabel(args);
|
|
return target ? `${toolName} → ${target}` : toolName;
|
|
}
|
|
|
|
function formatApprovalDetail(
|
|
toolName: string,
|
|
args: Record<string, unknown>,
|
|
reviewReason?: string,
|
|
): string | undefined {
|
|
const lines: string[] = [];
|
|
if (reviewReason?.trim()) {
|
|
lines.push(reviewReason.trim().replace(/\u2014|\u2013/g, "-"));
|
|
}
|
|
if (toolName === "create_space") {
|
|
lines.push(
|
|
"Bots, groups, chats, files, memory, and integrations in this space stay separate from other spaces.",
|
|
);
|
|
}
|
|
for (const key of ["collection", "title", "to", "subject", "amount", "body"]) {
|
|
const value = args[key];
|
|
if (value == null || value === "") continue;
|
|
lines.push(`${key}: ${String(value)}`);
|
|
}
|
|
if (lines.length === 0) return undefined;
|
|
return lines.join("\n");
|
|
}
|
|
|
|
function pickScopeLabel(args: Record<string, unknown>): string | undefined {
|
|
for (const key of ["to", "title", "collection", "subject", "amount"]) {
|
|
const value = args[key];
|
|
if (value != null && value !== "") return String(value);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function truncate(value: string, maxLength: number): string {
|
|
return value.length > maxLength ? `${value.slice(0, maxLength)}…` : value;
|
|
}
|