import { apiRequest } from './common.ts' import type { Canvas, CanvasVersion } from './canvas.ts' // ============================================================================ // Types // ============================================================================ export type TemplateKind = 'canvas' | 'workflow' export interface TemplateSlotColumn { key: string label: string placeholder?: string } /** * Where a list slot's rows are written into the structured output schema. * * `properties` turns each row into an output field; `enum` turns the rows into the allowed values * of one existing property. */ export type TemplateSlotSchemaTarget = | { mode: 'properties', nameFrom: string, descriptionFrom?: string } | { mode: 'enum', property: string, valueFrom: string } export interface TextTemplateSlot { key: string type: 'text' label: string description?: string required?: boolean multiline?: boolean placeholder?: string } export interface ListTemplateSlot { key: string type: 'list' label: string description?: string required?: boolean columns: TemplateSlotColumn[] schemaTarget?: TemplateSlotSchemaTarget } export type TemplateSlot = TextTemplateSlot | ListTemplateSlot /** A text slot takes a string; a list slot takes rows keyed by column. */ export type TemplateSlotValues = Record>> export interface Template { id: string name: string description: string | null type: TemplateKind /** Natural-language phrases describing what the template is for. Match against these. */ useCases: string[] /** Coarse tags such as `legal`, `finance`, `operations`, `customer-support`. */ industries: string[] /** Capability tags such as `pdf-treatment`. */ utilities: string[] /** Visible to every workspace when true. */ isGlobal: boolean slots: TemplateSlot[] schema: unknown graph: unknown variables: unknown configuration: unknown previewImage: string | null promptId: string promptVersionId: string workspaceId: string createdAt: string updatedAt: string } export interface ListTemplatesOptions { limit?: number offset?: number } export interface TemplateRecommendation { template: Template /** 0..1. Above ~0.3 is worth showing; below that, say nothing matched. */ score: number /** Why it matched, in words you can show the user. */ reason: string } // ============================================================================ // Discovery // ============================================================================ /** * The template catalog visible to this workspace: its own templates plus every global one. */ export async function listTemplates(options?: ListTemplatesOptions): Promise { const params = new URLSearchParams() if (options?.limit !== undefined) params.set('limit', String(options.limit)) if (options?.offset !== undefined) params.set('offset', String(options.offset)) const query = params.toString() const { data } = await apiRequest<{ data: Template[] }>(`/templates${query ? `?${query}` : ''}`) return data } export async function getTemplate(templateId: string): Promise