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/settings.ts

77 lines · 2.5 KB · TypeScript
/**
 * Read or update Jev Cloudflare ids in this package's storage.
 * When local storage is empty, reads fall back to `@kentcdodds/ai/settings`
 * so one setup can serve both packages. Does not duplicate the secret name —
 * reuse user secret `cloudflareApiToken`.
 *
 * @param input.accountId - Cloudflare account id to save.
 * @param input.gatewayId - AI Gateway id to save (default `kody`).
 * @param input.model - Optional Jev model id override to save.
 * @returns Current settings when reading, or `{ updated, settings }` when writing.
 *
 * @example
 * import jevSettings from 'kody:@kentcdodds/jev/settings'
 * const current = await jevSettings()
 * // => { accountId, gatewayId, model, sources }
 */

import { packageStorage } from 'kody:runtime'
import { resolveJevConfig, settingNames } from './resolve.ts'

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

export type JevSettingsInput = {
	accountId?: string
	gatewayId?: string
	model?: string
}

/**
 * Read or update Jev Cloudflare ids in this package's storage.
 * When local storage is empty, reads fall back to `@kentcdodds/ai/settings`
 * so one setup can serve both packages. Does not duplicate the secret name —
 * reuse user secret `cloudflareApiToken`.
 *
 * @param input.accountId - Cloudflare account id to save.
 * @param input.gatewayId - AI Gateway id to save (default `kody`).
 * @param input.model - Optional Jev model id override to save.
 * @returns Current settings when reading, or `{ updated, settings }` when writing.
 *
 * @example
 * import jevSettings from 'kody:@kentcdodds/jev/settings'
 * const current = await jevSettings()
 * // => { accountId, gatewayId, model, sources }
 */
export default async function jevSettings(input: JevSettingsInput = {}) {
	const updated: Array<string> = []
	const storage = packageStorage()
	const accountId = trimString(input.accountId)
	const gatewayId = trimString(input.gatewayId)
	const model = trimString(input.model)

	if (accountId) {
		await storage.set(settingNames.accountId, accountId)
		updated.push('accountId')
	}
	if (gatewayId) {
		await storage.set(settingNames.gatewayId, gatewayId)
		updated.push('gatewayId')
	}
	if (model) {
		await storage.set(settingNames.model, model)
		updated.push('model')
	}

	const resolved = await resolveJevConfig()
	const settings = {
		accountId: resolved.accountId,
		gatewayId: resolved.gatewayId,
		model: resolved.model,
		sources: resolved.sources,
	}

	if (updated.length === 0) return settings
	return { updated, settings }
}