mirror of
https://github.com/vee1e/workorder-desk.git
synced 2026-09-01 09:50:13 +00:00
feat(shared): agentic AI types, error codes, tool and SSE schemas
Extend the closed error catalog with the AI error codes (AI_UNAVAILABLE, AI_BUDGET_EXCEEDED, approval lifecycle codes, AI_INJECTION_BLOCKED), add the AgentRun/AgentToolCall/AgentConfig/CopilotSession/TriageSuggestion DTOs, add aiEnabled to UserAdmin, and add the LLM-facing tool arg schemas plus the zod-validated SSE event schema. Owner/version stay out of tool args per the agentic spec (the runtime injects them).
This commit is contained in:
parent
96f960e0c9
commit
3f3fdf8a85
2 changed files with 207 additions and 1 deletions
|
|
@ -103,6 +103,12 @@ export const updateStatusSchema = z
|
|||
})
|
||||
.strict();
|
||||
|
||||
export const updateAiSchema = z
|
||||
.object({
|
||||
aiEnabled: z.boolean(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
// ── Query params ─────────────────────────────────────────────────────
|
||||
|
||||
export const cursorQuerySchema = z.object({
|
||||
|
|
@ -120,6 +126,95 @@ export const offsetQuerySchema = z.object({
|
|||
search: z.string().trim().max(64).optional(),
|
||||
});
|
||||
|
||||
// ── Agentic AI ─────────────────────────────────────────────────────────────
|
||||
|
||||
// LLM-facing tool arg schemas. `version` and `owner` are intentionally absent:
|
||||
// the runtime injects them (see agent spec §4.3).
|
||||
|
||||
export const aiListWorkOrdersSchema = z
|
||||
.object({
|
||||
status: workOrderStatusSchema.optional(),
|
||||
priority: workOrderPrioritySchema.optional(),
|
||||
search: z.string().trim().max(64).optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const aiGetWorkOrderSchema = z
|
||||
.object({
|
||||
id: z.string().min(1),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const aiCreateWorkOrderSchema = createWorkOrderSchema;
|
||||
|
||||
export const aiUpdateWorkOrderSchema = z
|
||||
.object({
|
||||
id: z.string().min(1),
|
||||
title: z.string().trim().min(3).max(100).optional(),
|
||||
description: z.string().trim().max(2000).nullable().optional(),
|
||||
priority: workOrderPrioritySchema.optional(),
|
||||
status: workOrderStatusSchema.optional(),
|
||||
})
|
||||
.strict()
|
||||
.refine((v) => v.title !== undefined || v.description !== undefined || v.priority !== undefined || v.status !== undefined, {
|
||||
message: 'at least one field to update is required',
|
||||
});
|
||||
|
||||
export const aiDeleteWorkOrderSchema = z
|
||||
.object({
|
||||
id: z.string().min(1),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const triageProposalSchema = z
|
||||
.object({
|
||||
summary: z.string().trim().min(1).max(200),
|
||||
suggestedPriority: workOrderPrioritySchema,
|
||||
flagForDispatcher: z.boolean(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const sendCopilotMessageSchema = z
|
||||
.object({
|
||||
content: z.string().trim().min(1).max(4000),
|
||||
})
|
||||
.strict();
|
||||
|
||||
// ── SSE event payloads (agent spec §4.8) ──────────────────────────────────
|
||||
|
||||
export const sseEventSchema = z.discriminatedUnion('event', [
|
||||
z.object({ event: z.literal('token'), content: z.string() }),
|
||||
z.object({ event: z.literal('tool_call_start'), toolCallId: z.string(), tool: z.string(), args: z.unknown() }),
|
||||
z.object({
|
||||
event: z.literal('tool_approval_required'),
|
||||
toolCallId: z.string(),
|
||||
tool: z.string(),
|
||||
args: z.unknown(),
|
||||
preImage: z.unknown().nullable(),
|
||||
afterDiff: z.unknown(),
|
||||
summary: z.string(),
|
||||
expiresAt: z.string(),
|
||||
}),
|
||||
z.object({ event: z.literal('tool_approval_expired'), toolCallId: z.string() }),
|
||||
z.object({
|
||||
event: z.literal('tool_result'),
|
||||
toolCallId: z.string(),
|
||||
outcome: z.string(),
|
||||
result: z.unknown().optional(),
|
||||
}),
|
||||
z.object({
|
||||
event: z.literal('message_done'),
|
||||
runId: z.string(),
|
||||
content: z.string(),
|
||||
inputTokens: z.number().int().nonnegative(),
|
||||
outputTokens: z.number().int().nonnegative(),
|
||||
}),
|
||||
z.object({ event: z.literal('error'), code: z.string(), message: z.string(), requestId: z.string() }),
|
||||
z.object({ event: z.literal('ping'), ts: z.string() }),
|
||||
]);
|
||||
|
||||
export type SseEvent = z.infer<typeof sseEventSchema>;
|
||||
|
||||
// ── Inferred input types ─────────────────────────────────────────────
|
||||
|
||||
export type RegisterInput = z.infer<typeof registerSchema>;
|
||||
|
|
@ -133,5 +228,13 @@ export type UpdateProfileInput = z.infer<typeof updateProfileSchema>;
|
|||
export type ChangePasswordInput = z.infer<typeof changePasswordSchema>;
|
||||
export type UpdateRoleInput = z.infer<typeof updateRoleSchema>;
|
||||
export type UpdateStatusInput = z.infer<typeof updateStatusSchema>;
|
||||
export type UpdateAiInput = z.infer<typeof updateAiSchema>;
|
||||
export type CursorQuery = z.infer<typeof cursorQuerySchema>;
|
||||
export type OffsetQuery = z.infer<typeof offsetQuerySchema>;
|
||||
export type AiListWorkOrdersInput = z.infer<typeof aiListWorkOrdersSchema>;
|
||||
export type AiGetWorkOrderInput = z.infer<typeof aiGetWorkOrderSchema>;
|
||||
export type AiCreateWorkOrderInput = z.infer<typeof aiCreateWorkOrderSchema>;
|
||||
export type AiUpdateWorkOrderInput = z.infer<typeof aiUpdateWorkOrderSchema>;
|
||||
export type AiDeleteWorkOrderInput = z.infer<typeof aiDeleteWorkOrderSchema>;
|
||||
export type TriageProposal = z.infer<typeof triageProposalSchema>;
|
||||
export type SendCopilotMessageInput = z.infer<typeof sendCopilotMessageSchema>;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export interface UserPublic {
|
|||
export interface UserAdmin extends UserPublic {
|
||||
isActive: boolean;
|
||||
lastLoginAt: string | null;
|
||||
aiEnabled: boolean;
|
||||
}
|
||||
|
||||
export interface WorkOrderPublic {
|
||||
|
|
@ -53,7 +54,15 @@ export type ErrorCode =
|
|||
| 'AUTH_GENERIC'
|
||||
| 'EMAIL_TAKEN'
|
||||
| 'REFRESH_REUSE'
|
||||
| 'INTERNAL';
|
||||
| 'INTERNAL'
|
||||
| 'AI_UNAVAILABLE'
|
||||
| 'AI_BUDGET_EXCEEDED'
|
||||
| 'AI_APPROVAL_PENDING'
|
||||
| 'AI_APPROVAL_RESOLVED'
|
||||
| 'AI_APPROVAL_STALE'
|
||||
| 'AI_APPROVAL_EXPIRED'
|
||||
| 'AI_MESSAGE_DUPLICATE'
|
||||
| 'AI_INJECTION_BLOCKED';
|
||||
|
||||
export interface ApiErrorBody {
|
||||
code: ErrorCode;
|
||||
|
|
@ -97,3 +106,97 @@ export const REFRESH_TOKEN_TTL_SECONDS = 604800;
|
|||
|
||||
export const APP_ISS = 'workorders';
|
||||
export const APP_AUD = 'workorders-api';
|
||||
|
||||
// ── Agentic AI ─────────────────────────────────────────────────────────────
|
||||
|
||||
export type CopilotSessionStatus = 'active' | 'archived' | 'expired';
|
||||
|
||||
export interface CopilotSession {
|
||||
id: string;
|
||||
userId: string;
|
||||
status: CopilotSessionStatus;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export type AgentRunMode = 'copilot' | 'autonomous';
|
||||
|
||||
export type AgentRunStatus = 'running' | 'complete' | 'error' | 'budget_exceeded' | 'expired' | 'aborted';
|
||||
|
||||
export interface AgentRun {
|
||||
id: string;
|
||||
mode: AgentRunMode;
|
||||
actorId: string | null;
|
||||
agentName?: string;
|
||||
status: AgentRunStatus;
|
||||
model: string;
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
startedAt: string;
|
||||
finishedAt: string | null;
|
||||
errorCode?: ErrorCode;
|
||||
}
|
||||
|
||||
export type AgentToolOutcome =
|
||||
| 'executed'
|
||||
| 'approved'
|
||||
| 'rejected'
|
||||
| 'expired'
|
||||
| 'stale'
|
||||
| 'error'
|
||||
| 'blocked'
|
||||
| 'aborted';
|
||||
|
||||
export type AgentApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired' | 'stale';
|
||||
|
||||
export interface AgentApproval {
|
||||
status: AgentApprovalStatus;
|
||||
summary: string;
|
||||
expiresAt: string;
|
||||
decidedBy?: string;
|
||||
decidedAt?: string;
|
||||
}
|
||||
|
||||
export interface AgentToolCall {
|
||||
id: string;
|
||||
runId: string;
|
||||
tool: string;
|
||||
args: unknown;
|
||||
outcome: AgentToolOutcome;
|
||||
result?: unknown;
|
||||
latencyMs: number;
|
||||
createdAt: string;
|
||||
stagedVersion?: number;
|
||||
executedVersion?: number;
|
||||
preImage?: unknown;
|
||||
approval?: AgentApproval;
|
||||
}
|
||||
|
||||
export interface AgentToolCallPublic extends AgentToolCall {
|
||||
result?: never;
|
||||
}
|
||||
|
||||
export type TriageMode = 'suggest' | 'auto-apply';
|
||||
|
||||
export interface AgentConfig {
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
mode: TriageMode;
|
||||
allowedFields: string[];
|
||||
dailyActionCap: number;
|
||||
flagThreshold: WorkOrderPriority;
|
||||
workingHours: string;
|
||||
updatedBy: string | null;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface TriageSuggestion {
|
||||
id: string;
|
||||
workOrderId: string;
|
||||
runId: string;
|
||||
summary: string;
|
||||
suggestedPriority: WorkOrderPriority;
|
||||
flagForDispatcher: boolean;
|
||||
applied: boolean;
|
||||
createdAt: string;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue