feat: build an AI agent from 0 to 1 -- 11 progressive sessions

- 11 sessions from basic agent loop to autonomous teams
- Python MVP implementations for each session
- Mental-model-first docs in en/zh/ja
- Interactive web platform with step-through visualizations
- Incremental architecture: each session adds one mechanism
This commit is contained in:
CrazyBoyM
2026-02-21 14:37:42 +08:00
committed by CrazyBoyM
commit c6a27ef1d7
156 changed files with 28059 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
"use client";
import { useRef, useEffect, useState } from "react";
import { AnimatePresence } from "framer-motion";
import { useTranslations } from "@/lib/i18n";
import { useSimulator } from "@/hooks/useSimulator";
import { SimulatorControls } from "./simulator-controls";
import { SimulatorMessage } from "./simulator-message";
import type { Scenario } from "@/types/agent-data";
const scenarioModules: Record<string, () => Promise<{ default: Scenario }>> = {
s01: () => import("@/data/scenarios/s01.json") as Promise<{ default: Scenario }>,
s02: () => import("@/data/scenarios/s02.json") as Promise<{ default: Scenario }>,
s03: () => import("@/data/scenarios/s03.json") as Promise<{ default: Scenario }>,
s04: () => import("@/data/scenarios/s04.json") as Promise<{ default: Scenario }>,
s05: () => import("@/data/scenarios/s05.json") as Promise<{ default: Scenario }>,
s06: () => import("@/data/scenarios/s06.json") as Promise<{ default: Scenario }>,
s07: () => import("@/data/scenarios/s07.json") as Promise<{ default: Scenario }>,
s08: () => import("@/data/scenarios/s08.json") as Promise<{ default: Scenario }>,
s09: () => import("@/data/scenarios/s09.json") as Promise<{ default: Scenario }>,
s10: () => import("@/data/scenarios/s10.json") as Promise<{ default: Scenario }>,
s11: () => import("@/data/scenarios/s11.json") as Promise<{ default: Scenario }>,
};
interface AgentLoopSimulatorProps {
version: string;
}
export function AgentLoopSimulator({ version }: AgentLoopSimulatorProps) {
const t = useTranslations("version");
const [scenario, setScenario] = useState<Scenario | null>(null);
const scrollRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const loader = scenarioModules[version];
if (loader) {
loader().then((mod) => setScenario(mod.default));
}
}, [version]);
const sim = useSimulator(scenario?.steps ?? []);
useEffect(() => {
if (scrollRef.current) {
scrollRef.current.scrollTo({
top: scrollRef.current.scrollHeight,
behavior: "smooth",
});
}
}, [sim.visibleSteps.length]);
if (!scenario) return null;
return (
<section>
<h2 className="mb-2 text-xl font-semibold">{t("simulator")}</h2>
<p className="mb-4 text-sm text-[var(--color-text-secondary)]">
{scenario.description}
</p>
<div className="overflow-hidden rounded-xl border border-[var(--color-border)]">
<div className="border-b border-[var(--color-border)] bg-zinc-50 px-4 py-3 dark:bg-zinc-900">
<SimulatorControls
isPlaying={sim.isPlaying}
isComplete={sim.isComplete}
currentIndex={sim.currentIndex}
totalSteps={sim.totalSteps}
speed={sim.speed}
onPlay={sim.play}
onPause={sim.pause}
onStep={sim.stepForward}
onReset={sim.reset}
onSpeedChange={sim.setSpeed}
/>
</div>
<div
ref={scrollRef}
className="flex max-h-[500px] min-h-[200px] flex-col gap-3 overflow-y-auto p-4"
>
{sim.visibleSteps.length === 0 && (
<div className="flex flex-1 items-center justify-center text-sm text-[var(--color-text-secondary)]">
Press Play or Step to begin
</div>
)}
<AnimatePresence mode="popLayout">
{sim.visibleSteps.map((step, i) => (
<SimulatorMessage key={i} step={step} index={i} />
))}
</AnimatePresence>
</div>
</div>
</section>
);
}