refactor: rombak jadi full CLI/TUI only — hapus semua interface server (api/ws/grpc/web/daemon) + wire TUI ke agent beneran

- Hapus total interfaces: api (REST), ws (WebSocket), grpc, web, daemon (IPC)
- Hapus infra server-only yang jadi dead code: infrastructure/ipc + seluruh
  stack auth (domain/auth, application/auth, persistence/iam, infrastructure/auth jwt/password/oauth_loopback)
- TUI (OpenTUI) jadi interface utama: wire ke runSingleProcess() real runtime,
  ganti mock '(no LLM configured)' dengan turnService.runTurn asli + streaming
  stream_token/reasoning/tool_result/system_note/error ke transcript
- Tampilkan model asli di header (mis. claude-opus-5), abort turn via Ctrl+C
- CLI jadi mode headless tambahan: zesdex --headless '<prompt>' one-shot turn
- Bersihkan package.json (script tui/headless), tsconfig paths, docker-compose,
  AGENTS.md; hapus StartOAuth/login stub
- verified: tsc 0 err, 70 test pass, build dist/zesdex; headless 'pong' real; TUI
  interactive render + real turn 'say pong in one word' -> assistant 'pong'
This commit is contained in:
asepharyana committed 2026-09-03 01:19:27 +07:00
1 parent 34322e492a
commit 7e6ed34f0d
68 files changed
+250 -3661

No files matched your search

+53 -10
View File
@@ -1,22 +1,65 @@
#!/usr/bin/env bun
/**
* Zesdex TUI — OpenTUI entry point.
* Zesdex TUI — bootstrapper / composition root.
*
* Boots the OpenTUI CLI renderer and mounts `ZesdexApp`, which routes input
* through `handleKey` → `applyAction`. Replaced the earlier raw-mode stdin
* event loop with OpenTUI's native renderer/keyboard handling.
* Wires the real agent runtime (via `runSingleProcess` from the CLI compose
* root) into the OpenTUI app, and installs a `turnRunner` that executes real
* turns against the LLM + tool executor, streaming events into the transcript.
*/
import * as fs from "node:fs";
import { createTuiState } from "./state.ts";
import { newStore, userMessage, type TurnEventSink } from "@zesdex/domain";
import { runSingleProcess, type WiredRuntime } from "../cli/compose.ts";
import { createTuiState, type AppStateRest, type TurnRunner } from "./state.ts";
import { bootTui } from "./ui.tsx";
/** Run the interactive OpenTUI until the user quits. */
/** Build the real turn runner from the wired runtime. */
function makeTurnRunner(runtime: WiredRuntime): TurnRunner {
return async (text, onEvent) => {
const abort = new AbortController();
// Live sink: forward every event to the UI immediately as it happens.
const sink: TurnEventSink = {
push(ev) {
onEvent(ev);
},
drain() {
return [];
},
};
const messages = [userMessage(text)];
await runtime.turnService.runTurn({
messages,
session_dir: runtime.store.base_dir,
workspace_roots: [process.cwd()],
turn_events: sink,
in_flight: { value: false },
abort,
api_key: runtime.apiKey,
model: runtime.model,
api_base: runtime.apiBase,
});
};
}
/** Run the interactive OpenTUI with the real agent wired in. */
export async function runTui(): Promise<void> {
const cwd = process.cwd();
const dataDir = `${process.env.HOME ?? ""}/.local/share/zesdex`;
const sessionDir = `${dataDir}/sessions/${Date.now()}`;
fs.mkdirSync(sessionDir, { recursive: true });
const state = createTuiState([cwd], sessionDir, `${dataDir}/memory`);
// Build the real runtime once (LLM client + tool executor + turn service).
const runtime = await runSingleProcess();
const store = newStore();
void store;
const dataDir = `${process.env.HOME ?? ""}/.local/share/zesdex`;
fs.mkdirSync(dataDir, { recursive: true });
const sessionLabel = new Date().toISOString().replace(/[:T]/g, "-").slice(0, 19);
const sessionDir = `${dataDir}/sessions/${sessionLabel}`;
fs.mkdirSync(sessionDir, { recursive: true });
const memoryDir = `${dataDir}/memory`;
const state: AppStateRest = createTuiState([cwd], sessionDir, memoryDir);
state.turnRunner = makeTurnRunner(runtime);
state.misc.apiConnected = true;
// Surface the real effective model/provider in the header.
state.settings = { provider: runtime.model } as Record<string, unknown>;
await bootTui(state);
}