@xiaobuyu/nodesign 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +140 -0
- package/bin/nodesign.js +176 -0
- package/package.json +104 -0
- package/server/api/README.md +45 -0
- package/server/api/_guard.js +75 -0
- package/server/api/admin.js +187 -0
- package/server/api/assets/docx-page.js +103 -0
- package/server/api/assets/helpers.js +22 -0
- package/server/api/assets/notes.js +144 -0
- package/server/api/assets.js +896 -0
- package/server/api/board.js +57 -0
- package/server/api/browse.js +138 -0
- package/server/api/canvas.js +444 -0
- package/server/api/chatai.js +324 -0
- package/server/api/exports/build-standalone.js +980 -0
- package/server/api/exports/cards.js +118 -0
- package/server/api/exports/docx-pdf.js +46 -0
- package/server/api/exports/export-page.js +142 -0
- package/server/api/exports/handoff.js +147 -0
- package/server/api/exports.js +690 -0
- package/server/api/instruction.js +75 -0
- package/server/api/local.js +115 -0
- package/server/api/me.js +116 -0
- package/server/api/memory.js +185 -0
- package/server/api/pending-changes.js +366 -0
- package/server/api/plugins.js +164 -0
- package/server/api/projects.js +220 -0
- package/server/api/publish.js +64 -0
- package/server/api/recent.js +73 -0
- package/server/api/sessions.js +589 -0
- package/server/api/skills.js +77 -0
- package/server/api/standalone-fit.js +168 -0
- package/server/api/turn-compose.js +180 -0
- package/server/api/turn-inflight.js +44 -0
- package/server/api/turn.js +669 -0
- package/server/auth/README.md +17 -0
- package/server/auth/middleware.js +138 -0
- package/server/auth/origin-guard.js +71 -0
- package/server/auth/session.js +108 -0
- package/server/auth/tier.js +113 -0
- package/server/auth/users-store.js +348 -0
- package/server/edit/README.md +29 -0
- package/server/engine/README.md +113 -0
- package/server/engine/agent/agent-shared.js +550 -0
- package/server/engine/agent/auto-mode-default-hard-deny.txt +4 -0
- package/server/engine/agent/auto-mode-rules.js +78 -0
- package/server/engine/agent/context.js +418 -0
- package/server/engine/agent/events.js +464 -0
- package/server/engine/agent/hooks/canvas-validate.js +199 -0
- package/server/engine/agent/hooks/failure.js +120 -0
- package/server/engine/agent/hooks/file-events.js +75 -0
- package/server/engine/agent/hooks/lifecycle.js +233 -0
- package/server/engine/agent/hooks/post-canvas-focus.js +80 -0
- package/server/engine/agent/hooks/post-guidance.js +206 -0
- package/server/engine/agent/hooks/post-subagent-report.js +104 -0
- package/server/engine/agent/hooks/post-trim.js +58 -0
- package/server/engine/agent/hooks/pre-board-neighborhood.js +34 -0
- package/server/engine/agent/hooks/pre-defaults.js +84 -0
- package/server/engine/agent/hooks/pre-injectors.js +277 -0
- package/server/engine/agent/hooks/pre-performance-log-guard.js +78 -0
- package/server/engine/agent/hooks/pre-starter-files.js +61 -0
- package/server/engine/agent/hooks/pre-workspace-scope-guard.js +78 -0
- package/server/engine/agent/hooks/site-validate.js +94 -0
- package/server/engine/agent/hooks/tool-prompts.js +31 -0
- package/server/engine/agent/hooks/turn-state-memory.js +56 -0
- package/server/engine/agent/hooks/user-prompt-submit.js +215 -0
- package/server/engine/agent/hooks.js +354 -0
- package/server/engine/agent/init-contract.js +69 -0
- package/server/engine/agent/isolation.js +159 -0
- package/server/engine/agent/model-context.js +359 -0
- package/server/engine/agent/model-table.js +292 -0
- package/server/engine/agent/plugin-loader.js +266 -0
- package/server/engine/agent/prompts/nodesign-prelude.md +336 -0
- package/server/engine/agent/prompts/tools/ask-user-question-protocol.md +71 -0
- package/server/engine/agent/prompts/tools/direct-edit-protocol.md +98 -0
- package/server/engine/agent/prompts/tools/generate-image-cookbook.gemini-gateway.md +583 -0
- package/server/engine/agent/prompts/tools/generate-image-cookbook.md +483 -0
- package/server/engine/agent/prompts/tools/hybrid-reference.md +100 -0
- package/server/engine/agent/prompts/tools/paint-still-cookbook.md +270 -0
- package/server/engine/agent/prompts/tools/roll-film-cookbook.md +70 -0
- package/server/engine/agent/prompts/tools/site-reference.md +106 -0
- package/server/engine/agent/prompts/tools/tweaks-syntax.md +125 -0
- package/server/engine/agent/prompts/tools/vision-checker-dispatch.md +48 -0
- package/server/engine/agent/session-loop.js +1024 -0
- package/server/engine/agent/session-model.js +164 -0
- package/server/engine/agent/skill.js +204 -0
- package/server/engine/agent/system-prompts.js +86 -0
- package/server/engine/agent/task-events.js +78 -0
- package/server/engine/agents/ds-extractor.md +132 -0
- package/server/engine/agents/explorer.md +190 -0
- package/server/engine/agents/index.js +230 -0
- package/server/engine/agents/schemas/design-system.json +156 -0
- package/server/engine/agents/schemas/tweak-schema.json +113 -0
- package/server/engine/agents/tweak-proposer.md +127 -0
- package/server/engine/agents/vision-checker.md +254 -0
- package/server/engine/browse/capture.js +422 -0
- package/server/engine/browse/card.js +137 -0
- package/server/engine/browse/handover.js +59 -0
- package/server/engine/browse/page-digest.js +119 -0
- package/server/engine/browse/refs.js +196 -0
- package/server/engine/browse/registry.js +307 -0
- package/server/engine/browse/screencast.js +170 -0
- package/server/engine/browse/state.js +121 -0
- package/server/engine/chatai/chat-log.js +79 -0
- package/server/engine/chatai/index.js +193 -0
- package/server/engine/chatai/openai-compat.js +152 -0
- package/server/engine/chatai/orchestrate.js +309 -0
- package/server/engine/chatai/perform.js +40 -0
- package/server/engine/chatai/summarize.js +79 -0
- package/server/engine/mcp/capability-gate.js +52 -0
- package/server/engine/mcp/index.js +339 -0
- package/server/engine/mcp/param-sanitizer.js +142 -0
- package/server/engine/mcp/tools/arrange-on-board.js +124 -0
- package/server/engine/mcp/tools/artifact-session.js +278 -0
- package/server/engine/mcp/tools/browse-computer.js +421 -0
- package/server/engine/mcp/tools/browse-find-batch.js +183 -0
- package/server/engine/mcp/tools/browse-screenshot.js +157 -0
- package/server/engine/mcp/tools/browse.js +480 -0
- package/server/engine/mcp/tools/build-docx.js +101 -0
- package/server/engine/mcp/tools/clear-pending-changes.js +99 -0
- package/server/engine/mcp/tools/create-on-board.js +155 -0
- package/server/engine/mcp/tools/crystallize-skill.js +168 -0
- package/server/engine/mcp/tools/deliver-files.js +0 -0
- package/server/engine/mcp/tools/explain-style.js +237 -0
- package/server/engine/mcp/tools/export-handoff.js +133 -0
- package/server/engine/mcp/tools/expose-tweaks.js +149 -0
- package/server/engine/mcp/tools/generate-image.js +842 -0
- package/server/engine/mcp/tools/get-computed-styles.js +164 -0
- package/server/engine/mcp/tools/get-pending-changes.js +205 -0
- package/server/engine/mcp/tools/h3box-ssh.js +84 -0
- package/server/engine/mcp/tools/helpers/acquire-page.js +82 -0
- package/server/engine/mcp/tools/helpers/motion-lab.js +554 -0
- package/server/engine/mcp/tools/helpers/motion-scroll.js +112 -0
- package/server/engine/mcp/tools/helpers/perception-page.js +215 -0
- package/server/engine/mcp/tools/helpers/reference-download.js +103 -0
- package/server/engine/mcp/tools/helpers/rembg-bridge.py +80 -0
- package/server/engine/mcp/tools/helpers/rembg.js +273 -0
- package/server/engine/mcp/tools/helpers/shot-pipeline.js +280 -0
- package/server/engine/mcp/tools/highlight.js +68 -0
- package/server/engine/mcp/tools/list-pages.js +222 -0
- package/server/engine/mcp/tools/lookup-tags.js +59 -0
- package/server/engine/mcp/tools/navigate-to-page.js +60 -0
- package/server/engine/mcp/tools/organize-board.js +64 -0
- package/server/engine/mcp/tools/paint-still.js +434 -0
- package/server/engine/mcp/tools/pin-to-board.js +130 -0
- package/server/engine/mcp/tools/preview-deck.js +130 -0
- package/server/engine/mcp/tools/profile-scroll.js +305 -0
- package/server/engine/mcp/tools/publish-site.js +102 -0
- package/server/engine/mcp/tools/query-elements.js +195 -0
- package/server/engine/mcp/tools/read-board.js +103 -0
- package/server/engine/mcp/tools/read-document.js +93 -0
- package/server/engine/mcp/tools/read-page.js +264 -0
- package/server/engine/mcp/tools/read-tavern-json.js +143 -0
- package/server/engine/mcp/tools/record-decision.js +140 -0
- package/server/engine/mcp/tools/relate-on-board.js +110 -0
- package/server/engine/mcp/tools/remove-background.js +391 -0
- package/server/engine/mcp/tools/report-issue.js +115 -0
- package/server/engine/mcp/tools/roll-film.js +266 -0
- package/server/engine/mcp/tools/screenshot-docx.js +138 -0
- package/server/engine/mcp/tools/screenshot-url.js +195 -0
- package/server/engine/mcp/tools/screenshot.js +583 -0
- package/server/engine/mcp/tools/tier-gate.js +96 -0
- package/server/engine/mcp/tools/trace-motion.js +215 -0
- package/server/engine/mcp/tools/web-search.js +548 -0
- package/server/engine/motion/inventory.js +349 -0
- package/server/engine/perception/session.js +235 -0
- package/server/engine/plugins/nodesign/.claude-plugin/plugin.json +5 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/SKILL.md +192 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/canvas.template.html +667 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/hybrid-grid.md +22 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/image-led-cover.md +25 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/portrait.md +23 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/quote-backdrop.md +21 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/section-divider.md +23 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/text-led.md +21 -0
- package/server/engine/plugins/nodesign/skills/docx-craft/SKILL.md +162 -0
- package/server/engine/plugins/nodesign/skills/docx-craft/references/token-schema.md +407 -0
- package/server/engine/plugins/nodesign/skills/docx-craft//346/226/207/346/241/243.template.json +80 -0
- package/server/engine/plugins/nodesign/skills/rp-craft/SKILL.md +228 -0
- package/server/engine/plugins/nodesign/skills/rp-craft/patterns//346/274/224/345/207/272/351/241/265-/346/234/200/345/260/217/345/256/236/347/216/260.html +78 -0
- package/server/engine/plugins/nodesign/skills/rp-craft//346/274/224/345/207/272.template.js +268 -0
- package/server/engine/plugins/nodesign/skills/site-craft/SKILL.md +323 -0
- package/server/engine/plugins/nodesign/skills/site-craft/patterns/build-lane.md +134 -0
- package/server/engine/plugins/nodesign/skills/site-craft/patterns/cutout-collage.md +61 -0
- package/server/engine/plugins/nodesign/skills/site-craft/patterns/mock-app.md +163 -0
- package/server/engine/plugins/nodesign/skills/site-craft/patterns/page-transitions.md +86 -0
- package/server/engine/runs/active-runs.js +698 -0
- package/server/engine/runs/live-turn.js +252 -0
- package/server/engine/runs/store.js +364 -0
- package/server/engine/runs/turn-relay.js +217 -0
- package/server/engine/runtime/workspace.js +164 -0
- package/server/index.js +235 -0
- package/server/lib/artifact-file-path.js +80 -0
- package/server/lib/artifact-target.js +284 -0
- package/server/lib/asset-refs.js +239 -0
- package/server/lib/async-queue.js +104 -0
- package/server/lib/auto-relations.js +130 -0
- package/server/lib/binding-types.js +60 -0
- package/server/lib/board-kind-sizes.js +62 -0
- package/server/lib/board-relations.js +133 -0
- package/server/lib/browse-proxy.js +180 -0
- package/server/lib/canvas-id.js +36 -0
- package/server/lib/cover.js +227 -0
- package/server/lib/danbooru-tags.js +291 -0
- package/server/lib/doc-extract.js +156 -0
- package/server/lib/docx/build-from-source.js +260 -0
- package/server/lib/docx/build.js +490 -0
- package/server/lib/docx/dump-styles.js +287 -0
- package/server/lib/docx/fonts/nodesign-cjk.conf +164 -0
- package/server/lib/docx/merge-runs.js +129 -0
- package/server/lib/docx/numbering.js +218 -0
- package/server/lib/docx/order.js +152 -0
- package/server/lib/docx/rawzip.js +172 -0
- package/server/lib/docx/render.js +92 -0
- package/server/lib/docx/text-lint.js +225 -0
- package/server/lib/docx/tokens.js +335 -0
- package/server/lib/docx/units.js +29 -0
- package/server/lib/docx/xml.js +291 -0
- package/server/lib/docx-pages.js +187 -0
- package/server/lib/export-collect.js +289 -0
- package/server/lib/export-package.js +210 -0
- package/server/lib/html-srcset.js +145 -0
- package/server/lib/image-variant.js +460 -0
- package/server/lib/ingress/forward-openai-chat.js +305 -0
- package/server/lib/ingress/openai-chat.js +491 -0
- package/server/lib/ingress/session-notice.js +66 -0
- package/server/lib/ingress/session-routes.js +68 -0
- package/server/lib/ingress/slot-probe.js +130 -0
- package/server/lib/ingress/upstream-billing.js +52 -0
- package/server/lib/ingress/upstream-fail-streak.js +72 -0
- package/server/lib/ingress/upstream-truncation.js +48 -0
- package/server/lib/issues-store.js +182 -0
- package/server/lib/kinds/deck.js +72 -0
- package/server/lib/kinds/docx.js +283 -0
- package/server/lib/kinds/file-kinds.js +113 -0
- package/server/lib/kinds/index.js +202 -0
- package/server/lib/kinds/site.js +161 -0
- package/server/lib/model-ingress.js +543 -0
- package/server/lib/moderation.js +255 -0
- package/server/lib/notice-store.js +103 -0
- package/server/lib/plugin-install.js +104 -0
- package/server/lib/plugin-validator.js +721 -0
- package/server/lib/publish-store.js +115 -0
- package/server/lib/quick-summary.js +52 -0
- package/server/lib/quota.js +270 -0
- package/server/lib/rate-window.js +29 -0
- package/server/lib/reference-assets.js +92 -0
- package/server/lib/region-shot.js +135 -0
- package/server/lib/safe-path.js +73 -0
- package/server/lib/sdk-session.js +33 -0
- package/server/lib/showcase-store.js +92 -0
- package/server/lib/site-publish.js +465 -0
- package/server/lib/ssrf-guard.js +432 -0
- package/server/lib/task-scan.js +158 -0
- package/server/lib/tavern-json.js +154 -0
- package/server/lib/video-variant.js +237 -0
- package/server/lib/workspace-path.js +33 -0
- package/server/ops/fix-sdk-musl.mjs +40 -0
- package/server/ops/install-macos-fonts.sh +114 -0
- package/server/ops/macos-fonts.conf +336 -0
- package/server/ops/sandbox-shim/bwrap +57 -0
- package/server/projects/assets-summary.js +119 -0
- package/server/projects/auto-name.js +53 -0
- package/server/projects/board-store.js +640 -0
- package/server/projects/move-entry.js +103 -0
- package/server/projects/store.js +270 -0
- package/server/projects/ui-config.js +54 -0
- package/server/projects/workspace-templates.js +53 -0
- package/server/projects/workspace.js +1025 -0
- package/server/runtime/capabilities.js +153 -0
- package/server/runtime/local-config.js +177 -0
- package/server/runtime/local-env.js +88 -0
- package/server/runtime/platform.js +342 -0
- package/server/runtime/profile.js +72 -0
- package/server/services/rembg-launcher.js +313 -0
- package/server/services/rembg-service.py +334 -0
- package/server/shared/README.md +25 -0
- package/server/shared/deck.js +54 -0
- package/server/shared/time.js +49 -0
- package/server/style-pipeline/README.md +53 -0
- package/server/ws/broker.js +36 -0
- package/server/ws/browse-channel.js +177 -0
- package/server/ws/index.js +386 -0
- package/web/README.md +89 -0
- package/web/dist/assets/BrowserWindow-Dc7J7CYc.js +11 -0
- package/web/dist/assets/DeckWindow-4G0xX7P3.js +16 -0
- package/web/dist/assets/DocxWindow-BXQsoPkh.js +16 -0
- package/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/web/dist/assets/SiteWindow-D6eS-2gM.js +18 -0
- package/web/dist/assets/again-D8tfgKKO.webp +0 -0
- package/web/dist/assets/caveat-nd-CP6HlsNg.woff2 +0 -0
- package/web/dist/assets/clock-xJhvfYpS.webp +0 -0
- package/web/dist/assets/film-cut-BBKMwH7q.webp +0 -0
- package/web/dist/assets/film-still-BZ_DL9Tt.webp +0 -0
- package/web/dist/assets/index-C0KUf6Wd.css +1 -0
- package/web/dist/assets/index-Cbl3ATvp.js +2125 -0
- package/web/dist/assets/ink-desk-BRbxeDsR.webp +0 -0
- package/web/dist/assets/ink-night-Bz4BT3XH.webp +0 -0
- package/web/dist/assets/ink-portrait-C0DM4V8Q.webp +0 -0
- package/web/dist/assets/longcang-regular-C0uvTuKa.woff2 +0 -0
- package/web/dist/assets/lxgw-nd-bold-DbRfiTgo.woff2 +0 -0
- package/web/dist/assets/lxgw-nd-regular-CpMw9Ehg.woff2 +0 -0
- package/web/dist/assets/pending-edit-apply-DTjo2geW.js +31 -0
- package/web/dist/assets/question-8H4HSqxh.webp +0 -0
- package/web/dist/assets/reject-BaPJqElj.webp +0 -0
- package/web/dist/assets/rotate-cw-LMT3x1Zj.js +11 -0
- package/web/dist/assets/rp-portrait-CbrGpew2.webp +0 -0
- package/web/dist/assets/rp-street-C4jVKjxx.webp +0 -0
- package/web/dist/assets/square-dashed-mouse-pointer-CBoAkfhi.js +11 -0
- package/web/dist/assets/tangle-DIxHVNuT.webp +0 -0
- package/web/dist/assets/thisone-BylZKglV.webp +0 -0
- package/web/dist/assets/thumb-DO1wfK1I.webp +0 -0
- package/web/dist/index.html +18 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
|
3
|
+
<!--
|
|
4
|
+
server/ops/macos-fonts.conf — fontconfig 配置:让 Linux server 端的 generic
|
|
5
|
+
font family(serif / sans-serif / monospace / system-ui / -apple-system /
|
|
6
|
+
BlinkMacSystemFont)落到 macOS 字体上。
|
|
7
|
+
|
|
8
|
+
⚠️ 文件加载顺序(关键):必须装在 /etc/fonts/conf.d/65-macos.conf。
|
|
9
|
+
- 60-latin.conf:把 sans-serif → DejaVu/Liberation 等 latin alias
|
|
10
|
+
- 65-macos.conf(本文件):在 latin 之后强 prepend macOS 字体
|
|
11
|
+
- 69-language-selector-*.conf:lang-specific 中文/日文 alias
|
|
12
|
+
- 99-* 顺序最后,如果放 99 反而被 69-language-selector-zh-cn.conf 反 override
|
|
13
|
+
|
|
14
|
+
⚠️ alias 写法:必须用 `<match target="pattern">` + `mode="prepend_first"`。
|
|
15
|
+
prepend_first 是 fontconfig 文档里 "force strong binding + insert at head"
|
|
16
|
+
最高优先级写法。`<alias><prefer>` 和 `prepend + binding=strong` 都不够狠,
|
|
17
|
+
会被 Debian/Ubuntu 默认规则压在后面(实测 fc-match sans-serif:lang=zh-cn
|
|
18
|
+
仍命中 Helvetica Neue)。
|
|
19
|
+
|
|
20
|
+
⚠️ lang=zh 的 sans-serif/system-ui 必须有显式复合 match——光 prepend
|
|
21
|
+
PingFang 到 sans-serif 不够,因为 fontconfig 处理 lang=zh 时会用 charset
|
|
22
|
+
覆盖率重新排序,把没中文 glyph 的 latin 字体(Helvetica Neue)反而排前。
|
|
23
|
+
显式复合 match (sans-serif AND lang contains zh) 强 prepend,能盖过这条。
|
|
24
|
+
|
|
25
|
+
⚠️ 法律:苹果字体(PingFang / Songti / SF Pro)是 Apple 商业授权字体,
|
|
26
|
+
仅限内部使用,禁止打包进面向最终用户的产物(baked HTML 不内联这些字体)。
|
|
27
|
+
这份配置只影响 server 端渲染(PDF/PPT),不会让字体随 deck 外传。
|
|
28
|
+
-->
|
|
29
|
+
<fontconfig>
|
|
30
|
+
|
|
31
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
32
|
+
<!-- 第一组:generic family alias(lang 无关,统一 prepend 苹果字体) -->
|
|
33
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
34
|
+
|
|
35
|
+
<!-- generic serif → Songti SC(中文衬线宋体) -->
|
|
36
|
+
<match target="pattern">
|
|
37
|
+
<test qual="any" name="family">
|
|
38
|
+
<string>serif</string>
|
|
39
|
+
</test>
|
|
40
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
41
|
+
<string>Songti SC</string>
|
|
42
|
+
<string>STSong</string>
|
|
43
|
+
</edit>
|
|
44
|
+
</match>
|
|
45
|
+
|
|
46
|
+
<!-- generic sans-serif → PingFang SC(中文黑体) -->
|
|
47
|
+
<match target="pattern">
|
|
48
|
+
<test qual="any" name="family">
|
|
49
|
+
<string>sans-serif</string>
|
|
50
|
+
</test>
|
|
51
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
52
|
+
<string>PingFang SC</string>
|
|
53
|
+
<string>Heiti SC</string>
|
|
54
|
+
</edit>
|
|
55
|
+
</match>
|
|
56
|
+
|
|
57
|
+
<!-- system-ui → SF Pro(macOS 系统 UI 字体) -->
|
|
58
|
+
<match target="pattern">
|
|
59
|
+
<test qual="any" name="family">
|
|
60
|
+
<string>system-ui</string>
|
|
61
|
+
</test>
|
|
62
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
63
|
+
<string>.SF NS</string>
|
|
64
|
+
<string>.SF NS Text</string>
|
|
65
|
+
<string>SF Pro Text</string>
|
|
66
|
+
<string>SF Pro Display</string>
|
|
67
|
+
<string>Helvetica Neue</string>
|
|
68
|
+
<string>PingFang SC</string>
|
|
69
|
+
</edit>
|
|
70
|
+
</match>
|
|
71
|
+
|
|
72
|
+
<!-- -apple-system / BlinkMacSystemFont → 同 system-ui -->
|
|
73
|
+
<match target="pattern">
|
|
74
|
+
<test qual="any" name="family">
|
|
75
|
+
<string>-apple-system</string>
|
|
76
|
+
</test>
|
|
77
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
78
|
+
<string>.SF NS</string>
|
|
79
|
+
<string>SF Pro Text</string>
|
|
80
|
+
<string>Helvetica Neue</string>
|
|
81
|
+
<string>PingFang SC</string>
|
|
82
|
+
</edit>
|
|
83
|
+
</match>
|
|
84
|
+
<match target="pattern">
|
|
85
|
+
<test qual="any" name="family">
|
|
86
|
+
<string>BlinkMacSystemFont</string>
|
|
87
|
+
</test>
|
|
88
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
89
|
+
<string>.SF NS</string>
|
|
90
|
+
<string>SF Pro Text</string>
|
|
91
|
+
<string>Helvetica Neue</string>
|
|
92
|
+
<string>PingFang SC</string>
|
|
93
|
+
</edit>
|
|
94
|
+
</match>
|
|
95
|
+
|
|
96
|
+
<!-- monospace → SF Mono / Menlo -->
|
|
97
|
+
<match target="pattern">
|
|
98
|
+
<test qual="any" name="family">
|
|
99
|
+
<string>monospace</string>
|
|
100
|
+
</test>
|
|
101
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
102
|
+
<string>.SF NS Mono</string>
|
|
103
|
+
<string>SF Mono</string>
|
|
104
|
+
<string>Menlo</string>
|
|
105
|
+
<string>Monaco</string>
|
|
106
|
+
</edit>
|
|
107
|
+
</match>
|
|
108
|
+
|
|
109
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
110
|
+
<!-- 第二组:lang=zh 复合 match(强制中文字符走 PingFang/Songti) -->
|
|
111
|
+
<!-- -->
|
|
112
|
+
<!-- 必要性:第一组 prepend 把 PingFang 放 list 前面,但 fontconfig 处理 -->
|
|
113
|
+
<!-- lang=zh 时会用"charset 覆盖率"重新排序,没中文 glyph 的 latin 字体 -->
|
|
114
|
+
<!-- 反而排前。显式复合 match 强 prepend 中文字体,盖过 charset 重排。 -->
|
|
115
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
116
|
+
|
|
117
|
+
<!-- sans-serif:lang=zh → 强制 PingFang SC 在最前 -->
|
|
118
|
+
<match target="pattern">
|
|
119
|
+
<test name="lang" compare="contains">
|
|
120
|
+
<string>zh</string>
|
|
121
|
+
</test>
|
|
122
|
+
<test qual="any" name="family">
|
|
123
|
+
<string>sans-serif</string>
|
|
124
|
+
</test>
|
|
125
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
126
|
+
<string>PingFang SC</string>
|
|
127
|
+
</edit>
|
|
128
|
+
</match>
|
|
129
|
+
|
|
130
|
+
<!-- serif:lang=zh → 强制 Songti SC 在最前 -->
|
|
131
|
+
<match target="pattern">
|
|
132
|
+
<test name="lang" compare="contains">
|
|
133
|
+
<string>zh</string>
|
|
134
|
+
</test>
|
|
135
|
+
<test qual="any" name="family">
|
|
136
|
+
<string>serif</string>
|
|
137
|
+
</test>
|
|
138
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
139
|
+
<string>Songti SC</string>
|
|
140
|
+
</edit>
|
|
141
|
+
</match>
|
|
142
|
+
|
|
143
|
+
<!-- system-ui / -apple-system :lang=zh → PingFang SC 在最前 -->
|
|
144
|
+
<match target="pattern">
|
|
145
|
+
<test name="lang" compare="contains">
|
|
146
|
+
<string>zh</string>
|
|
147
|
+
</test>
|
|
148
|
+
<test qual="any" name="family">
|
|
149
|
+
<string>system-ui</string>
|
|
150
|
+
</test>
|
|
151
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
152
|
+
<string>PingFang SC</string>
|
|
153
|
+
</edit>
|
|
154
|
+
</match>
|
|
155
|
+
<match target="pattern">
|
|
156
|
+
<test name="lang" compare="contains">
|
|
157
|
+
<string>zh</string>
|
|
158
|
+
</test>
|
|
159
|
+
<test qual="any" name="family">
|
|
160
|
+
<string>-apple-system</string>
|
|
161
|
+
</test>
|
|
162
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
163
|
+
<string>PingFang SC</string>
|
|
164
|
+
</edit>
|
|
165
|
+
</match>
|
|
166
|
+
<match target="pattern">
|
|
167
|
+
<test name="lang" compare="contains">
|
|
168
|
+
<string>zh</string>
|
|
169
|
+
</test>
|
|
170
|
+
<test qual="any" name="family">
|
|
171
|
+
<string>BlinkMacSystemFont</string>
|
|
172
|
+
</test>
|
|
173
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
174
|
+
<string>PingFang SC</string>
|
|
175
|
+
</edit>
|
|
176
|
+
</match>
|
|
177
|
+
|
|
178
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
179
|
+
<!-- 第三组:通用 CJK fallback(任何字体在 zh charset 缺 glyph 时 append) -->
|
|
180
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
181
|
+
|
|
182
|
+
<match target="pattern">
|
|
183
|
+
<test name="lang" compare="contains">
|
|
184
|
+
<string>zh</string>
|
|
185
|
+
</test>
|
|
186
|
+
<edit name="family" mode="append" binding="strong">
|
|
187
|
+
<string>PingFang SC</string>
|
|
188
|
+
<string>Songti SC</string>
|
|
189
|
+
<string>Heiti SC</string>
|
|
190
|
+
<string>Noto Sans SC</string>
|
|
191
|
+
</edit>
|
|
192
|
+
</match>
|
|
193
|
+
|
|
194
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
195
|
+
<!-- 第四组:Helvetica 别名(让 css 写 Helvetica 命中 macOS 自带) -->
|
|
196
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
197
|
+
|
|
198
|
+
<match target="pattern">
|
|
199
|
+
<test qual="any" name="family">
|
|
200
|
+
<string>Helvetica</string>
|
|
201
|
+
</test>
|
|
202
|
+
<edit name="family" mode="prepend_first" binding="strong">
|
|
203
|
+
<string>Helvetica Neue</string>
|
|
204
|
+
</edit>
|
|
205
|
+
</match>
|
|
206
|
+
|
|
207
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
208
|
+
<!-- 第五组:剔除 Helvetica/Helvetica Neue 的 CJK lang 声明 -->
|
|
209
|
+
<!-- -->
|
|
210
|
+
<!-- Helvetica.ttc / HelveticaNeue.ttc 内部声明支持很多语言(macOS 用 -->
|
|
211
|
+
<!-- "中黑" 这种 style 名让 fontconfig 误识为它支持 zh),fc-match -->
|
|
212
|
+
<!-- :lang=zh-cn 命中前 4 位都是 Helvetica Neue 各 style,PingFang 排第 5。-->
|
|
213
|
+
<!-- -->
|
|
214
|
+
<!-- 解法:用 target="font" 改写 Helvetica/Helvetica Neue 的 lang 集合, -->
|
|
215
|
+
<!-- assign_replace 为只 latin 语言,剔除 zh/ja/ko。fontconfig 在 query -->
|
|
216
|
+
<!-- :lang=zh 时就不会把它们纳入候选,PingFang 自然顶到第 1 位。 -->
|
|
217
|
+
<!-- -->
|
|
218
|
+
<!-- 副作用:css 显式写 font-family: 'Helvetica Neue' 时 latin 字符仍命中 -->
|
|
219
|
+
<!-- Helvetica Neue(family 优先级 > lang),中文字符 fallback 到 PingFang。-->
|
|
220
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
221
|
+
<match target="font">
|
|
222
|
+
<test name="family">
|
|
223
|
+
<string>Helvetica Neue</string>
|
|
224
|
+
</test>
|
|
225
|
+
<edit name="lang" mode="assign_replace" binding="strong">
|
|
226
|
+
<langset>
|
|
227
|
+
<string>en</string>
|
|
228
|
+
<string>fr</string>
|
|
229
|
+
<string>de</string>
|
|
230
|
+
<string>es</string>
|
|
231
|
+
<string>it</string>
|
|
232
|
+
<string>pt</string>
|
|
233
|
+
<string>ru</string>
|
|
234
|
+
<string>nl</string>
|
|
235
|
+
<string>sv</string>
|
|
236
|
+
<string>no</string>
|
|
237
|
+
<string>da</string>
|
|
238
|
+
<string>fi</string>
|
|
239
|
+
<string>pl</string>
|
|
240
|
+
<string>tr</string>
|
|
241
|
+
</langset>
|
|
242
|
+
</edit>
|
|
243
|
+
</match>
|
|
244
|
+
<match target="font">
|
|
245
|
+
<test name="family">
|
|
246
|
+
<string>Helvetica</string>
|
|
247
|
+
</test>
|
|
248
|
+
<edit name="lang" mode="assign_replace" binding="strong">
|
|
249
|
+
<langset>
|
|
250
|
+
<string>en</string>
|
|
251
|
+
<string>fr</string>
|
|
252
|
+
<string>de</string>
|
|
253
|
+
<string>es</string>
|
|
254
|
+
<string>it</string>
|
|
255
|
+
<string>pt</string>
|
|
256
|
+
<string>ru</string>
|
|
257
|
+
<string>nl</string>
|
|
258
|
+
<string>sv</string>
|
|
259
|
+
<string>no</string>
|
|
260
|
+
<string>da</string>
|
|
261
|
+
<string>fi</string>
|
|
262
|
+
<string>pl</string>
|
|
263
|
+
<string>tr</string>
|
|
264
|
+
</langset>
|
|
265
|
+
</edit>
|
|
266
|
+
</match>
|
|
267
|
+
|
|
268
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
269
|
+
<!-- 第六组:reject Linux 系统字体——server 端只剩苹果字体可选 -->
|
|
270
|
+
<!-- -->
|
|
271
|
+
<!-- 之前现象:fc-match -s sans-serif:lang=zh-cn 输出 list 里 Helvetica -->
|
|
272
|
+
<!-- Neue 各 style 占前 4 位,PingFang 在第 5。Chromium 字符级 fallback -->
|
|
273
|
+
<!-- 链不一定能走到 PingFang——某些字符就 fallback 到 DejaVu Sans 或方块。 -->
|
|
274
|
+
<!-- -->
|
|
275
|
+
<!-- 干净方案:直接把 Debian/Ubuntu 自带的 latin/CJK 系统字体全 reject, -->
|
|
276
|
+
<!-- server 端字体池只剩苹果字体(PingFang/Songti/Helvetica/SF NS/Menlo) -->
|
|
277
|
+
<!-- + Google Fonts inline 字体。所有 generic family resolve 必然命中 -->
|
|
278
|
+
<!-- 苹果字体,不再有候选排序混乱。 -->
|
|
279
|
+
<!-- -->
|
|
280
|
+
<!-- 保留:Noto Color Emoji(不 reject 否则 emoji 渲染全断) -->
|
|
281
|
+
<!-- -->
|
|
282
|
+
<!-- ⚠️ 副作用:所有依赖 fontconfig 的应用都看不到这些字体了。NoDesign -->
|
|
283
|
+
<!-- server 独占场景 OK;如这台 server 上还跑别的应用要小心。 -->
|
|
284
|
+
<!-- ══════════════════════════════════════════════════════════════════ -->
|
|
285
|
+
<selectfont>
|
|
286
|
+
<rejectfont>
|
|
287
|
+
<!-- DejaVu 系列(Debian 默认 latin) -->
|
|
288
|
+
<pattern><patelt name="family"><string>DejaVu Sans</string></patelt></pattern>
|
|
289
|
+
<pattern><patelt name="family"><string>DejaVu Sans Mono</string></patelt></pattern>
|
|
290
|
+
<pattern><patelt name="family"><string>DejaVu Serif</string></patelt></pattern>
|
|
291
|
+
<pattern><patelt name="family"><string>DejaVu Math TeX Gyre</string></patelt></pattern>
|
|
292
|
+
|
|
293
|
+
<!-- Liberation 系列(RHEL 系 latin) -->
|
|
294
|
+
<pattern><patelt name="family"><string>Liberation Sans</string></patelt></pattern>
|
|
295
|
+
<pattern><patelt name="family"><string>Liberation Serif</string></patelt></pattern>
|
|
296
|
+
<pattern><patelt name="family"><string>Liberation Mono</string></patelt></pattern>
|
|
297
|
+
<pattern><patelt name="family"><string>Liberation Sans Narrow</string></patelt></pattern>
|
|
298
|
+
|
|
299
|
+
<!-- Noto 系列(latin + CJK 都 reject,让苹果字体接管) -->
|
|
300
|
+
<pattern><patelt name="family"><string>Noto Sans</string></patelt></pattern>
|
|
301
|
+
<pattern><patelt name="family"><string>Noto Serif</string></patelt></pattern>
|
|
302
|
+
<pattern><patelt name="family"><string>Noto Sans Mono</string></patelt></pattern>
|
|
303
|
+
<pattern><patelt name="family"><string>Noto Sans CJK SC</string></patelt></pattern>
|
|
304
|
+
<pattern><patelt name="family"><string>Noto Sans CJK TC</string></patelt></pattern>
|
|
305
|
+
<pattern><patelt name="family"><string>Noto Sans CJK JP</string></patelt></pattern>
|
|
306
|
+
<pattern><patelt name="family"><string>Noto Sans CJK KR</string></patelt></pattern>
|
|
307
|
+
<pattern><patelt name="family"><string>Noto Serif CJK SC</string></patelt></pattern>
|
|
308
|
+
<pattern><patelt name="family"><string>Noto Serif CJK TC</string></patelt></pattern>
|
|
309
|
+
<pattern><patelt name="family"><string>Noto Serif CJK JP</string></patelt></pattern>
|
|
310
|
+
<pattern><patelt name="family"><string>Noto Serif CJK KR</string></patelt></pattern>
|
|
311
|
+
<!-- Noto Color Emoji 故意保留——emoji 渲染必需 -->
|
|
312
|
+
|
|
313
|
+
<!-- 文泉驿系列(Debian 中文 fallback) -->
|
|
314
|
+
<pattern><patelt name="family"><string>WenQuanYi Zen Hei</string></patelt></pattern>
|
|
315
|
+
<pattern><patelt name="family"><string>WenQuanYi Micro Hei</string></patelt></pattern>
|
|
316
|
+
<pattern><patelt name="family"><string>WenQuanYi Zen Hei Mono</string></patelt></pattern>
|
|
317
|
+
<pattern><patelt name="family"><string>WenQuanYi Zen Hei Sharp</string></patelt></pattern>
|
|
318
|
+
|
|
319
|
+
<!-- GNU FreeFont 系列 -->
|
|
320
|
+
<pattern><patelt name="family"><string>FreeSans</string></patelt></pattern>
|
|
321
|
+
<pattern><patelt name="family"><string>FreeSerif</string></patelt></pattern>
|
|
322
|
+
<pattern><patelt name="family"><string>FreeMono</string></patelt></pattern>
|
|
323
|
+
|
|
324
|
+
<!-- Ubuntu 自带(如果是 Ubuntu server) -->
|
|
325
|
+
<pattern><patelt name="family"><string>Ubuntu</string></patelt></pattern>
|
|
326
|
+
<pattern><patelt name="family"><string>Ubuntu Mono</string></patelt></pattern>
|
|
327
|
+
<pattern><patelt name="family"><string>Ubuntu Condensed</string></patelt></pattern>
|
|
328
|
+
|
|
329
|
+
<!-- Bitstream / Vera(X11 老字体) -->
|
|
330
|
+
<pattern><patelt name="family"><string>Bitstream Vera Sans</string></patelt></pattern>
|
|
331
|
+
<pattern><patelt name="family"><string>Bitstream Vera Serif</string></patelt></pattern>
|
|
332
|
+
<pattern><patelt name="family"><string>Bitstream Vera Sans Mono</string></patelt></pattern>
|
|
333
|
+
</rejectfont>
|
|
334
|
+
</selectfont>
|
|
335
|
+
|
|
336
|
+
</fontconfig>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# bwrap 垫片 —— 绕开 apply-seccomp 的 unshare 竞态(2026-08-15)
|
|
3
|
+
#
|
|
4
|
+
# 📮 上游 issue:https://github.com/anthropics/claude-code/issues/86928
|
|
5
|
+
# (含 strace 时序、内核源码引用、49 行 C 最小复现、三条修法建议)
|
|
6
|
+
# ⏳ **这是临时设施**:上游修掉之后把整个目录连同 isolation.js 里的
|
|
7
|
+
# sandboxShimEnv() 一起摘掉,别让它变成永久的一层。
|
|
8
|
+
#
|
|
9
|
+
# 病:SDK 沙盒每条命令都以 `ARGV0=apply-seccomp /proc/self/fd/3 <命令>` 起手 ——
|
|
10
|
+
# 那是那个 306MB bun 二进制**自我重执行**成 seccomp helper。bun 启动时 mimalloc
|
|
11
|
+
# 会先起一根 `mi-scavenger` 线程,helper 随即把它关掉并 join;但内核在
|
|
12
|
+
# `mm_release()` 里唤醒 joiner 的时机**早于** `release_task` 把死线程从
|
|
13
|
+
# thread group 摘除,于是紧接着那句 `unshare(CLONE_NEWUSER)` 撞上
|
|
14
|
+
# `!thread_group_empty` → EINVAL。(kernel/fork.c:CLONE_NEWUSER 会被隐式加上
|
|
15
|
+
# CLONE_THREAD,而 check_unshare_flags 对 CLONE_THREAD 要求 thread group 为空。)
|
|
16
|
+
#
|
|
17
|
+
# 所以它是**内核级竞态**,不是配置问题:40 行 C 能脱离 claude 复现,1 vCPU 空载
|
|
18
|
+
# 200/200 必炸,join 后加 50µs 睡眠就 0/200。机器越闲越容易炸(joiner 抢占了
|
|
19
|
+
# 垂死线程),多核几乎见不到 —— 这是这台单核机特有的。
|
|
20
|
+
#
|
|
21
|
+
# 治:把那句 racy 的 syscall 从执行路径上拿掉。`unshare -U --map-current-user
|
|
22
|
+
# --keep-caps` 由 util-linux **单线程**先把 user namespace 建好并把能力放进
|
|
23
|
+
# ambient set,helper 进去后第一步 `unshare(NEWNS|NEWPID)` 直接成功,**根本不会
|
|
24
|
+
# 走到那句 CLONE_NEWUSER**。helper 在 exec 载荷之前自带 PR_CAP_AMBIENT_CLEAR_ALL,
|
|
25
|
+
# 能力不外泄。
|
|
26
|
+
#
|
|
27
|
+
# 安全不变量(每条都在真会话里验过,改这个文件前重验):
|
|
28
|
+
# Seccomp: 2(filter 仍在)· AF_UNIX socket() 仍被拒(pm2 rpc.sock 逃逸路照旧关着)
|
|
29
|
+
# · uid 仍是 1000 · userns 嵌套层数不变 · ambient caps 在载荷 exec 前清空
|
|
30
|
+
#
|
|
31
|
+
# ⚠️ 这是垫在 SDK 内部实现上的补丁,**pattern 变了就自动失效**(原样透传 = 退回
|
|
32
|
+
# 现状的偶发,不会退成"没有沙盒")。升 SDK 之后查 $NODESIGN_SHIM_LOG 里
|
|
33
|
+
# rewrote=1 的计数还在不在涨。
|
|
34
|
+
#
|
|
35
|
+
# 上游修法(issue 里提的三条):对 EINVAL 做有界重试 + sched_yield(最简单,
|
|
36
|
+
# 实测 50µs 退避就闭合窗口)/改成轮询 /proc/self/status 的 Threads: 到 1
|
|
37
|
+
# 再 unshare/让 helper 在运行时起线程之前就把 namespace 建好。
|
|
38
|
+
|
|
39
|
+
PAT='ARGV0=apply-seccomp /proc/self/fd/3 '
|
|
40
|
+
REP='/usr/bin/unshare -U --map-current-user --keep-caps /usr/bin/env ARGV0=apply-seccomp /proc/self/fd/3 '
|
|
41
|
+
REAL=${NODESIGN_REAL_BWRAP:-/usr/bin/bwrap}
|
|
42
|
+
|
|
43
|
+
# 兜底:unshare 不在(非 util-linux 系统)→ 原样透传,退回现状
|
|
44
|
+
[ -x /usr/bin/unshare ] || exec "$REAL" "$@"
|
|
45
|
+
|
|
46
|
+
args=()
|
|
47
|
+
hit=0
|
|
48
|
+
for a in "$@"; do
|
|
49
|
+
case "$a" in
|
|
50
|
+
*"$PAT"*) hit=1; a=${a//"$PAT"/"$REP"} ;;
|
|
51
|
+
esac
|
|
52
|
+
args+=("$a")
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
[ -n "$NODESIGN_SHIM_LOG" ] && printf '%s rewrote=%d nargs=%d\n' "$(date +%s)" "$hit" "$#" >>"$NODESIGN_SHIM_LOG" 2>/dev/null
|
|
56
|
+
|
|
57
|
+
exec "$REAL" "${args[@]}"
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/projects/assets-summary.js — 工作区素材摘要(2026-08-18 从 workspace.js 拆出)
|
|
3
|
+
*
|
|
4
|
+
* 这条摘要进每个会话的 system 提示:告诉 agent 工作区里已经有什么素材。
|
|
5
|
+
* 拆出来的理由是它跟"工作区生命周期"没关系 —— 它是个格式化器。
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ 存在的意义在于:**跨会话可见的东西如果没人提,等于不存在**。
|
|
8
|
+
* `assets/` 不随 sessionId 分桶,下个会话 Read 得到;但 agent 不会去猜有什么,
|
|
9
|
+
* 它会重新搜一遍、重新逛一遍那个站。
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import fs from 'node:fs/promises';
|
|
14
|
+
|
|
15
|
+
const IMAGE_EXT = new Set(['.png', '.jpg', '.jpeg', '.webp', '.gif', '.svg']);
|
|
16
|
+
const TEXT_DOC_EXT = new Set(['.md', '.txt', '.json']);
|
|
17
|
+
const BINARY_DOC_EXT = new Set(['.pdf', '.pptx', '.ppt', '.docx', '.doc', '.xlsx', '.xls']);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} sessionRoot - sessions/<sid>/ 绝对路径
|
|
21
|
+
* @returns {Promise<{ count: number, summary: string, hasBinaryDocs: boolean }>}
|
|
22
|
+
* count=0 时 summary 为空字符串,调用方据此判断是否注入提示。
|
|
23
|
+
* hasBinaryDocs=true 时调用方追加 python 处理提醒(Read 拿不到这些的内容)。
|
|
24
|
+
*/
|
|
25
|
+
export async function readAssetsSummary(sessionRoot) {
|
|
26
|
+
try {
|
|
27
|
+
const assetsLink = path.join(sessionRoot, 'assets');
|
|
28
|
+
const stat = await fs.stat(assetsLink).catch(() => null);
|
|
29
|
+
if (!stat) return { count: 0, summary: '', hasBinaryDocs: false };
|
|
30
|
+
|
|
31
|
+
const entries = await fs.readdir(assetsLink, { withFileTypes: true }).catch(() => []);
|
|
32
|
+
const files = entries.filter((e) => !e.name.startsWith('.') && (e.isFile() || e.isSymbolicLink()));
|
|
33
|
+
// ⚠️ 别在这儿提前 return:顶层一个文件都没有、但 assets/references/ 下有一堆
|
|
34
|
+
// 采集素材是**常见情形**(agent 逛过站但用户没上传过东西)。提前 return 会让
|
|
35
|
+
// 那些素材对 agent 彻底隐形。
|
|
36
|
+
|
|
37
|
+
const images = [];
|
|
38
|
+
const textDocs = [];
|
|
39
|
+
const binaryDocs = [];
|
|
40
|
+
const others = [];
|
|
41
|
+
for (const f of files) {
|
|
42
|
+
const ext = path.extname(f.name).toLowerCase();
|
|
43
|
+
if (IMAGE_EXT.has(ext)) images.push(f.name);
|
|
44
|
+
else if (TEXT_DOC_EXT.has(ext)) textDocs.push(f.name);
|
|
45
|
+
else if (BINARY_DOC_EXT.has(ext)) binaryDocs.push(f.name);
|
|
46
|
+
else others.push(f.name);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 摘要:种类 + 头几个文件名(避免太长)
|
|
50
|
+
const parts = [];
|
|
51
|
+
if (images.length > 0) {
|
|
52
|
+
const sample = images.slice(0, 3).join('、');
|
|
53
|
+
parts.push(`${images.length} 张图(${sample}${images.length > 3 ? ` 等` : ''})`);
|
|
54
|
+
}
|
|
55
|
+
if (textDocs.length > 0) {
|
|
56
|
+
const sample = textDocs.slice(0, 3).join('、');
|
|
57
|
+
parts.push(`${textDocs.length} 个文本文档(${sample}${textDocs.length > 3 ? ` 等` : ''})`);
|
|
58
|
+
}
|
|
59
|
+
if (binaryDocs.length > 0) {
|
|
60
|
+
const sample = binaryDocs.slice(0, 3).join('、');
|
|
61
|
+
parts.push(`${binaryDocs.length} 个 PDF/Office 文档(${sample}${binaryDocs.length > 3 ? ` 等` : ''})`);
|
|
62
|
+
}
|
|
63
|
+
if (others.length > 0) {
|
|
64
|
+
parts.push(`${others.length} 个其他文件`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 完整文件清单(按路径列)—— 让 agent 不用再 Glob/LS 探。
|
|
68
|
+
// (08-07 扁平化后 assets/ 是真目录,Glob 也能用;08-21 前这里还写着"symlink 别用 Glob",删了。)
|
|
69
|
+
const allNames = [...images, ...textDocs, ...binaryDocs, ...others];
|
|
70
|
+
|
|
71
|
+
// 参考素材(2026-08-18):`assets/references/**` 也要报,否则**没有任何机制
|
|
72
|
+
// 告诉 agent 它们存在** —— 上面这遍只列顶层文件,而参考图和 browser_capture
|
|
73
|
+
// 的采集都在子目录里。跨会话可见的东西如果没人提,等于不存在:agent 会重新
|
|
74
|
+
// 去搜一遍、重新逛一遍那个站。
|
|
75
|
+
// 只报数量和头几个名字(几十个文件全列会把这条 system 撑爆)。
|
|
76
|
+
const refs = [];
|
|
77
|
+
try {
|
|
78
|
+
const refRoot = path.join(assetsLink, 'references');
|
|
79
|
+
const walk = async (dir, rel, depth) => {
|
|
80
|
+
for (const e of await fs.readdir(dir, { withFileTypes: true })) {
|
|
81
|
+
if (e.name === '.meta' || e.name.startsWith('.')) continue;
|
|
82
|
+
if (e.isDirectory()) { if (depth > 0) await walk(path.join(dir, e.name), `${rel}/${e.name}`, depth - 1); continue; }
|
|
83
|
+
refs.push(`${rel}/${e.name}`);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
await walk(refRoot, 'assets/references', 2);
|
|
87
|
+
} catch { /* 没有这个目录就没有 */ }
|
|
88
|
+
|
|
89
|
+
const refLine = refs.length
|
|
90
|
+
? `另有 ${refs.length} 件参考素材在 assets/references/ 下(${refs.slice(0, 3).map(r => r.split('/').pop()).join('、')}`
|
|
91
|
+
+ `${refs.length > 3 ? ' 等' : ''})—— 逛站采回来的调色板/字体/结构/动效清单 json 就在这儿,`
|
|
92
|
+
+ '出处记在同目录的 .meta/<同名>.json 里。**先看有没有现成的,别重复去搜。**'
|
|
93
|
+
: '';
|
|
94
|
+
|
|
95
|
+
// ⚠️ `paths` 会被 UserPromptSubmit 首轮全量打进状态块(之后只报变化,见
|
|
96
|
+
// hooks/user-prompt-submit.js)。refs 随每次 browser_capture 单调增长,首轮也要封顶;
|
|
97
|
+
// `allPaths` 不封顶,给按项算变化用(不直接打进文案)。
|
|
98
|
+
const REF_CAP = 12;
|
|
99
|
+
const TOP_CAP = 60;
|
|
100
|
+
const refPaths = refs.slice(0, REF_CAP);
|
|
101
|
+
const overflow = refs.length - refPaths.length;
|
|
102
|
+
if (overflow > 0) {
|
|
103
|
+
// 别只是截断了不说 —— 「静默截断」读起来就是"全都在这儿了"
|
|
104
|
+
refPaths.push(`(另有 ${overflow} 件在 assets/references/ 下,名字和出处见同目录 .meta/)`);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
count: files.length + refs.length,
|
|
108
|
+
summary: [
|
|
109
|
+
files.length ? `workspace 里已有 ${files.length} 个参考素材:${parts.join('、')}` : '',
|
|
110
|
+
refLine,
|
|
111
|
+
].filter(Boolean).join('\n'),
|
|
112
|
+
hasBinaryDocs: binaryDocs.length > 0,
|
|
113
|
+
paths: [...allNames.slice(0, TOP_CAP).map((n) => `assets/${n}`), ...refPaths],
|
|
114
|
+
allPaths: [...allNames.map((n) => `assets/${n}`), ...refs],
|
|
115
|
+
};
|
|
116
|
+
} catch {
|
|
117
|
+
return { count: 0, summary: '', hasBinaryDocs: false, paths: [], allPaths: [] };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/projects/auto-name.js — 用会话摘要给项目起名(2026-07-28)
|
|
3
|
+
*
|
|
4
|
+
* 首页那个大输入框以前建的是"闪聊"(kind=quick),名字硬切用户第一句话前 30 字,
|
|
5
|
+
* 而且不算正经项目。现在它直接建真项目,名字先用那句话垫着(auto_named=1),
|
|
6
|
+
* 第一轮跑完就用 **SDK helper 写的会话摘要** 改一次名 —— 那是它本来就在写的东西
|
|
7
|
+
* (incrementally 落进 jsonl,我们列会话时读的就是它),不额外花一次模型调用。
|
|
8
|
+
*
|
|
9
|
+
* 只改一次:改完清 auto_named。用户自己改过名的项目(updateProject 带 name 会
|
|
10
|
+
* 自动清零)永远不动。
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import { getSessionInfo } from '@anthropic-ai/claude-agent-sdk';
|
|
15
|
+
import { getProject, updateProject } from './store.js';
|
|
16
|
+
import { getProjectWorkspace } from './workspace.js';
|
|
17
|
+
import { withConfigDir } from '../lib/sdk-session.js';
|
|
18
|
+
import { platform } from '../runtime/platform.js';
|
|
19
|
+
|
|
20
|
+
const MAX_NAME = 40;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} projectId
|
|
24
|
+
* @param {string} sessionId
|
|
25
|
+
* @returns {Promise<string|null>} 改成了什么名字;没改返 null
|
|
26
|
+
*/
|
|
27
|
+
export async function autoNameProjectFromSession(projectId, sessionId) {
|
|
28
|
+
if (!projectId || !sessionId) return null;
|
|
29
|
+
let project;
|
|
30
|
+
try { project = getProject(projectId); } catch { return null; }
|
|
31
|
+
if (!project || !project.autoNamed) return null;
|
|
32
|
+
|
|
33
|
+
const sessionRoot = path.join(getProjectWorkspace(projectId), 'sessions', sessionId);
|
|
34
|
+
let info;
|
|
35
|
+
try {
|
|
36
|
+
info = await withConfigDir(platform.claudeConfigDir, () =>
|
|
37
|
+
getSessionInfo(sessionId, { dir: sessionRoot }),
|
|
38
|
+
);
|
|
39
|
+
} catch {
|
|
40
|
+
return null; // 读不到就下轮再说,auto_named 还留着
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const summary = String(info?.customTitle || info?.summary || '').trim();
|
|
44
|
+
if (!summary) return null;
|
|
45
|
+
const name = summary.length > MAX_NAME ? summary.slice(0, MAX_NAME) + '…' : summary;
|
|
46
|
+
if (name === project.name) {
|
|
47
|
+
updateProject(projectId, { autoNamed: false }); // 同名也算定了,别每轮再问
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
updateProject(projectId, { name, autoNamed: false });
|
|
52
|
+
return name;
|
|
53
|
+
}
|