Files
openclaw/src/infra/command-explainer/format.ts
Jesse Merhi 297a164536 Highlight exec command risks in Web approvals (#77153)
Summary:
- Adds parser-derived exec approval command-span metadata through host registration, gateway validation, generated Swift models, Control UI parsing/rendering, tests, and changelog.
- Reproducibility: not applicable. this is a feature PR rather than a bug report. The before/after behavior is ... rom current main’s plain command rendering to PR-head span generation, validation, and Web rendering tests.

Automerge notes:
- PR branch already contained follow-up commit before automerge: refactor: use neutral exec command spans
- PR branch already contained follow-up commit before automerge: refactor: simplify exec command span extraction
- PR branch already contained follow-up commit before automerge: refactor: inline approval command span params
- PR branch already contained follow-up commit before automerge: fix: keep exec approval spans lazy
- PR branch already contained follow-up commit before automerge: build: refresh exec approval protocol models
- PR branch already contained follow-up commit before automerge: Highlight exec command risks in Web approvals

Validation:
- ClawSweeper review passed for head 8d9977eb53.
- Required merge gates passed before the squash merge.

Prepared head SHA: 8d9977eb53
Review: https://github.com/openclaw/openclaw/pull/77153#issuecomment-4368769228

Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-08 06:38:41 +00:00

28 lines
910 B
TypeScript

import type { ExecApprovalCommandSpan } from "../exec-approvals.js";
import type { CommandExplanation } from "./types.js";
function spanToCommandSpan(span: {
startIndex: number;
endIndex: number;
}): ExecApprovalCommandSpan | null {
if (!Number.isSafeInteger(span.startIndex) || !Number.isSafeInteger(span.endIndex)) {
return null;
}
if (span.startIndex < 0 || span.endIndex <= span.startIndex) {
return null;
}
return { startIndex: span.startIndex, endIndex: span.endIndex };
}
export function formatCommandSpans(explanation: CommandExplanation): ExecApprovalCommandSpan[] {
const commandSpans: ExecApprovalCommandSpan[] = [];
for (const command of [...explanation.topLevelCommands, ...explanation.nestedCommands]) {
const commandSpan = spanToCommandSpan(command.executableSpan);
if (commandSpan) {
commandSpans.push(commandSpan);
}
}
return commandSpans;
}