chore(repo): checkpoint current capakraken implementation state

This commit is contained in:
2026-03-29 12:47:12 +02:00
parent beae1a5d6e
commit 47e4d701ff
94 changed files with 4283 additions and 1710 deletions
File diff suppressed because it is too large Load Diff
+65 -5
View File
@@ -1,12 +1,12 @@
/**
* AI Assistant router — provides a chat endpoint that uses OpenAI Function Calling
* to answer questions about plANARCHY data and modify resources/projects.
* to answer questions about CapaKraken data and modify resources/projects.
*/
import { z } from "zod";
import { TRPCError } from "@trpc/server";
import { AssistantApprovalStatus, type PrismaClient } from "@capakraken/db";
import { PermissionKey, resolvePermissions, type PermissionOverrides, type SystemRole } from "@capakraken/shared";
import { PermissionKey, resolvePermissions, type PermissionOverrides, SystemRole } from "@capakraken/shared";
import { createTRPCRouter, protectedProcedure } from "../trpc.js";
import { createAiClient, isAiConfigured, loggedAiCall, parseAiError } from "../ai-client.js";
import { ADVANCED_ASSISTANT_TOOLS, MUTATION_TOOLS, TOOL_DEFINITIONS, executeTool, type ToolContext, type ToolAction } from "./assistant-tools.js";
@@ -112,6 +112,11 @@ const TOOL_PERMISSION_MAP: Record<string, string> = {
create_allocation: "manageAllocations",
cancel_allocation: "manageAllocations",
update_allocation_status: "manageAllocations",
update_timeline_allocation_inline: "manageAllocations",
apply_timeline_project_shift: "manageAllocations",
quick_assign_timeline_resource: "manageAllocations",
batch_quick_assign_timeline_resources: "manageAllocations",
batch_shift_timeline_allocations: "manageAllocations",
create_demand: "manageAllocations",
fill_demand: "manageAllocations",
// Vacation management
@@ -127,16 +132,71 @@ const TOOL_PERMISSION_MAP: Record<string, string> = {
};
/** Tools that require cost visibility */
const COST_TOOLS = new Set(["get_budget_status", "get_chargeability", "resolve_rate", "list_rate_cards", "get_estimate_detail", "find_best_project_resource"]);
const COST_TOOLS = new Set([
"get_budget_status",
"get_chargeability",
"get_chargeability_report",
"get_resource_computation_graph",
"get_project_computation_graph",
"resolve_rate",
"list_rate_cards",
"get_estimate_detail",
"find_best_project_resource",
]);
export function getAvailableAssistantTools(permissions: Set<PermissionKey>) {
/** Tools that follow controllerProcedure access rules in the main API. */
const CONTROLLER_ONLY_TOOLS = new Set([
"get_chargeability_report",
"get_resource_computation_graph",
"get_project_computation_graph",
]);
/** Tools that follow managerProcedure access rules in the main API. */
const MANAGER_ONLY_TOOLS = new Set([
"update_timeline_allocation_inline",
"apply_timeline_project_shift",
"quick_assign_timeline_resource",
"batch_quick_assign_timeline_resources",
"batch_shift_timeline_allocations",
]);
/** Tools that are intentionally limited to ADMIN because the backing routers are admin-only today. */
const ADMIN_ONLY_TOOLS = new Set([
"create_country",
"update_country",
"create_metro_city",
"update_metro_city",
"delete_metro_city",
"create_holiday_calendar",
"update_holiday_calendar",
"delete_holiday_calendar",
"create_holiday_calendar_entry",
"update_holiday_calendar_entry",
"delete_holiday_calendar_entry",
]);
export function getAvailableAssistantTools(permissions: Set<PermissionKey>, userRole: string) {
return TOOL_DEFINITIONS.filter((tool) => {
const toolName = tool.function.name;
const requiredPerm = TOOL_PERMISSION_MAP[toolName];
const hasControllerAccess = userRole === SystemRole.ADMIN
|| userRole === SystemRole.MANAGER
|| userRole === SystemRole.CONTROLLER;
const hasManagerAccess = userRole === SystemRole.ADMIN
|| userRole === SystemRole.MANAGER;
if (requiredPerm && !permissions.has(requiredPerm as PermissionKey)) {
return false;
}
if (ADMIN_ONLY_TOOLS.has(toolName) && userRole !== "ADMIN") {
return false;
}
if (MANAGER_ONLY_TOOLS.has(toolName) && !hasManagerAccess) {
return false;
}
if (CONTROLLER_ONLY_TOOLS.has(toolName) && !hasControllerAccess) {
return false;
}
if (COST_TOOLS.has(toolName) && !permissions.has(PermissionKey.VIEW_COSTS)) {
return false;
}
@@ -597,7 +657,7 @@ export const assistantRouter = createTRPCRouter({
}
// 4. Filter tools based on granular permissions
const availableTools = getAvailableAssistantTools(permissions);
const availableTools = getAvailableAssistantTools(permissions, userRole);
// 5. Function calling loop
const toolCtx: ToolContext = {