mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-21 14:11:26 +00:00
Terminal/Context: harden control filtering and align argv root-value parsing
This commit is contained in:
@@ -33,4 +33,32 @@ describe("lookupContextTokens", () => {
|
||||
const { lookupContextTokens } = await import("./context.js");
|
||||
expect(lookupContextTokens("openrouter/claude-sonnet")).toBe(321_000);
|
||||
});
|
||||
|
||||
it("does not skip eager warmup when --profile is followed by -- terminator", async () => {
|
||||
const loadConfigMock = vi.fn(() => ({ models: {} }));
|
||||
vi.doMock("../config/config.js", () => ({
|
||||
loadConfig: loadConfigMock,
|
||||
}));
|
||||
vi.doMock("./models-config.js", () => ({
|
||||
ensureOpenClawModelsJson: vi.fn(async () => {}),
|
||||
}));
|
||||
vi.doMock("./agent-paths.js", () => ({
|
||||
resolveOpenClawAgentDir: () => "/tmp/openclaw-agent",
|
||||
}));
|
||||
vi.doMock("./pi-model-discovery.js", () => ({
|
||||
discoverAuthStorage: vi.fn(() => ({})),
|
||||
discoverModels: vi.fn(() => ({
|
||||
getAll: () => [],
|
||||
})),
|
||||
}));
|
||||
|
||||
const argvSnapshot = process.argv;
|
||||
process.argv = ["node", "openclaw", "--profile", "--", "config", "validate"];
|
||||
try {
|
||||
await import("./context.js");
|
||||
expect(loadConfigMock).toHaveBeenCalledTimes(1);
|
||||
} finally {
|
||||
process.argv = argvSnapshot;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -69,10 +69,22 @@ const MODEL_CACHE = new Map<string, number>();
|
||||
let loadPromise: Promise<void> | null = null;
|
||||
let configuredWindowsPrimed = false;
|
||||
|
||||
function isValueToken(arg: string | undefined): boolean {
|
||||
if (!arg || arg === "--") {
|
||||
return false;
|
||||
}
|
||||
if (!arg.startsWith("-")) {
|
||||
return true;
|
||||
}
|
||||
return /^-\d+(?:\.\d+)?$/.test(arg);
|
||||
}
|
||||
|
||||
function getCommandPathFromArgv(argv: string[]): string[] {
|
||||
const args = argv.slice(2);
|
||||
const tokens: string[] = [];
|
||||
let skipNextAsRootValue = false;
|
||||
for (const arg of argv.slice(2)) {
|
||||
for (let i = 0; i < args.length; i += 1) {
|
||||
const arg = args[i];
|
||||
if (!arg || arg === "--") {
|
||||
break;
|
||||
}
|
||||
@@ -81,7 +93,8 @@ function getCommandPathFromArgv(argv: string[]): string[] {
|
||||
continue;
|
||||
}
|
||||
if (arg === "--profile" || arg === "--log-level") {
|
||||
skipNextAsRootValue = true;
|
||||
const next = args[i + 1];
|
||||
skipNextAsRootValue = isValueToken(next);
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
|
||||
12
src/terminal/safe-text.test.ts
Normal file
12
src/terminal/safe-text.test.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { sanitizeTerminalText } from "./safe-text.js";
|
||||
|
||||
describe("sanitizeTerminalText", () => {
|
||||
it("removes C1 control characters", () => {
|
||||
expect(sanitizeTerminalText("a\u009bb\u0085c")).toBe("abc");
|
||||
});
|
||||
|
||||
it("escapes line controls while preserving printable text", () => {
|
||||
expect(sanitizeTerminalText("a\tb\nc\rd")).toBe("a\\tb\\nc\\rd");
|
||||
});
|
||||
});
|
||||
@@ -11,7 +11,7 @@ export function sanitizeTerminalText(input: string): string {
|
||||
let sanitized = "";
|
||||
for (const char of normalized) {
|
||||
const code = char.charCodeAt(0);
|
||||
const isControl = (code >= 0x00 && code <= 0x1f) || code === 0x7f;
|
||||
const isControl = (code >= 0x00 && code <= 0x1f) || (code >= 0x7f && code <= 0x9f);
|
||||
if (!isControl) {
|
||||
sanitized += char;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user