nextclaw 0.44.2 → 0.45.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.
Files changed (144) hide show
  1. package/dist/cli/app/index.js +2 -2
  2. package/dist/cli/launcher/index.js +1 -1
  3. package/dist/{nextclaw-cli-app-B_ffeXOD.js → nextclaw-cli-app-Bwa2L2Jv.js} +115 -22
  4. package/dist/nextclaw-cli-app-Bwa2L2Jv.js.map +1 -0
  5. package/dist/{nextclaw-distribution.utils-BneKclXo.js → nextclaw-distribution.utils-Bba2GRvc.js} +4 -2
  6. package/dist/nextclaw-distribution.utils-Bba2GRvc.js.map +1 -0
  7. package/package.json +10 -10
  8. package/resources/apps/nextclaw-portable-runtime-lab/README.md +34 -0
  9. package/resources/apps/nextclaw-portable-runtime-lab/assets/icon.svg +12 -0
  10. package/resources/apps/nextclaw-portable-runtime-lab/manifest.json +74 -0
  11. package/resources/apps/nextclaw-portable-runtime-lab/marketplace.json +21 -0
  12. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-contacts.panel/assets/app.js +92 -0
  13. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-contacts.panel/assets/style.css +43 -0
  14. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-contacts.panel/index.html +43 -0
  15. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-contacts.panel/panel-app.json +10 -0
  16. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-focus.panel/assets/app.js +132 -0
  17. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-focus.panel/assets/style.css +39 -0
  18. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-focus.panel/index.html +40 -0
  19. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-focus.panel/panel-app.json +14 -0
  20. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-notes.panel/assets/app.js +117 -0
  21. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-notes.panel/assets/style.css +41 -0
  22. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-notes.panel/index.html +41 -0
  23. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-notes.panel/panel-app.json +12 -0
  24. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-panel.panel/assets/app.js +266 -0
  25. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-panel.panel/assets/style.css +87 -0
  26. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-panel.panel/index.html +154 -0
  27. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-panel.panel/panel-app.json +29 -0
  28. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-todos.panel/assets/app.js +143 -0
  29. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-todos.panel/assets/style.css +48 -0
  30. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-todos.panel/index.html +45 -0
  31. package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-todos.panel/panel-app.json +12 -0
  32. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-capabilities/service-app.json +20 -0
  33. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-capabilities/service.wasm +0 -0
  34. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-composition/service-app.json +30 -0
  35. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-composition/service.wasm +0 -0
  36. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-provider/service-app.json +30 -0
  37. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-provider/service.wasm +0 -0
  38. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-resident/service-app.json +31 -0
  39. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-resident/service.wasm +0 -0
  40. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-state/service-app.json +49 -0
  41. package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-state/service.wasm +0 -0
  42. package/ui-dist/assets/{api-DNLQPHfQ.js → api-m33O1Kb0.js} +3 -3
  43. package/ui-dist/assets/api-m33O1Kb0.js.gz +0 -0
  44. package/ui-dist/assets/{appearance-settings-page-BlAFMOGV.js → appearance-settings-page-x4Vjnfmz.js} +1 -1
  45. package/ui-dist/assets/appearance-settings-page-x4Vjnfmz.js.gz +0 -0
  46. package/ui-dist/assets/{book-open-BryfPTTa.js → book-open-BHiasMCg.js} +1 -1
  47. package/ui-dist/assets/{channels-list-page-Cfbgubyv.js → channels-list-page-DOxJZeXq.js} +1 -1
  48. package/ui-dist/assets/channels-list-page-DOxJZeXq.js.gz +0 -0
  49. package/ui-dist/assets/{config-split-page-Dd8xG0Jk.js → config-split-page-DBnMEP1o.js} +1 -1
  50. package/ui-dist/assets/config-split-page-DBnMEP1o.js.gz +0 -0
  51. package/ui-dist/assets/{confirm-dialog-CZIWjnJ6.js → confirm-dialog-f5NKLh5I.js} +2 -2
  52. package/ui-dist/assets/confirm-dialog-f5NKLh5I.js.gz +0 -0
  53. package/ui-dist/assets/{createLucideIcon-BxwVe8ZD.js → createLucideIcon-CHALGA42.js} +1 -1
  54. package/ui-dist/assets/{desktop-capabilities-page-C6YxsHeV.js → desktop-capabilities-page-DixayAe6.js} +1 -1
  55. package/ui-dist/assets/desktop-capabilities-page-DixayAe6.js.gz +0 -0
  56. package/ui-dist/assets/{desktop-update-config-BVN4QPJn.js → desktop-update-config-ChhfeOHj.js} +1 -1
  57. package/ui-dist/assets/desktop-update-config-ChhfeOHj.js.gz +0 -0
  58. package/ui-dist/assets/{dist-Cd8Nm3BW.js → dist-_UMsWSY0.js} +1 -1
  59. package/ui-dist/assets/{dist-Cd8Nm3BW.js.gz → dist-_UMsWSY0.js.gz} +0 -0
  60. package/ui-dist/assets/{dist-BRloKr3S.js → dist-sD6V4nHX.js} +1 -1
  61. package/ui-dist/assets/dist-sD6V4nHX.js.gz +0 -0
  62. package/ui-dist/assets/doc-browser-Bq7LJsQY.js +1 -0
  63. package/ui-dist/assets/doc-browser-Bq7LJsQY.js.gz +0 -0
  64. package/ui-dist/assets/doc-browser-BuDgpY2e.js +1 -0
  65. package/ui-dist/assets/{doc-browser-context-3JGufiMA.js → doc-browser-context-Capim3og.js} +1 -1
  66. package/ui-dist/assets/doc-browser-context-Capim3og.js.gz +0 -0
  67. package/ui-dist/assets/{extensions-Dedd2oDI.js → extensions-Bdclr3Wr.js} +1 -1
  68. package/ui-dist/assets/extensions-Bdclr3Wr.js.gz +0 -0
  69. package/ui-dist/assets/{form-actions-FWCEof3V.js → form-actions-CH0kWhEt.js} +1 -1
  70. package/ui-dist/assets/index-BjxnLYE3.js +109 -0
  71. package/ui-dist/assets/index-BjxnLYE3.js.gz +0 -0
  72. package/ui-dist/assets/index-CBmwJjwE.css +1 -0
  73. package/ui-dist/assets/index-CBmwJjwE.css.gz +0 -0
  74. package/ui-dist/assets/loader-circle-CH_0iPLy.js +1 -0
  75. package/ui-dist/assets/{mcp-marketplace-page-e9Rmfz-d.js → mcp-marketplace-page-BUsxLVB5.js} +2 -2
  76. package/ui-dist/assets/mcp-marketplace-page-BUsxLVB5.js.gz +0 -0
  77. package/ui-dist/assets/mcp-marketplace-page-GPRV3fB0.js +1 -0
  78. package/ui-dist/assets/{model-config-page-C173Ssil.js → model-config-page-CIevwqp4.js} +1 -1
  79. package/ui-dist/assets/model-config-page-CIevwqp4.js.gz +0 -0
  80. package/ui-dist/assets/{navigation-link-DTPOvGGL.js → navigation-link-CAUiM3zS.js} +1 -1
  81. package/ui-dist/assets/navigation-link-CAUiM3zS.js.gz +0 -0
  82. package/ui-dist/assets/plus-B3obD55V.js +1 -0
  83. package/ui-dist/assets/{privacy-settings-page-CRserBVF.js → privacy-settings-page-CNKfZsYH.js} +1 -1
  84. package/ui-dist/assets/privacy-settings-page-CNKfZsYH.js.gz +0 -0
  85. package/ui-dist/assets/{providers-config-page-C8jUtnZb.js → providers-config-page-DAah2NIS.js} +1 -1
  86. package/ui-dist/assets/providers-config-page-DAah2NIS.js.gz +0 -0
  87. package/ui-dist/assets/{react-BAzO6LZS.js → react-Co6JiC1n.js} +1 -1
  88. package/ui-dist/assets/react-Co6JiC1n.js.gz +0 -0
  89. package/ui-dist/assets/{refresh-cw-BCj-yjde.js → refresh-cw-BG_LX3SS.js} +1 -1
  90. package/ui-dist/assets/remote-DuscgfvR.js +1 -0
  91. package/ui-dist/assets/{rotate-cw-BPnW4qUl.js → rotate-cw-Cz7I_m7O.js} +1 -1
  92. package/ui-dist/assets/{runtime-config-page-aeQ1Dryz.js → runtime-config-page-Cl1RpmSC.js} +1 -1
  93. package/ui-dist/assets/runtime-config-page-Cl1RpmSC.js.gz +0 -0
  94. package/ui-dist/assets/{save-KT0MumfJ.js → save-BiHnb8ps.js} +1 -1
  95. package/ui-dist/assets/{search-Cv1Hx_nx.js → search-C47TyRg0.js} +1 -1
  96. package/ui-dist/assets/{search-config-page-b283V-fo.js → search-config-page-BAIzd6gN.js} +1 -1
  97. package/ui-dist/assets/search-config-page-BAIzd6gN.js.gz +0 -0
  98. package/ui-dist/assets/{secrets-config-page-ss7x3BOo.js → secrets-config-page-Ddi-n43R.js} +1 -1
  99. package/ui-dist/assets/secrets-config-page-Ddi-n43R.js.gz +0 -0
  100. package/ui-dist/assets/security-config-C8MHnE1r.js +1 -0
  101. package/ui-dist/assets/{select-BVgD4EpG.js → select-BzQKfW1e.js} +2 -2
  102. package/ui-dist/assets/select-BzQKfW1e.js.gz +0 -0
  103. package/ui-dist/assets/skeleton-BXFAE9SE.js +1 -0
  104. package/ui-dist/assets/{tag-chip-DZ4ircUB.js → tag-chip-C3K814HZ.js} +1 -1
  105. package/ui-dist/assets/x-C1r9IXet.js +1 -0
  106. package/ui-dist/index.html +29 -21
  107. package/ui-dist/index.html.gz +0 -0
  108. package/ui-dist/themes/island/island-atmosphere.webp +0 -0
  109. package/dist/nextclaw-cli-app-B_ffeXOD.js.map +0 -1
  110. package/dist/nextclaw-distribution.utils-BneKclXo.js.map +0 -1
  111. package/ui-dist/assets/api-DNLQPHfQ.js.gz +0 -0
  112. package/ui-dist/assets/appearance-settings-page-BlAFMOGV.js.gz +0 -0
  113. package/ui-dist/assets/channels-list-page-Cfbgubyv.js.gz +0 -0
  114. package/ui-dist/assets/config-split-page-Dd8xG0Jk.js.gz +0 -0
  115. package/ui-dist/assets/confirm-dialog-CZIWjnJ6.js.gz +0 -0
  116. package/ui-dist/assets/desktop-capabilities-page-C6YxsHeV.js.gz +0 -0
  117. package/ui-dist/assets/desktop-update-config-BVN4QPJn.js.gz +0 -0
  118. package/ui-dist/assets/dist-BRloKr3S.js.gz +0 -0
  119. package/ui-dist/assets/doc-browser-Bzgqmmiu.js +0 -1
  120. package/ui-dist/assets/doc-browser-Bzgqmmiu.js.gz +0 -0
  121. package/ui-dist/assets/doc-browser-D0qI0Z_R.js +0 -1
  122. package/ui-dist/assets/doc-browser-context-3JGufiMA.js.gz +0 -0
  123. package/ui-dist/assets/extensions-Dedd2oDI.js.gz +0 -0
  124. package/ui-dist/assets/index-CXkHcESm.css +0 -1
  125. package/ui-dist/assets/index-CXkHcESm.css.gz +0 -0
  126. package/ui-dist/assets/index-D25tRg1p.js +0 -109
  127. package/ui-dist/assets/index-D25tRg1p.js.gz +0 -0
  128. package/ui-dist/assets/loader-circle-BoyCoFps.js +0 -1
  129. package/ui-dist/assets/mcp-marketplace-page-Cn-9CDh3.js +0 -1
  130. package/ui-dist/assets/mcp-marketplace-page-e9Rmfz-d.js.gz +0 -0
  131. package/ui-dist/assets/model-config-page-C173Ssil.js.gz +0 -0
  132. package/ui-dist/assets/navigation-link-DTPOvGGL.js.gz +0 -0
  133. package/ui-dist/assets/plus-D1R4Vipq.js +0 -1
  134. package/ui-dist/assets/privacy-settings-page-CRserBVF.js.gz +0 -0
  135. package/ui-dist/assets/providers-config-page-C8jUtnZb.js.gz +0 -0
  136. package/ui-dist/assets/react-BAzO6LZS.js.gz +0 -0
  137. package/ui-dist/assets/remote-6BHWP5zi.js +0 -1
  138. package/ui-dist/assets/runtime-config-page-aeQ1Dryz.js.gz +0 -0
  139. package/ui-dist/assets/search-config-page-b283V-fo.js.gz +0 -0
  140. package/ui-dist/assets/secrets-config-page-ss7x3BOo.js.gz +0 -0
  141. package/ui-dist/assets/security-config-HHz62oxH.js +0 -1
  142. package/ui-dist/assets/select-BVgD4EpG.js.gz +0 -0
  143. package/ui-dist/assets/skeleton-ChUmcyys.js +0 -1
  144. package/ui-dist/assets/x-BWDRfVWL.js +0 -1
@@ -0,0 +1,154 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>开发者验证台</title>
7
+ <link rel="stylesheet" href="assets/style.css" />
8
+ </head>
9
+ <body>
10
+ <main class="shell">
11
+ <header class="hero">
12
+ <div>
13
+ <p class="eyebrow">RUST · WASM COMPONENT · HOST CAPABILITIES</p>
14
+ <h1>开发者验证台</h1>
15
+ <p class="lead">这里是四个日常小应用背后的技术证据。普通体验请直接打开「今日清单」「灵感便签」「专注小钟」或「联系人整理」。</p>
16
+ </div>
17
+ <span class="live-badge"><i></i> 可交互 Demo</span>
18
+ </header>
19
+
20
+ <section class="topology" aria-label="运行拓扑">
21
+ <div class="node guest">Action Components<small>State + Capability</small></div>
22
+ <span aria-hidden="true">→</span>
23
+ <div class="node host">Shared Runner<small>Wasmtime + WIT</small></div>
24
+ <span aria-hidden="true">←</span>
25
+ <div class="node guest">Resident Component<small>Retained instance + events</small></div>
26
+ </section>
27
+
28
+ <section class="scenario-grid" aria-label="验证场景">
29
+ <article class="scenario" data-scenario="shared">
30
+ <div class="scenario-copy">
31
+ <span class="number">01</span>
32
+ <div><h2>共享宿主</h2><p>分别调用两个 Component,比较 runner PID 与已加载模块数。</p></div>
33
+ </div>
34
+ <button type="button" data-run="shared">验证同一进程</button>
35
+ <pre class="result" aria-live="polite">尚未执行</pre>
36
+ </article>
37
+
38
+ <article class="scenario data-workbench" data-scenario="data">
39
+ <div class="scenario-copy">
40
+ <span class="number">02</span>
41
+ <div><h2>结构化数据与持久化证据</h2><p>在 Rust/WASM 中执行 CRUD;Guest 只使用宿主 KV,数据位置与生命周期仍由 NextClaw 管理。</p></div>
42
+ </div>
43
+ <div class="data-editor">
44
+ <label>ID<input data-field="record-id" value="delta" maxlength="48" /></label>
45
+ <label>标题<input data-field="record-title" value="从 Agent 与 Panel 共用 Action" /></label>
46
+ <label>状态<select data-field="record-status"><option value="active">active</option><option value="pending">pending</option><option value="done">done</option></select></label>
47
+ </div>
48
+ <div class="button-row">
49
+ <button type="button" data-run="data-refresh" class="secondary">读取数据</button>
50
+ <button type="button" data-run="data-seed">生成 3 条基线</button>
51
+ <button type="button" data-run="data-save">创建或修改</button>
52
+ <button type="button" data-run="data-delete" class="danger">删除 ID</button>
53
+ </div>
54
+ <div class="data-table-wrap">
55
+ <table>
56
+ <thead><tr><th>ID</th><th>标题</th><th>状态</th><th>标签</th><th>版本</th></tr></thead>
57
+ <tbody data-records><tr><td colspan="5">尚未读取</td></tr></tbody>
58
+ </table>
59
+ </div>
60
+ <pre class="result data-meta" aria-live="polite">尚未执行</pre>
61
+ </article>
62
+
63
+ <article class="scenario resident-workbench" data-scenario="resident">
64
+ <div class="scenario-copy">
65
+ <span class="number">03</span>
66
+ <div><h2>Resident Service 与后台事件</h2><p>宿主保留同一个 WASM 实例,每秒投递真实 timer event;关闭 Panel 后仍继续。内存计数证明实例连续,durable cursor 证明跨重启恢复。</p></div>
67
+ </div>
68
+ <div class="button-row">
69
+ <button type="button" data-run="resident-refresh" class="secondary">读取当前状态</button>
70
+ <button type="button" data-run="resident-event">投递手动事件</button>
71
+ <button type="button" data-run="resident-reset" class="danger">重置事件证据</button>
72
+ </div>
73
+ <dl class="resident-metrics">
74
+ <div><dt>实例代次</dt><dd data-resident="epoch">—</dd></div>
75
+ <div><dt>内存事件数</dt><dd data-resident="memory-count">—</dd></div>
76
+ <div><dt>持久事件数</dt><dd data-resident="event-count">—</dd></div>
77
+ <div><dt>最后事件</dt><dd data-resident="last-event">—</dd></div>
78
+ </dl>
79
+ <div class="data-table-wrap">
80
+ <table>
81
+ <thead><tr><th>Event ID</th><th>类型</th><th>宿主投递时间</th></tr></thead>
82
+ <tbody data-resident-events><tr><td colspan="3">尚未读取</td></tr></tbody>
83
+ </table>
84
+ </div>
85
+ <pre class="result data-meta" aria-live="polite">尚未执行</pre>
86
+ </article>
87
+
88
+ <article class="scenario composition-workbench" data-scenario="composition">
89
+ <div class="scenario-copy">
90
+ <span class="number">04</span>
91
+ <div><h2>Component Provider 与跨模块组合</h2><p>Consumer 不包含联系人规范化逻辑,而是通过宿主调用 manifest 明确声明的独立 Provider;未声明的 Provider 会被宿主拒绝。</p></div>
92
+ </div>
93
+ <div class="data-editor composition-editor">
94
+ <label>姓名<input data-field="contact-name" value=" Ada Lovelace " /></label>
95
+ <label>邮箱<input data-field="contact-email" value=" ADA@EXAMPLE.COM " /></label>
96
+ <label>标签<input data-field="contact-tags" value="AI, ai, Math" /></label>
97
+ </div>
98
+ <div class="button-row">
99
+ <button type="button" data-run="composition-run">执行组合工作流</button>
100
+ <button type="button" data-run="provider-status" class="secondary">读取 Provider 状态</button>
101
+ <button type="button" data-run="provider-denied" class="danger">验证未声明拒绝</button>
102
+ </div>
103
+ <pre class="result composition-result" aria-live="polite">尚未执行</pre>
104
+ </article>
105
+
106
+ <article class="scenario" data-scenario="network">
107
+ <div class="scenario-copy">
108
+ <span class="number">05</span>
109
+ <div><h2>受控网络</h2><p>同一个 HTTP 原语:manifest 白名单内放行,白名单外明确拒绝。</p></div>
110
+ </div>
111
+ <div class="button-row">
112
+ <button type="button" data-run="network-allowed">允许的请求</button>
113
+ <button type="button" data-run="network-denied" class="secondary">拒绝的请求</button>
114
+ </div>
115
+ <pre class="result" aria-live="polite">尚未执行</pre>
116
+ </article>
117
+
118
+ <article class="scenario" data-scenario="failure">
119
+ <div class="scenario-copy">
120
+ <span class="number">06</span>
121
+ <div><h2>失败与恢复</h2><p>观察 Guest 错误与执行超时;超时后 runner 自动重建,并重新读取相同数据快照。</p></div>
122
+ </div>
123
+ <div class="button-row">
124
+ <button type="button" data-run="structured-failure" class="danger">结构化失败</button>
125
+ <button type="button" data-run="timeout-recovery" class="secondary">超时并恢复</button>
126
+ </div>
127
+ <pre class="result" aria-live="polite">尚未执行</pre>
128
+ </article>
129
+
130
+ <article class="scenario benchmark-evidence">
131
+ <div class="scenario-copy">
132
+ <span class="number">07</span>
133
+ <div><h2>内存密度基准</h2><p>Apple Silicon、Node 22.16 上重复三轮;每个 Component 使用独立 artifact 路径,每个 Node Service 使用独立进程。</p></div>
134
+ </div>
135
+ <dl class="metric-grid">
136
+ <div><dt>空 runner</dt><dd>7.70–7.73 <small>MiB</small></dd></div>
137
+ <div><dt>1 Component</dt><dd>34.17–36.77 <small>MiB</small></dd></div>
138
+ <div><dt>5 Components</dt><dd>43.86–44.72 <small>MiB</small></dd></div>
139
+ <div><dt>10 Components</dt><dd>50.84–53.17 <small>MiB</small></dd></div>
140
+ <div><dt>1 Node Service</dt><dd>39.88–39.91 <small>MiB</small></dd></div>
141
+ <div><dt>5 Node Services</dt><dd>199.61–199.70 <small>MiB</small></dd></div>
142
+ <div><dt>10 Node Services</dt><dd>399.25–399.47 <small>MiB</small></dd></div>
143
+ </dl>
144
+ <p class="benchmark-note">这是开发机上的密度证据,不是等价业务 workload 的最终结论;Resident 密度、CPU/延迟和跨平台仍待验证。</p>
145
+ </article>
146
+ </section>
147
+
148
+ <footer>
149
+ <strong>当前覆盖:</strong>Action、Agent Tool、真实数据、Resident、后台事件、Component Provider、跨组件组合、网络权限、故障恢复与共享宿主。
150
+ </footer>
151
+ </main>
152
+ <script src="assets/app.js"></script>
153
+ </body>
154
+ </html>
@@ -0,0 +1,29 @@
1
+ {
2
+ "id": "nextclaw-portable-runtime-lab-panel",
3
+ "title": "开发者验证台",
4
+ "description": "查看四个日常小应用背后的 Rust/WASM 运行链证据。",
5
+ "entry": "index.html",
6
+ "actions": [
7
+ "nextclaw-portable-runtime-lab-state.counter_read",
8
+ "nextclaw-portable-runtime-lab-state.counter_increment",
9
+ "nextclaw-portable-runtime-lab-state.records_seed",
10
+ "nextclaw-portable-runtime-lab-state.records_list",
11
+ "nextclaw-portable-runtime-lab-state.record_upsert",
12
+ "nextclaw-portable-runtime-lab-state.record_delete",
13
+ "nextclaw-portable-runtime-lab-state.data_snapshot",
14
+ "nextclaw-portable-runtime-lab-state.runtime_info",
15
+ "nextclaw-portable-runtime-lab-capabilities.network_allowed",
16
+ "nextclaw-portable-runtime-lab-capabilities.network_denied",
17
+ "nextclaw-portable-runtime-lab-capabilities.structured_failure",
18
+ "nextclaw-portable-runtime-lab-capabilities.simulate_timeout",
19
+ "nextclaw-portable-runtime-lab-capabilities.runtime_info",
20
+ "nextclaw-portable-runtime-lab-resident.resident_status",
21
+ "nextclaw-portable-runtime-lab-resident.resident_emit_event",
22
+ "nextclaw-portable-runtime-lab-resident.resident_reset",
23
+ "nextclaw-portable-runtime-lab-resident.runtime_info",
24
+ "nextclaw-portable-runtime-lab-provider.provider_status",
25
+ "nextclaw-portable-runtime-lab-composition.compose_contact",
26
+ "nextclaw-portable-runtime-lab-composition.provider_denied",
27
+ "nextclaw-portable-runtime-lab-composition.runtime_info"
28
+ ]
29
+ }
@@ -0,0 +1,143 @@
1
+ const actionIds = {
2
+ list: "nextclaw-portable-runtime-lab-state.records_list",
3
+ upsert: "nextclaw-portable-runtime-lab-state.record_upsert",
4
+ remove: "nextclaw-portable-runtime-lab-state.record_delete",
5
+ };
6
+
7
+ const elements = {
8
+ form: document.querySelector("[data-todo-form]"),
9
+ input: document.querySelector("[data-todo-input]"),
10
+ list: document.querySelector("[data-todo-list]"),
11
+ openCount: document.querySelector("[data-open-count]"),
12
+ doneCount: document.querySelector("[data-done-count]"),
13
+ notice: document.querySelector("[data-notice]"),
14
+ revision: document.querySelector("[data-proof-revision]"),
15
+ };
16
+
17
+ let todos = [];
18
+
19
+ function serviceActions() {
20
+ const bridge = window.nextclaw?.serviceActions;
21
+ if (!bridge) throw new Error("应用还没有连接到 NextClaw,请刷新后重试。");
22
+ return bridge;
23
+ }
24
+
25
+ async function invoke(actionId, input = {}) {
26
+ return await serviceActions().invoke(actionId, input);
27
+ }
28
+
29
+ function setNotice(message, tone = "") {
30
+ elements.notice.textContent = message;
31
+ elements.notice.dataset.tone = tone;
32
+ }
33
+
34
+ function setBusy(busy) {
35
+ for (const control of document.querySelectorAll("button, input")) control.disabled = busy;
36
+ }
37
+
38
+ function createTodoRow(todo) {
39
+ const row = document.createElement("article");
40
+ row.className = `todo-item${todo.status === "done" ? " is-done" : ""}`;
41
+
42
+ const toggle = document.createElement("button");
43
+ toggle.type = "button";
44
+ toggle.className = "check-button";
45
+ toggle.dataset.todoToggle = todo.id;
46
+ toggle.setAttribute("aria-label", todo.status === "done" ? "恢复任务" : "完成任务");
47
+ toggle.textContent = todo.status === "done" ? "✓" : "";
48
+
49
+ const title = document.createElement("p");
50
+ title.textContent = todo.title;
51
+
52
+ const remove = document.createElement("button");
53
+ remove.type = "button";
54
+ remove.className = "remove-button";
55
+ remove.dataset.todoRemove = todo.id;
56
+ remove.setAttribute("aria-label", `删除 ${todo.title}`);
57
+ remove.textContent = "删除";
58
+
59
+ row.append(toggle, title, remove);
60
+ return row;
61
+ }
62
+
63
+ function render() {
64
+ const ordered = [...todos].sort((left, right) =>
65
+ Number(left.status === "done") - Number(right.status === "done") ||
66
+ right.version - left.version
67
+ );
68
+ elements.list.replaceChildren();
69
+ if (ordered.length === 0) {
70
+ const empty = document.createElement("div");
71
+ empty.className = "empty";
72
+ empty.innerHTML = "<strong>今天还没有任务</strong><span>从上面添加第一件要做的事吧。</span>";
73
+ elements.list.append(empty);
74
+ } else {
75
+ for (const todo of ordered) elements.list.append(createTodoRow(todo));
76
+ }
77
+ elements.openCount.textContent = String(todos.filter((todo) => todo.status !== "done").length);
78
+ elements.doneCount.textContent = String(todos.filter((todo) => todo.status === "done").length);
79
+ }
80
+
81
+ async function refresh() {
82
+ const data = await invoke(actionIds.list);
83
+ todos = (Array.isArray(data.records) ? data.records : [])
84
+ .filter((record) => Array.isArray(record.tags) && record.tags.includes("todo"));
85
+ elements.revision.textContent = `revision ${data.revision} · ${data.contentHash}`;
86
+ render();
87
+ }
88
+
89
+ async function run(operation, successMessage) {
90
+ setBusy(true);
91
+ setNotice("正在保存…");
92
+ try {
93
+ await operation();
94
+ await refresh();
95
+ setNotice(successMessage, "success");
96
+ } catch (error) {
97
+ setNotice(error instanceof Error ? error.message : String(error), "error");
98
+ } finally {
99
+ setBusy(false);
100
+ elements.input.focus();
101
+ }
102
+ }
103
+
104
+ elements.form.addEventListener("submit", (event) => {
105
+ event.preventDefault();
106
+ const title = elements.input.value.trim();
107
+ if (!title) return;
108
+ void run(async () => {
109
+ await invoke(actionIds.upsert, {
110
+ id: `todo-${Date.now().toString(36)}`,
111
+ title,
112
+ status: "open",
113
+ tags: ["todo", "daily"],
114
+ });
115
+ elements.input.value = "";
116
+ }, "已加入今天的清单");
117
+ });
118
+
119
+ elements.list.addEventListener("click", (event) => {
120
+ const target = event.target instanceof Element ? event.target : null;
121
+ const toggleId = target?.closest("[data-todo-toggle]")?.dataset.todoToggle;
122
+ const removeId = target?.closest("[data-todo-remove]")?.dataset.todoRemove;
123
+ if (toggleId) {
124
+ const todo = todos.find((entry) => entry.id === toggleId);
125
+ if (!todo) return;
126
+ void run(() => invoke(actionIds.upsert, {
127
+ id: todo.id,
128
+ title: todo.title,
129
+ status: todo.status === "done" ? "open" : "done",
130
+ tags: todo.tags,
131
+ }), todo.status === "done" ? "任务已恢复" : "做得好,完成一件");
132
+ }
133
+ if (removeId) void run(() => invoke(actionIds.remove, { id: removeId }), "任务已删除");
134
+ });
135
+
136
+ document.querySelector("[data-refresh]").addEventListener("click", () => {
137
+ void run(async () => undefined, "清单已刷新");
138
+ });
139
+
140
+ const now = new Date();
141
+ document.querySelector("[data-date-day]").textContent = String(now.getDate()).padStart(2, "0");
142
+ document.querySelector("[data-date-label]").textContent = now.toLocaleDateString("zh-CN", { month: "long", weekday: "short" });
143
+ void refresh().catch((error) => setNotice(error instanceof Error ? error.message : String(error), "error"));
@@ -0,0 +1,48 @@
1
+ :root {
2
+ color-scheme: light;
3
+ font-family: Inter, "PingFang SC", "Microsoft YaHei", sans-serif;
4
+ color: #24352d;
5
+ background: #edf3ed;
6
+ }
7
+
8
+ * { box-sizing: border-box; }
9
+ body { margin: 0; min-width: 320px; background: radial-gradient(circle at top left, #fff 0, #f6f8f3 36%, #e7efe8 100%); }
10
+ button, input { font: inherit; }
11
+ button { cursor: pointer; }
12
+ button:disabled, input:disabled { cursor: wait; opacity: .6; }
13
+ .app-shell { width: min(760px, calc(100% - 32px)); margin: 0 auto; padding: 36px 0 48px; }
14
+ .hero { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-bottom: 24px; }
15
+ .eyebrow { margin: 0 0 8px; color: #538164; font-size: 12px; font-weight: 800; letter-spacing: .18em; }
16
+ h1 { margin: 0; font-family: Georgia, "Noto Serif SC", serif; font-size: clamp(36px, 7vw, 56px); letter-spacing: -.04em; }
17
+ .hero p:last-child { margin: 8px 0 0; color: #6b7a70; }
18
+ .date-card { flex: 0 0 auto; width: 90px; padding: 16px 10px; border: 1px solid #d4dfd6; border-radius: 22px; background: rgba(255,255,255,.75); text-align: center; box-shadow: 0 12px 28px rgba(56,83,66,.08); }
19
+ .date-card strong { display: block; font-size: 32px; line-height: 1; }
20
+ .date-card span { display: block; margin-top: 7px; color: #738078; font-size: 12px; }
21
+ .composer { display: flex; gap: 10px; padding: 9px; border: 1px solid #dbe4dc; border-radius: 18px; background: #fff; box-shadow: 0 18px 50px rgba(64,90,72,.1); }
22
+ .composer input { min-width: 0; flex: 1; border: 0; outline: 0; padding: 12px 14px; color: #263a2e; background: transparent; }
23
+ .composer button, .actions button { border: 0; border-radius: 12px; padding: 12px 22px; color: #fff; background: #347052; font-weight: 700; }
24
+ .summary { display: flex; align-items: center; gap: 18px; padding: 18px 4px 10px; color: #68776d; font-size: 14px; }
25
+ .summary strong { color: #2d5d44; }
26
+ .text-button { margin-left: auto; border: 0; color: #4d725b; background: transparent; }
27
+ .todo-list { display: grid; gap: 10px; margin-top: 8px; }
28
+ .todo-item { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 14px; padding: 16px 18px; border: 1px solid #dae4db; border-radius: 16px; background: rgba(255,255,255,.88); transition: transform .16s ease, opacity .16s ease; }
29
+ .todo-item:hover { transform: translateY(-1px); }
30
+ .todo-item p { margin: 0; line-height: 1.55; }
31
+ .todo-item.is-done { opacity: .62; }
32
+ .todo-item.is-done p { text-decoration: line-through; }
33
+ .check-button { width: 24px; height: 24px; padding: 0; border: 2px solid #76a083; border-radius: 50%; color: #fff; background: transparent; font-size: 13px; }
34
+ .is-done .check-button { background: #4d8663; }
35
+ .remove-button { border: 0; color: #9a695f; background: transparent; font-size: 13px; opacity: .7; }
36
+ .empty { display: flex; min-height: 180px; flex-direction: column; align-items: center; justify-content: center; gap: 8px; border: 1px dashed #cbd8cd; border-radius: 18px; color: #7d8b81; text-align: center; }
37
+ .empty strong { color: #4e6254; font-size: 18px; }
38
+ .notice { min-height: 22px; margin: 14px 4px; color: #6e7d72; font-size: 14px; }
39
+ .notice[data-tone="success"] { color: #347052; }
40
+ .notice[data-tone="error"] { color: #b14e43; }
41
+ .behind-scenes { margin-top: 28px; padding: 16px 18px; border: 1px solid #dce4dc; border-radius: 16px; color: #66746a; background: rgba(255,255,255,.55); font-size: 13px; }
42
+ .behind-scenes summary { color: #46594b; cursor: pointer; font-weight: 700; }
43
+ .behind-scenes p { line-height: 1.65; }
44
+ .behind-scenes dl { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin: 12px 0 0; }
45
+ .behind-scenes dl div { padding: 10px; border-radius: 10px; background: #fff; }
46
+ .behind-scenes dt { color: #879188; font-size: 11px; }
47
+ .behind-scenes dd { margin: 3px 0 0; color: #3e5143; overflow-wrap: anywhere; }
48
+ @media (max-width: 560px) { .app-shell { width: min(100% - 22px, 760px); padding-top: 24px; } .hero { align-items: flex-end; } .date-card { width: 76px; } .composer button { padding-inline: 16px; } .summary { gap: 10px; } .behind-scenes dl { grid-template-columns: 1fr; } }
@@ -0,0 +1,45 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>今日清单</title>
7
+ <link rel="stylesheet" href="assets/style.css" />
8
+ </head>
9
+ <body>
10
+ <main class="app-shell">
11
+ <header class="hero">
12
+ <div>
13
+ <p class="eyebrow">TODAY</p>
14
+ <h1>今日清单</h1>
15
+ <p>把脑子里的事情放下来,一件一件完成。</p>
16
+ </div>
17
+ <div class="date-card"><strong data-date-day>—</strong><span data-date-label>—</span></div>
18
+ </header>
19
+
20
+ <form class="composer" data-todo-form>
21
+ <input data-todo-input maxlength="160" placeholder="今天还要做什么?" autocomplete="off" />
22
+ <button type="submit">添加</button>
23
+ </form>
24
+
25
+ <section class="summary" aria-label="任务概况">
26
+ <span><strong data-open-count>0</strong> 件待完成</span>
27
+ <span><strong data-done-count>0</strong> 件已完成</span>
28
+ <button type="button" class="text-button" data-refresh>刷新</button>
29
+ </section>
30
+
31
+ <section class="todo-list" data-todo-list aria-live="polite">
32
+ <div class="empty">正在读取你的清单…</div>
33
+ </section>
34
+
35
+ <p class="notice" data-notice></p>
36
+
37
+ <details class="behind-scenes">
38
+ <summary>这个小应用背后发生了什么?</summary>
39
+ <p>每次添加、完成和删除都会调用同一组 Rust/WASM Service Action,并写入 NextClaw 管理的持久数据。关掉再打开,清单仍然存在;授权后的 Agent 也可以操作同一份数据。</p>
40
+ <dl><div><dt>数据</dt><dd data-proof-revision>等待读取</dd></div><div><dt>存储</dt><dd>NextClaw Host KV</dd></div></dl>
41
+ </details>
42
+ </main>
43
+ <script src="assets/app.js"></script>
44
+ </body>
45
+ </html>
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "nextclaw-portable-runtime-lab-todos",
3
+ "title": "今日清单",
4
+ "description": "记下今天要做的事,完成后轻轻划掉。",
5
+ "entry": "index.html",
6
+ "actions": [
7
+ "nextclaw-portable-runtime-lab-state.records_list",
8
+ "nextclaw-portable-runtime-lab-state.record_upsert",
9
+ "nextclaw-portable-runtime-lab-state.record_delete",
10
+ "nextclaw-portable-runtime-lab-state.data_snapshot"
11
+ ]
12
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "id": "nextclaw-portable-runtime-lab-capabilities",
3
+ "title": "Portable Capability Component",
4
+ "description": "Rust/WASM 网络、拒绝、错误与超时演示模块。",
5
+ "protocol": "wasi-component",
6
+ "component": {
7
+ "entry": "service.wasm"
8
+ },
9
+ "actions": {
10
+ "network_allowed": { "risk": "external", "title": "访问允许的网络" },
11
+ "network_denied": { "risk": "read", "title": "验证网络拒绝" },
12
+ "structured_failure": { "risk": "dangerous", "title": "触发结构化失败" },
13
+ "simulate_timeout": {
14
+ "risk": "dangerous",
15
+ "title": "触发执行超时",
16
+ "timeoutMs": 1200
17
+ },
18
+ "runtime_info": { "risk": "read", "title": "查看共享宿主" }
19
+ }
20
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "id": "nextclaw-portable-runtime-lab-composition",
3
+ "title": "Portable Composition Consumer",
4
+ "description": "通过宿主受控 component-call 调用 manifest 声明的 Provider。",
5
+ "protocol": "wasi-component",
6
+ "component": {
7
+ "entry": "service.wasm"
8
+ },
9
+ "providers": [
10
+ "nextclaw-portable-runtime-lab-provider"
11
+ ],
12
+ "actions": {
13
+ "compose_contact": {
14
+ "risk": "write",
15
+ "title": "组合联系人工作流",
16
+ "inputSchema": {
17
+ "type": "object",
18
+ "properties": {
19
+ "name": { "type": "string", "minLength": 1 },
20
+ "email": { "type": "string", "minLength": 3 },
21
+ "tags": { "type": "array", "items": { "type": "string" } }
22
+ },
23
+ "required": ["name", "email"],
24
+ "additionalProperties": false
25
+ }
26
+ },
27
+ "provider_denied": { "risk": "read", "title": "验证 Provider 拒绝" },
28
+ "runtime_info": { "risk": "read", "title": "查看 Consumer 宿主" }
29
+ }
30
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "id": "nextclaw-portable-runtime-lab-provider",
3
+ "title": "Portable Contact Provider",
4
+ "description": "以独立 Rust/WASM 实例提供可复用联系人规范化合同。",
5
+ "protocol": "wasi-component",
6
+ "component": {
7
+ "entry": "service.wasm"
8
+ },
9
+ "lifecycle": {
10
+ "mode": "provider"
11
+ },
12
+ "actions": {
13
+ "contact_normalize": {
14
+ "risk": "write",
15
+ "title": "规范化联系人",
16
+ "inputSchema": {
17
+ "type": "object",
18
+ "properties": {
19
+ "name": { "type": "string", "minLength": 1 },
20
+ "email": { "type": "string", "minLength": 3 },
21
+ "tags": { "type": "array", "items": { "type": "string" } }
22
+ },
23
+ "required": ["name", "email"],
24
+ "additionalProperties": false
25
+ }
26
+ },
27
+ "provider_status": { "risk": "read", "title": "读取 Provider 状态" },
28
+ "runtime_info": { "risk": "read", "title": "查看 Provider 宿主" }
29
+ }
30
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "id": "nextclaw-portable-runtime-lab-resident",
3
+ "title": "Portable Resident Component",
4
+ "description": "宿主持有同一个 Rust/WASM 实例,并在 Panel 关闭后继续投递定时事件。",
5
+ "protocol": "wasi-component",
6
+ "component": {
7
+ "entry": "service.wasm"
8
+ },
9
+ "lifecycle": {
10
+ "mode": "resident",
11
+ "eventIntervalMs": 1000
12
+ },
13
+ "actions": {
14
+ "resident_status": { "risk": "read", "title": "读取 Resident 状态" },
15
+ "resident_emit_event": {
16
+ "risk": "write",
17
+ "title": "向 Resident 投递事件",
18
+ "inputSchema": {
19
+ "type": "object",
20
+ "properties": {
21
+ "eventId": { "type": "string" },
22
+ "kind": { "type": "string" },
23
+ "triggeredAt": { "type": "string" }
24
+ },
25
+ "additionalProperties": false
26
+ }
27
+ },
28
+ "resident_reset": { "risk": "write", "title": "重置 Resident 证据" },
29
+ "runtime_info": { "risk": "read", "title": "查看 Resident 宿主" }
30
+ }
31
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "id": "nextclaw-portable-runtime-lab-state",
3
+ "title": "Portable State Component",
4
+ "description": "Rust/WASM 状态与共享宿主演示模块。",
5
+ "protocol": "wasi-component",
6
+ "component": {
7
+ "entry": "service.wasm"
8
+ },
9
+ "actions": {
10
+ "counter_read": { "risk": "read", "title": "读取持久计数" },
11
+ "counter_increment": {
12
+ "risk": "write",
13
+ "title": "增加持久计数",
14
+ "inputSchema": {
15
+ "type": "object",
16
+ "properties": { "step": { "type": "integer" } }
17
+ }
18
+ },
19
+ "records_seed": { "risk": "write", "title": "生成验证数据" },
20
+ "records_list": { "risk": "read", "title": "列出验证数据" },
21
+ "record_upsert": {
22
+ "risk": "write",
23
+ "title": "创建或修改记录",
24
+ "inputSchema": {
25
+ "type": "object",
26
+ "properties": {
27
+ "id": { "type": "string", "minLength": 1, "maxLength": 48 },
28
+ "title": { "type": "string", "minLength": 1 },
29
+ "status": { "type": "string" },
30
+ "tags": { "type": "array", "items": { "type": "string" } }
31
+ },
32
+ "required": ["id", "title"],
33
+ "additionalProperties": false
34
+ }
35
+ },
36
+ "record_delete": {
37
+ "risk": "write",
38
+ "title": "删除记录",
39
+ "inputSchema": {
40
+ "type": "object",
41
+ "properties": { "id": { "type": "string", "minLength": 1, "maxLength": 48 } },
42
+ "required": ["id"],
43
+ "additionalProperties": false
44
+ }
45
+ },
46
+ "data_snapshot": { "risk": "read", "title": "读取数据快照" },
47
+ "runtime_info": { "risk": "read", "title": "查看共享宿主" }
48
+ }
49
+ }