refactor(api): extract assistant import export dispo slice
This commit is contained in:
@@ -43,12 +43,13 @@
|
||||
- the scenario simulation, project narrative, and rate lookup assistant helpers now live in their own domain module, keeping the remaining controller-side scenario/AI analytics wiring out of the monolithic assistant router without changing the assistant contract
|
||||
- the comment listing and comment mutation assistant helpers now live in their own domain module, keeping collaboration-side comment flows out of the monolithic assistant router without changing the assistant contract
|
||||
- the audit-history assistant helpers now live in their own domain module, keeping controller-side change-history reads out of the monolithic assistant router without changing the assistant contract
|
||||
- the import/export and staged Dispo assistant helpers now live in their own domain module, keeping file-bound export/import and batch-staging orchestration out of the monolithic assistant router without changing the assistant contract
|
||||
|
||||
## Next Up
|
||||
|
||||
Pin the next structural cleanup on the API side:
|
||||
continue splitting `packages/api/src/router/assistant-tools.ts` into domain-oriented tool modules without changing the public tool contract.
|
||||
The next clean slice should stay adjacent to the extracted domains and target one cohesive leftover block such as the remaining import/export or staged-dispo helpers still living in the monolithic router.
|
||||
The next clean slice should stay adjacent to the extracted domains and target one cohesive leftover block such as the remaining navigation/search helpers or other small read-only assistant clusters still living in the monolithic router.
|
||||
|
||||
## Remaining Major Themes
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Each tool has a JSON schema (for the AI) and an execute function (for the server).
|
||||
*/
|
||||
|
||||
import { Prisma, ImportBatchStatus, StagedRecordStatus, DispoStagedRecordType, VacationType } from "@capakraken/db";
|
||||
import { Prisma, VacationType } from "@capakraken/db";
|
||||
import {
|
||||
CreateAssignmentSchema,
|
||||
AllocationStatus,
|
||||
@@ -131,6 +131,10 @@ import {
|
||||
createScenarioRateAnalysisExecutors,
|
||||
scenarioRateAnalysisToolDefinitions,
|
||||
} from "./assistant-tools/scenario-rate-analysis.js";
|
||||
import {
|
||||
createImportExportDispoExecutors,
|
||||
importExportDispoToolDefinitions,
|
||||
} from "./assistant-tools/import-export-dispo.js";
|
||||
import {
|
||||
commentMutationToolDefinitions,
|
||||
commentReadToolDefinitions,
|
||||
@@ -430,24 +434,6 @@ const LEGACY_MONOLITHIC_TOOL_ACCESS: Partial<Record<string, ToolAccessRequiremen
|
||||
delete_project: { requiredPermissions: [PermissionKey.MANAGE_PROJECTS] },
|
||||
generate_project_cover: { requiredPermissions: [PermissionKey.MANAGE_PROJECTS] },
|
||||
remove_project_cover: { requiredPermissions: [PermissionKey.MANAGE_PROJECTS] },
|
||||
export_resources_csv: { allowedSystemRoles: [...CONTROLLER_ASSISTANT_ROLES] },
|
||||
export_projects_csv: { allowedSystemRoles: [...CONTROLLER_ASSISTANT_ROLES] },
|
||||
import_csv_data: {
|
||||
requiredPermissions: [PermissionKey.IMPORT_DATA],
|
||||
allowedSystemRoles: [...MANAGER_ASSISTANT_ROLES],
|
||||
},
|
||||
list_dispo_import_batches: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
get_dispo_import_batch: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
stage_dispo_import_batch: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
validate_dispo_import_batch: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
cancel_dispo_import_batch: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
list_dispo_staged_resources: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
list_dispo_staged_projects: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
list_dispo_staged_assignments: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
list_dispo_staged_vacations: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
list_dispo_staged_unresolved_records: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
resolve_dispo_staged_record: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
commit_dispo_import_batch: { allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES] },
|
||||
};
|
||||
|
||||
const ASSISTANT_VACATION_REQUEST_TYPES = [
|
||||
@@ -2328,252 +2314,7 @@ export const TOOL_DEFINITIONS: ToolDef[] = withToolAccess([
|
||||
...scenarioRateAnalysisToolDefinitions,
|
||||
...commentMutationToolDefinitions,
|
||||
...auditHistoryToolDefinitions,
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "export_resources_csv",
|
||||
description: "Export the current active resource list as CSV via the real import/export router. Controller/manager/admin roles only.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "export_projects_csv",
|
||||
description: "Export the current project list as CSV via the real import/export router. Controller/manager/admin roles only.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "import_csv_data",
|
||||
description: "Import CSV-style row data for resources, projects, or allocations via the real import/export router. Requires manager/admin, importData permission, and confirmation.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
entityType: { type: "string", enum: ["resources", "projects", "allocations"], description: "Import target entity type." },
|
||||
rows: {
|
||||
type: "array",
|
||||
description: "CSV rows already parsed to key/value objects.",
|
||||
items: {
|
||||
type: "object",
|
||||
additionalProperties: { type: "string" },
|
||||
},
|
||||
},
|
||||
dryRun: { type: "boolean", description: "Validate only without persisting changes. Default: true." },
|
||||
},
|
||||
required: ["entityType", "rows"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_import_batches",
|
||||
description: "List Dispo import batches with pagination and optional status filter via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
status: { type: "string", description: "Optional batch status filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "get_dispo_import_batch",
|
||||
description: "Get one Dispo import batch including staged record counters via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "Import batch ID." },
|
||||
},
|
||||
required: ["id"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "stage_dispo_import_batch",
|
||||
description: "Stage a Dispo import batch via the real dispo router. Admin role required. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
planningWorkbookPath: { type: "string", description: "Filesystem path to the planning workbook." },
|
||||
referenceWorkbookPath: { type: "string", description: "Filesystem path to the reference workbook." },
|
||||
chargeabilityWorkbookPath: { type: "string", description: "Filesystem path to the chargeability workbook." },
|
||||
costWorkbookPath: { type: "string", description: "Optional filesystem path to the cost workbook." },
|
||||
rosterWorkbookPath: { type: "string", description: "Optional filesystem path to the roster workbook." },
|
||||
notes: { type: "string", description: "Optional import notes." },
|
||||
},
|
||||
required: ["planningWorkbookPath", "referenceWorkbookPath", "chargeabilityWorkbookPath"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "validate_dispo_import_batch",
|
||||
description: "Validate a Dispo import batch readiness check via the real dispo router without committing anything. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
planningWorkbookPath: { type: "string", description: "Filesystem path to the planning workbook." },
|
||||
referenceWorkbookPath: { type: "string", description: "Filesystem path to the reference workbook." },
|
||||
chargeabilityWorkbookPath: { type: "string", description: "Filesystem path to the chargeability workbook." },
|
||||
costWorkbookPath: { type: "string", description: "Optional filesystem path to the cost workbook." },
|
||||
rosterWorkbookPath: { type: "string", description: "Optional filesystem path to the roster workbook." },
|
||||
importBatchId: { type: "string", description: "Optional existing staged import batch ID." },
|
||||
notes: { type: "string", description: "Optional import notes." },
|
||||
},
|
||||
required: ["planningWorkbookPath", "referenceWorkbookPath", "chargeabilityWorkbookPath"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "cancel_dispo_import_batch",
|
||||
description: "Cancel a staged Dispo import batch via the real dispo router. Admin role required. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "Import batch ID." },
|
||||
},
|
||||
required: ["id"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_resources",
|
||||
description: "List staged Dispo resources for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
status: { type: "string", description: "Optional staged record status filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_projects",
|
||||
description: "List staged Dispo projects for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
status: { type: "string", description: "Optional staged record status filter." },
|
||||
isTbd: { type: "boolean", description: "Optional TBD-project filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_assignments",
|
||||
description: "List staged Dispo assignments for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
status: { type: "string", description: "Optional staged record status filter." },
|
||||
resourceExternalId: { type: "string", description: "Optional resource external ID filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_vacations",
|
||||
description: "List staged Dispo vacations for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
resourceExternalId: { type: "string", description: "Optional resource external ID filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_unresolved_records",
|
||||
description: "List staged unresolved Dispo records for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
recordType: { type: "string", description: "Optional unresolved record type filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "resolve_dispo_staged_record",
|
||||
description: "Resolve one staged Dispo record via the real dispo router. Admin role required. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "Staged record ID." },
|
||||
recordType: { type: "string", description: "Staged record type." },
|
||||
action: { type: "string", enum: ["APPROVE", "REJECT", "SKIP"], description: "Resolution action." },
|
||||
},
|
||||
required: ["id", "recordType", "action"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "commit_dispo_import_batch",
|
||||
description: "Commit a staged Dispo import batch via the real dispo router. Admin role required. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
allowTbdUnresolved: { type: "boolean", description: "Allow unresolved TBD projects during commit." },
|
||||
importTbdProjects: { type: "boolean", description: "Whether TBD projects should be imported." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
...importExportDispoToolDefinitions,
|
||||
...settingsAdminToolDefinitions,
|
||||
], LEGACY_MONOLITHIC_TOOL_ACCESS);
|
||||
|
||||
@@ -3206,219 +2947,13 @@ const executors = {
|
||||
toAssistantNotificationCreationError,
|
||||
}),
|
||||
|
||||
async export_resources_csv(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createImportExportCaller(createScopedCallerContext(ctx));
|
||||
const csv = await caller.exportResourcesCSV();
|
||||
return {
|
||||
format: "csv",
|
||||
lineCount: csv.length === 0 ? 0 : csv.split("\n").length,
|
||||
csv,
|
||||
};
|
||||
},
|
||||
|
||||
async export_projects_csv(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = createImportExportCaller(createScopedCallerContext(ctx));
|
||||
const csv = await caller.exportProjectsCSV();
|
||||
return {
|
||||
format: "csv",
|
||||
lineCount: csv.length === 0 ? 0 : csv.split("\n").length,
|
||||
csv,
|
||||
};
|
||||
},
|
||||
|
||||
async import_csv_data(params: {
|
||||
entityType: "resources" | "projects" | "allocations";
|
||||
rows: Array<Record<string, string>>;
|
||||
dryRun?: boolean;
|
||||
}, ctx: ToolContext) {
|
||||
assertPermission(ctx, PermissionKey.IMPORT_DATA);
|
||||
const caller = createImportExportCaller(createScopedCallerContext(ctx));
|
||||
return caller.importCSV({
|
||||
entityType: params.entityType,
|
||||
rows: params.rows,
|
||||
dryRun: params.dryRun ?? true,
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_import_batches(params: {
|
||||
status?: ImportBatchStatus;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.listImportBatches({
|
||||
...(params.status ? { status: params.status } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(params.limit !== undefined ? { limit: Math.min(Math.max(params.limit, 1), 200) } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async get_dispo_import_batch(params: {
|
||||
id: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
try {
|
||||
return await caller.getImportBatch({ id: params.id });
|
||||
} catch (error) {
|
||||
const mapped = toAssistantDispoImportBatchNotFoundError(error);
|
||||
if (mapped) {
|
||||
return mapped;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async stage_dispo_import_batch(params: {
|
||||
chargeabilityWorkbookPath: string;
|
||||
costWorkbookPath?: string;
|
||||
notes?: string | null;
|
||||
planningWorkbookPath: string;
|
||||
referenceWorkbookPath: string;
|
||||
rosterWorkbookPath?: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.stageImportBatch({
|
||||
chargeabilityWorkbookPath: params.chargeabilityWorkbookPath,
|
||||
planningWorkbookPath: params.planningWorkbookPath,
|
||||
referenceWorkbookPath: params.referenceWorkbookPath,
|
||||
...(params.costWorkbookPath !== undefined ? { costWorkbookPath: params.costWorkbookPath } : {}),
|
||||
...(params.notes !== undefined ? { notes: params.notes } : {}),
|
||||
...(params.rosterWorkbookPath !== undefined ? { rosterWorkbookPath: params.rosterWorkbookPath } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async validate_dispo_import_batch(params: {
|
||||
chargeabilityWorkbookPath: string;
|
||||
costWorkbookPath?: string;
|
||||
importBatchId?: string;
|
||||
notes?: string | null;
|
||||
planningWorkbookPath: string;
|
||||
referenceWorkbookPath: string;
|
||||
rosterWorkbookPath?: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.validateImportBatch({
|
||||
chargeabilityWorkbookPath: params.chargeabilityWorkbookPath,
|
||||
planningWorkbookPath: params.planningWorkbookPath,
|
||||
referenceWorkbookPath: params.referenceWorkbookPath,
|
||||
...(params.costWorkbookPath !== undefined ? { costWorkbookPath: params.costWorkbookPath } : {}),
|
||||
...(params.importBatchId !== undefined ? { importBatchId: params.importBatchId } : {}),
|
||||
...(params.notes !== undefined ? { notes: params.notes } : {}),
|
||||
...(params.rosterWorkbookPath !== undefined ? { rosterWorkbookPath: params.rosterWorkbookPath } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async cancel_dispo_import_batch(params: {
|
||||
id: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.cancelImportBatch({ id: params.id });
|
||||
},
|
||||
|
||||
async list_dispo_staged_resources(params: {
|
||||
importBatchId: string;
|
||||
status?: StagedRecordStatus;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.listStagedResources({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.status !== undefined ? { status: params.status } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(params.limit !== undefined ? { limit: Math.min(Math.max(params.limit, 1), 200) } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_staged_projects(params: {
|
||||
importBatchId: string;
|
||||
status?: StagedRecordStatus;
|
||||
isTbd?: boolean;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.listStagedProjects({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.status !== undefined ? { status: params.status } : {}),
|
||||
...(params.isTbd !== undefined ? { isTbd: params.isTbd } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(params.limit !== undefined ? { limit: Math.min(Math.max(params.limit, 1), 200) } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_staged_assignments(params: {
|
||||
importBatchId: string;
|
||||
status?: StagedRecordStatus;
|
||||
resourceExternalId?: string;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.listStagedAssignments({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.status !== undefined ? { status: params.status } : {}),
|
||||
...(params.resourceExternalId !== undefined ? { resourceExternalId: params.resourceExternalId } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(params.limit !== undefined ? { limit: Math.min(Math.max(params.limit, 1), 200) } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_staged_vacations(params: {
|
||||
importBatchId: string;
|
||||
resourceExternalId?: string;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.listStagedVacations({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.resourceExternalId !== undefined ? { resourceExternalId: params.resourceExternalId } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(params.limit !== undefined ? { limit: Math.min(Math.max(params.limit, 1), 200) } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_staged_unresolved_records(params: {
|
||||
importBatchId: string;
|
||||
recordType?: DispoStagedRecordType;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.listStagedUnresolvedRecords({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.recordType !== undefined ? { recordType: params.recordType } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(params.limit !== undefined ? { limit: Math.min(Math.max(params.limit, 1), 200) } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async resolve_dispo_staged_record(params: {
|
||||
action: "APPROVE" | "REJECT" | "SKIP";
|
||||
id: string;
|
||||
recordType: DispoStagedRecordType;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.resolveStagedRecord({
|
||||
action: params.action,
|
||||
id: params.id,
|
||||
recordType: params.recordType,
|
||||
});
|
||||
},
|
||||
|
||||
async commit_dispo_import_batch(params: {
|
||||
allowTbdUnresolved?: boolean;
|
||||
importBatchId: string;
|
||||
importTbdProjects?: boolean;
|
||||
}, ctx: ToolContext) {
|
||||
const caller = createDispoCaller(createScopedCallerContext(ctx));
|
||||
return caller.commitImportBatch({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.allowTbdUnresolved !== undefined ? { allowTbdUnresolved: params.allowTbdUnresolved } : {}),
|
||||
...(params.importTbdProjects !== undefined ? { importTbdProjects: params.importTbdProjects } : {}),
|
||||
});
|
||||
},
|
||||
...createImportExportDispoExecutors({
|
||||
assertPermission,
|
||||
createImportExportCaller,
|
||||
createDispoCaller,
|
||||
createScopedCallerContext,
|
||||
toAssistantDispoImportBatchNotFoundError,
|
||||
}),
|
||||
|
||||
...createSettingsAdminExecutors({
|
||||
createSettingsCaller,
|
||||
|
||||
@@ -0,0 +1,613 @@
|
||||
import { DispoStagedRecordType, ImportBatchStatus, StagedRecordStatus } from "@capakraken/db";
|
||||
import { PermissionKey, SystemRole } from "@capakraken/shared";
|
||||
import type { TRPCContext } from "../../trpc.js";
|
||||
import { withToolAccess, type ToolContext, type ToolDef, type ToolExecutor } from "./shared.js";
|
||||
|
||||
type ImportExportDispoDeps = {
|
||||
assertPermission: (ctx: ToolContext, perm: PermissionKey) => void;
|
||||
createImportExportCaller: (ctx: TRPCContext) => {
|
||||
exportResourcesCSV: () => Promise<string>;
|
||||
exportProjectsCSV: () => Promise<string>;
|
||||
importCSV: (params: {
|
||||
entityType: "resources" | "projects" | "allocations";
|
||||
rows: Array<Record<string, string>>;
|
||||
dryRun: boolean;
|
||||
}) => Promise<unknown>;
|
||||
};
|
||||
createDispoCaller: (ctx: TRPCContext) => {
|
||||
listImportBatches: (params: {
|
||||
status?: ImportBatchStatus;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}) => Promise<unknown>;
|
||||
getImportBatch: (params: { id: string }) => Promise<unknown>;
|
||||
stageImportBatch: (params: {
|
||||
chargeabilityWorkbookPath: string;
|
||||
costWorkbookPath?: string;
|
||||
notes?: string | null;
|
||||
planningWorkbookPath: string;
|
||||
referenceWorkbookPath: string;
|
||||
rosterWorkbookPath?: string;
|
||||
}) => Promise<unknown>;
|
||||
validateImportBatch: (params: {
|
||||
chargeabilityWorkbookPath: string;
|
||||
costWorkbookPath?: string;
|
||||
importBatchId?: string;
|
||||
notes?: string | null;
|
||||
planningWorkbookPath: string;
|
||||
referenceWorkbookPath: string;
|
||||
rosterWorkbookPath?: string;
|
||||
}) => Promise<unknown>;
|
||||
cancelImportBatch: (params: { id: string }) => Promise<unknown>;
|
||||
listStagedResources: (params: {
|
||||
importBatchId: string;
|
||||
status?: StagedRecordStatus;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}) => Promise<unknown>;
|
||||
listStagedProjects: (params: {
|
||||
importBatchId: string;
|
||||
status?: StagedRecordStatus;
|
||||
isTbd?: boolean;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}) => Promise<unknown>;
|
||||
listStagedAssignments: (params: {
|
||||
importBatchId: string;
|
||||
status?: StagedRecordStatus;
|
||||
resourceExternalId?: string;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}) => Promise<unknown>;
|
||||
listStagedVacations: (params: {
|
||||
importBatchId: string;
|
||||
resourceExternalId?: string;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}) => Promise<unknown>;
|
||||
listStagedUnresolvedRecords: (params: {
|
||||
importBatchId: string;
|
||||
recordType?: DispoStagedRecordType;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}) => Promise<unknown>;
|
||||
resolveStagedRecord: (params: {
|
||||
action: "APPROVE" | "REJECT" | "SKIP";
|
||||
id: string;
|
||||
recordType: DispoStagedRecordType;
|
||||
}) => Promise<unknown>;
|
||||
commitImportBatch: (params: {
|
||||
importBatchId: string;
|
||||
allowTbdUnresolved?: boolean;
|
||||
importTbdProjects?: boolean;
|
||||
}) => Promise<unknown>;
|
||||
};
|
||||
createScopedCallerContext: (ctx: ToolContext) => TRPCContext;
|
||||
toAssistantDispoImportBatchNotFoundError: (error: unknown) => { error: string } | null;
|
||||
};
|
||||
|
||||
const CONTROLLER_ASSISTANT_ROLES = [SystemRole.ADMIN, SystemRole.MANAGER, SystemRole.CONTROLLER] as const;
|
||||
const MANAGER_ASSISTANT_ROLES = [SystemRole.ADMIN, SystemRole.MANAGER] as const;
|
||||
const ADMIN_ASSISTANT_ROLES = [SystemRole.ADMIN] as const;
|
||||
|
||||
export const importExportDispoToolDefinitions: ToolDef[] = withToolAccess([
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "export_resources_csv",
|
||||
description: "Export the current active resource list as CSV via the real import/export router. Controller/manager/admin roles only.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "export_projects_csv",
|
||||
description: "Export the current project list as CSV via the real import/export router. Controller/manager/admin roles only.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "import_csv_data",
|
||||
description: "Import CSV-style row data for resources, projects, or allocations via the real import/export router. Requires manager/admin, importData permission, and defaults to dry-run.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
entityType: { type: "string", enum: ["resources", "projects", "allocations"], description: "Import target entity type." },
|
||||
rows: {
|
||||
type: "array",
|
||||
description: "CSV rows already parsed to key/value objects.",
|
||||
items: {
|
||||
type: "object",
|
||||
additionalProperties: { type: "string" },
|
||||
},
|
||||
},
|
||||
dryRun: { type: "boolean", description: "Validate only without persisting changes. Default: true." },
|
||||
},
|
||||
required: ["entityType", "rows"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_import_batches",
|
||||
description: "List Dispo import batches with pagination and optional status filter via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
status: { type: "string", description: "Optional batch status filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "get_dispo_import_batch",
|
||||
description: "Get one Dispo import batch including staged record counters via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "Import batch ID." },
|
||||
},
|
||||
required: ["id"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "stage_dispo_import_batch",
|
||||
description: "Stage a Dispo import batch via the real dispo router. Admin role required. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
planningWorkbookPath: { type: "string", description: "Filesystem path to the planning workbook." },
|
||||
referenceWorkbookPath: { type: "string", description: "Filesystem path to the reference workbook." },
|
||||
chargeabilityWorkbookPath: { type: "string", description: "Filesystem path to the chargeability workbook." },
|
||||
costWorkbookPath: { type: "string", description: "Optional filesystem path to the cost workbook." },
|
||||
rosterWorkbookPath: { type: "string", description: "Optional filesystem path to the roster workbook." },
|
||||
notes: { type: "string", description: "Optional import notes." },
|
||||
},
|
||||
required: ["planningWorkbookPath", "referenceWorkbookPath", "chargeabilityWorkbookPath"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "validate_dispo_import_batch",
|
||||
description: "Validate a Dispo import batch readiness check via the real dispo router without committing anything. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
planningWorkbookPath: { type: "string", description: "Filesystem path to the planning workbook." },
|
||||
referenceWorkbookPath: { type: "string", description: "Filesystem path to the reference workbook." },
|
||||
chargeabilityWorkbookPath: { type: "string", description: "Filesystem path to the chargeability workbook." },
|
||||
costWorkbookPath: { type: "string", description: "Optional filesystem path to the cost workbook." },
|
||||
rosterWorkbookPath: { type: "string", description: "Optional filesystem path to the roster workbook." },
|
||||
importBatchId: { type: "string", description: "Optional existing staged import batch ID." },
|
||||
notes: { type: "string", description: "Optional import notes." },
|
||||
},
|
||||
required: ["planningWorkbookPath", "referenceWorkbookPath", "chargeabilityWorkbookPath"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "cancel_dispo_import_batch",
|
||||
description: "Cancel a staged Dispo import batch via the real dispo router. Admin role required. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "Import batch ID." },
|
||||
},
|
||||
required: ["id"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_resources",
|
||||
description: "List staged Dispo resources for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
status: { type: "string", description: "Optional staged record status filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_projects",
|
||||
description: "List staged Dispo projects for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
status: { type: "string", description: "Optional staged record status filter." },
|
||||
isTbd: { type: "boolean", description: "Optional TBD-project filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_assignments",
|
||||
description: "List staged Dispo assignments for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
status: { type: "string", description: "Optional staged record status filter." },
|
||||
resourceExternalId: { type: "string", description: "Optional resource external ID filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_vacations",
|
||||
description: "List staged Dispo vacations for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
resourceExternalId: { type: "string", description: "Optional resource external ID filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "list_dispo_staged_unresolved_records",
|
||||
description: "List staged unresolved Dispo records for one import batch via the real dispo router. Admin role required.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
recordType: { type: "string", description: "Optional unresolved record type filter." },
|
||||
limit: { type: "integer", description: "Max results. Default: 50, max: 200." },
|
||||
cursor: { type: "string", description: "Optional pagination cursor." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "resolve_dispo_staged_record",
|
||||
description: "Resolve one staged Dispo record via the real dispo router. Admin role required. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", description: "Staged record ID." },
|
||||
recordType: { type: "string", description: "Staged record type." },
|
||||
action: { type: "string", enum: ["APPROVE", "REJECT", "SKIP"], description: "Resolution action." },
|
||||
},
|
||||
required: ["id", "recordType", "action"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "commit_dispo_import_batch",
|
||||
description: "Commit a staged Dispo import batch via the real dispo router. Admin role required. Always confirm first.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
importBatchId: { type: "string", description: "Import batch ID." },
|
||||
allowTbdUnresolved: { type: "boolean", description: "Allow unresolved TBD projects during commit." },
|
||||
importTbdProjects: { type: "boolean", description: "Whether TBD projects should be imported." },
|
||||
},
|
||||
required: ["importBatchId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
], {
|
||||
export_resources_csv: {
|
||||
allowedSystemRoles: [...CONTROLLER_ASSISTANT_ROLES],
|
||||
},
|
||||
export_projects_csv: {
|
||||
allowedSystemRoles: [...CONTROLLER_ASSISTANT_ROLES],
|
||||
},
|
||||
import_csv_data: {
|
||||
requiredPermissions: [PermissionKey.IMPORT_DATA],
|
||||
allowedSystemRoles: [...MANAGER_ASSISTANT_ROLES],
|
||||
},
|
||||
list_dispo_import_batches: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
get_dispo_import_batch: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
stage_dispo_import_batch: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
validate_dispo_import_batch: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
cancel_dispo_import_batch: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
list_dispo_staged_resources: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
list_dispo_staged_projects: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
list_dispo_staged_assignments: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
list_dispo_staged_vacations: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
list_dispo_staged_unresolved_records: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
resolve_dispo_staged_record: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
commit_dispo_import_batch: {
|
||||
allowedSystemRoles: [...ADMIN_ASSISTANT_ROLES],
|
||||
},
|
||||
});
|
||||
|
||||
function clampLimit(limit: number | undefined): number | undefined {
|
||||
return limit !== undefined ? Math.min(Math.max(limit, 1), 200) : undefined;
|
||||
}
|
||||
|
||||
export function createImportExportDispoExecutors(
|
||||
deps: ImportExportDispoDeps,
|
||||
): Record<string, ToolExecutor> {
|
||||
return {
|
||||
async export_resources_csv(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = deps.createImportExportCaller(deps.createScopedCallerContext(ctx));
|
||||
const csv = await caller.exportResourcesCSV();
|
||||
return {
|
||||
format: "csv",
|
||||
lineCount: csv.length === 0 ? 0 : csv.split("\n").length,
|
||||
csv,
|
||||
};
|
||||
},
|
||||
|
||||
async export_projects_csv(_params: Record<string, never>, ctx: ToolContext) {
|
||||
const caller = deps.createImportExportCaller(deps.createScopedCallerContext(ctx));
|
||||
const csv = await caller.exportProjectsCSV();
|
||||
return {
|
||||
format: "csv",
|
||||
lineCount: csv.length === 0 ? 0 : csv.split("\n").length,
|
||||
csv,
|
||||
};
|
||||
},
|
||||
|
||||
async import_csv_data(
|
||||
params: {
|
||||
entityType: "resources" | "projects" | "allocations";
|
||||
rows: Array<Record<string, string>>;
|
||||
dryRun?: boolean;
|
||||
},
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
deps.assertPermission(ctx, PermissionKey.IMPORT_DATA);
|
||||
const caller = deps.createImportExportCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.importCSV({
|
||||
entityType: params.entityType,
|
||||
rows: params.rows,
|
||||
dryRun: params.dryRun ?? true,
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_import_batches(
|
||||
params: { status?: ImportBatchStatus; limit?: number; cursor?: string },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const limit = clampLimit(params.limit);
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.listImportBatches({
|
||||
...(params.status ? { status: params.status } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(limit !== undefined ? { limit } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async get_dispo_import_batch(
|
||||
params: { id: string },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
try {
|
||||
return await caller.getImportBatch({ id: params.id });
|
||||
} catch (error) {
|
||||
const mapped = deps.toAssistantDispoImportBatchNotFoundError(error);
|
||||
if (mapped) {
|
||||
return mapped;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async stage_dispo_import_batch(
|
||||
params: {
|
||||
chargeabilityWorkbookPath: string;
|
||||
costWorkbookPath?: string;
|
||||
notes?: string | null;
|
||||
planningWorkbookPath: string;
|
||||
referenceWorkbookPath: string;
|
||||
rosterWorkbookPath?: string;
|
||||
},
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.stageImportBatch({
|
||||
chargeabilityWorkbookPath: params.chargeabilityWorkbookPath,
|
||||
planningWorkbookPath: params.planningWorkbookPath,
|
||||
referenceWorkbookPath: params.referenceWorkbookPath,
|
||||
...(params.costWorkbookPath !== undefined ? { costWorkbookPath: params.costWorkbookPath } : {}),
|
||||
...(params.notes !== undefined ? { notes: params.notes } : {}),
|
||||
...(params.rosterWorkbookPath !== undefined ? { rosterWorkbookPath: params.rosterWorkbookPath } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async validate_dispo_import_batch(
|
||||
params: {
|
||||
chargeabilityWorkbookPath: string;
|
||||
costWorkbookPath?: string;
|
||||
importBatchId?: string;
|
||||
notes?: string | null;
|
||||
planningWorkbookPath: string;
|
||||
referenceWorkbookPath: string;
|
||||
rosterWorkbookPath?: string;
|
||||
},
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.validateImportBatch({
|
||||
chargeabilityWorkbookPath: params.chargeabilityWorkbookPath,
|
||||
planningWorkbookPath: params.planningWorkbookPath,
|
||||
referenceWorkbookPath: params.referenceWorkbookPath,
|
||||
...(params.costWorkbookPath !== undefined ? { costWorkbookPath: params.costWorkbookPath } : {}),
|
||||
...(params.importBatchId !== undefined ? { importBatchId: params.importBatchId } : {}),
|
||||
...(params.notes !== undefined ? { notes: params.notes } : {}),
|
||||
...(params.rosterWorkbookPath !== undefined ? { rosterWorkbookPath: params.rosterWorkbookPath } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async cancel_dispo_import_batch(
|
||||
params: { id: string },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.cancelImportBatch({ id: params.id });
|
||||
},
|
||||
|
||||
async list_dispo_staged_resources(
|
||||
params: { importBatchId: string; status?: StagedRecordStatus; limit?: number; cursor?: string },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const limit = clampLimit(params.limit);
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.listStagedResources({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.status !== undefined ? { status: params.status } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(limit !== undefined ? { limit } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_staged_projects(
|
||||
params: { importBatchId: string; status?: StagedRecordStatus; isTbd?: boolean; limit?: number; cursor?: string },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const limit = clampLimit(params.limit);
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.listStagedProjects({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.status !== undefined ? { status: params.status } : {}),
|
||||
...(params.isTbd !== undefined ? { isTbd: params.isTbd } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(limit !== undefined ? { limit } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_staged_assignments(
|
||||
params: { importBatchId: string; status?: StagedRecordStatus; resourceExternalId?: string; limit?: number; cursor?: string },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const limit = clampLimit(params.limit);
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.listStagedAssignments({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.status !== undefined ? { status: params.status } : {}),
|
||||
...(params.resourceExternalId !== undefined ? { resourceExternalId: params.resourceExternalId } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(limit !== undefined ? { limit } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_staged_vacations(
|
||||
params: { importBatchId: string; resourceExternalId?: string; limit?: number; cursor?: string },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const limit = clampLimit(params.limit);
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.listStagedVacations({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.resourceExternalId !== undefined ? { resourceExternalId: params.resourceExternalId } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(limit !== undefined ? { limit } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async list_dispo_staged_unresolved_records(
|
||||
params: { importBatchId: string; recordType?: DispoStagedRecordType; limit?: number; cursor?: string },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const limit = clampLimit(params.limit);
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.listStagedUnresolvedRecords({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.recordType !== undefined ? { recordType: params.recordType } : {}),
|
||||
...(params.cursor ? { cursor: params.cursor } : {}),
|
||||
...(limit !== undefined ? { limit } : {}),
|
||||
});
|
||||
},
|
||||
|
||||
async resolve_dispo_staged_record(
|
||||
params: { action: "APPROVE" | "REJECT" | "SKIP"; id: string; recordType: DispoStagedRecordType },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.resolveStagedRecord({
|
||||
action: params.action,
|
||||
id: params.id,
|
||||
recordType: params.recordType,
|
||||
});
|
||||
},
|
||||
|
||||
async commit_dispo_import_batch(
|
||||
params: { allowTbdUnresolved?: boolean; importBatchId: string; importTbdProjects?: boolean },
|
||||
ctx: ToolContext,
|
||||
) {
|
||||
const caller = deps.createDispoCaller(deps.createScopedCallerContext(ctx));
|
||||
return caller.commitImportBatch({
|
||||
importBatchId: params.importBatchId,
|
||||
...(params.allowTbdUnresolved !== undefined ? { allowTbdUnresolved: params.allowTbdUnresolved } : {}),
|
||||
...(params.importTbdProjects !== undefined ? { importTbdProjects: params.importTbdProjects } : {}),
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user