Initial commit

Signed-off-by: Ilan Bigio <ilan@openai.com>
This commit is contained in:
Ilan Bigio
2025-04-16 12:56:08 -04:00
commit 59a180ddec
163 changed files with 30587 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
// use-confirmation.ts
import type { ReviewDecision } from "../utils/agent/review";
import type React from "react";
import { useState, useCallback, useRef } from "react";
type ConfirmationResult = {
decision: ReviewDecision;
customDenyMessage?: string;
};
type ConfirmationItem = {
prompt: React.ReactNode;
resolve: (result: ConfirmationResult) => void;
};
export function useConfirmation(): {
submitConfirmation: (result: ConfirmationResult) => void;
requestConfirmation: (prompt: React.ReactNode) => Promise<ConfirmationResult>;
confirmationPrompt: React.ReactNode | null;
} {
// The current prompt is just the head of the queue
const [current, setCurrent] = useState<ConfirmationItem | null>(null);
// The entire queue is stored in a ref to avoid re-renders
const queueRef = useRef<Array<ConfirmationItem>>([]);
// Move queue forward to the next prompt
const advanceQueue = useCallback(() => {
const next = queueRef.current.shift() ?? null;
setCurrent(next);
}, []);
// Called whenever someone wants a confirmation
const requestConfirmation = useCallback(
(prompt: React.ReactNode) => {
return new Promise<ConfirmationResult>((resolve) => {
const wasEmpty = queueRef.current.length === 0;
queueRef.current.push({ prompt, resolve });
// If the queue was empty, we need to kick off the first prompt
if (wasEmpty) {
advanceQueue();
}
});
},
[advanceQueue],
);
// Called whenever user picks Yes / No
const submitConfirmation = (result: ConfirmationResult) => {
if (current) {
current.resolve(result);
advanceQueue();
}
};
return {
confirmationPrompt: current?.prompt, // the prompt to render now
requestConfirmation,
submitConfirmation,
};
}

View File

@@ -0,0 +1,26 @@
import { useEffect, useState } from "react";
const TERMINAL_PADDING_X = 8;
export function useTerminalSize(): { columns: number; rows: number } {
const [size, setSize] = useState({
columns: (process.stdout.columns || 60) - TERMINAL_PADDING_X,
rows: process.stdout.rows || 20,
});
useEffect(() => {
function updateSize() {
setSize({
columns: (process.stdout.columns || 60) - TERMINAL_PADDING_X,
rows: process.stdout.rows || 20,
});
}
process.stdout.on("resize", updateSize);
return () => {
process.stdout.off("resize", updateSize);
};
}, []);
return size;
}