merge pi
This commit is contained in:
@@ -2,7 +2,7 @@ export type SessionEntry = {
|
||||
id: string;
|
||||
title: string;
|
||||
createdAt: number;
|
||||
provider: 'claude' | 'opencode';
|
||||
provider: 'claude' | 'opencode' | 'pi-mono';
|
||||
model?: string | null;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ArrowLeft, Archive, Trash2, Maximize2, Minimize2 } from 'lucide-react';
|
||||
|
||||
type SessionBarProps = {
|
||||
listPath: string;
|
||||
provider: 'claude' | 'opencode';
|
||||
provider: 'claude' | 'opencode' | 'pi-mono';
|
||||
sessionTitle: string | undefined;
|
||||
isConnected: boolean;
|
||||
isGenerating: boolean;
|
||||
|
||||
@@ -26,6 +26,7 @@ export type TerminalViewProps = {
|
||||
autoFocus?: boolean;
|
||||
onReady?: (term: XTerm) => void;
|
||||
onExit?: () => void;
|
||||
onCommandDone?: (exitCode: number, output: string) => void;
|
||||
onDisconnect?: () => void;
|
||||
};
|
||||
|
||||
@@ -62,6 +63,7 @@ export const TerminalView = ({
|
||||
autoFocus = true,
|
||||
onReady,
|
||||
onExit,
|
||||
onCommandDone,
|
||||
onDisconnect,
|
||||
}: TerminalViewProps) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -71,11 +73,15 @@ export const TerminalView = ({
|
||||
const isMounted = useMounted();
|
||||
const onReadyRef = useRef<TerminalViewProps['onReady']>(onReady);
|
||||
const onExitRef = useRef<TerminalViewProps['onExit']>(onExit);
|
||||
const onCommandDoneRef = useRef<TerminalViewProps['onCommandDone']>(onCommandDone);
|
||||
const onDisconnectRef = useRef<TerminalViewProps['onDisconnect']>(onDisconnect);
|
||||
const commandRef = useRef(command);
|
||||
|
||||
onReadyRef.current = onReady;
|
||||
onExitRef.current = onExit;
|
||||
onCommandDoneRef.current = onCommandDone;
|
||||
onDisconnectRef.current = onDisconnect;
|
||||
commandRef.current = command;
|
||||
|
||||
const background = theme?.background ?? DEFAULT_THEME.background;
|
||||
const foreground = theme?.foreground ?? DEFAULT_THEME.foreground;
|
||||
@@ -121,6 +127,12 @@ export const TerminalView = ({
|
||||
|
||||
const ws = new WebSocket(buildWsUrl(wsPath, sessionId, sandboxed, cwd, command));
|
||||
wsRef.current = ws;
|
||||
let commandSent = false;
|
||||
let commandDone = false;
|
||||
let commandOutput = '';
|
||||
const EXIT_MARKER = '__OFFICER_EXIT_';
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const stripAnsi = (s: string) => s.replace(/\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07]*\x07/g, '');
|
||||
|
||||
const handleOpen = () => {
|
||||
ws.send(JSON.stringify({ type: 'resize', cols: term.cols, rows: term.rows }));
|
||||
@@ -131,6 +143,30 @@ export const TerminalView = ({
|
||||
const msg = JSON.parse(ev.data as string);
|
||||
if (msg.type === 'output') {
|
||||
term.write(msg.data);
|
||||
if (commandRef.current && !commandSent) {
|
||||
commandSent = true;
|
||||
setTimeout(() => {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
const wrapped = onCommandDoneRef.current
|
||||
? `${commandRef.current}; echo "${EXIT_MARKER}$?__"`
|
||||
: commandRef.current;
|
||||
ws.send(JSON.stringify({ type: 'input', data: wrapped + '\r' }));
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
if (commandSent && !commandDone && onCommandDoneRef.current) {
|
||||
commandOutput += msg.data as string;
|
||||
const markerMatch = stripAnsi(commandOutput).match(/__OFFICER_EXIT_(\d+)__/);
|
||||
if (markerMatch) {
|
||||
const exitCode = Number(markerMatch[1]);
|
||||
const raw = stripAnsi(commandOutput).slice(0, markerMatch.index);
|
||||
const lines = raw.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
||||
const cmdLine = lines.findIndex((l) => l.includes(commandRef.current!.slice(0, 20)));
|
||||
const output = lines.slice(cmdLine >= 0 ? cmdLine + 1 : 0).join('\n').trim();
|
||||
commandDone = true;
|
||||
onCommandDoneRef.current(exitCode, output);
|
||||
}
|
||||
}
|
||||
} else if (msg.type === 'exit') {
|
||||
term.write('\r\n[Process exited]\r\n');
|
||||
onExitRef.current?.();
|
||||
|
||||
Reference in New Issue
Block a user