mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-29 19:01:44 +00:00
144 lines
3.6 KiB
TypeScript
144 lines
3.6 KiB
TypeScript
export function createEditorSubmitHandler(params: {
|
|
editor: {
|
|
setText: (value: string) => void;
|
|
addToHistory: (value: string) => void;
|
|
};
|
|
handleCommand: (value: string) => Promise<void> | void;
|
|
sendMessage: (value: string) => Promise<void> | void;
|
|
handleBangLine: (value: string) => Promise<void> | void;
|
|
}) {
|
|
return (text: string) => {
|
|
const raw = text;
|
|
const value = raw.trim();
|
|
params.editor.setText("");
|
|
|
|
// Keep previous behavior: ignore empty/whitespace-only submissions.
|
|
if (!value) {
|
|
return;
|
|
}
|
|
|
|
// Bash mode: only if the very first character is '!' and it's not just '!'.
|
|
// IMPORTANT: use the raw (untrimmed) text so leading spaces do NOT trigger.
|
|
// Per requirement: a lone '!' should be treated as a normal message.
|
|
if (raw.startsWith("!") && raw !== "!") {
|
|
params.editor.addToHistory(raw);
|
|
void params.handleBangLine(raw);
|
|
return;
|
|
}
|
|
|
|
// Enable built-in editor prompt history navigation (up/down).
|
|
params.editor.addToHistory(value);
|
|
|
|
if (value.startsWith("/")) {
|
|
void params.handleCommand(value);
|
|
return;
|
|
}
|
|
|
|
void params.sendMessage(value);
|
|
};
|
|
}
|
|
|
|
export function shouldEnableWindowsGitBashPasteFallback(params?: {
|
|
platform?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
}): boolean {
|
|
const platform = params?.platform ?? process.platform;
|
|
const env = params?.env ?? process.env;
|
|
const termProgram = (env.TERM_PROGRAM ?? "").toLowerCase();
|
|
|
|
// Some macOS terminals emit multiline paste as rapid single-line submits.
|
|
// Enable burst coalescing so pasted blocks stay as one user message.
|
|
if (platform === "darwin") {
|
|
if (termProgram.includes("iterm") || termProgram.includes("apple_terminal")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (platform !== "win32") {
|
|
return false;
|
|
}
|
|
|
|
const msystem = (env.MSYSTEM ?? "").toUpperCase();
|
|
const shell = env.SHELL ?? "";
|
|
if (msystem.startsWith("MINGW") || msystem.startsWith("MSYS")) {
|
|
return true;
|
|
}
|
|
if (shell.toLowerCase().includes("bash")) {
|
|
return true;
|
|
}
|
|
return termProgram.includes("mintty");
|
|
}
|
|
|
|
export function createSubmitBurstCoalescer(params: {
|
|
submit: (value: string) => void;
|
|
enabled: boolean;
|
|
burstWindowMs?: number;
|
|
now?: () => number;
|
|
setTimer?: typeof setTimeout;
|
|
clearTimer?: typeof clearTimeout;
|
|
}) {
|
|
const windowMs = Math.max(1, params.burstWindowMs ?? 50);
|
|
const now = params.now ?? (() => Date.now());
|
|
const setTimer = params.setTimer ?? setTimeout;
|
|
const clearTimer = params.clearTimer ?? clearTimeout;
|
|
let pending: string | null = null;
|
|
let pendingAt = 0;
|
|
let flushTimer: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
const clearFlushTimer = () => {
|
|
if (!flushTimer) {
|
|
return;
|
|
}
|
|
clearTimer(flushTimer);
|
|
flushTimer = null;
|
|
};
|
|
|
|
const flushPending = () => {
|
|
if (pending === null) {
|
|
return;
|
|
}
|
|
const value = pending;
|
|
pending = null;
|
|
pendingAt = 0;
|
|
clearFlushTimer();
|
|
params.submit(value);
|
|
};
|
|
|
|
const scheduleFlush = () => {
|
|
clearFlushTimer();
|
|
flushTimer = setTimer(() => {
|
|
flushPending();
|
|
}, windowMs);
|
|
};
|
|
|
|
return (value: string) => {
|
|
if (!params.enabled) {
|
|
params.submit(value);
|
|
return;
|
|
}
|
|
if (value.includes("\n")) {
|
|
flushPending();
|
|
params.submit(value);
|
|
return;
|
|
}
|
|
const ts = now();
|
|
if (pending === null) {
|
|
pending = value;
|
|
pendingAt = ts;
|
|
scheduleFlush();
|
|
return;
|
|
}
|
|
if (ts - pendingAt <= windowMs) {
|
|
pending = `${pending}\n${value}`;
|
|
pendingAt = ts;
|
|
scheduleFlush();
|
|
return;
|
|
}
|
|
flushPending();
|
|
pending = value;
|
|
pendingAt = ts;
|
|
scheduleFlush();
|
|
};
|
|
}
|