Skip to content

Kody is live

Watch the launch video — what Kody is, and why it exists.

← Public packages

@kentcdodds/jev

Call TypeSafe Jev evaluations via Cloudflare AI Gateway (same token/gateway as @kentcdodds/ai).

src/types.ts

153 lines · 3.4 KB · TypeScript
/**
 * Shared TypeSafe Jev question and answer TypeScript types.
 * Import when you need typed `questions` / `answers` shapes without calling the model.
 */

/** Boolean probability question (Jev `noul`). */
export type NoulQuestion = {
	type: 'noul'
	instructions: string
	criteria?: {
		true?: string
		false?: string
	}
}

/** Single-choice question with a criteria map of option → description. */
export type ChoiceQuestion = {
	type: 'choice'
	instructions: string
	criteria: Record<string, string>
}

/** Ordered rubric score question with a criteria array. */
export type ScoreQuestion = {
	type: 'score'
	instructions: string
	criteria: string[]
}

export type Question = NoulQuestion | ChoiceQuestion | ScoreQuestion

export type Questions = Record<string, Question>

export type JevState = string | Record<string, unknown> | unknown[]

export type NoulAnswer = {
	type: 'noul'
	noul: number
}

export type ChoiceAnswer = {
	type: 'choice'
	choice: string
	confidence: number
	probabilities: Record<string, number>
}

export type ScoreAnswer = {
	type: 'score'
	score: number
	confidence: number
	legend: Record<string, string>
	probabilities: Record<string, number>
}

export type Answer = NoulAnswer | ChoiceAnswer | ScoreAnswer

export type JevUsage = {
	input_tokens?: number
	output_tokens?: number
	[key: string]: unknown
}

/** Parsed model body returned by TypeSafe Jev. */
export type JevResult = {
	model: string
	answers: Record<string, Answer>
	usage?: JevUsage
}

export type EvaluateInput = {
	state: JevState
	questions: Questions
	/** Override Cloudflare account id for this call. */
	accountId?: string
	/** Override AI Gateway id (default `kody` / package settings). */
	gatewayId?: string
	/** Override model id (default `typesafe/jev`). */
	model?: string
}

export type EvaluateSuccess = {
	ok: true
	status: number
	answers: Record<string, Answer>
	model: string
	usage?: JevUsage
	/** Gateway / account ids used (never secrets). */
	meta: {
		accountIdSet: boolean
		gatewayId: string
		model: string
	}
}

export type EvaluateFailure = {
	ok: false
	status?: number
	error: string
	setup?: {
		secretsNewUrl?: string
		settingsHint?: string
	}
}

export type EvaluateResult = EvaluateSuccess | EvaluateFailure

export type JevRequestInput = {
	state: JevState
	questions: Questions
	accountId?: string
	gatewayId?: string
	model?: string
	/** Extra headers for progressive disclosure (never log secrets). */
	headers?: Record<string, string>
}

export type JevRequestResult = {
	ok: boolean
	status: number
	/** Raw Cloudflare `/ai/run` JSON (or text fallback). */
	data: unknown
	error?: string
	setup?: {
		secretsNewUrl?: string
		settingsHint?: string
	}
}

export const DEFAULT_JEV_MODEL = 'typesafe/jev'
export const DEFAULT_GATEWAY_ID = 'kody'

/**
 * Type metadata overview for Jev question/answer shapes.
 * Prefer importing named types from this module; call this for a safe inventory.
 *
 * @returns Type inventory for agents (no secrets).
 *
 * @example
 * import describeJevTypes from 'kody:@kentcdodds/jev/types'
 * const meta = await describeJevTypes()
 */
export default async function describeJevTypes() {
	return {
		packageId: 'jev',
		exportName: './types',
		description:
			'TypeSafe Jev question/answer types: noul, choice, score; evaluate request/result shapes.',
		questionTypes: ['noul', 'choice', 'score'],
		defaultModel: DEFAULT_JEV_MODEL,
		defaultGatewayId: DEFAULT_GATEWAY_ID,
	}
}