nextclaw 0.46.0 → 0.47.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/dist/cli/app/index.js +1 -1
- package/dist/{nextclaw-cli-app-BVdP2e0w.js → nextclaw-cli-app-wU9aUEKj.js} +233 -1
- package/dist/nextclaw-cli-app-wU9aUEKj.js.map +1 -0
- package/package.json +14 -14
- package/resources/apps/nextclaw-github-issue-watcher/README.md +43 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/Cargo.lock +455 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/Cargo.toml +27 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/src/bindings.rs +11177 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/src/lib.rs +307 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/clocks@0.2.6/monotonic-clock.wit +50 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/clocks@0.2.6/timezone.wit +55 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/clocks@0.2.6/wall-clock.wit +46 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/clocks@0.2.6/world.wit +11 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/config@0.2.0-draft-2024-09-27/package.wit +1 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/config@0.2.0-draft-2024-09-27/store.wit +9 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/http@0.2.6/handler.wit +49 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/http@0.2.6/package.wit +1 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/http@0.2.6/types.wit +688 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/io@0.2.6/error.wit +34 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/io@0.2.6/poll.wit +47 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/io@0.2.6/streams.wit +290 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/io@0.2.6/world.wit +10 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/deps/keyvalue@0.2.0-draft2/store.wit +124 -0
- package/resources/apps/nextclaw-github-issue-watcher/guest/wit/portable-service.wit +56 -0
- package/resources/apps/nextclaw-github-issue-watcher/manifest.json +34 -0
- package/resources/apps/nextclaw-github-issue-watcher/marketplace.json +18 -0
- package/resources/apps/nextclaw-github-issue-watcher/panels/nextclaw-github-issue-watcher-panel.panel/assets/app.js +148 -0
- package/resources/apps/nextclaw-github-issue-watcher/panels/nextclaw-github-issue-watcher-panel.panel/index.html +190 -0
- package/resources/apps/nextclaw-github-issue-watcher/panels/nextclaw-github-issue-watcher-panel.panel/panel-app.json +11 -0
- package/resources/apps/nextclaw-github-issue-watcher/service-components/nextclaw-github-issue-watcher-service/service-app.json +36 -0
- package/resources/apps/nextclaw-github-issue-watcher/service-components/nextclaw-github-issue-watcher-service/service.wasm +0 -0
- package/resources/apps/nextclaw-github-issue-watcher/tests/public-github-runner-smoke.tools.mjs +150 -0
- package/resources/apps/nextclaw-github-issue-watcher/tests/service-smoke.json +12 -0
- package/resources/apps/nextclaw-portable-runtime-lab/README.md +5 -3
- package/resources/apps/nextclaw-portable-runtime-lab/manifest.json +14 -2
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-contacts.panel/assets/app.js +21 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-contacts.panel/index.html +1 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-focus.panel/assets/app.js +21 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-focus.panel/index.html +1 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-notes.panel/assets/app.js +21 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-notes.panel/index.html +1 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-panel.panel/assets/app.js +201 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-panel.panel/assets/style.css +42 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-panel.panel/index.html +40 -19
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-panel.panel/panel-app.json +2 -2
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-todos.panel/assets/app.js +21 -0
- package/resources/apps/nextclaw-portable-runtime-lab/panels/nextclaw-portable-runtime-lab-todos.panel/index.html +1 -0
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-capabilities/service-app.json +110 -3
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-capabilities/service.wasm +0 -0
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-composition/service-app.json +12 -3
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-composition/service.wasm +0 -0
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-provider/service-app.json +11 -0
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-provider/service.wasm +0 -0
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-resident/service.wasm +0 -0
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-sqlite/service-app.json +37 -0
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-sqlite/service.wasm +0 -0
- package/resources/apps/nextclaw-portable-runtime-lab/service-components/nextclaw-portable-runtime-lab-state/service.wasm +0 -0
- package/ui-dist/assets/{api-aEu9cEI8.js → api-n96IfCKb.js} +2 -2
- package/ui-dist/assets/{api-aEu9cEI8.js.gz → api-n96IfCKb.js.gz} +0 -0
- package/ui-dist/assets/{appearance-settings-page-z4DaHc_E.js → appearance-settings-page-C_AqxSF_.js} +1 -1
- package/ui-dist/assets/appearance-settings-page-C_AqxSF_.js.gz +0 -0
- package/ui-dist/assets/{channels-list-page-x07sGqsT.js → channels-list-page-uR-M4Ls8.js} +1 -1
- package/ui-dist/assets/channels-list-page-uR-M4Ls8.js.gz +0 -0
- package/ui-dist/assets/{confirm-dialog-BALTnP33.js → confirm-dialog-CHVBMpla.js} +1 -1
- package/ui-dist/assets/confirm-dialog-CHVBMpla.js.gz +0 -0
- package/ui-dist/assets/{desktop-capabilities-page-4-v3wKLV.js → desktop-capabilities-page-phMuNq1B.js} +1 -1
- package/ui-dist/assets/desktop-capabilities-page-phMuNq1B.js.gz +0 -0
- package/ui-dist/assets/{desktop-update-config-Cl-_XHqU.js → desktop-update-config-C77hkbor.js} +1 -1
- package/ui-dist/assets/desktop-update-config-C77hkbor.js.gz +0 -0
- package/ui-dist/assets/{extensions-DFQXmSwG.js → extensions-CQKXTqTI.js} +1 -1
- package/ui-dist/assets/extensions-CQKXTqTI.js.gz +0 -0
- package/ui-dist/assets/{index-zuqzAvNx.js → index-CLw9DuCJ.js} +4 -4
- package/ui-dist/assets/index-CLw9DuCJ.js.gz +0 -0
- package/ui-dist/assets/mcp-marketplace-page-CbWOamyW.js +1 -0
- package/ui-dist/assets/{mcp-marketplace-page-COUopIOc.js → mcp-marketplace-page-s9PTnSDT.js} +1 -1
- package/ui-dist/assets/mcp-marketplace-page-s9PTnSDT.js.gz +0 -0
- package/ui-dist/assets/{model-config-page-g9_-hZqZ.js → model-config-page-CxnCUWRW.js} +1 -1
- package/ui-dist/assets/model-config-page-CxnCUWRW.js.gz +0 -0
- package/ui-dist/assets/{privacy-settings-page-pNhQQT4r.js → privacy-settings-page-D8HZHHjL.js} +1 -1
- package/ui-dist/assets/privacy-settings-page-D8HZHHjL.js.gz +0 -0
- package/ui-dist/assets/{providers-config-page-DftW_6KU.js → providers-config-page-C0GIoGxm.js} +1 -1
- package/ui-dist/assets/providers-config-page-C0GIoGxm.js.gz +0 -0
- package/ui-dist/assets/remote-DvTCSAxQ.js +1 -0
- package/ui-dist/assets/{runtime-config-page-Cd9sOYvn.js → runtime-config-page-VNJZui5f.js} +1 -1
- package/ui-dist/assets/runtime-config-page-VNJZui5f.js.gz +0 -0
- package/ui-dist/assets/{search-config-page-BqoDbKpM.js → search-config-page-D3_qNXbB.js} +1 -1
- package/ui-dist/assets/search-config-page-D3_qNXbB.js.gz +0 -0
- package/ui-dist/assets/{secrets-config-page-GsahsEVw.js → secrets-config-page-Be4P1E8o.js} +1 -1
- package/ui-dist/assets/secrets-config-page-Be4P1E8o.js.gz +0 -0
- package/ui-dist/assets/security-config-BtcpKIhQ.js +1 -0
- package/ui-dist/assets/{tag-chip-ClBWeQ4p.js → tag-chip-Dc_NcCEe.js} +1 -1
- package/ui-dist/index.html +5 -5
- package/ui-dist/index.html.gz +0 -0
- package/dist/nextclaw-cli-app-BVdP2e0w.js.map +0 -1
- package/ui-dist/assets/appearance-settings-page-z4DaHc_E.js.gz +0 -0
- package/ui-dist/assets/channels-list-page-x07sGqsT.js.gz +0 -0
- package/ui-dist/assets/confirm-dialog-BALTnP33.js.gz +0 -0
- package/ui-dist/assets/desktop-capabilities-page-4-v3wKLV.js.gz +0 -0
- package/ui-dist/assets/desktop-update-config-Cl-_XHqU.js.gz +0 -0
- package/ui-dist/assets/extensions-DFQXmSwG.js.gz +0 -0
- package/ui-dist/assets/index-zuqzAvNx.js.gz +0 -0
- package/ui-dist/assets/mcp-marketplace-page-COUopIOc.js.gz +0 -0
- package/ui-dist/assets/mcp-marketplace-page-DxPPmYqh.js +0 -1
- package/ui-dist/assets/model-config-page-g9_-hZqZ.js.gz +0 -0
- package/ui-dist/assets/privacy-settings-page-pNhQQT4r.js.gz +0 -0
- package/ui-dist/assets/providers-config-page-DftW_6KU.js.gz +0 -0
- package/ui-dist/assets/remote-DS2TkMPm.js +0 -1
- package/ui-dist/assets/runtime-config-page-Cd9sOYvn.js.gz +0 -0
- package/ui-dist/assets/search-config-page-BqoDbKpM.js.gz +0 -0
- package/ui-dist/assets/secrets-config-page-GsahsEVw.js.gz +0 -0
- package/ui-dist/assets/security-config-BnHQyrtG.js +0 -1
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
<details class="behind-scenes">
|
|
33
33
|
<summary>关闭页面后,为什么计时还会继续?</summary>
|
|
34
34
|
<p>计时不属于这个页面,而是由 NextClaw 宿主持续向一个常驻 Rust/WASM Component 投递事件;完成点同时写入持久数据 Component。Panel 只负责查看和控制,所以页面关闭、重新打开,甚至宿主恢复后都能继续。</p>
|
|
35
|
+
<p><strong>已验证能力</strong>:<span data-verification-status>读取中…</span></p>
|
|
35
36
|
<dl><div><dt>本次实例</dt><dd data-proof-epoch>等待读取</dd></div><div><dt>持久事件</dt><dd data-proof-events>等待读取</dd></div></dl>
|
|
36
37
|
</details>
|
|
37
38
|
</main>
|
|
@@ -23,6 +23,12 @@ function serviceActions() {
|
|
|
23
23
|
return bridge;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
function verificationRecords() {
|
|
27
|
+
const bridge = window.nextclaw?.verificationRecords;
|
|
28
|
+
if (!bridge) throw new Error("验收记录桥尚未就绪。");
|
|
29
|
+
return bridge;
|
|
30
|
+
}
|
|
31
|
+
|
|
26
32
|
async function invoke(actionId, input = {}) {
|
|
27
33
|
return await serviceActions().invoke(actionId, input);
|
|
28
34
|
}
|
|
@@ -115,3 +121,18 @@ elements.grid.addEventListener("click", (event) => {
|
|
|
115
121
|
});
|
|
116
122
|
|
|
117
123
|
void refresh().catch((error) => setNotice(error instanceof Error ? error.message : String(error), "error"));
|
|
124
|
+
async function refreshVerificationStatus() {
|
|
125
|
+
const element = document.querySelector("[data-verification-status]");
|
|
126
|
+
if (!element) return;
|
|
127
|
+
try {
|
|
128
|
+
const payload = await verificationRecords().list({ appId: "nextclaw.portable-runtime-lab", limit: 500 });
|
|
129
|
+
const entry = (payload?.entries || []).find((candidate) => candidate.acceptanceId === "PRT-ENTRY-001");
|
|
130
|
+
element.textContent = entry
|
|
131
|
+
? `${entry.status === "passed" ? "已有局部证据" : entry.status} · ${new Date(entry.finishedAt).toLocaleString()}`
|
|
132
|
+
: "未验证(暂无 PRT-ENTRY-001 记录)";
|
|
133
|
+
} catch {
|
|
134
|
+
element.textContent = "暂时无法读取验收记录";
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
void refreshVerificationStatus();
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
<details class="behind-scenes">
|
|
34
34
|
<summary>为什么它也是运行时 Demo?</summary>
|
|
35
35
|
<p>便签和“今日清单”是两个独立 Panel,却复用同一个底层数据 Component。产品可以变,稳定的存储与授权能力不用为每个页面重新实现。</p>
|
|
36
|
+
<p><strong>已验证能力</strong>:<span data-verification-status>读取中…</span></p>
|
|
36
37
|
<dl><div><dt>当前数据版本</dt><dd data-proof-revision>等待读取</dd></div><div><dt>可被 Agent 使用</dt><dd>是,同一 Service Action</dd></div></dl>
|
|
37
38
|
</details>
|
|
38
39
|
</main>
|
|
@@ -20,6 +20,190 @@ const actions = {
|
|
|
20
20
|
providerDenied: "nextclaw-portable-runtime-lab-composition.provider_denied",
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
const APP_ID = "nextclaw.portable-runtime-lab";
|
|
24
|
+
const verificationElements = {
|
|
25
|
+
root: document.querySelector(".verification"),
|
|
26
|
+
list: document.querySelector("[data-verification-list]"),
|
|
27
|
+
app: document.querySelector("[data-verification-app]"),
|
|
28
|
+
runtime: document.querySelector("[data-verification-runtime]"),
|
|
29
|
+
count: document.querySelector("[data-verification-count]"),
|
|
30
|
+
environment: document.querySelector("[data-verification-environment]"),
|
|
31
|
+
implementation: document.querySelector("[data-verification-implementation]"),
|
|
32
|
+
contract: document.querySelector("[data-verification-contract]"),
|
|
33
|
+
sources: document.querySelector("[data-verification-sources]"),
|
|
34
|
+
evidence: document.querySelector("[data-verification-evidence]"),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
let acceptanceStatus = null;
|
|
38
|
+
|
|
39
|
+
const statusLabels = {
|
|
40
|
+
"current-passed": "当前通过",
|
|
41
|
+
failed: "失败",
|
|
42
|
+
stale: "证据已过期",
|
|
43
|
+
missing: "尚无证据",
|
|
44
|
+
"not-applicable": "当前平台不适用",
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const categoryLabels = {
|
|
48
|
+
execution: "执行",
|
|
49
|
+
capability: "基础能力",
|
|
50
|
+
lifecycle: "生命周期",
|
|
51
|
+
entry: "入口",
|
|
52
|
+
quality: "质量与交付",
|
|
53
|
+
release: "发布",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
async function fetchAcceptanceStatus() {
|
|
57
|
+
const payload = await portableRuntimeAcceptance().status({ locale: "zh-CN" });
|
|
58
|
+
if (!Array.isArray(payload?.entries) || !payload?.contract || !payload?.identity) {
|
|
59
|
+
throw new Error("验收状态返回格式无效。");
|
|
60
|
+
}
|
|
61
|
+
return payload;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function portableRuntimeAcceptance() {
|
|
65
|
+
const bridge = window.nextclaw?.portableRuntimeAcceptance;
|
|
66
|
+
if (!bridge) throw new Error("NextClaw 验收桥尚未就绪,请刷新后重试。");
|
|
67
|
+
return bridge;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function formatTime(value) {
|
|
71
|
+
if (!value) return "—";
|
|
72
|
+
const date = new Date(value);
|
|
73
|
+
return Number.isNaN(date.getTime()) ? String(value) : date.toLocaleString();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function renderVerificationList() {
|
|
77
|
+
verificationElements.list.replaceChildren();
|
|
78
|
+
const groups = new Map();
|
|
79
|
+
for (const entry of acceptanceStatus.entries) {
|
|
80
|
+
const group = groups.get(entry.category) || [];
|
|
81
|
+
group.push(entry);
|
|
82
|
+
groups.set(entry.category, group);
|
|
83
|
+
}
|
|
84
|
+
for (const [category, entries] of groups) {
|
|
85
|
+
const group = document.createElement("section");
|
|
86
|
+
group.className = "verification-category";
|
|
87
|
+
const groupHeading = document.createElement("h3");
|
|
88
|
+
groupHeading.textContent = categoryLabels[category] || category;
|
|
89
|
+
group.append(groupHeading);
|
|
90
|
+
const cards = document.createElement("div");
|
|
91
|
+
cards.className = "verification-category-cards";
|
|
92
|
+
for (const item of entries) {
|
|
93
|
+
const acceptanceId = item.id;
|
|
94
|
+
const evidence = item.result.latestRecord;
|
|
95
|
+
const status = item.result.status;
|
|
96
|
+
const card = document.createElement("article");
|
|
97
|
+
card.className = "verification-item";
|
|
98
|
+
card.dataset.status = status;
|
|
99
|
+
|
|
100
|
+
const heading = document.createElement("div");
|
|
101
|
+
heading.className = "verification-item-heading";
|
|
102
|
+
const titleBlock = document.createElement("div");
|
|
103
|
+
const id = document.createElement("code");
|
|
104
|
+
id.textContent = acceptanceId;
|
|
105
|
+
const name = document.createElement("h3");
|
|
106
|
+
name.textContent = item.presentation.title;
|
|
107
|
+
const copy = document.createElement("p");
|
|
108
|
+
copy.textContent = item.presentation.description;
|
|
109
|
+
titleBlock.append(id, name, copy);
|
|
110
|
+
const badge = document.createElement("span");
|
|
111
|
+
badge.className = "status-badge";
|
|
112
|
+
badge.textContent = statusLabels[status] || status;
|
|
113
|
+
heading.append(titleBlock, badge);
|
|
114
|
+
card.append(heading);
|
|
115
|
+
|
|
116
|
+
const meta = document.createElement("dl");
|
|
117
|
+
meta.className = "verification-meta";
|
|
118
|
+
for (const [label, value] of [
|
|
119
|
+
["最近运行", formatTime(evidence?.finishedAt)],
|
|
120
|
+
["环境", evidence?.environment || acceptanceStatus.identity.environment || "尚未验证"],
|
|
121
|
+
["来源", item.evidenceSource],
|
|
122
|
+
["动作", evidence?.actionOrEvent || "尚未验证"],
|
|
123
|
+
]) {
|
|
124
|
+
const wrapper = document.createElement("div");
|
|
125
|
+
const term = document.createElement("dt");
|
|
126
|
+
term.textContent = label;
|
|
127
|
+
const detail = document.createElement("dd");
|
|
128
|
+
detail.textContent = value;
|
|
129
|
+
wrapper.append(term, detail);
|
|
130
|
+
meta.append(wrapper);
|
|
131
|
+
}
|
|
132
|
+
card.append(meta);
|
|
133
|
+
|
|
134
|
+
const controls = document.createElement("div");
|
|
135
|
+
controls.className = "verification-controls";
|
|
136
|
+
if (evidence) {
|
|
137
|
+
const viewButton = document.createElement("button");
|
|
138
|
+
viewButton.type = "button";
|
|
139
|
+
viewButton.className = "text-button";
|
|
140
|
+
viewButton.dataset.viewEvidence = evidence.verificationRunId;
|
|
141
|
+
viewButton.textContent = "查看证据";
|
|
142
|
+
controls.append(viewButton);
|
|
143
|
+
} else {
|
|
144
|
+
const note = document.createElement("span");
|
|
145
|
+
note.className = "verification-note";
|
|
146
|
+
note.textContent = "尚无可展示的当前证据";
|
|
147
|
+
controls.append(note);
|
|
148
|
+
}
|
|
149
|
+
card.append(controls);
|
|
150
|
+
cards.append(card);
|
|
151
|
+
}
|
|
152
|
+
group.append(cards);
|
|
153
|
+
verificationElements.list.append(group);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function refreshVerification() {
|
|
158
|
+
verificationElements.root.dataset.state = "pending";
|
|
159
|
+
try {
|
|
160
|
+
acceptanceStatus = await fetchAcceptanceStatus();
|
|
161
|
+
const { identity, contract, summary } = acceptanceStatus;
|
|
162
|
+
verificationElements.app.textContent = acceptanceStatus.appId;
|
|
163
|
+
verificationElements.runtime.textContent = identity.available
|
|
164
|
+
? `${identity.context.productVersion} / ${identity.context.runtimeVersion} (${identity.runtimeVersionSource})`
|
|
165
|
+
: "身份不可用";
|
|
166
|
+
verificationElements.count.textContent = `${summary["current-passed"]}/${acceptanceStatus.entries.length}`;
|
|
167
|
+
verificationElements.environment.textContent = identity.available ? identity.context.environment : (identity.environment || "尚未验证");
|
|
168
|
+
verificationElements.implementation.textContent = identity.available ? identity.context.implementationFingerprint : identity.reason;
|
|
169
|
+
verificationElements.contract.textContent = contract.contractFingerprint;
|
|
170
|
+
verificationElements.sources.textContent = acceptanceStatus.entries.map((entry) => entry.evidenceSource).filter((value, index, values) => values.indexOf(value) === index).join(", ");
|
|
171
|
+
renderVerificationList();
|
|
172
|
+
verificationElements.root.dataset.state = "ready";
|
|
173
|
+
} catch (error) {
|
|
174
|
+
verificationElements.list.replaceChildren();
|
|
175
|
+
const message = document.createElement("p");
|
|
176
|
+
message.className = "verification-empty error-copy";
|
|
177
|
+
message.textContent = error instanceof Error ? error.message : String(error);
|
|
178
|
+
verificationElements.list.append(message);
|
|
179
|
+
verificationElements.runtime.textContent = "无法读取";
|
|
180
|
+
verificationElements.root.dataset.state = "error";
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function showEvidence(runId) {
|
|
185
|
+
const entry = acceptanceStatus?.entries
|
|
186
|
+
.map((candidate) => candidate.result.latestRecord)
|
|
187
|
+
.find((candidate) => candidate?.verificationRunId === runId);
|
|
188
|
+
if (!entry) return;
|
|
189
|
+
verificationElements.evidence.textContent = JSON.stringify(entry, null, 2);
|
|
190
|
+
const details = document.querySelector("[data-evidence-details]");
|
|
191
|
+
details?.setAttribute("open", "");
|
|
192
|
+
details?.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function exportVerification() {
|
|
196
|
+
const payload = await portableRuntimeAcceptance().export({ locale: "zh-CN" });
|
|
197
|
+
const blob = new Blob([`${JSON.stringify(payload, null, 2)}\n`], { type: "application/json" });
|
|
198
|
+
const url = URL.createObjectURL(blob);
|
|
199
|
+
const link = document.createElement("a");
|
|
200
|
+
link.href = url;
|
|
201
|
+
link.download = `${payload.appId}.portable-runtime-acceptance.json`;
|
|
202
|
+
link.click();
|
|
203
|
+
URL.revokeObjectURL(url);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
23
207
|
const scenarios = {
|
|
24
208
|
shared: document.querySelector('[data-scenario="shared"]'),
|
|
25
209
|
data: document.querySelector('[data-scenario="data"]'),
|
|
@@ -249,6 +433,23 @@ for (const button of document.querySelectorAll("[data-run]")) {
|
|
|
249
433
|
button.addEventListener("click", () => operations[button.dataset.run]?.());
|
|
250
434
|
}
|
|
251
435
|
|
|
436
|
+
document.querySelector("[data-refresh-verification]")?.addEventListener("click", () => {
|
|
437
|
+
void refreshVerification();
|
|
438
|
+
});
|
|
439
|
+
document.querySelector("[data-export-verification]")?.addEventListener("click", () => {
|
|
440
|
+
void exportVerification().catch((error) => {
|
|
441
|
+
verificationElements.root.dataset.state = "error";
|
|
442
|
+
verificationElements.evidence.textContent = JSON.stringify(errorValue(error), null, 2);
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
verificationElements.list.addEventListener("click", (event) => {
|
|
446
|
+
const target = event.target;
|
|
447
|
+
if (!(target instanceof HTMLElement)) return;
|
|
448
|
+
const viewButton = target.closest("[data-view-evidence]");
|
|
449
|
+
if (viewButton instanceof HTMLElement) showEvidence(viewButton.dataset.viewEvidence);
|
|
450
|
+
});
|
|
451
|
+
void refreshVerification();
|
|
452
|
+
|
|
252
453
|
void refreshResident().then((result) => {
|
|
253
454
|
setState("resident", "success", result);
|
|
254
455
|
}).catch((error) => {
|
|
@@ -42,6 +42,45 @@ button.secondary:hover:not(:disabled) { background: #16304b; }
|
|
|
42
42
|
button.danger { border-color: #9f3b52; background: #7f1d36; }
|
|
43
43
|
button.danger:hover:not(:disabled) { background: #9f2444; }
|
|
44
44
|
button:disabled { cursor: wait; opacity: .55; }
|
|
45
|
+
.verification { margin: 32px 0 34px; border: 1px solid #25516a; border-radius: 18px; padding: 20px; background: #0b1d2ddd; }
|
|
46
|
+
.verification[data-state="pending"] { border-color: #38bdf866; }
|
|
47
|
+
.verification[data-state="error"] { border-color: #fb718566; }
|
|
48
|
+
.section-heading { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; }
|
|
49
|
+
.section-heading h2 { font-size: 21px; }
|
|
50
|
+
.section-heading p { margin: 7px 0 0; color: #8099b5; font-size: 13px; line-height: 1.55; }
|
|
51
|
+
.verification-actions, .verification-controls { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
52
|
+
.verification-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 9px; margin: 18px 0 12px; }
|
|
53
|
+
.verification-summary div { min-width: 0; border: 1px solid #183c55; border-radius: 11px; padding: 10px 12px; background: #071522; }
|
|
54
|
+
.verification-summary dt { color: #7892ae; font-size: 10px; }
|
|
55
|
+
.verification-summary dd { overflow: hidden; margin: 5px 0 0; color: #c4d9ed; font-family: "SFMono-Regular", Consolas, monospace; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
|
|
56
|
+
.verification-list { display: grid; gap: 16px; }
|
|
57
|
+
.verification-category { min-width: 0; }
|
|
58
|
+
.verification-category > h3 { margin: 0 0 8px; color: #87a6c3; font-size: 12px; letter-spacing: .05em; }
|
|
59
|
+
.verification-category-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
|
|
60
|
+
.verification-empty { grid-column: 1 / -1; margin: 10px 0; color: #91a8c2; font-size: 13px; }
|
|
61
|
+
.error-copy { color: #fda4af; }
|
|
62
|
+
.verification-item { min-width: 0; border: 1px solid #18314c; border-radius: 12px; padding: 13px; background: #071522; }
|
|
63
|
+
.verification-item[data-status="current-passed"] { border-color: #2dd4bf66; }
|
|
64
|
+
.verification-item[data-status="failed"] { border-color: #fb718566; }
|
|
65
|
+
.verification-item-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
|
|
66
|
+
.verification-item code { color: #b4c3d3; font-family: "SFMono-Regular", Consolas, monospace; font-size: 10px; font-weight: 700; }
|
|
67
|
+
.verification-item[data-status="current-passed"] code { color: #5eead4; }
|
|
68
|
+
.verification-item h3 { margin: 5px 0 0; color: #dce9f8; font-size: 14px; }
|
|
69
|
+
.verification-item p { margin: 5px 0 0; color: #7892ae; font-size: 11px; line-height: 1.45; }
|
|
70
|
+
.status-badge { flex: none; border: 1px solid #2b4866; border-radius: 999px; padding: 4px 7px; color: #9eb6ce; font-size: 10px; white-space: nowrap; }
|
|
71
|
+
.verification-item[data-status="current-passed"] .status-badge { border-color: #2dd4bf66; color: #9be8dc; }
|
|
72
|
+
.verification-item[data-status="failed"] .status-badge { border-color: #fb718566; color: #fda4af; }
|
|
73
|
+
.verification-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 7px 10px; margin: 11px 0; }
|
|
74
|
+
.verification-meta div:last-child { grid-column: 1 / -1; }
|
|
75
|
+
.verification-meta dt { color: #66829f; font-size: 9px; }
|
|
76
|
+
.verification-meta dd { overflow: hidden; margin: 3px 0 0; color: #aac1d8; font-family: "SFMono-Regular", Consolas, monospace; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
|
|
77
|
+
.verification-controls button { min-height: 30px; padding: 6px 9px; font-size: 11px; }
|
|
78
|
+
.verification-note { align-self: center; color: #607b97; font-size: 10px; }
|
|
79
|
+
.text-button { border-color: transparent; padding-right: 0; padding-left: 0; color: #7dd3fc; background: transparent; }
|
|
80
|
+
.text-button:hover:not(:disabled) { border-color: transparent; color: #bae6fd; background: transparent; }
|
|
81
|
+
.evidence-details { margin-top: 12px; border-top: 1px solid #183c55; padding-top: 11px; }
|
|
82
|
+
.evidence-details summary { color: #aac1d8; cursor: pointer; font-size: 12px; }
|
|
83
|
+
.evidence-details pre { max-height: 260px; overflow: auto; margin: 10px 0 0; border: 1px solid #142a40; border-radius: 9px; padding: 11px; color: #9eb6ce; background: #050d17; font-family: "SFMono-Regular", Consolas, monospace; font-size: 10px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
45
84
|
.data-editor { display: grid; grid-template-columns: minmax(120px, .7fr) minmax(220px, 2fr) minmax(110px, .6fr); gap: 10px; }
|
|
46
85
|
.data-editor label { display: grid; gap: 6px; color: #7892ae; font-size: 11px; font-weight: 650; }
|
|
47
86
|
.data-editor input, .data-editor select { width: 100%; min-height: 38px; border: 1px solid #23425f; border-radius: 9px; padding: 8px 10px; color: #dce9f8; background: #071321; font: inherit; font-size: 13px; }
|
|
@@ -77,6 +116,9 @@ footer strong { color: #a8bfd7; }
|
|
|
77
116
|
.topology { grid-template-columns: 1fr; }
|
|
78
117
|
.topology > span { transform: rotate(90deg); text-align: center; }
|
|
79
118
|
.scenario-grid { grid-template-columns: 1fr; }
|
|
119
|
+
.section-heading { align-items: flex-start; flex-direction: column; }
|
|
120
|
+
.verification-summary, .verification-category-cards { grid-template-columns: 1fr; }
|
|
121
|
+
.verification-empty { grid-column: auto; }
|
|
80
122
|
.data-editor { grid-template-columns: 1fr; }
|
|
81
123
|
.metric-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
82
124
|
.resident-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title
|
|
6
|
+
<title>运行时验收与证据</title>
|
|
7
7
|
<link rel="stylesheet" href="assets/style.css" />
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
@@ -11,25 +11,55 @@
|
|
|
11
11
|
<header class="hero">
|
|
12
12
|
<div>
|
|
13
13
|
<p class="eyebrow">RUST · WASM COMPONENT · HOST CAPABILITIES</p>
|
|
14
|
-
<h1
|
|
15
|
-
<p class="lead"
|
|
14
|
+
<h1>运行时验收与证据</h1>
|
|
15
|
+
<p class="lead">查看当前安装实例真实产生的验收记录。没有记录就显示“未验证”,不会把静态说明当成通过。</p>
|
|
16
16
|
</div>
|
|
17
17
|
<span class="live-badge"><i></i> 可交互 Demo</span>
|
|
18
18
|
</header>
|
|
19
19
|
|
|
20
|
+
<section class="verification" aria-labelledby="verification-title">
|
|
21
|
+
<div class="section-heading">
|
|
22
|
+
<div>
|
|
23
|
+
<p class="eyebrow">EVIDENCE CENTER</p>
|
|
24
|
+
<h2 id="verification-title">能力验收矩阵</h2>
|
|
25
|
+
<p>每条状态都由当前产品、当前 runner 指纹和实际证据共同判定;只有“当前通过”是绿色。</p>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="verification-actions">
|
|
28
|
+
<button type="button" data-refresh-verification class="secondary">刷新记录</button>
|
|
29
|
+
<button type="button" data-export-verification>导出证据</button>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
<dl class="verification-summary" aria-label="验收摘要">
|
|
33
|
+
<div><dt>验收应用</dt><dd data-verification-app>读取中…</dd></div>
|
|
34
|
+
<div><dt>产品 / Runtime</dt><dd data-verification-runtime>读取中…</dd></div>
|
|
35
|
+
<div><dt>当前通过</dt><dd data-verification-count>0</dd></div>
|
|
36
|
+
<div><dt>环境</dt><dd data-verification-environment>尚未验证</dd></div>
|
|
37
|
+
<div><dt>实现指纹</dt><dd data-verification-implementation>读取中…</dd></div>
|
|
38
|
+
<div><dt>合同指纹</dt><dd data-verification-contract>读取中…</dd></div>
|
|
39
|
+
<div><dt>证据来源</dt><dd data-verification-sources>读取中…</dd></div>
|
|
40
|
+
</dl>
|
|
41
|
+
<div class="verification-list" data-verification-list aria-live="polite">
|
|
42
|
+
<p class="verification-empty">正在读取真实验收记录…</p>
|
|
43
|
+
</div>
|
|
44
|
+
<details class="evidence-details" data-evidence-details>
|
|
45
|
+
<summary>查看最近证据</summary>
|
|
46
|
+
<pre data-verification-evidence>选择上方已有证据即可查看详情;该页不会把手动点击包装成验收通过。</pre>
|
|
47
|
+
</details>
|
|
48
|
+
</section>
|
|
49
|
+
|
|
20
50
|
<section class="topology" aria-label="运行拓扑">
|
|
21
51
|
<div class="node guest">Action Components<small>State + Capability</small></div>
|
|
22
52
|
<span aria-hidden="true">→</span>
|
|
23
|
-
<div class="node host">Shared Runner<small>Wasmtime + WIT</small></div>
|
|
53
|
+
<div class="node host">Shared Runner<small>Spin + Wasmtime + WIT</small></div>
|
|
24
54
|
<span aria-hidden="true">←</span>
|
|
25
55
|
<div class="node guest">Resident Component<small>Retained instance + events</small></div>
|
|
26
56
|
</section>
|
|
27
57
|
|
|
28
|
-
<section class="scenario-grid" aria-label="
|
|
58
|
+
<section class="scenario-grid" aria-label="运行时交互场景">
|
|
29
59
|
<article class="scenario" data-scenario="shared">
|
|
30
60
|
<div class="scenario-copy">
|
|
31
61
|
<span class="number">01</span>
|
|
32
|
-
|
|
62
|
+
<div><h2>共享宿主</h2><p>分别调用两个 Component,比较 runner PID 与已加载模块数。</p></div>
|
|
33
63
|
</div>
|
|
34
64
|
<button type="button" data-run="shared">验证同一进程</button>
|
|
35
65
|
<pre class="result" aria-live="polite">尚未执行</pre>
|
|
@@ -130,23 +160,14 @@
|
|
|
130
160
|
<article class="scenario benchmark-evidence">
|
|
131
161
|
<div class="scenario-copy">
|
|
132
162
|
<span class="number">07</span>
|
|
133
|
-
<div><h2
|
|
134
|
-
</div>
|
|
135
|
-
<
|
|
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>
|
|
163
|
+
<div><h2>性能与资源证据</h2><p>发布流水线在三个目标平台运行同一套持久计数 workload,记录冷/热延迟、吞吐、CPU、RSS/PSS、1/5/10 实例密度和卸载回收。</p></div>
|
|
164
|
+
</div>
|
|
165
|
+
<p class="benchmark-note">该页不内置容易过期的开发机数字。请在上方选择 <code>PRT-PERF-001</code> 查看与当前产品、当前 runner 指纹一致的结构化证据;没有当前证据时会明确显示“尚无证据”。</p>
|
|
145
166
|
</article>
|
|
146
167
|
</section>
|
|
147
168
|
|
|
148
169
|
<footer>
|
|
149
|
-
<strong
|
|
170
|
+
<strong>说明:</strong>下方交互场景用于复验当前已安装应用;上方矩阵只显示后端真实写入的 PRT 记录。
|
|
150
171
|
</footer>
|
|
151
172
|
</main>
|
|
152
173
|
<script src="assets/app.js"></script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "nextclaw-portable-runtime-lab-panel",
|
|
3
|
-
"title": "
|
|
4
|
-
"description": "
|
|
3
|
+
"title": "运行时验收与证据",
|
|
4
|
+
"description": "查看已安装应用真实产生的 PRT 验收记录、环境和证据。",
|
|
5
5
|
"entry": "index.html",
|
|
6
6
|
"actions": [
|
|
7
7
|
"nextclaw-portable-runtime-lab-state.counter_read",
|
|
@@ -22,6 +22,12 @@ function serviceActions() {
|
|
|
22
22
|
return bridge;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function verificationRecords() {
|
|
26
|
+
const bridge = window.nextclaw?.verificationRecords;
|
|
27
|
+
if (!bridge) throw new Error("验收记录桥尚未就绪。");
|
|
28
|
+
return bridge;
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
async function invoke(actionId, input = {}) {
|
|
26
32
|
return await serviceActions().invoke(actionId, input);
|
|
27
33
|
}
|
|
@@ -141,3 +147,18 @@ const now = new Date();
|
|
|
141
147
|
document.querySelector("[data-date-day]").textContent = String(now.getDate()).padStart(2, "0");
|
|
142
148
|
document.querySelector("[data-date-label]").textContent = now.toLocaleDateString("zh-CN", { month: "long", weekday: "short" });
|
|
143
149
|
void refresh().catch((error) => setNotice(error instanceof Error ? error.message : String(error), "error"));
|
|
150
|
+
async function refreshVerificationStatus() {
|
|
151
|
+
const element = document.querySelector("[data-verification-status]");
|
|
152
|
+
if (!element) return;
|
|
153
|
+
try {
|
|
154
|
+
const payload = await verificationRecords().list({ appId: "nextclaw.portable-runtime-lab", limit: 500 });
|
|
155
|
+
const entry = (payload?.entries || []).find((candidate) => candidate.acceptanceId === "PRT-ENTRY-001");
|
|
156
|
+
element.textContent = entry
|
|
157
|
+
? `${entry.status === "passed" ? "已有局部证据" : entry.status} · ${new Date(entry.finishedAt).toLocaleString()}`
|
|
158
|
+
: "未验证(暂无 PRT-ENTRY-001 记录)";
|
|
159
|
+
} catch {
|
|
160
|
+
element.textContent = "暂时无法读取验收记录";
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
void refreshVerificationStatus();
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
<details class="behind-scenes">
|
|
38
38
|
<summary>这个小应用背后发生了什么?</summary>
|
|
39
39
|
<p>每次添加、完成和删除都会调用同一组 Rust/WASM Service Action,并写入 NextClaw 管理的持久数据。关掉再打开,清单仍然存在;授权后的 Agent 也可以操作同一份数据。</p>
|
|
40
|
+
<p><strong>已验证能力</strong>:<span data-verification-status>读取中…</span></p>
|
|
40
41
|
<dl><div><dt>数据</dt><dd data-proof-revision>等待读取</dd></div><div><dt>存储</dt><dd>NextClaw Host KV</dd></div></dl>
|
|
41
42
|
</details>
|
|
42
43
|
</main>
|
|
@@ -1,20 +1,127 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "nextclaw-portable-runtime-lab-capabilities",
|
|
3
3
|
"title": "Portable Capability Component",
|
|
4
|
-
"description": "Rust/WASM
|
|
4
|
+
"description": "Rust/WASM 网络、文件权限、拒绝、错误与超时演示模块。",
|
|
5
5
|
"protocol": "wasi-component",
|
|
6
6
|
"component": {
|
|
7
7
|
"entry": "service.wasm"
|
|
8
8
|
},
|
|
9
|
+
"requires": {
|
|
10
|
+
"modelSlots": [
|
|
11
|
+
{
|
|
12
|
+
"id": "summary",
|
|
13
|
+
"title": "摘要模型",
|
|
14
|
+
"description": "用于验证受限的 Guest 模型调用。",
|
|
15
|
+
"required": false,
|
|
16
|
+
"maxTokens": 256,
|
|
17
|
+
"timeoutMs": 10000
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"agentSlots": [
|
|
21
|
+
{
|
|
22
|
+
"id": "review",
|
|
23
|
+
"title": "审阅 Agent",
|
|
24
|
+
"description": "用于验证异步 Guest Agent 调用。",
|
|
25
|
+
"required": false
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
9
29
|
"actions": {
|
|
10
|
-
"
|
|
30
|
+
"network_standard_http": {
|
|
31
|
+
"risk": "external",
|
|
32
|
+
"title": "通过标准 WASI HTTP 访问网络",
|
|
33
|
+
"inputSchema": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"properties": {
|
|
36
|
+
"url": { "type": "string", "format": "uri" },
|
|
37
|
+
"timeoutMs": { "type": "integer", "minimum": 1, "maximum": 30000 },
|
|
38
|
+
"maxResponseBytes": { "type": "integer", "minimum": 1, "maximum": 65536 }
|
|
39
|
+
},
|
|
40
|
+
"additionalProperties": false
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"network_allowed": { "risk": "external", "title": "访问允许的网络(旧兼容接口)" },
|
|
11
44
|
"network_denied": { "risk": "read", "title": "验证网络拒绝" },
|
|
45
|
+
"network_private_denied": { "risk": "read", "title": "验证私网拒绝" },
|
|
46
|
+
"network_redirect_denied": { "risk": "read", "title": "验证越权重定向拒绝" },
|
|
12
47
|
"structured_failure": { "risk": "dangerous", "title": "触发结构化失败" },
|
|
13
48
|
"simulate_timeout": {
|
|
14
49
|
"risk": "dangerous",
|
|
15
50
|
"title": "触发执行超时",
|
|
16
51
|
"timeoutMs": 1200
|
|
17
52
|
},
|
|
18
|
-
"
|
|
53
|
+
"long_task": {
|
|
54
|
+
"risk": "write",
|
|
55
|
+
"title": "运行可观测长任务",
|
|
56
|
+
"timeoutMs": 10000
|
|
57
|
+
},
|
|
58
|
+
"stream_overflow": {
|
|
59
|
+
"risk": "dangerous",
|
|
60
|
+
"title": "验证流背压边界",
|
|
61
|
+
"timeoutMs": 10000
|
|
62
|
+
},
|
|
63
|
+
"memory_pressure": {
|
|
64
|
+
"risk": "dangerous",
|
|
65
|
+
"title": "验证内存边界",
|
|
66
|
+
"timeoutMs": 10000
|
|
67
|
+
},
|
|
68
|
+
"runtime_info": { "risk": "read", "title": "查看共享宿主" },
|
|
69
|
+
"filesystem_read": {
|
|
70
|
+
"risk": "read",
|
|
71
|
+
"title": "读取已授权文件"
|
|
72
|
+
},
|
|
73
|
+
"filesystem_write": {
|
|
74
|
+
"risk": "write",
|
|
75
|
+
"title": "写入已授权文件",
|
|
76
|
+
"inputSchema": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"required": ["path", "content"],
|
|
79
|
+
"properties": {
|
|
80
|
+
"path": { "type": "string", "minLength": 1 },
|
|
81
|
+
"content": { "type": "string" }
|
|
82
|
+
},
|
|
83
|
+
"additionalProperties": false
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"secret_verify": {
|
|
87
|
+
"risk": "read",
|
|
88
|
+
"title": "验证已绑定 Secret",
|
|
89
|
+
"inputSchema": {
|
|
90
|
+
"type": "object",
|
|
91
|
+
"required": ["slot"],
|
|
92
|
+
"properties": {
|
|
93
|
+
"slot": { "type": "string", "minLength": 1 },
|
|
94
|
+
"expectedSha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
|
|
95
|
+
},
|
|
96
|
+
"additionalProperties": false
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"model_complete": {
|
|
100
|
+
"risk": "external",
|
|
101
|
+
"title": "调用已授权模型",
|
|
102
|
+
"inputSchema": {
|
|
103
|
+
"type": "object",
|
|
104
|
+
"required": ["slotId", "messages"],
|
|
105
|
+
"properties": {
|
|
106
|
+
"slotId": { "type": "string", "minLength": 1 },
|
|
107
|
+
"messages": { "type": "array", "minItems": 1 },
|
|
108
|
+
"maxTokens": { "type": "integer", "minimum": 1, "maximum": 4096 }
|
|
109
|
+
},
|
|
110
|
+
"additionalProperties": false
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"agent_start": {
|
|
114
|
+
"risk": "external",
|
|
115
|
+
"title": "启动已授权 Agent",
|
|
116
|
+
"inputSchema": {
|
|
117
|
+
"type": "object",
|
|
118
|
+
"required": ["slotId", "input"],
|
|
119
|
+
"properties": {
|
|
120
|
+
"slotId": { "type": "string", "minLength": 1 },
|
|
121
|
+
"input": { "type": "object" }
|
|
122
|
+
},
|
|
123
|
+
"additionalProperties": false
|
|
124
|
+
}
|
|
125
|
+
}
|
|
19
126
|
}
|
|
20
127
|
}
|
|
Binary file
|
|
@@ -6,9 +6,18 @@
|
|
|
6
6
|
"component": {
|
|
7
7
|
"entry": "service.wasm"
|
|
8
8
|
},
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
9
|
+
"requires": {
|
|
10
|
+
"capabilities": [{
|
|
11
|
+
"id": "nextclaw.contacts.normalize",
|
|
12
|
+
"version": "1",
|
|
13
|
+
"provider": "nextclaw-portable-runtime-lab-provider",
|
|
14
|
+
"wit": {
|
|
15
|
+
"package": "nextclaw:portable-service",
|
|
16
|
+
"interface": "host",
|
|
17
|
+
"version": "^0.1.0"
|
|
18
|
+
}
|
|
19
|
+
}]
|
|
20
|
+
},
|
|
12
21
|
"actions": {
|
|
13
22
|
"compose_contact": {
|
|
14
23
|
"risk": "write",
|
|
Binary file
|
|
@@ -9,6 +9,17 @@
|
|
|
9
9
|
"lifecycle": {
|
|
10
10
|
"mode": "provider"
|
|
11
11
|
},
|
|
12
|
+
"provides": {
|
|
13
|
+
"capabilities": [{
|
|
14
|
+
"id": "nextclaw.contacts.normalize",
|
|
15
|
+
"version": "1",
|
|
16
|
+
"wit": {
|
|
17
|
+
"package": "nextclaw:portable-service",
|
|
18
|
+
"interface": "host",
|
|
19
|
+
"version": "0.1.0"
|
|
20
|
+
}
|
|
21
|
+
}]
|
|
22
|
+
},
|
|
12
23
|
"actions": {
|
|
13
24
|
"contact_normalize": {
|
|
14
25
|
"risk": "write",
|