[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
242
components/terminal/terminalAutocompletePrompt.test.ts
Normal file
242
components/terminal/terminalAutocompletePrompt.test.ts
Normal file
@@ -0,0 +1,242 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
computeAutocompleteAcceptWrite,
|
||||
isSameAutocompleteQuery,
|
||||
resolveAutocompleteQueryInput,
|
||||
shouldBlockAutocompleteForSensitivePrompt,
|
||||
} from "./autocomplete/terminalAutocompletePrompt.ts";
|
||||
import type { PromptDetectionResult } from "./autocomplete/promptDetector.ts";
|
||||
|
||||
function atPrompt(userInput: string, promptText = "$ "): PromptDetectionResult {
|
||||
return {
|
||||
isAtPrompt: true,
|
||||
promptText,
|
||||
userInput,
|
||||
cursorOffset: userInput.length,
|
||||
};
|
||||
}
|
||||
|
||||
test("shouldBlockAutocompleteForSensitivePrompt ignores empty-echo alone", () => {
|
||||
// Empty-echo shell PS1s are handled by allowExternalProviders:false wait,
|
||||
// not by this helper — it only covers explicit sensitive prompts / latches.
|
||||
assert.equal(
|
||||
shouldBlockAutocompleteForSensitivePrompt({
|
||||
sensitiveInputActive: false,
|
||||
promptText: "$ ",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldBlockAutocompleteForSensitivePrompt({
|
||||
sensitiveInputActive: false,
|
||||
promptText: "➜ ",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldBlockAutocompleteForSensitivePrompt blocks marked sensitive input", () => {
|
||||
assert.equal(
|
||||
shouldBlockAutocompleteForSensitivePrompt({
|
||||
sensitiveInputActive: true,
|
||||
promptText: "$ ",
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldBlockAutocompleteForSensitivePrompt blocks auth-challenge prompts", () => {
|
||||
assert.equal(
|
||||
shouldBlockAutocompleteForSensitivePrompt({
|
||||
sensitiveInputActive: false,
|
||||
promptText: "Password:",
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("isSameAutocompleteQuery keeps late paths alive during live preview", () => {
|
||||
// Highlighting a candidate rewrites typedInputBuffer to the preview text.
|
||||
// Late path listings for the original query must still apply.
|
||||
assert.equal(
|
||||
isSameAutocompleteQuery({
|
||||
queryInput: "cd /u",
|
||||
currentInput: "cd /usr/",
|
||||
previewActive: true,
|
||||
previewBaseline: "cd /u",
|
||||
}),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
isSameAutocompleteQuery({
|
||||
queryInput: "cd /u",
|
||||
currentInput: "cd /var/",
|
||||
previewActive: false,
|
||||
previewBaseline: "cd /u",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
isSameAutocompleteQuery({
|
||||
queryInput: "cd /u",
|
||||
currentInput: "cd /usr/",
|
||||
previewActive: true,
|
||||
previewBaseline: "ls /u",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveAutocompleteQueryInput prefers reliable typed buffer when remote echo lags", () => {
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt("s"), "systemctl", true),
|
||||
"systemctl",
|
||||
);
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt("syst"), "systemctl", true),
|
||||
"systemctl",
|
||||
);
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt(""), "systemctl", true),
|
||||
"systemctl",
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveAutocompleteQueryInput keeps echoed input when the typed buffer is unreliable", () => {
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt("sys"), "systemctl", false),
|
||||
"sys",
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveAutocompleteQueryInput preserves a reliably tracked empty line under echo lag", () => {
|
||||
// User typed then deleted everything; remote echo still shows the old char.
|
||||
// Autocomplete must not keep matching / accepting against the stale echo.
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt("g"), "", true),
|
||||
"",
|
||||
);
|
||||
// Unreliable empty buffer (history recall / cursor move) still trusts echo.
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt("git status"), "", false),
|
||||
"git status",
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveAutocompleteQueryInput prefers reliable typed buffer after partial backspace under echo lag", () => {
|
||||
// User typed `git` then backspaced to `gi`; remote echo still shows `git`.
|
||||
// Completions/accept must track the shorter reliable buffer, not the stale echo.
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt("git"), "gi", true),
|
||||
"gi",
|
||||
);
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt("git status"), "git ", true),
|
||||
"git ",
|
||||
);
|
||||
});
|
||||
|
||||
test("computeAutocompleteAcceptWrite does not reinsert deleted text from a lagging echo", () => {
|
||||
assert.equal(
|
||||
computeAutocompleteAcceptWrite({
|
||||
prompt: atPrompt("g"),
|
||||
typedBuffer: "",
|
||||
typedBufferReliable: true,
|
||||
candidate: "git status",
|
||||
os: "linux",
|
||||
}),
|
||||
"git status",
|
||||
);
|
||||
// Partial delete: typed `gi`, echo still `git`, accept `git status` must
|
||||
// only send the missing suffix — never ` status` onto a truncated line.
|
||||
assert.equal(
|
||||
computeAutocompleteAcceptWrite({
|
||||
prompt: atPrompt("git"),
|
||||
typedBuffer: "gi",
|
||||
typedBufferReliable: true,
|
||||
candidate: "git status",
|
||||
os: "linux",
|
||||
}),
|
||||
"t status",
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveAutocompleteQueryInput returns null when not at a prompt", () => {
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(
|
||||
{
|
||||
isAtPrompt: false,
|
||||
promptText: "",
|
||||
userInput: "",
|
||||
cursorOffset: 0,
|
||||
},
|
||||
"systemctl",
|
||||
true,
|
||||
),
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveAutocompleteQueryInput does not invent input from an unrelated typed buffer", () => {
|
||||
assert.equal(
|
||||
resolveAutocompleteQueryInput(atPrompt("echo hello"), "sudo", true),
|
||||
"echo hello",
|
||||
);
|
||||
});
|
||||
|
||||
test("computeAutocompleteAcceptWrite uses typed buffer under echo lag so accept does not duplicate keystrokes", () => {
|
||||
// Remote shell already has the full typed command; only the local echo lags.
|
||||
// Accept/preview must extend from the typed buffer, not the short echoed prefix.
|
||||
assert.equal(
|
||||
computeAutocompleteAcceptWrite({
|
||||
prompt: atPrompt("s"),
|
||||
typedBuffer: "systemctl",
|
||||
typedBufferReliable: true,
|
||||
candidate: "systemctl restart nginx",
|
||||
os: "linux",
|
||||
}),
|
||||
" restart nginx",
|
||||
);
|
||||
assert.equal(
|
||||
computeAutocompleteAcceptWrite({
|
||||
prompt: atPrompt(""),
|
||||
typedBuffer: "systemctl",
|
||||
typedBufferReliable: true,
|
||||
candidate: "systemctl status",
|
||||
os: "linux",
|
||||
execute: true,
|
||||
}),
|
||||
" status\r",
|
||||
);
|
||||
});
|
||||
|
||||
test("computeAutocompleteAcceptWrite refuses line replacement when disabled", () => {
|
||||
assert.equal(
|
||||
computeAutocompleteAcceptWrite({
|
||||
prompt: atPrompt("dock"),
|
||||
typedBuffer: "dock",
|
||||
typedBufferReliable: true,
|
||||
candidate: "systemctl status",
|
||||
os: "linux",
|
||||
allowLineReplacement: false,
|
||||
}),
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
test("computeAutocompleteAcceptWrite clears with backspaces on a mislabeled Windows shell (#3184)", () => {
|
||||
// Windows PowerShell host saved with the os:"linux" default: the detected
|
||||
// drive-letter prompt must route the clear to backspaces, not Ctrl-U.
|
||||
assert.equal(
|
||||
computeAutocompleteAcceptWrite({
|
||||
prompt: atPrompt("tkn", "(base) PS C:\\Users\\Administrator>"),
|
||||
typedBuffer: "tkn",
|
||||
typedBufferReliable: true,
|
||||
candidate: "uv run tkauto video sync-fs",
|
||||
os: "linux",
|
||||
}),
|
||||
"\b\b\buv run tkauto video sync-fs",
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user