Midday / apps /api /src /ai /artifacts /forecast.ts
Jules
Final deployment with all fixes and verified content
c09f67c
import { artifact } from "@ai-sdk-tools/artifacts";
import { z } from "zod";
export const forecastArtifact = artifact(
"forecast-canvas",
z.object({
// Processing stage
stage: z.enum([
"loading",
"chart_ready",
"metrics_ready",
"analysis_ready",
]),
// Basic info
currency: z.string(),
from: z.string().optional().describe("Start date (ISO 8601)"),
to: z.string().optional().describe("End date (ISO 8601)"),
description: z
.string()
.optional()
.describe("Generated description based on date range"),
// Chart data (available at chart_ready stage)
chart: z
.object({
monthlyData: z.array(
z.object({
month: z.string(),
forecasted: z.number().nullable().optional(),
actual: z.number().nullable().optional(),
date: z.string().optional(),
// Enhanced forecast fields (matching dashboard metrics widget)
optimistic: z.number().nullable().optional(),
pessimistic: z.number().nullable().optional(),
confidence: z.number().nullable().optional(),
breakdown: z
.object({
recurringInvoices: z.number(),
recurringTransactions: z.number(),
scheduled: z.number(),
collections: z.number(),
billableHours: z.number(),
newBusiness: z.number(),
})
.nullable()
.optional(),
}),
),
forecastStartIndex: z.number().optional(),
})
.optional(),
// Core metrics (available at metrics_ready stage)
metrics: z
.object({
peakMonth: z.string(),
peakMonthValue: z.number(),
growthRate: z.number(),
unpaidInvoices: z.number(),
billableHours: z.number(),
// Overall confidence score (matching dashboard)
confidenceScore: z.number().nullable().optional(),
})
.optional(),
// Analysis data (available at analysis_ready stage)
analysis: z
.object({
summary: z.string(),
recommendations: z.array(z.string()).optional(),
})
.optional(),
}),
);