v3: AI SDK pivot — pi removed, Next.js 16 + AI SDK 7 + AI Elements teacher app

The teaching agent no longer runs on pi. Stack:
- ToolLoopAgent (ai@7) + OpenRouter (OPENROUTER_API_KEY), model via LH_MODEL,
  default anthropic/claude-sonnet-4.5 with reasoning tokens
- quiz/ask_user_question = client-side tools (no server execute): the call
  lands as a typed tool part in input-available state; the card grades via
  src/core/question-core.ts; addToolOutput sends the verdict; the teacher's
  reaction continues the same assistant message
- resume-mid-quiz is free: the pending tool part persists in the transcript
- persistence: one JSON per chat (data/chats/), full UIMessage transcripts,
  saved onFinish (also on abort)
- UI: AI Elements (owned copy-paste components, pruned to the five in use)
  + button-based QuizCard/AnsweredCard (ask answers never graded)
- pi fully removed: TUI, extensions, Fastify+WS server, bridge, custom
  protocol all deleted (recoverable from git history)
- tests: question-core units carry over; chat-flow integration drives
  handleChatRequest with MockLanguageModelV4 (48 tests, zero tokens);
  render smoke tests guard the cards (renderToStaticMarkup)

Carried over unchanged: teacher system prompt, question-core, schema/
ledger/derive/extract pipeline, data model.
This commit is contained in:
Amos
2026-08-22 02:18:27 +03:00
parent e127a9bfbd
commit a72c902d30
81 changed files with 9643 additions and 10860 deletions
+3 -15
View File
@@ -2,18 +2,15 @@
/**
* learning-harness CLI
*
* teach [message] launch an interactive teaching session (full pi TUI)
* doctor [--web] non-interactive smoke test of the teacher wiring
* (--web checks the web-dispatch extension set)
* serve start the web server (teacher agent + REST + WebSocket)
* ingest <file> normalize a session JSONL and print the canonical document
* (Stage 1 only — extractor/merger not yet implemented)
* graph print graph/ledger stats
* what-next (not yet implemented)
*
* The web app (Next.js + AI SDK): npm run dev
*/
import * as fs from "node:fs";
import { doctor, runTeachingSession } from "./teacher/create-session.ts";
import { normalizeSession } from "./extract/normalize.ts";
import { ledgers } from "./ledger.ts";
import { deriveAll } from "./derive.ts";
@@ -23,15 +20,6 @@ async function main() {
const [command, ...rest] = process.argv.slice(2);
switch (command) {
case "teach": {
await runTeachingSession(rest.join(" ") || undefined);
break;
}
case "doctor": {
const mode = rest.includes("--web") ? "web" : "tui";
await doctor(mode);
break;
}
case "ingest": {
const file = rest[0];
if (!file) {
@@ -69,7 +57,7 @@ async function main() {
process.exit(1);
}
default: {
console.log("Commands: teach [message] | doctor | ingest <file> | graph | what-next");
console.log("Commands: ingest <file> | graph | what-next");
process.exit(command ? 1 : 0);
}
}