shadow-claw 1.27.0 → 1.28.0
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/.well-known/ai-catalog.json +11 -0
- package/.well-known/mcp/index.html +19 -0
- package/.well-known/mcp/server-card.json +52 -0
- package/.well-known/mcp/servers.json +15 -0
- package/.well-known/mcp.json +52 -0
- package/.well-known/oauth-protected-resource +10 -0
- package/.well-known/oauth-protected-resource.json +10 -0
- package/bin/assert-version-bump.mjs +61 -3
- package/bin/assert-version-bump.test.mjs +77 -1
- package/bin/build/build.mjs +116 -49
- package/bin/build/build.test.mjs +103 -0
- package/bin/cli.mjs +299 -237
- package/bin/cli.test.mjs +27 -0
- package/bin/commands/mcp.mjs +132 -2
- package/bin/commands/mcp.test.mjs +166 -0
- package/bin/commands/skills-index.mjs +139 -20
- package/bin/commands/skills-index.test.mjs +82 -0
- package/bin/utils/control-client.mjs +17 -0
- package/bin/utils/control-client.test.mjs +46 -0
- package/bin/version.mjs +208 -0
- package/bin/version.test.mjs +138 -0
- package/dist/electron/main.cjs +195 -185
- package/dist/lib/components/index.js +21 -21
- package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/settings/shadow-claw-git.js +1 -1
- package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
- package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
- package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
- package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
- package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw/shadow-claw.d.ts +1 -0
- package/dist/lib/components/shadow-claw/utils/setupAppLifecycle.d.ts +23 -0
- package/dist/lib/components/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/shadow-claw-channels.js +1 -1
- package/dist/lib/components/shadow-claw-chat.js +1 -1
- package/dist/lib/components/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/shadow-claw-conversations.js +1 -1
- package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
- package/dist/lib/components/shadow-claw-files.js +1 -1
- package/dist/lib/components/shadow-claw-git.js +1 -1
- package/dist/lib/components/shadow-claw-llm.js +1 -1
- package/dist/lib/components/shadow-claw-networking.js +1 -1
- package/dist/lib/components/shadow-claw-notifications.js +1 -1
- package/dist/lib/components/shadow-claw-pages.js +1 -1
- package/dist/lib/components/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/shadow-claw-settings.js +1 -1
- package/dist/lib/components/shadow-claw-storage.js +1 -1
- package/dist/lib/components/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/shadow-claw-tasks.js +1 -1
- package/dist/lib/components/shadow-claw-terminal.js +1 -1
- package/dist/lib/components/shadow-claw-tools.js +1 -1
- package/dist/lib/components/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw.js +1 -1
- package/dist/lib/{configurePeerJs-oODzltaC.js → configurePeerJs-D8Ph0-A9.js} +2 -2
- package/dist/lib/{configurePeerJs-oODzltaC.js.map → configurePeerJs-D8Ph0-A9.js.map} +1 -1
- package/dist/lib/core/control-plane-client.d.ts +2 -0
- package/dist/lib/core/orchestrator/orchestrator.d.ts +10 -0
- package/dist/lib/core/orchestrator/utils/operations/channel.d.ts +2 -2
- package/dist/lib/core/utils/initControlPlane.d.ts +6 -0
- package/dist/lib/index.js +21 -21
- package/dist/lib/{initControlPlane-C2zURVIS.js → initControlPlane-BIrWmpzc.js} +76 -9
- package/dist/lib/initControlPlane-BIrWmpzc.js.map +1 -0
- package/dist/lib/{markdown-C6EHl9zs.js → markdown-DEUoM1c6.js} +2 -2
- package/dist/lib/{markdown-C6EHl9zs.js.map → markdown-DEUoM1c6.js.map} +1 -1
- package/dist/lib/{orchestrator-KRjx0eba.js → orchestrator-BtVj9bBB.js} +11 -10
- package/dist/lib/{orchestrator-KRjx0eba.js.map → orchestrator-BtVj9bBB.js.map} +1 -1
- package/dist/lib/{orchestrator-CACLa_Ro.js → orchestrator-CFCW-l1O.js} +52 -4
- package/dist/lib/orchestrator-CFCW-l1O.js.map +1 -0
- package/dist/lib/{peerjs-DFWOBcXf.js → peerjs-BoBkx9DJ.js} +23 -3
- package/dist/lib/peerjs-BoBkx9DJ.js.map +1 -0
- package/dist/lib/{push-client-_tiWQsCT.js → push-client-D6hbzDNV.js} +10 -4
- package/dist/lib/push-client-D6hbzDNV.js.map +1 -0
- package/dist/lib/{shadow-claw-6UHdiy4a.js → shadow-claw-Cuf2O5bZ.js} +71 -4
- package/dist/lib/shadow-claw-Cuf2O5bZ.js.map +1 -0
- package/dist/lib/{shadow-claw-channel-config-DmfwJc6G.js → shadow-claw-channel-config-BDPKt6Bd.js} +3 -3
- package/dist/lib/{shadow-claw-channel-config-DmfwJc6G.js.map → shadow-claw-channel-config-BDPKt6Bd.js.map} +1 -1
- package/dist/lib/{shadow-claw-channels-1N6Jl-By.js → shadow-claw-channels-BsP5JABM.js} +2 -2
- package/dist/lib/{shadow-claw-channels-1N6Jl-By.js.map → shadow-claw-channels-BsP5JABM.js.map} +1 -1
- package/dist/lib/{shadow-claw-chat-BMoqQJRK.js → shadow-claw-chat-Cam2lX4k.js} +4 -4
- package/dist/lib/{shadow-claw-chat-BMoqQJRK.js.map → shadow-claw-chat-Cam2lX4k.js.map} +1 -1
- package/dist/lib/{shadow-claw-control-plane-UG0o7pCz.js → shadow-claw-control-plane-DB2qcCFs.js} +20 -10
- package/dist/lib/shadow-claw-control-plane-DB2qcCFs.js.map +1 -0
- package/dist/lib/{shadow-claw-conversations-BwXep3iu.js → shadow-claw-conversations-C9Vf4XGx.js} +2 -2
- package/dist/lib/{shadow-claw-conversations-BwXep3iu.js.map → shadow-claw-conversations-C9Vf4XGx.js.map} +1 -1
- package/dist/lib/{shadow-claw-file-viewer-DUxzVxDT.js → shadow-claw-file-viewer-B4HYiI0v.js} +3 -3
- package/dist/lib/{shadow-claw-file-viewer-DUxzVxDT.js.map → shadow-claw-file-viewer-B4HYiI0v.js.map} +1 -1
- package/dist/lib/{shadow-claw-files-DIREEnT2.js → shadow-claw-files-DVROUESO.js} +2 -2
- package/dist/lib/{shadow-claw-files-DIREEnT2.js.map → shadow-claw-files-DVROUESO.js.map} +1 -1
- package/dist/lib/{shadow-claw-git-Bg1SWgsF.js → shadow-claw-git-BqrO7cHJ.js} +3 -3
- package/dist/lib/{shadow-claw-git-Bg1SWgsF.js.map → shadow-claw-git-BqrO7cHJ.js.map} +1 -1
- package/dist/lib/{shadow-claw-llm-CazBrVpM.js → shadow-claw-llm-BexUQdYo.js} +2 -2
- package/dist/lib/{shadow-claw-llm-CazBrVpM.js.map → shadow-claw-llm-BexUQdYo.js.map} +1 -1
- package/dist/lib/{shadow-claw-networking-Df85tCbO.js → shadow-claw-networking-CfXRGpUD.js} +2 -2
- package/dist/lib/{shadow-claw-networking-Df85tCbO.js.map → shadow-claw-networking-CfXRGpUD.js.map} +1 -1
- package/dist/lib/{shadow-claw-notifications-v62FryTc.js → shadow-claw-notifications-C9KPMgx_.js} +2 -2
- package/dist/lib/{shadow-claw-notifications-v62FryTc.js.map → shadow-claw-notifications-C9KPMgx_.js.map} +1 -1
- package/dist/lib/{shadow-claw-pages-BgPyIEZO.js → shadow-claw-pages-CGzGXmrI.js} +3 -3
- package/dist/lib/{shadow-claw-pages-BgPyIEZO.js.map → shadow-claw-pages-CGzGXmrI.js.map} +1 -1
- package/dist/lib/{shadow-claw-peerjs-xkBXILed.js → shadow-claw-peerjs-B0ZB7yhB.js} +3 -3
- package/dist/lib/{shadow-claw-peerjs-xkBXILed.js.map → shadow-claw-peerjs-B0ZB7yhB.js.map} +1 -1
- package/dist/lib/{shadow-claw-settings-CN89xRVU.js → shadow-claw-settings-DBfMZdDS.js} +2 -2
- package/dist/lib/{shadow-claw-settings-CN89xRVU.js.map → shadow-claw-settings-DBfMZdDS.js.map} +1 -1
- package/dist/lib/{shadow-claw-storage-VnhcObCe.js → shadow-claw-storage-CM-w6mgG.js} +2 -2
- package/dist/lib/{shadow-claw-storage-VnhcObCe.js.map → shadow-claw-storage-CM-w6mgG.js.map} +1 -1
- package/dist/lib/{shadow-claw-task-server-jgEC2hHB.js → shadow-claw-task-server-DV4b1g2-.js} +4 -2
- package/dist/lib/{shadow-claw-task-server-jgEC2hHB.js.map → shadow-claw-task-server-DV4b1g2-.js.map} +1 -1
- package/dist/lib/{shadow-claw-tasks-i_evIufy.js → shadow-claw-tasks-K-foOHSE.js} +3 -3
- package/dist/lib/{shadow-claw-tasks-i_evIufy.js.map → shadow-claw-tasks-K-foOHSE.js.map} +1 -1
- package/dist/lib/{shadow-claw-terminal-CwScROlu.js → shadow-claw-terminal-CpAknKyA.js} +2 -2
- package/dist/lib/{shadow-claw-terminal-CwScROlu.js.map → shadow-claw-terminal-CpAknKyA.js.map} +1 -1
- package/dist/lib/{shadow-claw-tools-DD3fyXP4.js → shadow-claw-tools-D98XZ0Ep.js} +3 -3
- package/dist/lib/{shadow-claw-tools-DD3fyXP4.js.map → shadow-claw-tools-D98XZ0Ep.js.map} +1 -1
- package/dist/lib/{shadow-claw-webvm-DbJq4I3-.js → shadow-claw-webvm-DLOb8dMI.js} +2 -2
- package/dist/lib/{shadow-claw-webvm-DbJq4I3-.js.map → shadow-claw-webvm-DLOb8dMI.js.map} +1 -1
- package/dist/lib/subsystems/channels/imessage.d.ts +1 -0
- package/dist/lib/subsystems/channels/peerjs.d.ts +1 -0
- package/dist/lib/subsystems/channels/telegram.d.ts +1 -0
- package/dist/lib/subsystems/channels/types.d.ts +2 -0
- package/dist/lib/subsystems/notifications/push-client.d.ts +1 -1
- package/dist/lib/{syncWebMcpRegistration-DNLnQ-jz.js → syncWebMcpRegistration-NspKefOI.js} +2 -2
- package/dist/lib/{syncWebMcpRegistration-DNLnQ-jz.js.map → syncWebMcpRegistration-NspKefOI.js.map} +1 -1
- package/dist/public/.well-known/ai-catalog.json +11 -0
- package/dist/public/.well-known/mcp/index.html +19 -0
- package/dist/public/.well-known/mcp/server-card.json +52 -0
- package/dist/public/.well-known/mcp/servers.json +15 -0
- package/dist/public/.well-known/mcp.json +52 -0
- package/dist/public/.well-known/oauth-protected-resource +10 -0
- package/dist/public/.well-known/oauth-protected-resource.json +10 -0
- package/dist/public/404.html +28 -1
- package/dist/public/AGENTS.md +1 -1
- package/dist/public/agent.worker.js +1 -1
- package/dist/public/{configurePeerJs-BqgeBjP7.js → configurePeerJs-BhBokQlC.js} +1 -1
- package/dist/public/docs/example/article/index.html +3 -3
- package/dist/public/docs/publishing/index.html +3 -3
- package/dist/public/docs/skill-creator/index.html +3 -3
- package/dist/public/docs/subsystems/cli.md +11 -8
- package/dist/public/docs/subsystems/mcp-server.md +1 -0
- package/dist/public/docs/subsystems/notifications.md +10 -0
- package/dist/public/{e2e-bridge-Ceqr5kGc.js → e2e-bridge-DcBoeFvd.js} +1 -1
- package/dist/public/{file-viewer-C-6Jc_tb.js → file-viewer-CKtVC9Ix.js} +1 -1
- package/dist/public/index.css +1 -1
- package/dist/public/index.html +3 -3
- package/dist/public/index.js +1 -1
- package/dist/public/initControlPlane-Bi8ouFEb.js +1 -0
- package/dist/public/llms.txt +36 -1
- package/dist/public/main/index.html +3 -3
- package/dist/public/main/memory/index.html +3 -3
- package/dist/public/{markdown-C3M4OW_A.js → markdown-C-hCVJtc.js} +1 -1
- package/dist/public/orchestrator-8qNGfw8r.js +15 -0
- package/dist/public/{orchestrator-DHjdLtqa.js → orchestrator-BT3Ks5ip.js} +2 -2
- package/dist/public/peerjs-DfhwEiiq.js +1 -0
- package/dist/public/push-client-BVLrE9pK.js +1 -0
- package/dist/public/service-worker/fetch-proxy.js +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-EAt2ml5Y.js → shadow-claw-DCjxNDCX.js} +3 -3
- package/dist/public/{shadow-claw-channels-XsfuWFF8.js → shadow-claw-channels-CITDrqMl.js} +1 -1
- package/dist/public/{shadow-claw-chat-CbSaOZ4q.js → shadow-claw-chat-BQrSgSKF.js} +1 -1
- package/dist/public/{shadow-claw-control-plane-DHvN3Ukg.js → shadow-claw-control-plane-Cp001OY0.js} +2 -2
- package/dist/public/{shadow-claw-conversations-BWs5VVfs.js → shadow-claw-conversations-EhX4RvIj.js} +1 -1
- package/dist/public/{shadow-claw-file-viewer-BWsoW5QS.js → shadow-claw-file-viewer-DiQXIjZD.js} +1 -1
- package/dist/public/{shadow-claw-files-CG7MqWiV.js → shadow-claw-files-lkTnSJsn.js} +1 -1
- package/dist/public/{shadow-claw-git-DBRPZNav.js → shadow-claw-git-BlcA_z8x.js} +2 -2
- package/dist/public/{shadow-claw-llm-DMvLgKXo.js → shadow-claw-llm-CW16X9Rg.js} +1 -1
- package/dist/public/{shadow-claw-networking-Dd8Rw31D.js → shadow-claw-networking-ySsMBY_i.js} +1 -1
- package/dist/public/{shadow-claw-notifications-Dbevj-lq.js → shadow-claw-notifications-CyV2zCQ8.js} +1 -1
- package/dist/public/{shadow-claw-pages-3_lQAv0t.js → shadow-claw-pages-Cx7cF9ah.js} +1 -1
- package/dist/public/{shadow-claw-settings-t8TIlgrM.js → shadow-claw-settings-zm4PHHGi.js} +2 -2
- package/dist/public/{shadow-claw-storage-CfEXoSIE.js → shadow-claw-storage-dy9JAEGd.js} +1 -1
- package/dist/public/{shadow-claw-task-server-DxQSsgRZ.js → shadow-claw-task-server-Bleww48s.js} +2 -2
- package/dist/public/{shadow-claw-tasks-DNpicQwz.js → shadow-claw-tasks-CTI5oaLN.js} +1 -1
- package/dist/public/{shadow-claw-terminal-DpY6zU_r.js → shadow-claw-terminal-mZ3i4HaQ.js} +1 -1
- package/dist/public/{shadow-claw-tools-WSwWohnk.js → shadow-claw-tools-B_nuk8Zl.js} +1 -1
- package/dist/public/{shadow-claw-webvm-CP6oFjg5.js → shadow-claw-webvm-Vl_jH5YL.js} +1 -1
- package/dist/public/{syncWebMcpRegistration-DOn9gLnD.js → syncWebMcpRegistration-n2vAMJ4w.js} +1 -1
- package/dist/server.js +197 -187
- package/package.json +2 -1
- package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.test.ts +6 -0
- package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.ts +19 -9
- package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.test.ts +14 -0
- package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.ts +12 -0
- package/src/components/shadow-claw/shadow-claw.ts +6 -0
- package/src/components/shadow-claw/utils/bindEventListeners.test.ts +57 -0
- package/src/components/shadow-claw/utils/bindEventListeners.ts +14 -0
- package/src/components/shadow-claw/utils/setupAppLifecycle.test.ts +201 -0
- package/src/components/shadow-claw/utils/setupAppLifecycle.ts +101 -0
- package/src/core/control-plane-client.test.ts +82 -1
- package/src/core/control-plane-client.ts +35 -1
- package/src/core/orchestrator/orchestrator.test.ts +49 -0
- package/src/core/orchestrator/orchestrator.ts +43 -0
- package/src/core/orchestrator/utils/operations/channel.test.ts +17 -0
- package/src/core/orchestrator/utils/operations/channel.ts +11 -5
- package/src/core/orchestrator/utils/operations/task.test.ts +26 -0
- package/src/core/orchestrator/utils/operations/task.ts +8 -1
- package/src/core/utils/initControlPlane.test.ts +138 -0
- package/src/core/utils/initControlPlane.ts +82 -0
- package/src/core/utils/initializeApp.test.ts +27 -1
- package/src/core/utils/initializeApp.ts +6 -13
- package/src/server/mcp/mcp-server.test.ts +6 -0
- package/src/server/mcp/mcp-server.ts +2 -1
- package/src/server/mcp/tools/built-in-tools.ts +88 -1
- package/src/server/mcp/tools/client-tool-relay.ts +6 -0
- package/src/server/mcp/tools/mcp-tools.test.ts +128 -0
- package/src/server/openapi/openapi-coverage.test.ts +2 -1
- package/src/server/openapi/openapi-spec.ts +2 -1
- package/src/server/openapi/paths/mcp.ts +104 -0
- package/src/server/openapi/paths/push.ts +3 -0
- package/src/server/routes/mcp.test.ts +92 -0
- package/src/server/routes/mcp.ts +138 -2
- package/src/server/utils/packageVersion.test.ts +10 -0
- package/src/server/utils/packageVersion.ts +32 -0
- package/src/service-worker/fetch-proxy-rules.test.ts +73 -0
- package/src/service-worker/fetch-proxy-rules.ts +44 -0
- package/src/service-worker/fetch-proxy.ts +1 -1
- package/src/subsystems/channels/imessage.test.ts +36 -0
- package/src/subsystems/channels/imessage.ts +11 -0
- package/src/subsystems/channels/peerjs.test.ts +56 -0
- package/src/subsystems/channels/peerjs.ts +29 -0
- package/src/subsystems/channels/telegram.test.ts +38 -0
- package/src/subsystems/channels/telegram.ts +13 -0
- package/src/subsystems/channels/types.ts +2 -0
- package/src/subsystems/notifications/push-client.test.ts +70 -0
- package/src/subsystems/notifications/push-client.ts +28 -3
- package/src/subsystems/notifications/push-routes.test.ts +82 -0
- package/src/subsystems/notifications/push-routes.ts +70 -16
- package/src/subsystems/notifications/push-store.test.ts +59 -0
- package/src/subsystems/notifications/push-store.ts +113 -19
- package/src/testing/jest-setup.ts +15 -0
- package/dist/lib/initControlPlane-C2zURVIS.js.map +0 -1
- package/dist/lib/orchestrator-CACLa_Ro.js.map +0 -1
- package/dist/lib/peerjs-DFWOBcXf.js.map +0 -1
- package/dist/lib/push-client-_tiWQsCT.js.map +0 -1
- package/dist/lib/shadow-claw-6UHdiy4a.js.map +0 -1
- package/dist/lib/shadow-claw-control-plane-UG0o7pCz.js.map +0 -1
- package/dist/public/initControlPlane-BN9cWyO0.js +0 -1
- package/dist/public/orchestrator-CMbCTjBf.js +0 -15
- package/dist/public/peerjs-DUCKH-m9.js +0 -1
- package/dist/public/push-client-D0lkwrK0.js +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>ShadowClaw MCP Server Discovery</title>
|
|
6
|
+
<meta name="description" content="ShadowClaw MCP Server Card and Discovery metadata">
|
|
7
|
+
<link rel="alternate" type="application/json" href="../mcp.json" title="MCP Server Card">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<h1>ShadowClaw MCP Server Discovery</h1>
|
|
11
|
+
<p>Model Context Protocol (MCP) server endpoints and discovery metadata for ShadowClaw.</p>
|
|
12
|
+
<ul>
|
|
13
|
+
<li><a href="../mcp.json">MCP Server Card (SEP-2127)</a></li>
|
|
14
|
+
<li><a href="../ai-catalog.json">AI Catalog Discovery</a></li>
|
|
15
|
+
<li><a href="servers.json">Servers Manifest (Discussion #1147)</a></li>
|
|
16
|
+
<li><a href="../oauth-protected-resource">OAuth Protected Resource Metadata (RFC 9728)</a></li>
|
|
17
|
+
</ul>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://modelcontextprotocol.io/schemas/server-card/v1.json",
|
|
3
|
+
"name": "shadow-claw",
|
|
4
|
+
"version": "1.28.0",
|
|
5
|
+
"description": "Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.",
|
|
6
|
+
"title": "ShadowClaw MCP Server",
|
|
7
|
+
"websiteUrl": "https://xt-ml.github.io/shadow-claw/",
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "https://github.com/xt-ml/shadow-claw",
|
|
10
|
+
"source": "github"
|
|
11
|
+
},
|
|
12
|
+
"icons": [
|
|
13
|
+
{
|
|
14
|
+
"src": "https://xt-ml.github.io/shadow-claw/assets/icons/favicon.svg",
|
|
15
|
+
"mimeType": "image/svg+xml",
|
|
16
|
+
"sizes": [
|
|
17
|
+
"any"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"src": "https://xt-ml.github.io/shadow-claw/assets/icons/512.png",
|
|
22
|
+
"mimeType": "image/png",
|
|
23
|
+
"sizes": [
|
|
24
|
+
"512x512"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"remotes": [
|
|
29
|
+
{
|
|
30
|
+
"type": "streamable-http",
|
|
31
|
+
"url": "http://localhost:8888/mcp",
|
|
32
|
+
"supportedProtocolVersions": [
|
|
33
|
+
"2026-07-28",
|
|
34
|
+
"2025-11-25",
|
|
35
|
+
"2024-11-05"
|
|
36
|
+
],
|
|
37
|
+
"headers": [
|
|
38
|
+
{
|
|
39
|
+
"name": "MCP-Protocol-Version",
|
|
40
|
+
"default": "2026-07-28",
|
|
41
|
+
"isRequired": false
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "x-control-token",
|
|
45
|
+
"description": "Control plane token for authorized client access",
|
|
46
|
+
"isSecret": true,
|
|
47
|
+
"isRequired": false
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"servers": [
|
|
4
|
+
{
|
|
5
|
+
"name": "shadow-claw",
|
|
6
|
+
"description": "ShadowClaw Browser-Native AI Assistant MCP Server",
|
|
7
|
+
"endpoint": "http://localhost:8888/mcp",
|
|
8
|
+
"capabilities": [
|
|
9
|
+
"tools",
|
|
10
|
+
"extensions"
|
|
11
|
+
],
|
|
12
|
+
"card": "https://xt-ml.github.io/shadow-claw/.well-known/mcp.json"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://modelcontextprotocol.io/schemas/server-card/v1.json",
|
|
3
|
+
"name": "shadow-claw",
|
|
4
|
+
"version": "1.28.0",
|
|
5
|
+
"description": "Browser-native personal AI assistant with local and remote LLM orchestration, Web Workers, OPFS storage, and agentic tool execution.",
|
|
6
|
+
"title": "ShadowClaw MCP Server",
|
|
7
|
+
"websiteUrl": "https://xt-ml.github.io/shadow-claw/",
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "https://github.com/xt-ml/shadow-claw",
|
|
10
|
+
"source": "github"
|
|
11
|
+
},
|
|
12
|
+
"icons": [
|
|
13
|
+
{
|
|
14
|
+
"src": "https://xt-ml.github.io/shadow-claw/assets/icons/favicon.svg",
|
|
15
|
+
"mimeType": "image/svg+xml",
|
|
16
|
+
"sizes": [
|
|
17
|
+
"any"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"src": "https://xt-ml.github.io/shadow-claw/assets/icons/512.png",
|
|
22
|
+
"mimeType": "image/png",
|
|
23
|
+
"sizes": [
|
|
24
|
+
"512x512"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"remotes": [
|
|
29
|
+
{
|
|
30
|
+
"type": "streamable-http",
|
|
31
|
+
"url": "http://localhost:8888/mcp",
|
|
32
|
+
"supportedProtocolVersions": [
|
|
33
|
+
"2026-07-28",
|
|
34
|
+
"2025-11-25",
|
|
35
|
+
"2024-11-05"
|
|
36
|
+
],
|
|
37
|
+
"headers": [
|
|
38
|
+
{
|
|
39
|
+
"name": "MCP-Protocol-Version",
|
|
40
|
+
"default": "2026-07-28",
|
|
41
|
+
"isRequired": false
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "x-control-token",
|
|
45
|
+
"description": "Control plane token for authorized client access",
|
|
46
|
+
"isSecret": true,
|
|
47
|
+
"isRequired": false
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
@@ -49,15 +49,21 @@ export async function assertVersionBump({
|
|
|
49
49
|
pkgName,
|
|
50
50
|
publishedVersion,
|
|
51
51
|
silent = false,
|
|
52
|
+
wellKnownMcpVersion,
|
|
53
|
+
wellKnownServerCardVersion,
|
|
52
54
|
}) {
|
|
53
55
|
if (!silent) {
|
|
54
56
|
console.log(`Checking version bump for package "${pkgName}"...`);
|
|
55
|
-
console.log(
|
|
57
|
+
console.log(
|
|
58
|
+
`- Local package.json version : ${localPkgVersion}`,
|
|
59
|
+
);
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
if (localLockVersion) {
|
|
59
63
|
if (!silent) {
|
|
60
|
-
console.log(
|
|
64
|
+
console.log(
|
|
65
|
+
`- Local package-lock.json version : ${localLockVersion}`,
|
|
66
|
+
);
|
|
61
67
|
}
|
|
62
68
|
if (localPkgVersion !== localLockVersion) {
|
|
63
69
|
throw new Error(
|
|
@@ -66,9 +72,40 @@ export async function assertVersionBump({
|
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
|
|
75
|
+
if (wellKnownMcpVersion !== undefined && wellKnownMcpVersion !== null) {
|
|
76
|
+
if (!silent) {
|
|
77
|
+
console.log(
|
|
78
|
+
`- Local .well-known/mcp.json version : ${wellKnownMcpVersion}`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (localPkgVersion !== wellKnownMcpVersion) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Version mismatch: package.json (${localPkgVersion}) does not match .well-known/mcp.json (${wellKnownMcpVersion})!`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
wellKnownServerCardVersion !== undefined &&
|
|
90
|
+
wellKnownServerCardVersion !== null
|
|
91
|
+
) {
|
|
92
|
+
if (!silent) {
|
|
93
|
+
console.log(
|
|
94
|
+
`- Local .well-known/mcp/server-card version: ${wellKnownServerCardVersion}`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (localPkgVersion !== wellKnownServerCardVersion) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`Version mismatch: package.json (${localPkgVersion}) does not match .well-known/mcp/server-card.json (${wellKnownServerCardVersion})!`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
69
104
|
if (publishedVersion) {
|
|
70
105
|
if (!silent) {
|
|
71
|
-
console.log(
|
|
106
|
+
console.log(
|
|
107
|
+
`- Published npm registry version : ${publishedVersion}`,
|
|
108
|
+
);
|
|
72
109
|
}
|
|
73
110
|
const cmp = compareSemver(localPkgVersion, publishedVersion);
|
|
74
111
|
if (cmp <= 0) {
|
|
@@ -98,6 +135,25 @@ async function main() {
|
|
|
98
135
|
const localPkgVersion = pkg.version;
|
|
99
136
|
const localLockVersion = lock?.version;
|
|
100
137
|
|
|
138
|
+
let wellKnownMcpVersion = null;
|
|
139
|
+
try {
|
|
140
|
+
const mcpJson = JSON.parse(
|
|
141
|
+
await readFile(path.join(rootDir, ".well-known/mcp.json"), "utf8"),
|
|
142
|
+
);
|
|
143
|
+
wellKnownMcpVersion = mcpJson?.version || null;
|
|
144
|
+
} catch {}
|
|
145
|
+
|
|
146
|
+
let wellKnownServerCardVersion = null;
|
|
147
|
+
try {
|
|
148
|
+
const serverCard = JSON.parse(
|
|
149
|
+
await readFile(
|
|
150
|
+
path.join(rootDir, ".well-known/mcp/server-card.json"),
|
|
151
|
+
"utf8",
|
|
152
|
+
),
|
|
153
|
+
);
|
|
154
|
+
wellKnownServerCardVersion = serverCard?.version || null;
|
|
155
|
+
} catch {}
|
|
156
|
+
|
|
101
157
|
let publishedVersion = null;
|
|
102
158
|
try {
|
|
103
159
|
const rawOut = execSync(`npm view ${pkgName} version --json`, {
|
|
@@ -129,6 +185,8 @@ async function main() {
|
|
|
129
185
|
localLockVersion,
|
|
130
186
|
pkgName,
|
|
131
187
|
publishedVersion,
|
|
188
|
+
wellKnownMcpVersion,
|
|
189
|
+
wellKnownServerCardVersion,
|
|
132
190
|
});
|
|
133
191
|
}
|
|
134
192
|
|
|
@@ -73,7 +73,83 @@ describe("assert-version-bump", () => {
|
|
|
73
73
|
publishedVersion: "1.23.2",
|
|
74
74
|
silent: true,
|
|
75
75
|
}),
|
|
76
|
-
).rejects.toThrow(
|
|
76
|
+
).rejects.toThrow(
|
|
77
|
+
"Version mismatch: package.json (1.23.4) does not match package-lock.json (1.23.3)!",
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("throws when package.json does not match .well-known/mcp.json", async () => {
|
|
82
|
+
await expect(
|
|
83
|
+
assertVersionBump({
|
|
84
|
+
localPkgVersion: "1.23.4",
|
|
85
|
+
localLockVersion: "1.23.4",
|
|
86
|
+
wellKnownMcpVersion: "1.23.3",
|
|
87
|
+
pkgName: "shadow-claw",
|
|
88
|
+
publishedVersion: "1.23.2",
|
|
89
|
+
silent: true,
|
|
90
|
+
}),
|
|
91
|
+
).rejects.toThrow(
|
|
92
|
+
"Version mismatch: package.json (1.23.4) does not match .well-known/mcp.json (1.23.3)!",
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("throws when package.json does not match .well-known/mcp/server-card.json", async () => {
|
|
97
|
+
await expect(
|
|
98
|
+
assertVersionBump({
|
|
99
|
+
localPkgVersion: "1.23.4",
|
|
100
|
+
localLockVersion: "1.23.4",
|
|
101
|
+
wellKnownMcpVersion: "1.23.4",
|
|
102
|
+
wellKnownServerCardVersion: "1.23.3",
|
|
103
|
+
pkgName: "shadow-claw",
|
|
104
|
+
publishedVersion: "1.23.2",
|
|
105
|
+
silent: true,
|
|
106
|
+
}),
|
|
107
|
+
).rejects.toThrow(
|
|
108
|
+
"Version mismatch: package.json (1.23.4) does not match .well-known/mcp/server-card.json (1.23.3)!",
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("passes when package.json, lockfile, and .well-known versions all match", async () => {
|
|
113
|
+
await expect(
|
|
114
|
+
assertVersionBump({
|
|
115
|
+
localPkgVersion: "1.23.4",
|
|
116
|
+
localLockVersion: "1.23.4",
|
|
117
|
+
wellKnownMcpVersion: "1.23.4",
|
|
118
|
+
wellKnownServerCardVersion: "1.23.4",
|
|
119
|
+
pkgName: "shadow-claw",
|
|
120
|
+
publishedVersion: "1.23.3",
|
|
121
|
+
silent: true,
|
|
122
|
+
}),
|
|
123
|
+
).resolves.toBeUndefined();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe("repository live version parity", () => {
|
|
128
|
+
it("verifies package.json, package-lock.json, and .well-known discovery files are strictly in sync", async () => {
|
|
129
|
+
const { readFile } = await import("node:fs/promises");
|
|
130
|
+
const { fileURLToPath } = await import("node:url");
|
|
131
|
+
const path = await import("node:path");
|
|
132
|
+
const rootDir = fileURLToPath(new URL("..", import.meta.url));
|
|
133
|
+
|
|
134
|
+
const pkg = JSON.parse(
|
|
135
|
+
await readFile(path.join(rootDir, "package.json"), "utf8"),
|
|
136
|
+
);
|
|
137
|
+
const lock = JSON.parse(
|
|
138
|
+
await readFile(path.join(rootDir, "package-lock.json"), "utf8"),
|
|
139
|
+
);
|
|
140
|
+
const mcpJson = JSON.parse(
|
|
141
|
+
await readFile(path.join(rootDir, ".well-known/mcp.json"), "utf8"),
|
|
142
|
+
);
|
|
143
|
+
const serverCard = JSON.parse(
|
|
144
|
+
await readFile(
|
|
145
|
+
path.join(rootDir, ".well-known/mcp/server-card.json"),
|
|
146
|
+
"utf8",
|
|
147
|
+
),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(lock.version).toBe(pkg.version);
|
|
151
|
+
expect(mcpJson.version).toBe(pkg.version);
|
|
152
|
+
expect(serverCard.version).toBe(pkg.version);
|
|
77
153
|
});
|
|
78
154
|
});
|
|
79
155
|
});
|
package/bin/build/build.mjs
CHANGED
|
@@ -149,19 +149,15 @@ export async function runBuild(options = {}) {
|
|
|
149
149
|
const { generateSkillsIndex } =
|
|
150
150
|
await import("../commands/skills-index.mjs");
|
|
151
151
|
await generateSkillsIndex(projectRoot);
|
|
152
|
-
if (await pathExists(".well-known/agent-skills/index.json")) {
|
|
153
|
-
await cp(".well-known", "dist/public/.well-known", {
|
|
154
|
-
recursive: true,
|
|
155
|
-
force: true,
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
152
|
} catch (err) {
|
|
159
153
|
console.warn(
|
|
160
154
|
"Notice: Failed to auto-generate agent-skills index:",
|
|
161
155
|
err,
|
|
162
156
|
);
|
|
163
157
|
}
|
|
164
|
-
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (await pathExists(".well-known")) {
|
|
165
161
|
try {
|
|
166
162
|
await cp(".well-known", "dist/public/.well-known", {
|
|
167
163
|
recursive: true,
|
|
@@ -190,6 +186,42 @@ export async function runBuild(options = {}) {
|
|
|
190
186
|
await run(`node bin/site-config/apply.mjs dist/public ${siteConfigPath}`);
|
|
191
187
|
} catch {}
|
|
192
188
|
|
|
189
|
+
try {
|
|
190
|
+
const pkgJson = JSON.parse(await readFile("package.json", "utf8"));
|
|
191
|
+
if (pkgJson.version) {
|
|
192
|
+
const idxPath = "dist/public/index.html";
|
|
193
|
+
const idxHtml = await readFile(idxPath, "utf8");
|
|
194
|
+
await writeFile(
|
|
195
|
+
idxPath,
|
|
196
|
+
idxHtml.replace(
|
|
197
|
+
/<meta\s+name="version"[^>]*>/,
|
|
198
|
+
`<meta name="version" content="${pkgJson.version}" />`,
|
|
199
|
+
),
|
|
200
|
+
"utf8",
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
for (const relPath of [
|
|
204
|
+
".well-known/mcp.json",
|
|
205
|
+
".well-known/mcp/server-card.json",
|
|
206
|
+
]) {
|
|
207
|
+
const cardPath = join("dist/public", relPath);
|
|
208
|
+
if (await pathExists(cardPath)) {
|
|
209
|
+
try {
|
|
210
|
+
const card = JSON.parse(await readFile(cardPath, "utf8"));
|
|
211
|
+
if (card.version !== pkgJson.version) {
|
|
212
|
+
card.version = pkgJson.version;
|
|
213
|
+
await writeFile(
|
|
214
|
+
cardPath,
|
|
215
|
+
JSON.stringify(card, null, 2) + "\n",
|
|
216
|
+
"utf8",
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
} catch {}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} catch {}
|
|
224
|
+
|
|
193
225
|
if (isProduction) {
|
|
194
226
|
log("Running production post-build steps...");
|
|
195
227
|
|
|
@@ -225,6 +257,7 @@ export async function runBuild(options = {}) {
|
|
|
225
257
|
try {
|
|
226
258
|
meta = execSync("npm run -s build:pkg:get:meta", {
|
|
227
259
|
encoding: "utf8",
|
|
260
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
228
261
|
}).trim();
|
|
229
262
|
} catch {}
|
|
230
263
|
if (meta) {
|
|
@@ -388,51 +421,43 @@ export async function runBuild(options = {}) {
|
|
|
388
421
|
}
|
|
389
422
|
}
|
|
390
423
|
|
|
391
|
-
// 6b.
|
|
392
|
-
|
|
424
|
+
// 6b. Copy .well-known discovery files & generate/sync Agent Skills index
|
|
425
|
+
const toolchainWellKnown = join(toolchainRoot, ".well-known");
|
|
426
|
+
if (await pathExists(toolchainWellKnown)) {
|
|
427
|
+
await cp(toolchainWellKnown, join(distPublicDir, ".well-known"), {
|
|
428
|
+
recursive: true,
|
|
429
|
+
force: true,
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const contentWellKnown = join(contentRoot, ".well-known");
|
|
434
|
+
if (contentRoot !== toolchainRoot && (await pathExists(contentWellKnown))) {
|
|
435
|
+
await cp(contentWellKnown, join(distPublicDir, ".well-known"), {
|
|
436
|
+
recursive: true,
|
|
437
|
+
force: true,
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const distSkillsDir = join(distPublicDir, ".agents/skills");
|
|
442
|
+
if (await pathExists(distSkillsDir)) {
|
|
393
443
|
try {
|
|
394
444
|
const { generateSkillsIndex } =
|
|
395
445
|
await import("../commands/skills-index.mjs");
|
|
396
|
-
await generateSkillsIndex(
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
if (await pathExists(
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
},
|
|
409
|
-
);
|
|
446
|
+
await generateSkillsIndex(distPublicDir, {
|
|
447
|
+
metadataRoot: contentRoot,
|
|
448
|
+
outDir: ".well-known/agent-skills",
|
|
449
|
+
});
|
|
450
|
+
// Also keep contentRoot/.well-known/agent-skills/index.json in sync if contentSkills exists
|
|
451
|
+
if (await pathExists(contentSkills)) {
|
|
452
|
+
try {
|
|
453
|
+
await generateSkillsIndex(contentRoot, {
|
|
454
|
+
toolchainRoot,
|
|
455
|
+
includeBundled: true,
|
|
456
|
+
});
|
|
457
|
+
} catch {}
|
|
410
458
|
}
|
|
411
459
|
} catch (err) {
|
|
412
460
|
console.warn("Notice: Failed to auto-generate agent-skills index:", err);
|
|
413
|
-
const contentWellKnown = join(contentRoot, ".well-known");
|
|
414
|
-
if (await pathExists(contentWellKnown)) {
|
|
415
|
-
await cp(contentWellKnown, join(distPublicDir, ".well-known"), {
|
|
416
|
-
recursive: true,
|
|
417
|
-
force: true,
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
} else {
|
|
422
|
-
const contentWellKnown = join(contentRoot, ".well-known");
|
|
423
|
-
if (await pathExists(contentWellKnown)) {
|
|
424
|
-
await cp(contentWellKnown, join(distPublicDir, ".well-known"), {
|
|
425
|
-
recursive: true,
|
|
426
|
-
force: true,
|
|
427
|
-
});
|
|
428
|
-
} else {
|
|
429
|
-
const toolchainWellKnown = join(toolchainRoot, ".well-known");
|
|
430
|
-
if (await pathExists(toolchainWellKnown)) {
|
|
431
|
-
await cp(toolchainWellKnown, join(distPublicDir, ".well-known"), {
|
|
432
|
-
recursive: true,
|
|
433
|
-
force: true,
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
461
|
}
|
|
437
462
|
}
|
|
438
463
|
|
|
@@ -470,12 +495,51 @@ export async function runBuild(options = {}) {
|
|
|
470
495
|
const basePath = defaultBasePath;
|
|
471
496
|
|
|
472
497
|
try {
|
|
473
|
-
|
|
474
|
-
|
|
498
|
+
let idxHtml = await readFile(indexPath, "utf8");
|
|
499
|
+
idxHtml = idxHtml.replace(
|
|
475
500
|
/<base\s+href="[^"]*"\s*\/?>/i,
|
|
476
501
|
`<base href="${basePath}" />`,
|
|
477
502
|
);
|
|
478
|
-
|
|
503
|
+
|
|
504
|
+
let pkgVersion = "";
|
|
505
|
+
try {
|
|
506
|
+
const pkgPath = await findFirstExistingPath([
|
|
507
|
+
join(contentRoot, "package.json"),
|
|
508
|
+
join(toolchainRoot, "package.json"),
|
|
509
|
+
]);
|
|
510
|
+
if (pkgPath) {
|
|
511
|
+
const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
|
|
512
|
+
pkgVersion = pkg.version || "";
|
|
513
|
+
}
|
|
514
|
+
} catch {}
|
|
515
|
+
|
|
516
|
+
if (pkgVersion) {
|
|
517
|
+
idxHtml = idxHtml.replace(
|
|
518
|
+
/<meta\s+name="version"[^>]*>/,
|
|
519
|
+
`<meta name="version" content="${pkgVersion}" />`,
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
for (const relPath of [
|
|
523
|
+
".well-known/mcp.json",
|
|
524
|
+
".well-known/mcp/server-card.json",
|
|
525
|
+
]) {
|
|
526
|
+
const cardPath = join(distPublicDir, relPath);
|
|
527
|
+
if (await pathExists(cardPath)) {
|
|
528
|
+
try {
|
|
529
|
+
const card = JSON.parse(await readFile(cardPath, "utf8"));
|
|
530
|
+
if (card.version !== pkgVersion) {
|
|
531
|
+
card.version = pkgVersion;
|
|
532
|
+
await writeFile(
|
|
533
|
+
cardPath,
|
|
534
|
+
JSON.stringify(card, null, 2) + "\n",
|
|
535
|
+
"utf8",
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
} catch {}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
await writeFile(indexPath, idxHtml, "utf8");
|
|
479
543
|
} catch {}
|
|
480
544
|
|
|
481
545
|
if (isProduction) {
|
|
@@ -508,15 +572,18 @@ export async function runBuild(options = {}) {
|
|
|
508
572
|
meta = execSync("git rev-parse HEAD", {
|
|
509
573
|
cwd: contentRoot,
|
|
510
574
|
encoding: "utf8",
|
|
575
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
511
576
|
}).trim();
|
|
512
577
|
} catch {
|
|
513
578
|
try {
|
|
514
579
|
meta = execSync("git rev-parse HEAD", {
|
|
515
580
|
cwd: toolchainRoot,
|
|
516
581
|
encoding: "utf8",
|
|
582
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
517
583
|
}).trim();
|
|
518
584
|
} catch {}
|
|
519
585
|
}
|
|
586
|
+
|
|
520
587
|
if (meta) {
|
|
521
588
|
const idxHtml = await readFile(indexPath, "utf8");
|
|
522
589
|
await writeFile(
|