diff --git a/.agents/skills/openclaw-carapace/SKILL.md b/.agents/skills/openclaw-carapace/SKILL.md index 3b8ec9e11..7a944f8d6 100644 --- a/.agents/skills/openclaw-carapace/SKILL.md +++ b/.agents/skills/openclaw-carapace/SKILL.md @@ -13,11 +13,12 @@ Keep consumer-specific behavior, data, routes, and layout composition local. 1. Read [tokens.md](references/tokens.md) before choosing colors, spacing, type, radii, or shadows. 2. Read [consumer-adapters.md](references/consumer-adapters.md) for the current framework. 3. Read [application-surfaces.md](references/application-surfaces.md) when working on shells, panes, settings, or operational screens. -4. Read [embedded-surfaces.md](references/embedded-surfaces.md) when the surface renders inside a host frame, such as an MCP app. -5. Inspect the consumer's existing shared primitives before creating a component. -6. Use semantic tokens for UI intent; use palette primitives only for documented exceptions. -7. Keep application behavior, routes, and information architecture unchanged unless the task says otherwise. -8. Validate the affected routes with existing tests and real browser screenshots. +4. Read [terminal-ui.md](references/terminal-ui.md) when designing or auditing a terminal interface. +5. Read [embedded-surfaces.md](references/embedded-surfaces.md) when the surface renders inside a host frame, such as an MCP app. +6. Inspect the consumer's existing shared primitives before creating a component. +7. Use semantic tokens for UI intent; use palette primitives only for documented exceptions. +8. Keep application behavior, routes, and information architecture unchanged unless the task says otherwise. +9. Validate the affected routes with existing tests and real browser screenshots. ## Interface Rules diff --git a/.agents/skills/openclaw-carapace/references/terminal-ui.md b/.agents/skills/openclaw-carapace/references/terminal-ui.md new file mode 100644 index 000000000..da235177e --- /dev/null +++ b/.agents/skills/openclaw-carapace/references/terminal-ui.md @@ -0,0 +1,193 @@ +# Terminal UI + +Carapace documents terminal translations of its existing design language. The +terminal consumer keeps runtime behavior, ANSI rendering, keybindings, +commands, session state, and framework adapters. + +Browser specimens use the runtime as their source of truth. Run the real +OpenClaw Pi or Clack component in a fixed-size PTY, capture its output bytes +with `@openclaw/libterminal`, and replay those bytes through libterminal's +Ghostty WASM renderer. Use HTML only for documentation around the terminal. +Never redraw a terminal specimen with HTML elements or browser controls. + +The current reference covers both OpenClaw terminal compositions: + +- the retained agent TUI on `@earendil-works/pi-tui@0.81.1` +- onboarding and command setup on `@clack/prompts@1.7.0` + +Re-audit OpenClaw, Pi, and Clack before treating version-specific behavior as +current. + +## Reuse first + +Use existing Carapace Colors, Typography, Layout, Motion, Base styles, inputs, +selections, approvals, loaders, flows, and Agent Components. Terminal UI adds +only terminal-specific constraints: ANSI and cell width, the host foreground +and font, focus and cursor ownership, scrollback/history, and row/column limits. + +Do not create a TUI palette, typography scale, CSS export, component package, or +second renderer. + +## Structure + +Model the agent TUI as one vertical conversation buffer: + +1. header identity +2. transcript rows and work cards +3. connection and activity status +4. session footer +5. focused editor + +Pickers, settings, consent, approvals, and task suggestions are transient +focus-capturing overlays. Help, command feedback, local-shell output, and most +errors return to the transcript; do not present them as separate screens. + +Model setup as one append-only guide with a single active prompt. Completed +ordinary answers collapse into history; notes and progress preserve context; +intro, outro, and cancellation visibly close the guide. + +## Visual roles + +- Preserve assistant prose in the terminal's default foreground. +- Use a neutral inset surface for user-authored turns. +- Keep system notices muted and inline. +- Use primary accent for the active choice or explicit confirmation. +- Use secondary accent for focus, connection, and current context. +- Reserve success, warning, and error colors for outcomes. +- Pair every colored state with text, a glyph, ordering, or another non-color + signal. +- Do not infer severity colors when the consumer currently renders severity as + text metadata. + +Carapace's browser specimens may map these relationships to coral, sea, and +semantic status roles. That mapping is documentation, not an exported ANSI +theme API. + +## Reference tokens + +The Terminal UI Lab keeps a small reference token map for relationships shared +by the audited Clack and Pi surfaces. It is design guidance and preview input, +not a published component or token package. + +- Terminal color roles alias the existing Carapace background, text, accent, + status, and monospace-font variables. Do not add terminal-only colors. +- `terminal.space.marker-label` is the one-cell gap between a marker and label. +- `terminal.space.leading-prefix` is the two-cell guide, focus, or selection + prefix before content. +- `terminal.viewport.compact` is 40 columns. +- `terminal.viewport.standard` is 80 columns. +- `terminal.viewport.reference` is 120 columns and drives canonical captures. + +The viewport values are validation profiles, not component dimensions. A +terminal implementation must still fit the column count supplied by its +runtime. + +## Cells and width + +- Design and test in terminal columns and rows, not browser pixels. +- Ensure every rendered line fits its supplied width after ANSI sequences are + ignored. +- Preserve grapheme clusters, ANSI styles, and OSC 8 links when wrapping or + truncating. +- Remove optional descriptions before labels, selection prefixes, or actions. +- Bound long output and name omitted content; expansion behavior stays in the + consumer. +- Treat consumer-specific line, item, and output limits as audited facts, not + Terminal UI tokens. + +## Setup prompts + +- Keep text, sensitive text, select, multiselect, searchable variants, confirm, + and progress within one connected guide. +- Keep validation next to the active value or list. +- Mask sensitive input, omit it from submitted history, and never cache it for + replay. +- Preserve the focused option when clipping long lists. Remove descriptions + before labels, selection markers, or actions. +- Keep option anatomy explicit: marker, human label, stable value, annotation, + optional description, and availability reason. `current`, `default`, + `selected`, `recommended`, and `configured` are separate meanings; do not + collapse them into one state. +- At wide widths, concise metadata may follow the label. At narrow widths, move + metadata to a second line and remove optional description before identity or + status. +- Show Back and Next only when available. Next accepts a remembered answer + without replaying output or side effects. +- Disable Back after irreversible work instead of rerunning unsafe steps. +- Use notes for framed human context and plain output for raw disclosure. + +## Input and decisions + +- The focused surface owns Enter, Escape, arrows, paging, and confirmation. +- Propagate focus to embedded text inputs so hardware-cursor and IME placement + remain correct. +- Keep a conservative action selected first when one is available. +- Require an explicit second commit for privileged or costly actions. +- Changing selection disarms confirmation. +- Name the consequence in the confirmation sentence. +- Preserve visible stale, expired, denied, accepted, dismissed, and failed + outcomes. +- Keep one active decision at a time even when the runtime can stack overlays. + +Simple setup confirmation can render inline or vertically. Detailed agent +approvals may use overlays and an explicit arm-then-commit sequence. Label +specimens by renderer instead of implying that Pi and Clack are one component +implementation. + +## Approvals + +Treat an approval as a bounded authorization surface, not a verbose +confirmation. Show the approval family and requested action first, then +severity, owner metadata, request context, the allowed decision set, and the +eventual outcome. + +- Render only decisions supplied by the request. Never invent persistent + authorization when `allow-always` is unavailable. +- Focus Deny first whenever it is available. Escape resolves Deny in that + case; an allow-only prompt dismisses without authorizing and remains pending. +- `Allow once` authorizes the current request. `Always allow` authorizes only + the matching future scope defined by the owner and must name that persistence + clearly. +- Require a visible second commit when an allow action starts focused. Moving + to another decision clears the armed state. +- Sanitize untrusted title, description, tool, and plugin text before terminal + rendering. Preserve bidi, ANSI, OSC, and control-sequence defenses. +- Return allowed, denied, dismissed, expired, stale, and failed outcomes to the + transcript. Do not silently close the overlay or imply that dismissal denied + an allow-only request. +- Queue one session-matching request at a time. Resolution from another client + closes the local overlay and records that the request is no longer pending. + +## Ownership + +Use the existing terminal runtime. Do not introduce a second renderer, copy its +width or focus algorithms into Carapace, import browser CSS into an ANSI +surface, or publish a terminal component API from one consumer's implementation. + +Markup sections may show Carapace's standalone copy-and-paste libterminal +replay interface. They must not present local Pi classes, WizardPrompter calls, +or partial Clack excerpts as reusable Carapace components. Link those audited +OpenClaw sources as implementation evidence instead. + +Keep the Carapace Terminal UI area in Lab until a second terminal consumer +proves a shared reusable interface. Cross-link existing Carapace pages for +medium-neutral semantics; Terminal UI owns only the translation into cells, +terminal focus, ANSI, scrollback/history, and terminal compositions. + +## Validation + +- Verify comfortable, narrow, and short terminal sizes with real PTY proof. +- Verify light and dark theme relationships. +- Verify idle, streaming, tool success/error, approval, task suggestion, and + picker states. +- Verify onboarding intro/outro/cancel, ordinary and sensitive fields, + validation, select/multiselect/searchable variants, inline/vertical confirm, + progress, remembered answers, replay suppression, and irreversible + boundaries. +- Verify Enter and Escape precedence across editor, inline result, active run, + filter, and overlay scopes. +- Verify state remains understandable without color. +- Regenerate the libterminal fixtures from the audited OpenClaw revision before + updating a specimen. +- Use browser screenshots to validate Carapace reference pages, not as proof of + the terminal runtime; the captured PTY bytes are the runtime evidence. diff --git a/.github/scripts/i18n/tests/test_i18n_scripts.py b/.github/scripts/i18n/tests/test_i18n_scripts.py index b1df00af8..3f120fc6e 100644 --- a/.github/scripts/i18n/tests/test_i18n_scripts.py +++ b/.github/scripts/i18n/tests/test_i18n_scripts.py @@ -436,7 +436,7 @@ def test_translation_workflows_pin_latest_codex_and_tier_effort(self) -> None: full = (REPO_ROOT / ".github/workflows/translate-all.yml").read_text(encoding="utf-8") incremental = (REPO_ROOT / ".github/workflows/translate-incremental.yml").read_text(encoding="utf-8") - self.assertIn("npm install -g @openai/codex@0.144.4", reusable) + self.assertIn("npm install -g @openai/codex@0.146.0", reusable) self.assertIn("effort: xhigh", reusable) self.assertNotIn("effort: max", reusable) self.assertEqual(1, full.count('thinking_effort: "xhigh"')) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4d432b8ab..9dbf8290e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -29,12 +29,12 @@ jobs: uses: actions/checkout@v7.0.1 - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.2 + uses: github/codeql-action/init@v4.37.4 with: languages: ${{ matrix.language }} build-mode: none - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4.37.2 + uses: github/codeql-action/analyze@v4.37.4 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/docs-code-ci.yml b/.github/workflows/docs-code-ci.yml index e0e4d5ea0..f2098e60b 100644 --- a/.github/workflows/docs-code-ci.yml +++ b/.github/workflows/docs-code-ci.yml @@ -56,7 +56,7 @@ jobs: run: npm test - name: Validate Worker bundle - run: npx wrangler@4.88.0 deploy --dry-run --config wrangler.toml + run: npx wrangler@4.118.0 deploy --dry-run --config wrangler.toml - name: Build shell artifact run: npm run docs:build:r2:shell diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 83a03d419..0828a6274 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -53,7 +53,7 @@ jobs: run: npm ci - name: Validate Worker bundle - run: npx wrangler@4.88.0 deploy --dry-run --config wrangler.toml + run: npx wrangler@4.118.0 deploy --dry-run --config wrangler.toml - name: Deploy to Cloudflare if: github.event_name == 'workflow_dispatch' && inputs.deploy_worker == true @@ -61,7 +61,7 @@ jobs: CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} run: | - npx wrangler@4.88.0 deploy --config wrangler.toml \ + npx wrangler@4.118.0 deploy --config wrangler.toml \ --tag "${GITHUB_SHA::12}" \ --message "openclaw/docs ${GITHUB_SHA}" diff --git a/.github/workflows/r2-pages.yml b/.github/workflows/r2-pages.yml index 8a18f30da..55bf688c0 100644 --- a/.github/workflows/r2-pages.yml +++ b/.github/workflows/r2-pages.yml @@ -357,7 +357,7 @@ jobs: CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} run: | - npx wrangler@4.88.0 deploy --config wrangler.toml \ + npx wrangler@4.118.0 deploy --config wrangler.toml \ --tag "${GITHUB_SHA::12}" \ --message "openclaw/docs ${GITHUB_SHA}" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 8a1945b78..56e729d0f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -4,6 +4,11 @@ on: schedule: - cron: "43 4 * * *" workflow_dispatch: + inputs: + debug_only: + description: Run without changing issues or pull requests + type: boolean + default: false permissions: {} @@ -15,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Mark stale unassigned issues and pull requests - uses: actions/stale@v10.4.0 + uses: actions/stale@v11.0.0 with: days-before-issue-stale: 14 days-before-issue-close: 7 @@ -26,6 +31,7 @@ jobs: exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale exempt-pr-labels: maintainer,no-stale operations-per-run: 1000 + debug-only: ${{ inputs.debug_only || false }} ascending: true exempt-all-assignees: true remove-stale-when-updated: true @@ -44,7 +50,7 @@ jobs: If this PR should be revived, reopen it with current context and validation. - name: Mark stale assigned issues - uses: actions/stale@v10.4.0 + uses: actions/stale@v11.0.0 with: days-before-issue-stale: 30 days-before-issue-close: 10 @@ -53,6 +59,7 @@ jobs: stale-issue-label: stale exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale operations-per-run: 1000 + debug-only: ${{ inputs.debug_only || false }} ascending: true include-only-assigned: true remove-stale-when-updated: true @@ -65,7 +72,7 @@ jobs: close-issue-reason: not_planned - name: Mark stale assigned pull requests - uses: actions/stale@v10.4.0 + uses: actions/stale@v11.0.0 with: days-before-issue-stale: -1 days-before-issue-close: -1 @@ -74,6 +81,7 @@ jobs: stale-pr-label: stale exempt-pr-labels: maintainer,no-stale operations-per-run: 1000 + debug-only: ${{ inputs.debug_only || false }} ascending: true include-only-assigned: true ignore-pr-updates: true diff --git a/.github/workflows/translate-locale-reusable.yml b/.github/workflows/translate-locale-reusable.yml index 098dd2ed2..b7ba98b08 100644 --- a/.github/workflows/translate-locale-reusable.yml +++ b/.github/workflows/translate-locale-reusable.yml @@ -142,7 +142,7 @@ jobs: - name: Install Codex CLI if: steps.stale.outputs.skip != 'true' - run: npm install -g @openai/codex@0.144.4 + run: npm install -g @openai/codex@0.146.0 - name: Prune stale locale pages if: steps.stale.outputs.skip != 'true' diff --git a/package-lock.json b/package-lock.json index 48e098f1e..ecfe02371 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,18 +6,18 @@ "": { "name": "openclaw-docs-site", "dependencies": { - "@openclaw/carapace": "git+https://github.com/openclaw/carapace.git#v0.2.0" + "@openclaw/carapace": "git+https://github.com/openclaw/carapace.git#v0.6.1" }, "devDependencies": { "@mdx-js/mdx": "3.1.1", "@resvg/resvg-js": "^2.6.2", "highlight.js": "11.11.1", - "lucide": "1.25.0", - "markdown-it": "14.3.0", + "lucide": "1.28.0", + "markdown-it": "15.0.0", "markdown-it-anchor": "9.2.1", "mermaid": "11.16.0", "pagefind": "1.5.2", - "playwright": "^1.61.1", + "playwright": "^1.62.1", "yaml": "2.9.0" } }, @@ -117,8 +117,9 @@ } }, "node_modules/@openclaw/carapace": { - "version": "0.2.0", - "resolved": "git+ssh://git@github.com/openclaw/carapace.git#eca45706190e98a07434a40f8a39b0ed89258930", + "version": "0.6.1", + "resolved": "git+ssh://git@github.com/openclaw/carapace.git#6c64d6b67edf169c32a452ce8ccdbec65a75bab3", + "integrity": "sha512-ecQGw60gyUljuuWZfnKt1vvUnrUq1KpXLmzo7+g/3QwTi7U8xpNykFrHtF1Qql6zMA4aikJCnKDwIQCZGlzT4g==", "license": "MIT", "engines": { "bun": ">=1.3.0" @@ -899,10 +900,20 @@ } }, "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.0.tgz", + "integrity": "sha512-BOp5NMrHqKxmq/OLr+clzzrRxgOKSLkcjmkWuChp7Irqwn4s74WjOBPIgWfA/HMcBnVkZ5XEuf9uUqzlpfCQ6A==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "Python-2.0" }, "node_modules/astring": { @@ -1648,13 +1659,13 @@ } }, "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" @@ -2056,9 +2067,9 @@ "license": "MIT" }, "node_modules/linkify-it": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", - "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-6.1.0.tgz", + "integrity": "sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==", "dev": true, "funding": [ { @@ -2072,7 +2083,7 @@ ], "license": "MIT", "dependencies": { - "uc.micro": "^2.0.0" + "uc.micro": "^3.0.0" } }, "node_modules/lodash-es": { @@ -2094,9 +2105,9 @@ } }, "node_modules/lucide": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/lucide/-/lucide-1.25.0.tgz", - "integrity": "sha512-Pg/9Ga1xTbrnI6GY/7J9krIYmJIkAf3PkK6wPmsAeUtAQsBdGxs1+dfvLqjf9nPI5aFm9+VquT75JGpO3QXSpQ==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/lucide/-/lucide-1.28.0.tgz", + "integrity": "sha512-sxVxWEXfq7rRNzmffDBRohYBOFjfoOhrO7jGGCLNNRoY2fPjeuqi2boXR2UAROEyQUm+xe13DGOQNtnmwv6Y3w==", "dev": true, "license": "ISC" }, @@ -2114,9 +2125,9 @@ } }, "node_modules/markdown-it": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz", - "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-15.0.0.tgz", + "integrity": "sha512-Lf8ajvVNdRpzSNB4VegxNy7gjs8gU35l4b4+ET49LrQC5PKYwLZ72u60LeJ9gv3qiaesuYjJWCyVeQmv/QWKQw==", "dev": true, "funding": [ { @@ -2130,12 +2141,12 @@ ], "license": "MIT", "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.5.0", - "linkify-it": "^5.0.2", - "mdurl": "^2.0.0", + "argparse": "^3.0.0", + "entities": "^8.0.0", + "linkify-it": "^6.0.0", + "mdurl": "^2.1.0", "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" + "uc.micro": "^3.0.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" @@ -2345,9 +2356,9 @@ } }, "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", + "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", "dev": true, "license": "MIT" }, @@ -3073,35 +3084,35 @@ "license": "MIT" }, "node_modules/playwright": { - "version": "1.61.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", - "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.61.1" + "playwright-core": "1.62.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.61.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", - "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/points-on-curve": { @@ -3420,9 +3431,9 @@ } }, "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-3.0.0.tgz", + "integrity": "sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index aa8bd8ef6..e5217fcae 100644 --- a/package.json +++ b/package.json @@ -16,22 +16,22 @@ "docs:smoke:shell": "DOCS_SITE_ARTIFACT_MODE=shell node scripts/docs-site/smoke.mjs", "docs:visual": "node scripts/docs-site/visual-smoke.mjs", "docs:check": "npm run docs:build && npm run docs:smoke && npm run docs:visual && node --check scripts/docs-site/llms-full.mjs", - "skills:install": "npx --yes skills@1.5.15 add openclaw/carapace --skill openclaw-design openclaw-brand openclaw-carapace openclaw-design-system openclaw-marketing-pages openclaw-design-audit --agent codex --copy --yes", + "skills:install": "npx --yes skills@1.5.21 add openclaw/carapace --skill openclaw-design openclaw-brand openclaw-carapace openclaw-design-system openclaw-marketing-pages openclaw-design-audit --agent codex --copy --yes", "test": "node --test scripts/docs-site/*.test.mjs" }, "devDependencies": { "@mdx-js/mdx": "3.1.1", "@resvg/resvg-js": "^2.6.2", "highlight.js": "11.11.1", - "lucide": "1.25.0", - "markdown-it": "14.3.0", + "lucide": "1.28.0", + "markdown-it": "15.0.0", "markdown-it-anchor": "9.2.1", "mermaid": "11.16.0", "pagefind": "1.5.2", - "playwright": "^1.61.1", + "playwright": "^1.62.1", "yaml": "2.9.0" }, "dependencies": { - "@openclaw/carapace": "git+https://github.com/openclaw/carapace.git#v0.2.0" + "@openclaw/carapace": "git+https://github.com/openclaw/carapace.git#v0.6.1" } } diff --git a/scripts/docs-site/assets.mjs b/scripts/docs-site/assets.mjs index be4de688f..5c42f45c2 100644 --- a/scripts/docs-site/assets.mjs +++ b/scripts/docs-site/assets.mjs @@ -135,7 +135,9 @@ const mermaidCloseIcon='"} function removeMermaidRenderArtifact(id){document.getElementById("d"+id)?.remove();const svg=document.getElementById(id);if(svg&&!svg.closest("[data-mermaid]"))svg.remove()} -function mermaidOptions(){const styles=getComputedStyle(root);return {startOnLoad:false,securityLevel:"strict",theme:root.dataset.theme==="light"?"base":"dark",themeVariables:{fontFamily:'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',primaryColor:styles.getPropertyValue("--paper").trim(),primaryTextColor:styles.getPropertyValue("--ink").trim(),primaryBorderColor:styles.getPropertyValue("--line-strong").trim(),lineColor:styles.getPropertyValue("--muted").trim(),actorBorder:styles.getPropertyValue("--brand").trim(),actorBkg:styles.getPropertyValue("--paper-2").trim(),actorTextColor:styles.getPropertyValue("--ink").trim(),signalColor:styles.getPropertyValue("--brand").trim(),signalTextColor:styles.getPropertyValue("--ink").trim()}}} +// Mermaid's color parser cannot consume CSS Color 4 values such as OKLCH. +function mermaidColor(styles,name){const value=styles.getPropertyValue(name).trim();if(!value||!CSS.supports("color",value))return value;const canvas=document.createElement("canvas");canvas.width=canvas.height=1;const context=canvas.getContext("2d",{willReadFrequently:true});if(!context)return value;context.fillStyle=value;context.fillRect(0,0,1,1);const [r,g,b,a]=context.getImageData(0,0,1,1).data;return a===255?"rgb("+r+", "+g+", "+b+")":"rgba("+r+", "+g+", "+b+", "+a/255+")"} +function mermaidOptions(){const styles=getComputedStyle(root);return {startOnLoad:false,securityLevel:"strict",theme:root.dataset.theme==="light"?"base":"dark",themeVariables:{fontFamily:'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',primaryColor:mermaidColor(styles,"--paper"),primaryTextColor:mermaidColor(styles,"--ink"),primaryBorderColor:mermaidColor(styles,"--line-strong"),lineColor:mermaidColor(styles,"--muted"),actorBorder:mermaidColor(styles,"--brand"),actorBkg:mermaidColor(styles,"--paper-2"),actorTextColor:mermaidColor(styles,"--ink"),signalColor:mermaidColor(styles,"--brand"),signalTextColor:mermaidColor(styles,"--ink")}}} async function renderMermaidSvg(source,renderId){const mermaid=await (mermaidReady??=import(withBase("/assets/mermaid.esm.min.mjs")).then(module=>module.default));mermaid.initialize(mermaidOptions());return mermaid.render(renderId,source)} function mermaidExpandButton(){return '
'} function ensureMermaidOverlay(){let overlay=document.querySelector("[data-mermaid-overlay]");if(overlay)return overlay;overlay=document.createElement("div");overlay.className="oc-mermaid-overlay";overlay.dataset.mermaidOverlay="";overlay.setAttribute("role","dialog");overlay.setAttribute("aria-modal","true");overlay.setAttribute("aria-label","Expanded diagram");overlay.innerHTML='
';document.body.appendChild(overlay);return overlay} diff --git a/scripts/docs-site/smoke.mjs b/scripts/docs-site/smoke.mjs index 959eea456..41f137a8a 100644 --- a/scripts/docs-site/smoke.mjs +++ b/scripts/docs-site/smoke.mjs @@ -358,6 +358,11 @@ if (!fs.existsSync(path.join(site, "assets/mermaid.esm.min.mjs")) || !fs.existsSync(path.join(site, "assets/chunks/mermaid.esm.min"))) { throw new Error("assets: Mermaid runtime was not copied"); } +if (!/function mermaidColor/.test(siteJs) + || !/getImageData\(0,0,1,1\)/.test(siteJs) + || !/primaryColor:mermaidColor/.test(siteJs)) { + throw new Error("assets: Mermaid theme colors are not normalized for its legacy color parser"); +} if (!/\.sidebar\{[^}]*padding:0 6px var\(--oc-space-8\) 0;[^}]*scrollbar-gutter:stable/.test(siteCss)) { throw new Error("assets: sidebar scroll-end padding is missing"); } diff --git a/skills-lock.json b/skills-lock.json index f7cba423c..8c2dca30a 100644 --- a/skills-lock.json +++ b/skills-lock.json @@ -11,7 +11,7 @@ "source": "openclaw/carapace", "sourceType": "github", "skillPath": "openclaw-carapace/SKILL.md", - "computedHash": "ce95a22199ccdce22ca392f3b6bbf9903cdbd611f8879e74b8378f28439d0b25" + "computedHash": "6d7a33003875107ab35d4ac978753cc95b38b38aaaa306ae3db54f935d5451f7" }, "openclaw-design": { "source": "openclaw/carapace",