UNPKG

aiwg

Version:

Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo

113 lines 4.62 kB
/** * OrchestratorAdapter — wires ScreenReader + OrchestratorPTY to live PTY sessions * * Provides factory functions that connect the orchestrator assess loop to a * real PTY session from the WebSocket bridge: * * createScreenReaderFromSession — attach ScreenReader to a PtySession's output * createSessionAdapter — implement OrchestratorSession over PtyLike * attachOrchestrator — full attach: reader + adapter + orchestrator * * @issue #756 * @see src/serve/screen-reader.ts — ScreenReader / ScreenState * @see src/serve/orchestrator-pty.ts — OrchestratorPTY / OrchestratorSession * @see src/serve/pty-bridge.ts — PtySession / PtyLike */ import { ScreenReader } from './screen-reader.js'; import { OrchestratorPTY } from './orchestrator-pty.js'; // ============================================================ // createScreenReaderFromSession // ============================================================ /** * Creates a ScreenReader that consumes data from a PtySession's output. * * - Replays session.outputBuffer immediately so the reader has current screen * state from the moment it is constructed. * - If the session's PTY is live, registers an onData listener so subsequent * output continues to flow into the reader. * * Callers are responsible for calling reader.dispose() when done. */ export function createScreenReaderFromSession(session, opts) { const reader = new ScreenReader({ rows: opts?.rows ?? 24, cols: opts?.cols ?? 80, }); // Replay any buffered output so the orchestrator starts with current state if (session.outputBuffer) { reader.write(session.outputBuffer); } // Attach to live PTY output when a PTY is running if (session.pty) { session.pty.onData((data) => { reader.write(data); }); } return reader; } // ============================================================ // createSessionAdapter // ============================================================ /** * Creates an OrchestratorSession adapter that writes to a PtySession's PTY stdin. * * Translates orchestrator write() and signal() calls into direct PTY operations. * Rejects if the session's PTY is null (not yet spawned or already cleaned up). */ export function createSessionAdapter(session) { return { async write(data) { if (!session.pty) { throw new Error('PTY session has no active pty — cannot write'); } session.pty.write(data); }, async signal(sig) { if (!session.pty) { throw new Error('PTY session has no active pty — cannot send signal'); } session.pty.kill(sig); }, }; } /** * Attaches an orchestrator to a running PTY session. * * Creates a ScreenReader (with outputBuffer replay), creates a session adapter, * and wires them together in an OrchestratorPTY instance ready to call run() on. * * The returned detach() function stops data flow and pauses the orchestrator * without killing the PTY. Re-attaching is supported by calling attachOrchestrator * again on the same session — it will replay the updated outputBuffer. */ export function attachOrchestrator(opts) { const { session, llm, context, rows, cols } = opts; // Track whether we have detached so the forwarding closure can skip writes let detached = false; // Build the ScreenReader with detach-aware live data forwarding. // We inline the attachment here (rather than delegating to createScreenReaderFromSession) // so that the onData callback is guarded by the detached flag from the start. const guardedReader = new ScreenReader({ rows: rows ?? 24, cols: cols ?? 80 }); // Replay outputBuffer so the orchestrator starts with current screen state if (session.outputBuffer) { guardedReader.write(session.outputBuffer); } // Attach live data feed through a detach guard if (session.pty) { session.pty.onData((data) => { if (!detached) { guardedReader.write(data); } }); } // Build the session adapter (write/signal → PTY) const sessionAdapter = createSessionAdapter(session); // Build the orchestrator const orchestrator = new OrchestratorPTY(sessionAdapter, guardedReader, llm, context); const detach = () => { detached = true; orchestrator.pause(); }; return { orchestrator, screenReader: guardedReader, detach }; } //# sourceMappingURL=orchestrator-adapter.js.map