81 lines
3.7 KiB
TypeScript
81 lines
3.7 KiB
TypeScript
import { FileHelper } from '@start9labs/start-sdk'
|
|
import { Volume } from '@start9labs/start-sdk/package/lib/util/Volume'
|
|
import { z } from 'zod'
|
|
|
|
const mainVolume = new Volume('main')
|
|
|
|
// Operator-side configuration for the Recap Relay package. All fields
|
|
// are optional and ship with sensible defaults — the relay will boot
|
|
// even with an empty config, but will refuse to serve traffic until at
|
|
// least relay_gemini_api_key and relay_admin_password_hash are set.
|
|
export const configFile = FileHelper.json(
|
|
{
|
|
base: mainVolume,
|
|
subpath: 'config/relay-config.json',
|
|
},
|
|
z.object({
|
|
// ── Backend credentials ──
|
|
// The relay's Gemini API key. Used for all transcribe + analyze
|
|
// forwarding until a user exceeds their tier's Gemini cap (then
|
|
// overflows to operator hardware below). Empty disables the
|
|
// Gemini backend entirely — relay will then either route to
|
|
// hardware (if configured) or 503 every request.
|
|
relay_gemini_api_key: z.string().default(''),
|
|
|
|
// ── Operator hardware (optional fallback) ──
|
|
// When a Pro/Max user exceeds their monthly Gemini cap, the relay
|
|
// routes overflow here. Leave empty to hard-cap at the Gemini limit
|
|
// and return 402 once exceeded (no fallback).
|
|
relay_parakeet_base_url: z.string().default(''),
|
|
relay_gemma_base_url: z.string().default(''),
|
|
// Model identifiers to send in the upstream request bodies. The
|
|
// operator's Ollama or Parakeet wrapper may serve different models
|
|
// depending on what's been pulled; making these config-driven
|
|
// means the operator can swap models without rebuilding the relay.
|
|
// Live-reloaded — change applies to the next request.
|
|
relay_parakeet_model: z.string().default('parakeet-tdt-0.6b-v3'),
|
|
relay_gemma_model: z.string().default('gemma3:27b'),
|
|
|
|
// ── License server ──
|
|
// URL of the Keysat license server used for the cached online
|
|
// license-validation check. Defaults to the public endpoint;
|
|
// operators co-located with Keysat on the same Start9 server can
|
|
// override to the internal `http://keysat.startos:<port>` hostname
|
|
// for a lower-latency hot path.
|
|
relay_keysat_base_url: z.string().default('https://keysat.xyz'),
|
|
|
|
// ── Admin dashboard auth ──
|
|
// Username + scrypt-hashed password + session secret for the
|
|
// /admin/* dashboard. Same shape Recap uses (see Recap's
|
|
// server/admin-auth.js for the hash + verify code). Empty hash
|
|
// disables /admin entirely — useful while testing the public
|
|
// /relay/* endpoints.
|
|
relay_admin_username: z.string().default(''),
|
|
relay_admin_password_hash: z.string().default(''),
|
|
relay_admin_password_salt: z.string().default(''),
|
|
relay_admin_session_secret: z.string().default(''),
|
|
|
|
// ── Tier quotas (operator-adjustable without redeploy) ──
|
|
// JSON blob driving credits.js. Defaults match the v1 product
|
|
// spec: Core lifetime-5, Pro 50/mo with 25 Gemini cap, Max
|
|
// unlimited with 50 Gemini cap. Operators can tweak via the
|
|
// "Adjust Tier Quotas" action without a code change or restart.
|
|
relay_tier_quotas_json: z.string().default(
|
|
JSON.stringify({
|
|
// Core: 10 lifetime credits total — first 5 served via Gemini
|
|
// (operator's cloud spend), final 5 fall through to operator
|
|
// hardware so the user can keep going on free tier without
|
|
// costing the operator more cloud $.
|
|
core: {
|
|
lifetime: 10,
|
|
geminiCapLifetime: 5,
|
|
monthly: null,
|
|
geminiCapMonthly: null,
|
|
},
|
|
pro: { lifetime: null, monthly: 50, geminiCapMonthly: 25 },
|
|
max: { lifetime: null, monthly: null, geminiCapMonthly: 50 },
|
|
}),
|
|
),
|
|
}),
|
|
)
|