(chore) init commit and add tasks

This commit is contained in:
Story Crater Bot
2026-08-18 18:33:49 -07:00
commit 6c6218ef36
61 changed files with 9851 additions and 0 deletions
+217
View File
@@ -0,0 +1,217 @@
'use client'
import { useEffect, useRef, useState } from 'react'
import { ChevronDown } from 'lucide-react'
import { Panel } from '@/components/cluster/Panel'
import { SlotMeter } from '@/components/cluster/SlotMeter'
const DAILY_BUDGET = 12
type Turn = {
role: 'user' | 'model'
reasoning?: string
content: string
streaming?: boolean
}
const SEED: Turn[] = [
{ role: 'user', content: 'Why is the sms application degraded?' },
{
role: 'model',
reasoning:
'The snapshot lists sms with health "degraded" and sync "synced". Sync being clean means the manifests applied fine, so this is a runtime problem rather than a delivery one. The sms namespace shows 0 of 1 pods running. A single pod that never reaches Running, with Argo reporting the desired state as applied, usually means the pod cannot be placed at all.',
content:
'Delivery is fine — sms is Synced, so Argo applied everything it was asked to. The failure is at runtime: the namespace has one pod and zero running. Argo marks the app degraded because the workload never became ready, not because the manifests are wrong.',
},
]
const REPLY =
'Wave 4 is empty. Waves are sort keys, not a sequence — Argo orders by value and skips gaps, so 3 is followed directly by 5. Nothing is missing.'
const REPLY_REASONING =
'The user is asking about a gap in the wave column display. Argo CD sync waves are integers used purely for ordering; there is no requirement that they be contiguous. The cluster uses 0,1,2,3,5,6,7,8. This is normal and usually happens when a wave is retired or intentionally reserved.'
export default function ChatPage() {
const [turns, setTurns] = useState<Turn[]>(SEED)
const [value, setValue] = useState('')
const [queue, setQueue] = useState<number | null>(null)
const [slots, setSlots] = useState(3)
const [used, setUsed] = useState(2)
const [openReasoning, setOpenReasoning] = useState<number | null>(1)
const scrollRef = useRef<HTMLDivElement>(null)
useEffect(() => {
scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: 'smooth' })
}, [turns, queue])
const send = () => {
if (!value.trim() || queue !== null || used >= DAILY_BUDGET) return
setTurns((t) => [...t, { role: 'user', content: value }])
setValue('')
setQueue(3)
}
// Placeholder for the queue → stream transition. Real version is SSE from atlas.
useEffect(() => {
if (queue === null) return
if (queue > 0) {
const t = setTimeout(() => setQueue((q) => (q === null ? null : q - 1)), 700)
return () => clearTimeout(t)
}
setQueue(null)
setSlots((s) => Math.min(s + 1, 6))
setUsed((u) => u + 1)
setTurns((t) => [...t, { role: 'model', reasoning: REPLY_REASONING, content: '', streaming: true }])
let i = 0
const stream = setInterval(() => {
i += 3
setTurns((t) => {
const next = [...t]
const last = next[next.length - 1]
if (last?.role !== 'model') return t
next[next.length - 1] = { ...last, content: REPLY.slice(0, i), streaming: i < REPLY.length }
return next
})
if (i >= REPLY.length) {
clearInterval(stream)
setSlots((s) => Math.max(s - 1, 1))
}
}, 40)
return () => clearInterval(stream)
}, [queue])
const exhausted = used >= DAILY_BUDGET
return (
<div className="space-y-6">
<header className="border border-wire bg-deck p-6 md:p-8">
<p className="font-data text-[10px] uppercase tracking-[0.2em] text-dim">Surface D — Chat</p>
<h1 className="mt-3 max-w-3xl font-signage text-3xl font-semibold leading-[1.1] tracking-signage md:text-5xl">
A 32B model, running on one card, <span className="text-lamp">two rooms from here.</span>
</h1>
<p className="mt-5 max-w-2xl font-plex text-sm leading-relaxed text-dim">
It reads a redacted snapshot of the cluster and answers questions about it. It cannot query anything, run
anything, or change anything. When all six public slots are busy, you wait in line — the queue is real,
and so is the hardware.
</p>
<div className="mt-6 flex flex-wrap items-center gap-6">
<SlotMeter used={slots} size="lg" showCap />
<span className="font-data text-[10px] uppercase tracking-[0.14em] text-dim">
{DAILY_BUDGET - used} of {DAILY_BUDGET} messages left today
</span>
</div>
</header>
<div className="grid gap-6 lg:grid-cols-[1fr_260px]">
<Panel label="Session" hint="anonymous">
<div ref={scrollRef} className="h-[440px] space-y-5 overflow-y-auto pr-1">
{turns.map((turn, i) =>
turn.role === 'user' ? (
<div key={i} className="flex justify-end">
<p className="max-w-[85%] border border-wire-lit bg-riser px-3 py-2 font-plex text-sm text-chalk">
{turn.content}
</p>
</div>
) : (
<div key={i} className="max-w-[92%] space-y-2">
{turn.reasoning && (
<div className="border-l-2 border-lamp/50">
<button
onClick={() => setOpenReasoning(openReasoning === i ? null : i)}
aria-expanded={openReasoning === i}
className="flex w-full items-center gap-2 py-1 pl-3 font-data text-[10px] uppercase tracking-[0.16em] text-lamp focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-lamp"
>
<ChevronDown
size={12}
className={`transition-transform ${openReasoning === i ? '' : '-rotate-90'}`}
/>
thinking
</button>
{openReasoning === i && (
<p className="py-1 pl-3 pr-2 font-data text-[11px] leading-relaxed text-dim">
{turn.reasoning}
</p>
)}
</div>
)}
<p className="font-plex text-sm leading-relaxed text-chalk">
{turn.content}
{turn.streaming && <span className="ml-0.5 inline-block h-4 w-2 animate-pulse bg-lamp align-text-bottom" />}
</p>
</div>
),
)}
{queue !== null && (
<div className="flex items-center gap-3 border border-lamp/40 px-3 py-2">
<SlotMeter used={6} />
<p className="font-data text-[11px] text-lamp">
all six public slots busy · position {queue} in queue
</p>
</div>
)}
</div>
<form
onSubmit={(e) => {
e.preventDefault()
send()
}}
className="mt-3 flex items-center gap-2 border-t border-wire pt-3"
>
<input
value={value}
onChange={(e) => setValue(e.target.value)}
disabled={exhausted}
aria-label="Message"
placeholder={exhausted ? 'Daily limit reached — resets in 14h' : 'Ask about the cluster'}
className="min-w-0 flex-1 bg-transparent font-plex text-sm text-chalk placeholder:text-dim/60 focus:outline-none disabled:cursor-not-allowed"
/>
<button
type="submit"
disabled={exhausted || queue !== null}
className="border border-lamp px-3 py-1 font-data text-[10px] uppercase tracking-[0.14em] text-lamp transition-colors hover:bg-lamp hover:text-void focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-lamp disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-lamp"
>
send
</button>
</form>
</Panel>
<div className="space-y-6">
<Panel label="Limits" hint="tier 3">
<dl className="space-y-2.5 font-data text-[11px]">
{[
['public slots', '6 of 8'],
['queue depth', '20'],
['per session', '12 / day'],
['request timeout', '120s'],
['output cap', '1500 tokens'],
].map(([k, v]) => (
<div key={k} className="flex items-baseline gap-2">
<dt className="text-dim">{k}</dt>
<dd className="ml-auto tabular-nums text-chalk">{v}</dd>
</div>
))}
</dl>
<p className="mt-4 border-t border-wire pt-3 font-plex text-[11px] leading-relaxed text-dim">
Closing this tab frees your slot immediately. Two slots stay reserved so the operator is never locked
out of their own hardware.
</p>
</Panel>
<Panel label="Cannot do" hint="by construction">
<ul className="space-y-1.5 font-data text-[10px] text-dim">
{['call tools', 'query the cluster', 'read logs', 'change anything', 'see Secret contents'].map((x) => (
<li key={x} className="flex items-center gap-2">
<span className="h-px w-3 bg-wire-lit" />
{x}
</li>
))}
</ul>
</Panel>
</div>
</div>
</div>
)
}