linted and working

This commit is contained in:
Eason Goodale
2025-04-20 01:26:40 -07:00
parent 1e0a7cc313
commit b1cef74d8c
12 changed files with 121 additions and 65 deletions

View File

@@ -5,4 +5,4 @@
// without the “.tsx” extension when running under ts-node/esm in the test
// environment.
export { default } from "./image-picker-overlay.tsx";
export { default } from "./image-picker-overlay.tsx";

View File

@@ -1,7 +1,6 @@
/* eslint-disable import/order */
import path from "node:path";
import { Box, Text, useInput, useStdin } from "ink";
import SelectInput from "../select-input/select-input.js";
@@ -37,7 +36,7 @@ export default function ImagePickerOverlay({
if (process.env["DEBUG_OVERLAY"]) {
// eslint-disable-next-line no-console
console.log('[overlay] mount, items:', items.map((i) => i.label).join(','));
console.log("[overlay] mount, items:", items.map((i) => i.label).join(","));
}
// Keep track of currently highlighted item so <Enter> can act synchronously.
@@ -64,7 +63,7 @@ export default function ImagePickerOverlay({
function onData(data: Buffer) {
if (process.env["DEBUG_OVERLAY"]) {
// eslint-disable-next-line no-console
console.log('[overlay] stdin data', JSON.stringify(data.toString()));
console.log("[overlay] stdin data", JSON.stringify(data.toString()));
}
// ink-testing-library pipes mocked input through `stdin.emit("data", …)`
@@ -117,48 +116,48 @@ export default function ImagePickerOverlay({
// in the spec).
useInput(
(input, key) => {
if (process.env["DEBUG_OVERLAY"]) {
// eslint-disable-next-line no-console
console.log(
"[overlay] root useInput",
JSON.stringify(input),
key.return,
);
}
if (key.escape || key.backspace || input === "\u007f") {
if (process.env["DEBUG_OVERLAY"]) {
// eslint-disable-next-line no-console
console.log("[overlay] cancel");
}
perform(onCancel);
} else if (key.return) {
// Act on the currently highlighted item synchronously so tests that
// simulate a bare "\r" keypress without triggering SelectInputs
// onSelect callback still work. This mirrors <SelectInput>s own
// behaviour but executing the logic here avoids having to depend on
// that implementation detail.
const item = highlighted.current;
if (!item) {
return;
console.log(
"[overlay] root useInput",
JSON.stringify(input),
key.return,
);
}
if (process.env["DEBUG_OVERLAY"]) {
// eslint-disable-next-line no-console
console.log('[overlay] return on', item.label, item.value);
}
perform(() => {
if (item.value === "__UP__") {
onChangeDir(path.dirname(cwd));
} else if (item.label.endsWith("/")) {
onChangeDir(item.value);
} else {
onPick(item.value);
if (key.escape || key.backspace || input === "\u007f") {
if (process.env["DEBUG_OVERLAY"]) {
// eslint-disable-next-line no-console
console.log("[overlay] cancel");
}
});
}
perform(onCancel);
} else if (key.return) {
// Act on the currently highlighted item synchronously so tests that
// simulate a bare "\r" keypress without triggering SelectInputs
// onSelect callback still work. This mirrors <SelectInput>s own
// behaviour but executing the logic here avoids having to depend on
// that implementation detail.
const item = highlighted.current;
if (!item) {
return;
}
if (process.env["DEBUG_OVERLAY"]) {
// eslint-disable-next-line no-console
console.log("[overlay] return on", item.label, item.value);
}
perform(() => {
if (item.value === "__UP__") {
onChangeDir(path.dirname(cwd));
} else if (item.label.endsWith("/")) {
onChangeDir(item.value);
} else {
onPick(item.value);
}
});
}
},
{ isActive: true },
);

View File

@@ -84,7 +84,11 @@ export default function TerminalChatInput({
if (process.env["DEBUG_TCI"]) {
// eslint-disable-next-line no-console
console.log('[TCI] render stage', { input, pickerCwd, attachedCount: attachedImages.length });
console.log("[TCI] render stage", {
input,
pickerCwd,
attachedCount: attachedImages.length,
});
}
// Open picker when user finished typing '@'
React.useEffect(() => {
@@ -115,7 +119,7 @@ export default function TerminalChatInput({
if (process.env["DEBUG_TCI"]) {
// eslint-disable-next-line no-console
console.log('[TCI] raw stdin', JSON.stringify(str));
console.log("[TCI] raw stdin", JSON.stringify(str));
}
if (str === "@" && pickerCwd == null) {
@@ -162,7 +166,7 @@ export default function TerminalChatInput({
(_input, _key) => {
if (process.env["DEBUG_TCI"]) {
// eslint-disable-next-line no-console
console.log('[TCI] useInput raw', JSON.stringify(_input), _key);
console.log("[TCI] useInput raw", JSON.stringify(_input), _key);
}
// When image picker overlay is open delegate all keystrokes to it.
@@ -172,7 +176,7 @@ export default function TerminalChatInput({
if (!confirmationPrompt && !loading) {
if (process.env["DEBUG_TCI"]) {
// eslint-disable-next-line no-console
console.log('useInput received', JSON.stringify(_input));
console.log("useInput received", JSON.stringify(_input));
}
// Open image picker when user types '@' and picker not already open.
@@ -227,7 +231,10 @@ export default function TerminalChatInput({
}
// Backspace on empty draft removes last attached image
if ((_key.backspace || _input === "\u007f") && attachedImages.length > 0) {
if (
(_key.backspace || _input === "\u007f") &&
attachedImages.length > 0
) {
if (input.length === 0) {
setAttachedImages((prev) => prev.slice(0, -1));
}
@@ -450,7 +457,11 @@ export default function TerminalChatInput({
text:
missingImages.length === 1
? `Warning: image "${missingImages[0]}" not found and was not attached.`
: `Warning: ${missingImages.length} images were not found and were skipped: ${missingImages.join(", ")}`,
: `Warning: ${
missingImages.length
} images were not found and were skipped: ${missingImages.join(
", ",
)}`,
},
],
},
@@ -520,7 +531,12 @@ export default function TerminalChatInput({
if (process.env["DEBUG_TCI"]) {
// eslint-disable-next-line no-console
console.log('[TCI] attached image added', filePath, 'total', attachedImages.length + 1);
console.log(
"[TCI] attached image added",
filePath,
"total",
attachedImages.length + 1,
);
}
setPickerCwd(null);
}}
@@ -535,7 +551,7 @@ export default function TerminalChatInput({
}
if (process.env["DEBUG_TCI"]) {
// eslint-disable-next-line no-console
console.log('[TCI] render AttachmentPreview', attachedImages);
console.log("[TCI] render AttachmentPreview", attachedImages);
}
return (
<Box flexDirection="column" paddingX={1} marginBottom={1}>

View File

@@ -119,7 +119,12 @@ function TerminalChatResponseMessage({
: c.type === "input_text"
? c.text
: c.type === "input_image"
? imageFilenameByDataUrl.get(c.image_url as string) || "<Image>"
? (() => {
const label = imageFilenameByDataUrl.get(
c.image_url as string,
);
return label ? `<Image path="${label}">` : "<Image>";
})()
: c.type === "input_file"
? c.filename
: "", // unknown content type

View File

@@ -9,6 +9,8 @@ export interface TerminalInlineImageProps {
}
// During tests or when terminal does not support images, fallback to alt.
export default function TerminalInlineImage({ alt = "[image]" }: TerminalInlineImageProps): React.ReactElement {
export default function TerminalInlineImage({
alt = "[image]",
}: TerminalInlineImageProps): React.ReactElement {
return <Text>{alt}</Text>;
}