treefmt: apply prettier
Pure `nix fmt` output from the commit before this one — no hand edits. 203 files: 52 md, 42 tsx, 32 js, 32 css, 21 ts, 13 html, 8 json, 3 mjs. Reproduce with `nix develop -c nix fmt` on the parent commit; the result should be byte-identical to this tree. None of the 13 `.prettierignore` entries appears here — verified by intersecting the changed-file list against the ignore file, with a control proving the intersection finds a match when one exists.
This commit is contained in:
parent
5d24bedd60
commit
39b95c2ede
203 changed files with 10090 additions and 6085 deletions
|
|
@ -10,9 +10,15 @@
|
|||
// a text-input flow anyway. Instead: typing the command once arms it
|
||||
// (a local note explains what confirming does), typing it again within
|
||||
// the same "armed" state fires it — a keyboard-native two-step confirm.
|
||||
import { useRef, useState } from 'preact/hooks';
|
||||
import { postModel, postEffort } from '../lib/modelEffort.js';
|
||||
import { postCancelTurn, postCompact, postNewSession, postLogout, postSend } from '../lib/termActions.js';
|
||||
import { useRef, useState } from "preact/hooks";
|
||||
import { postModel, postEffort } from "../lib/modelEffort.js";
|
||||
import {
|
||||
postCancelTurn,
|
||||
postCompact,
|
||||
postNewSession,
|
||||
postLogout,
|
||||
postSend,
|
||||
} from "../lib/termActions.js";
|
||||
|
||||
export interface TermInputProps {
|
||||
label: string;
|
||||
|
|
@ -22,14 +28,26 @@ export interface TermInputProps {
|
|||
}
|
||||
|
||||
const SLASH_COMMANDS: { name: string; desc: string }[] = [
|
||||
{ name: '/help', desc: 'list slash commands' },
|
||||
{ name: '/clear', desc: 'wipe the terminal panel (local-only)' },
|
||||
{ name: '/cancel', desc: 'SIGINT the in-flight claude turn' },
|
||||
{ name: '/compact', desc: 'compact the persistent claude session' },
|
||||
{ name: '/model', desc: '/model <name> — switch claude model for future turns' },
|
||||
{ name: '/effort', desc: '/effort <level> — set claude effort (medium/high/xhigh) for future turns' },
|
||||
{ name: '/new-session', desc: 'fresh claude session next turn (type twice to confirm)' },
|
||||
{ name: '/logout', desc: 'rotate OAuth creds + park in needs-login (type twice to confirm)' },
|
||||
{ name: "/help", desc: "list slash commands" },
|
||||
{ name: "/clear", desc: "wipe the terminal panel (local-only)" },
|
||||
{ name: "/cancel", desc: "SIGINT the in-flight claude turn" },
|
||||
{ name: "/compact", desc: "compact the persistent claude session" },
|
||||
{
|
||||
name: "/model",
|
||||
desc: "/model <name> — switch claude model for future turns",
|
||||
},
|
||||
{
|
||||
name: "/effort",
|
||||
desc: "/effort <level> — set claude effort (medium/high/xhigh) for future turns",
|
||||
},
|
||||
{
|
||||
name: "/new-session",
|
||||
desc: "fresh claude session next turn (type twice to confirm)",
|
||||
},
|
||||
{
|
||||
name: "/logout",
|
||||
desc: "rotate OAuth creds + park in needs-login (type twice to confirm)",
|
||||
},
|
||||
];
|
||||
|
||||
const MAX_PX = 12 * 16; // ~8 lines @ 1.5 line-height, 1em base
|
||||
|
|
@ -41,8 +59,13 @@ function completeSlash(prefix: string): string | null {
|
|||
return matches[(idx + 1) % matches.length].name;
|
||||
}
|
||||
|
||||
export function TermInput({ label, online, onLocalNote, onClear }: TermInputProps) {
|
||||
const [value, setValue] = useState('');
|
||||
export function TermInput({
|
||||
label,
|
||||
online,
|
||||
onLocalNote,
|
||||
onClear,
|
||||
}: TermInputProps) {
|
||||
const [value, setValue] = useState("");
|
||||
const taRef = useRef<HTMLTextAreaElement>(null);
|
||||
// Which destructive command is currently "armed" (typed once, waiting
|
||||
// for the confirming repeat) — any other command clears it.
|
||||
|
|
@ -51,59 +74,82 @@ export function TermInput({ label, online, onLocalNote, onClear }: TermInputProp
|
|||
function grow() {
|
||||
const ta = taRef.current;
|
||||
if (!ta) return;
|
||||
ta.style.height = 'auto';
|
||||
ta.style.height = Math.min(ta.scrollHeight, MAX_PX) + 'px';
|
||||
ta.style.height = "auto";
|
||||
ta.style.height = Math.min(ta.scrollHeight, MAX_PX) + "px";
|
||||
}
|
||||
|
||||
function reportFailure(label_: string, detail?: string) {
|
||||
onLocalNote(`✗ ${label_} failed${detail ? ': ' + detail : ''}`);
|
||||
onLocalNote(`✗ ${label_} failed${detail ? ": " + detail : ""}`);
|
||||
}
|
||||
|
||||
function handleSlash(line: string): boolean {
|
||||
const trimmed = line.trim();
|
||||
const [cmd, ...rest] = trimmed.split(/\s+/);
|
||||
const arg = rest.join(' ');
|
||||
const arg = rest.join(" ");
|
||||
const wasArmed = armedRef.current === cmd;
|
||||
armedRef.current = null;
|
||||
|
||||
switch (cmd) {
|
||||
case '/help':
|
||||
onLocalNote('/help');
|
||||
for (const c of SLASH_COMMANDS) onLocalNote(` ${c.name.padEnd(13)} — ${c.desc}`);
|
||||
case "/help":
|
||||
onLocalNote("/help");
|
||||
for (const c of SLASH_COMMANDS)
|
||||
onLocalNote(` ${c.name.padEnd(13)} — ${c.desc}`);
|
||||
return true;
|
||||
case '/clear':
|
||||
case "/clear":
|
||||
onClear();
|
||||
onLocalNote('· terminal cleared (local view only — server history kept)');
|
||||
onLocalNote(
|
||||
"· terminal cleared (local view only — server history kept)",
|
||||
);
|
||||
return true;
|
||||
case '/cancel':
|
||||
postCancelTurn().then((r) => !r.ok && reportFailure('/cancel', r.detail));
|
||||
case "/cancel":
|
||||
postCancelTurn().then(
|
||||
(r) => !r.ok && reportFailure("/cancel", r.detail),
|
||||
);
|
||||
return true;
|
||||
case '/compact':
|
||||
postCompact().then((r) => !r.ok && reportFailure('/compact', r.detail));
|
||||
case "/compact":
|
||||
postCompact().then((r) => !r.ok && reportFailure("/compact", r.detail));
|
||||
return true;
|
||||
case '/new-session':
|
||||
case "/new-session":
|
||||
if (wasArmed) {
|
||||
postNewSession().then((r) => !r.ok && reportFailure('/new-session', r.detail));
|
||||
postNewSession().then(
|
||||
(r) => !r.ok && reportFailure("/new-session", r.detail),
|
||||
);
|
||||
} else {
|
||||
armedRef.current = '/new-session';
|
||||
onLocalNote('⚠ drops all prior --continue context. type /new-session again to confirm.');
|
||||
armedRef.current = "/new-session";
|
||||
onLocalNote(
|
||||
"⚠ drops all prior --continue context. type /new-session again to confirm.",
|
||||
);
|
||||
}
|
||||
return true;
|
||||
case '/logout':
|
||||
case "/logout":
|
||||
if (wasArmed) {
|
||||
postLogout().then((r) => !r.ok && reportFailure('/logout', r.detail));
|
||||
postLogout().then((r) => !r.ok && reportFailure("/logout", r.detail));
|
||||
} else {
|
||||
armedRef.current = '/logout';
|
||||
onLocalNote('⚠ SIGINTs the current turn + rotates OAuth credentials. type /logout again to confirm.');
|
||||
armedRef.current = "/logout";
|
||||
onLocalNote(
|
||||
"⚠ SIGINTs the current turn + rotates OAuth credentials. type /logout again to confirm.",
|
||||
);
|
||||
}
|
||||
return true;
|
||||
case '/model':
|
||||
if (!arg) onLocalNote('✗ /model needs a name (e.g. /model haiku, /model sonnet, /model opus)');
|
||||
else postModel(arg).then((r) => !r.ok && reportFailure('/model', r.detail));
|
||||
case "/model":
|
||||
if (!arg)
|
||||
onLocalNote(
|
||||
"✗ /model needs a name (e.g. /model haiku, /model sonnet, /model opus)",
|
||||
);
|
||||
else
|
||||
postModel(arg).then(
|
||||
(r) => !r.ok && reportFailure("/model", r.detail),
|
||||
);
|
||||
return true;
|
||||
case '/effort':
|
||||
if (!arg) onLocalNote('✗ /effort needs a level (e.g. /effort medium, /effort high, /effort xhigh)');
|
||||
else postEffort(arg).then((r) => !r.ok && reportFailure('/effort', r.detail));
|
||||
case "/effort":
|
||||
if (!arg)
|
||||
onLocalNote(
|
||||
"✗ /effort needs a level (e.g. /effort medium, /effort high, /effort xhigh)",
|
||||
);
|
||||
else
|
||||
postEffort(arg).then(
|
||||
(r) => !r.ok && reportFailure("/effort", r.detail),
|
||||
);
|
||||
return true;
|
||||
default:
|
||||
onLocalNote(`✗ unknown slash command: ${cmd} — try /help`);
|
||||
|
|
@ -114,14 +160,14 @@ export function TermInput({ label, online, onLocalNote, onClear }: TermInputProp
|
|||
function submit() {
|
||||
const line = value;
|
||||
if (!line.trim()) return;
|
||||
setValue('');
|
||||
setValue("");
|
||||
requestAnimationFrame(grow);
|
||||
if (line.trim().startsWith('/')) {
|
||||
if (line.trim().startsWith("/")) {
|
||||
handleSlash(line);
|
||||
return;
|
||||
}
|
||||
armedRef.current = null;
|
||||
postSend(line).then((r) => !r.ok && reportFailure('send', r.detail));
|
||||
postSend(line).then((r) => !r.ok && reportFailure("send", r.detail));
|
||||
}
|
||||
|
||||
function onInput(e: Event) {
|
||||
|
|
@ -130,7 +176,7 @@ export function TermInput({ label, online, onLocalNote, onClear }: TermInputProp
|
|||
}
|
||||
|
||||
function onKeyDown(e: KeyboardEvent) {
|
||||
if (e.key === 'Tab' && value.startsWith('/') && !value.includes(' ')) {
|
||||
if (e.key === "Tab" && value.startsWith("/") && !value.includes(" ")) {
|
||||
const next = completeSlash(value);
|
||||
if (next) {
|
||||
e.preventDefault();
|
||||
|
|
@ -138,14 +184,14 @@ export function TermInput({ label, online, onLocalNote, onClear }: TermInputProp
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) {
|
||||
if (e.key === "Enter" && !e.shiftKey && !e.isComposing) {
|
||||
e.preventDefault();
|
||||
submit();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div class={`term-input${online ? '' : ' disabled'}`}>
|
||||
<div class={`term-input${online ? "" : " disabled"}`}>
|
||||
<form
|
||||
class="sendform-term"
|
||||
onSubmit={(e) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue