Files
zesdex/src/interfaces/tui/run.ts
T

66 lines
2.3 KiB
TypeScript
Raw Normal View History

#!/usr/bin/env bun
/**
* Zesdex TUI — bootstrapper / composition root.
*
* 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 { newStore, userMessage } from "@zesdex/domain";
import type { TurnEventSink } from "@zesdex/agent";
import { runSingleProcess, type WiredRuntime } from "../cli/compose.ts";
import { createTuiState, type AppStateRest, type TurnRunner } from "./state.ts";
import { bootTui } from "./ui.tsx";
/** 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();
// 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);
}