Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
- Surface OpenClaw sessions in the dashboard's audit + history browser: reads the real JSONL transcripts at `~/.openclaw/agents/<agentId>/sessions/<uuid>.jsonl` (skipping the heavy `.trajectory.jsonl` OTel traces) via `lib/openclaw-sessions.ts` (a pure, unit-tested type-discriminated parser that pairs assistant `toolCall` blocks with their `toolResult` by `toolCallId`) and `lib/openclaw-projects.ts` (reads the `sessions.json` index, groups by agentId into `openclaw-<agentId>` projects, parses channel metadata from the sessionKey). Wired through `src/audit/cli-adapters/openclaw.ts`, `lib/cli-registry.ts` (teal badge), `lib/projects.ts`, `lib/download-session.ts` (real-file download — no synthesis needed), and the `app/project/[name]` routes. (#489)

### Fixes
- Fix the Mintlify docs deployment failing on every `docs/i18n/README.*.md` translation. Mintlify parses each page as MDX, where the README's top-level HTML comment (`<!-- … -->`) is a hard syntax error — it rejects the leading `!` of `<!--`, and Mintlify's own message suggests the `{/* text */}` form — so all 14 locale READMEs failed to publish. The README translator now converts HTML comments to MDX comments (`{/* … */}`) on output via a new fence-aware `convertHtmlComments` sanitizer — applied in both `readme-translator.ts` and `translateMdxPage`, and leaving `<!-- -->` inside code fences literal (e.g. the AgentEye collector plist sample) — and the 14 committed translations are regenerated to match. Also aligns `readme-translator.ts` with `translateMdxPage` by running `sanitizeJsxAttributes` over its JSX-bearing output. (#535)
- Close the gap that let the above reach `main`: the `validate:mdx` CI safety net (`scripts/validate-mdx.ts`) only walked `.mdx` files, but Mintlify parses `.md` pages as MDX too — so the `docs/i18n/README.*.md` breakage sailed past CI and only failed at the post-merge deploy. `collectMdxFiles` now validates `.md` pages as well, so this whole class of translation breakage fails on the PR instead. (#535)
- Fix Copilot CLI file policies silently allowing file access (re-verified live against Copilot CLI 1.0.71, whose hook contract drifted since the 1.0.41 verification). Copilot's snake_case hook events deliver canonical tool names but its own input keys — Read `{path}`, Write `{path, file_text}`, Edit `{path, old_str, new_str}` — so path/content builtins like `block-env-files` never fired (a live `.env` read was observed passing). Adds `COPILOT_TOOL_INPUT_MAP` mapping them to `file_path`/`content`/`old_string`/`new_string`. Also normalizes the `permissionRequest` event's camelCase payload (`toolName`/`toolInput`/`sessionId`, lowercase tool names) in the handler so PermissionRequest-matched policies (e.g. `block-sudo`'s escalation guard) fire instead of seeing a null tool name. Verified end-to-end: the previously-passing `.env` read replay is now denied, and Copilot 1.0.71 honors the deny (`code:"denied"`, tool never runs). (#516)
- Make documentation translation publishing atomic: require every locale and cache artifact, pin the Mintlify validator, validate the final overlaid PR tree, and emit the canonical `pt-BR` Mintlify locale while preserving `pt-br` paths.
- Make the dashboard header responsive. On narrow windows the single-row header crushed its children: the active nav tab clipped mid-word ("policie…"), the version string wrapped mid-token ("V0.0.14-/BETA.1"), and "Reach Us" broke onto two lines. The version + section cluster now never wraps mid-token and sheds entirely below 900px (it duplicates the active-tab highlight), tab/header padding tightens, and below 620px the actions row wraps under the nav right-aligned instead of crushing it. Verified headless at 1500/760/480px. (#516)
Expand Down
71 changes: 71 additions & 0 deletions __tests__/scripts/translate-docs/mdx-translator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
rewriteInternalLinks,
sanitizeJsxAttributes,
stripStrayTrailingFence,
convertHtmlComments,
getEnglishMdxPages,
} from "@/scripts/translate-docs/mdx-translator";

Expand Down Expand Up @@ -187,3 +188,73 @@ describe("stripStrayTrailingFence", () => {
expect(stripStrayTrailingFence(input)).toBe(input);
});
});

describe("convertHtmlComments", () => {
it("converts a single-line HTML comment to an MDX comment", () => {
expect(convertHtmlComments("<!-- hello -->")).toBe("{/* hello */}");
});

it("converts a multi-line HTML comment, preserving inner content", () => {
const input =
"## Heading\n\n<!-- A note about the\n table layout below. -->\n<table></table>\n";
const expected =
"## Heading\n\n{/* A note about the\n table layout below. */}\n<table></table>\n";
expect(convertHtmlComments(input)).toBe(expected);
});

it("keeps HTML that only looks like a comment inside inline text intact", () => {
// Regression guard for the real README note that mentions `<img>`.
const input = "<!-- prefer a table over inline <img> runs -->";
expect(convertHtmlComments(input)).toBe(
"{/* prefer a table over inline <img> runs */}",
);
});

it("leaves HTML comments inside fenced code blocks untouched", () => {
// A plist sample in a ```xml fence must stay literal — MDX does not parse
// fenced content, so the collector-installation docs are already valid.
const input =
"```xml\n<!-- ~/Library/LaunchAgents/foo.plist -->\n<plist></plist>\n```\n";
expect(convertHtmlComments(input)).toBe(input);
});

it("converts a top-level comment but not one nested in a later fence", () => {
const input =
"<!-- top note -->\n\n```html\n<!-- literal sample -->\n```\n";
const expected =
"{/* top note */}\n\n```html\n<!-- literal sample -->\n```\n";
expect(convertHtmlComments(input)).toBe(expected);
});

it("neutralizes a `*/` inside the body so the MDX comment can't close early", () => {
expect(convertHtmlComments("<!-- a */ b -->")).toBe("{/* a * / b */}");
});

it("returns content with no comments unchanged", () => {
const input = "# Title\n\nJust prose, no comments here.\n";
expect(convertHtmlComments(input)).toBe(input);
});

it("converts a top-level comment after a ```` block that embeds ```", () => {
// A generic fence toggle would count the inner ``` as a boundary and leave
// this comment mis-flagged as inside a fence, breaking the deploy.
const input = "````\ninner ``` fence\n````\n\n<!-- note -->\n";
const expected = "````\ninner ``` fence\n````\n\n{/* note */}\n";
expect(convertHtmlComments(input)).toBe(expected);
});

it("does not treat a ~~~ line inside a ``` block as a fence boundary", () => {
// The tilde line is inner content of the backtick fence, so the comment on
// the next line stays literal; only the comment after the fence converts.
const input =
"```\n~~~ still inside\n<!-- inside -->\n```\n\n<!-- outside -->\n";
const expected =
"```\n~~~ still inside\n<!-- inside -->\n```\n\n{/* outside */}\n";
expect(convertHtmlComments(input)).toBe(expected);
});

it("treats an unterminated fence as running to end of document", () => {
const input = "```\n<!-- inside an unclosed fence -->\n";
expect(convertHtmlComments(input)).toBe(input);
});
});
46 changes: 46 additions & 0 deletions __tests__/scripts/validate-mdx.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// @vitest-environment node
import { describe, it, expect } from "vitest";
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
import { join, relative } from "node:path";
import { tmpdir } from "node:os";
import {
collectMdxFiles,
encodeAnnotation,
findMdxParseError,
stripFrontmatter,
Expand Down Expand Up @@ -84,4 +88,46 @@ describe("findMdxParseError", () => {
expect(error).not.toBeNull();
expect(error?.line).toBe(5);
});

it("flags a top-level HTML comment (the docs/i18n README deploy failure)", async () => {
// Mintlify parses .md/.mdx as MDX, where `<!-- -->` is a hard syntax error
// ("Unexpected character `!` … use the MDX comment form"). This is exactly
// what broke every docs/i18n/README.*.md translation at deploy time.
const error = await findMdxParseError("# Title\n\n<!-- a note -->\n");
expect(error).not.toBeNull();
expect(error?.message).toMatch(/character/i);
});

it("accepts the MDX comment form the translator now emits", async () => {
expect(await findMdxParseError("# Title\n\n{/* a note */}\n")).toBeNull();
});

it("leaves an HTML comment inside a code fence alone", async () => {
// Fenced content is literal in MDX, so the AgentEye collector plist sample
// keeps its `<!-- -->` — which is why convertHtmlComments skips fences.
const src = "```xml\n<!-- ~/Library/LaunchAgents/foo.plist -->\n```\n";
expect(await findMdxParseError(src)).toBeNull();
});
});

describe("collectMdxFiles", () => {
it("collects .md and .mdx pages recursively but ignores other files", () => {
// Regression guard: Mintlify parses .md pages (e.g. the docs/i18n READMEs)
// as MDX too, so the walk must not be restricted to .mdx.
const dir = mkdtempSync(join(tmpdir(), "validate-mdx-collect-"));
try {
writeFileSync(join(dir, "page.mdx"), "# mdx\n");
writeFileSync(join(dir, "readme.md"), "# md\n");
writeFileSync(join(dir, "notes.txt"), "ignore me\n");
mkdirSync(join(dir, "sub"));
writeFileSync(join(dir, "sub", "nested.md"), "# nested\n");

const found = collectMdxFiles(dir)
.map((f) => relative(dir, f))
.sort();
expect(found).toEqual(["page.mdx", "readme.md", "sub/nested.md"].sort());
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
});
4 changes: 2 additions & 2 deletions docs/i18n/README.ar.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@

## واجهات سطر الأوامر للعملاء المدعومة

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.de.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ bevor sie zu Vorfällen werden. Nulllatenz. Läuft lokal.

## Unterstützte Agenten-CLIs

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ antes de que se conviertan en incidentes. Latencia cero. Se ejecuta localmente.

## CLIs de agentes compatibles

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ avant qu'ils ne deviennent des incidents. Zéro latence. Fonctionne en local.

## CLI d'agents pris en charge

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.he.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@

## ממשקי CLI של סוכנים נתמכים

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.hi.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ Claude Code और Codex में हुक करता है। लूप्

## समर्थित एजेंट CLIs

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.it.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ prima che diventino incidenti. Zero latenza. Eseguito localmente.

## CLI agenti supportati

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ Claude Code および Codex にフックし、ループ・危険な操作・シ

## 対応エージェント CLI

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ Claude Code 및 Codex에 훅으로 연결됩니다. 루프, 위험한 작업,

## 지원되는 에이전트 CLI

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.pt-br.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ antes que se tornem incidentes. Latência zero. Executa localmente.

## CLIs de agentes suportados

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@

## Поддерживаемые CLI агентов

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.tr.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ olay haline gelmeden yakalar. Sıfır gecikme. Yerel olarak çalışır.

## Desteklenen ajan CLIleri

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.vi.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ trước khi chúng trở thành sự cố. Không độ trễ. Chạy cục b

## Các CLI agent được hỗ trợ

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
4 changes: 2 additions & 2 deletions docs/i18n/README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@

## 支持的 Agent CLI

<!-- A 6-column table instead of inline <img> runs: table columns never re-wrap,
{/* A 6-column table instead of inline <img> runs: table columns never re-wrap,
so the grid stays 2×6 at any window width (scrolling on very narrow screens
instead of collapsing into ragged orphan rows). -->
instead of collapsing into ragged orphan rows). */}
<table align="center">
<tr>
<td align="center" width="96">
Expand Down
Loading