refactor(api): extract assistant self-service slice
This commit is contained in:
@@ -95,6 +95,10 @@ import {
|
||||
countryMetroAdminToolDefinitions,
|
||||
createCountryMetroAdminExecutors,
|
||||
} from "./assistant-tools/country-metro-admin.js";
|
||||
import {
|
||||
createUserSelfServiceExecutors,
|
||||
userSelfServiceToolDefinitions,
|
||||
} from "./assistant-tools/user-self-service.js";
|
||||
import type { ToolContext, ToolDef, ToolExecutor } from "./assistant-tools/shared.js";
|
||||
import { getCommentToolEntityDescription, getCommentToolScopeSentence } from "../lib/comment-entity-registry.js";
|
||||
|
||||
@@ -2794,152 +2798,7 @@ export const TOOL_DEFINITIONS: ToolDef[] = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_assignable_users",
|
||||
description: "List lightweight users available for assignment workflows. Manager or admin role required.",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "get_current_user",
|
||||
description: "Get the authenticated user's own profile, role, and permission overrides.",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "get_dashboard_layout",
|
||||
description: "Get the authenticated user's saved dashboard widget layout and last update timestamp.",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "save_dashboard_layout",
|
||||
description: "Save the authenticated user's dashboard layout. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
layout: {
|
||||
type: "array",
|
||||
description: "Dashboard layout items as stored by the user router.",
|
||||
items: { type: "object" },
|
||||
},
|
||||
},
|
||||
required: ["layout"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "get_favorite_project_ids",
|
||||
description: "Get the authenticated user's favorite project IDs.",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "toggle_favorite_project",
|
||||
description: "Add or remove a project from the authenticated user's favorites. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
projectId: { type: "string", description: "Project ID." },
|
||||
},
|
||||
required: ["projectId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "get_column_preferences",
|
||||
description: "Get the authenticated user's saved table column preferences for all supported views.",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "set_column_preferences",
|
||||
description: "Update the authenticated user's table column preferences for one view. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
view: {
|
||||
type: "string",
|
||||
enum: ["resources", "projects", "allocations", "vacations", "roles", "users", "blueprints"],
|
||||
description: "View key to update.",
|
||||
},
|
||||
visible: {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
description: "Visible column IDs.",
|
||||
},
|
||||
sort: {
|
||||
type: ["object", "null"],
|
||||
properties: {
|
||||
field: { type: "string" },
|
||||
dir: { type: "string", enum: ["asc", "desc"] },
|
||||
},
|
||||
description: "Sort state. Use null to clear it.",
|
||||
},
|
||||
rowOrder: {
|
||||
type: ["array", "null"],
|
||||
items: { type: "string" },
|
||||
description: "Optional row order. Use null to clear it.",
|
||||
},
|
||||
},
|
||||
required: ["view"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "generate_totp_secret",
|
||||
description: "Generate a new MFA TOTP secret and provisioning URI for the authenticated user. Always confirm first. The secret is sensitive.",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "verify_and_enable_totp",
|
||||
description: "Verify a 6-digit MFA TOTP token and enable MFA for the authenticated user. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
token: { type: "string", description: "6-digit TOTP token." },
|
||||
},
|
||||
required: ["token"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "get_mfa_status",
|
||||
description: "Get the authenticated user's MFA status.",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "get_active_user_count",
|
||||
description: "Get the number of users active in the last five minutes. Admin role required.",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
...userSelfServiceToolDefinitions,
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
@@ -5482,120 +5341,11 @@ const executors = {
|
||||
const users = await caller.list();
|
||||
return users.slice(0, Math.min(params.limit ?? 50, 100));
|
||||
},
|
||||
|
||||
async list_assignable_users(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
return caller.listAssignable();
|
||||
},
|
||||
|
||||
async get_current_user(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
return caller.me();
|
||||
},
|
||||
|
||||
async get_dashboard_layout(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
return caller.getDashboardLayout();
|
||||
},
|
||||
|
||||
async save_dashboard_layout(params: { layout: unknown[] }, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
const result = await caller.saveDashboardLayout({ layout: params.layout });
|
||||
return {
|
||||
__action: "invalidate",
|
||||
scope: ["dashboard"],
|
||||
success: true,
|
||||
...result,
|
||||
message: "Saved dashboard layout.",
|
||||
};
|
||||
},
|
||||
|
||||
async get_favorite_project_ids(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
return caller.getFavoriteProjectIds();
|
||||
},
|
||||
|
||||
async toggle_favorite_project(params: { projectId: string }, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
const result = await caller.toggleFavoriteProject({ projectId: params.projectId });
|
||||
return {
|
||||
__action: "invalidate",
|
||||
scope: ["project"],
|
||||
success: true,
|
||||
...result,
|
||||
message: result.added ? "Added project to favorites." : "Removed project from favorites.",
|
||||
};
|
||||
},
|
||||
|
||||
async get_column_preferences(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
return caller.getColumnPreferences();
|
||||
},
|
||||
|
||||
async set_column_preferences(params: {
|
||||
view: "resources" | "projects" | "allocations" | "vacations" | "roles" | "users" | "blueprints";
|
||||
visible?: string[];
|
||||
sort?: { field: string; dir: "asc" | "desc" } | null;
|
||||
rowOrder?: string[] | null;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
const result = await caller.setColumnPreferences({
|
||||
view: params.view,
|
||||
...(params.visible !== undefined ? { visible: params.visible } : {}),
|
||||
...(params.sort !== undefined ? { sort: params.sort } : {}),
|
||||
...(params.rowOrder !== undefined ? { rowOrder: params.rowOrder } : {}),
|
||||
});
|
||||
return {
|
||||
__action: "invalidate",
|
||||
scope: ["user"],
|
||||
success: true,
|
||||
...result,
|
||||
message: `Updated column preferences for ${params.view}.`,
|
||||
};
|
||||
},
|
||||
|
||||
async generate_totp_secret(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
const result = await caller.generateTotpSecret();
|
||||
return {
|
||||
__action: "invalidate",
|
||||
scope: ["user"],
|
||||
success: true,
|
||||
...result,
|
||||
message: "Generated a new MFA TOTP secret.",
|
||||
};
|
||||
},
|
||||
|
||||
async verify_and_enable_totp(params: { token: string }, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
let result;
|
||||
try {
|
||||
result = await caller.verifyAndEnableTotp({ token: params.token });
|
||||
} catch (error) {
|
||||
const mapped = toAssistantTotpEnableError(error);
|
||||
if (mapped) {
|
||||
return mapped;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
return {
|
||||
__action: "invalidate",
|
||||
scope: ["user"],
|
||||
success: true,
|
||||
...result,
|
||||
message: "Enabled MFA TOTP.",
|
||||
};
|
||||
},
|
||||
|
||||
async get_mfa_status(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
return caller.getMfaStatus();
|
||||
},
|
||||
|
||||
async get_active_user_count(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createUserCaller(createScopedCallerContext(ctx));
|
||||
return caller.activeCount();
|
||||
},
|
||||
...createUserSelfServiceExecutors({
|
||||
createUserCaller,
|
||||
createScopedCallerContext,
|
||||
toAssistantTotpEnableError,
|
||||
}),
|
||||
|
||||
async create_user(params: {
|
||||
email: string;
|
||||
|
||||
Reference in New Issue
Block a user