Skip to content
← Public packages

@kentcdodds/ai

Kody tool-using agent turns with Vercel AI SDK and Cloudflare AI Gateway.

src/settings.ts

86 lines · 2.6 KB · TypeScript
/**
 * Read or update Cloudflare AI ids. Pass a field to persist it in this
 * package's storage (no republish).
 *
 * @param input.accountId - Cloudflare account id to save.
 * @param input.gatewayId - AI Gateway id to save.
 * @param input.model - Model id to save.
 * @returns Current `{ accountId, gatewayId, model }` when reading, or `{ updated, settings }` when writing.
 *
 * @example
 * import aiSettings from 'kody:@kentcdodds/ai/settings'
 * const current = await aiSettings()
 * // => { accountId: '...', gatewayId: 'kody', model: '...' }
 */

import { z } from 'zod'
import {
	migrateAiFromValues,
	readLocalSetting,
	writeNamedSetting,
} from './legacy-value.ts'

const settingNames = {
	accountId: 'cloudflareAccountId',
	gatewayId: 'cloudflareAiGatewayId',
	model: 'cloudflareAiModel',
} as const

function trimString(value: unknown) {
	return typeof value === 'string' ? value.trim() : ''
}

export async function readAiSettings() {
	return {
		accountId: await readLocalSetting(settingNames.accountId),
		gatewayId: await readLocalSetting(settingNames.gatewayId),
		model: await readLocalSetting(settingNames.model),
	}
}

const aiSettingsInputSchema = z.object({
	accountId: z.string().optional(),
	gatewayId: z.string().optional(),
	model: z.string().optional(),
})

export type AiSettingsInput = z.input<typeof aiSettingsInputSchema>

/**
 * Read or update Cloudflare AI ids. Pass a field to persist it in this
 * package's storage (no republish).
 *
 * @param input.accountId - Cloudflare account id to save.
 * @param input.gatewayId - AI Gateway id to save.
 * @param input.model - Model id to save.
 * @returns Current `{ accountId, gatewayId, model }` when reading, or `{ updated, settings }` when writing.
 *
 * @example
 * import aiSettings from 'kody:@kentcdodds/ai/settings'
 * const current = await aiSettings()
 * // => { accountId: '...', gatewayId: 'kody', model: '...' }
 */
export default async function aiSettings(input: AiSettingsInput = {}) {
	const parsed = aiSettingsInputSchema.parse(input ?? {})
	const updated: Array<string> = []
	const accountId = trimString(parsed.accountId)
	const gatewayId = trimString(parsed.gatewayId)
	const model = trimString(parsed.model)
	if (accountId) {
		await writeNamedSetting(settingNames.accountId, accountId)
		updated.push('accountId')
	}
	if (gatewayId) {
		await writeNamedSetting(settingNames.gatewayId, gatewayId)
		updated.push('gatewayId')
	}
	if (model) {
		await writeNamedSetting(settingNames.model, model)
		updated.push('model')
	}
	if (updated.length === 0) {
		await migrateAiFromValues()
		return await readAiSettings()
	}
	return { updated, settings: await readAiSettings() }
}