@webskill/sdk 0.5.0 → 0.7.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/agent.d.ts +2 -2
- package/dist/agent.js +274 -42
- package/dist/browser.d.ts +127 -5
- package/dist/browser.js +611 -17
- package/dist/{catalogComponents-DV7cPpUm-C77AEEx9.js → catalogComponents-Dr5dFMAb-DKH_7VPI.js} +848 -974
- package/dist/{dist-6C03DShK.js → dist-D0qW6e40.js} +1213 -210
- package/dist/{dist-bewtXYlO.js → dist-DnYG2-eY.js} +53 -14
- package/dist/{env--jJB-TSX-04klhTYi.js → env-8cY40DXB-CGnEVZby.js} +7 -6
- package/dist/{env-BPUBZCwJ-4jat_SVG.d.ts → env-AK3cSMEA-Dli6QU5E.d.ts} +4 -3
- package/dist/eventTypes-DjIQpt8Y-Bj3vghj4.js +32 -0
- package/dist/governance.d.ts +78 -11
- package/dist/governance.js +173 -50
- package/dist/{index-D_7ZZjkl.d.ts → index-Ba3xFtfz.d.ts} +222 -8
- package/dist/{index-Bsqg4ftU.d.ts → index-BwsK9lGk.d.ts} +13 -7
- package/dist/{index-vBz_FC9w.d.ts → index-DkbABR43.d.ts} +336 -52
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/mcp.d.ts +159 -11
- package/dist/mcp.js +276 -45
- package/dist/{memoryArtifactStore-BtOeB_hm-tj3fC5ip.js → memoryArtifactStore-52Zn9npI-BMPYwvoy.js} +10 -2
- package/dist/node.d.ts +4 -4
- package/dist/node.js +11 -3
- package/dist/{openUiLibrary-W3Ce896k-ClFTRZFs.js → openUiLibrary-Bdrji9qK-D2LxmM-a.js} +3 -3
- package/dist/{skillVersionStore-BzLbzFOL-CxwIewHJ.d.ts → skillVersionStore-Bl-ElD45-CWPvGvoq.d.ts} +8 -2
- package/dist/{testing-DDCJWvgA.js → testing-CYTFqkDm.js} +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +3 -3
- package/dist/{types-D_hoCri8-BnNPiZCi.d.ts → types-CcxRLdJG-DCXyw1US.d.ts} +62 -10
- package/dist/ui-react.d.ts +5 -3
- package/dist/ui-react.js +72 -47
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui-vue.js +13 -8
- package/dist/ui.d.ts +3 -3
- package/dist/ui.js +2 -2
- package/dist/{webskillLitCatalog-_mugzRHx-DiuJpCuf.js → webskillLitCatalog-_mugzRHx-B_54vxum.js} +1 -1
- package/package.json +1 -1
|
@@ -992,6 +992,7 @@ function shapeInteractionValue(model, values) {
|
|
|
992
992
|
case "confirm": return values["confirmed"] === true;
|
|
993
993
|
case "select": return values["selected"];
|
|
994
994
|
case "authorize": return true;
|
|
995
|
+
case "file-pick": return values["file"];
|
|
995
996
|
case "form": return values;
|
|
996
997
|
}
|
|
997
998
|
}
|
|
@@ -1005,7 +1006,8 @@ function interactionToFormModel(request) {
|
|
|
1005
1006
|
name: "answer",
|
|
1006
1007
|
label: request.message,
|
|
1007
1008
|
control: "text",
|
|
1008
|
-
required: true
|
|
1009
|
+
required: true,
|
|
1010
|
+
...request.suggestion ? { suggestion: request.suggestion } : {}
|
|
1009
1011
|
}],
|
|
1010
1012
|
submitLabel: "Submit",
|
|
1011
1013
|
cancelLabel: "Cancel"
|
|
@@ -1046,7 +1048,8 @@ function interactionToFormModel(request) {
|
|
|
1046
1048
|
label: request.message,
|
|
1047
1049
|
control: "select",
|
|
1048
1050
|
required: true,
|
|
1049
|
-
options: request.options
|
|
1051
|
+
options: request.options,
|
|
1052
|
+
...request.suggestion ? { suggestion: request.suggestion } : {}
|
|
1050
1053
|
}],
|
|
1051
1054
|
submitLabel: "Select",
|
|
1052
1055
|
cancelLabel: "Cancel"
|
|
@@ -1059,6 +1062,21 @@ function interactionToFormModel(request) {
|
|
|
1059
1062
|
submitLabel: "Allow",
|
|
1060
1063
|
cancelLabel: "Deny"
|
|
1061
1064
|
};
|
|
1065
|
+
case "file-pick": return {
|
|
1066
|
+
kind: "file-pick",
|
|
1067
|
+
title: "File requested",
|
|
1068
|
+
message: request.message,
|
|
1069
|
+
controls: [{
|
|
1070
|
+
name: "file",
|
|
1071
|
+
label: request.field ?? "file",
|
|
1072
|
+
control: "file",
|
|
1073
|
+
required: true,
|
|
1074
|
+
...request.accept ? { accept: request.accept } : {},
|
|
1075
|
+
...request.multiple ? { multiple: true } : {}
|
|
1076
|
+
}],
|
|
1077
|
+
submitLabel: "Choose file",
|
|
1078
|
+
cancelLabel: "Decline"
|
|
1079
|
+
};
|
|
1062
1080
|
}
|
|
1063
1081
|
}
|
|
1064
1082
|
const isEmpty = (v) => v === void 0 || v === "";
|
|
@@ -1133,7 +1151,10 @@ function applySuggestion(control, container) {
|
|
|
1133
1151
|
* 全部经 doc.createElementNS 构建(内容来自技能输出,不拼 innerHTML)。
|
|
1134
1152
|
*/
|
|
1135
1153
|
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
1136
|
-
/**
|
|
1154
|
+
/**
|
|
1155
|
+
* 固定 8 色循环调色板。这是**数据编码**(区分序列),不是主题色;
|
|
1156
|
+
* 图表的轴线与文字等“外壳”颜色走 currentColor,跟随宿主容器的主题。
|
|
1157
|
+
*/
|
|
1137
1158
|
const CHART_PALETTE = [
|
|
1138
1159
|
"#4e79a7",
|
|
1139
1160
|
"#f28e2b",
|
|
@@ -1156,7 +1177,8 @@ function text(doc, x, y, content, attrs = {}) {
|
|
|
1156
1177
|
x: String(x),
|
|
1157
1178
|
y: String(y),
|
|
1158
1179
|
"font-size": "9",
|
|
1159
|
-
fill: "
|
|
1180
|
+
fill: "currentColor",
|
|
1181
|
+
"fill-opacity": "0.65",
|
|
1160
1182
|
...attrs
|
|
1161
1183
|
});
|
|
1162
1184
|
node.textContent = content;
|
|
@@ -1181,14 +1203,16 @@ function renderBar(chart, svg, doc) {
|
|
|
1181
1203
|
y1: String(plot.y0),
|
|
1182
1204
|
x2: String(plot.x0),
|
|
1183
1205
|
y2: String(plot.y1),
|
|
1184
|
-
stroke: "
|
|
1206
|
+
stroke: "currentColor",
|
|
1207
|
+
"stroke-opacity": "0.35"
|
|
1185
1208
|
}));
|
|
1186
1209
|
svg.appendChild(el(doc, "line", {
|
|
1187
1210
|
x1: String(plot.x0),
|
|
1188
1211
|
y1: String(plot.y1),
|
|
1189
1212
|
x2: String(plot.x1),
|
|
1190
1213
|
y2: String(plot.y1),
|
|
1191
|
-
stroke: "
|
|
1214
|
+
stroke: "currentColor",
|
|
1215
|
+
"stroke-opacity": "0.35"
|
|
1192
1216
|
}));
|
|
1193
1217
|
if (max <= 0 || chart.labels.length === 0 || chart.series.length === 0) return;
|
|
1194
1218
|
const groupWidth = (plot.x1 - plot.x0) / chart.labels.length;
|
|
@@ -1228,14 +1252,16 @@ function renderLine(chart, svg, doc) {
|
|
|
1228
1252
|
y1: String(plot.y0),
|
|
1229
1253
|
x2: String(plot.x0),
|
|
1230
1254
|
y2: String(plot.y1),
|
|
1231
|
-
stroke: "
|
|
1255
|
+
stroke: "currentColor",
|
|
1256
|
+
"stroke-opacity": "0.35"
|
|
1232
1257
|
}));
|
|
1233
1258
|
svg.appendChild(el(doc, "line", {
|
|
1234
1259
|
x1: String(plot.x0),
|
|
1235
1260
|
y1: String(plot.y1),
|
|
1236
1261
|
x2: String(plot.x1),
|
|
1237
1262
|
y2: String(plot.y1),
|
|
1238
|
-
stroke: "
|
|
1263
|
+
stroke: "currentColor",
|
|
1264
|
+
"stroke-opacity": "0.35"
|
|
1239
1265
|
}));
|
|
1240
1266
|
if (max <= 0 || chart.labels.length === 0 || chart.series.length === 0) return;
|
|
1241
1267
|
const step = chart.labels.length > 1 ? (plot.x1 - plot.x0) / (chart.labels.length - 1) : 0;
|
|
@@ -1315,7 +1341,8 @@ function renderMiniChart(chart, doc) {
|
|
|
1315
1341
|
if (chart.title) svg.appendChild(text(doc, WIDTH / 2, 14, chart.title, {
|
|
1316
1342
|
"text-anchor": "middle",
|
|
1317
1343
|
"font-size": "11",
|
|
1318
|
-
fill: "
|
|
1344
|
+
fill: "currentColor",
|
|
1345
|
+
"fill-opacity": "1"
|
|
1319
1346
|
}));
|
|
1320
1347
|
switch (chart.kind) {
|
|
1321
1348
|
case "bar":
|
|
@@ -1632,7 +1659,7 @@ var WebFormBridge = class {
|
|
|
1632
1659
|
wrapper.appendChild(error);
|
|
1633
1660
|
return wrapper;
|
|
1634
1661
|
}
|
|
1635
|
-
/**
|
|
1662
|
+
/** 建议值以**建议**形态出现(FR-19.4):控件初始值仍为空,点「使用」才写入 */
|
|
1636
1663
|
#renderSuggestion(control, container) {
|
|
1637
1664
|
const doc = this.#doc;
|
|
1638
1665
|
const row = doc.createElement("div");
|
|
@@ -1640,8 +1667,15 @@ var WebFormBridge = class {
|
|
|
1640
1667
|
row.setAttribute("data-webskill-suggestion", control.name);
|
|
1641
1668
|
const preview = doc.createElement("span");
|
|
1642
1669
|
preview.className = "webskill-form__suggestion-value";
|
|
1643
|
-
preview.textContent = `
|
|
1670
|
+
preview.textContent = `Suggested: ${String(control.suggestion?.value)}`;
|
|
1644
1671
|
row.appendChild(preview);
|
|
1672
|
+
const reason = control.suggestion?.reason;
|
|
1673
|
+
if (reason !== void 0 && reason !== "") {
|
|
1674
|
+
const why = doc.createElement("span");
|
|
1675
|
+
why.className = "webskill-form__suggestion-reason";
|
|
1676
|
+
why.textContent = `(${reason})`;
|
|
1677
|
+
row.appendChild(why);
|
|
1678
|
+
}
|
|
1645
1679
|
const use = doc.createElement("button");
|
|
1646
1680
|
use.type = "button";
|
|
1647
1681
|
use.className = "webskill-form__suggestion-use";
|
|
@@ -2016,7 +2050,8 @@ const FIELD_TYPE = {
|
|
|
2016
2050
|
number: "number",
|
|
2017
2051
|
boolean: "toggle",
|
|
2018
2052
|
select: "select",
|
|
2019
|
-
textarea: "textarea"
|
|
2053
|
+
textarea: "textarea",
|
|
2054
|
+
file: "file"
|
|
2020
2055
|
};
|
|
2021
2056
|
function toOptions(options) {
|
|
2022
2057
|
return (options ?? []).map((option) => ({
|
|
@@ -2035,6 +2070,8 @@ function toField(control) {
|
|
|
2035
2070
|
...control.description ? { description: control.description } : {},
|
|
2036
2071
|
...control.defaultValue !== void 0 ? { defaultValue: control.defaultValue } : {},
|
|
2037
2072
|
...control.suggestion ? { suggestion: control.suggestion } : {},
|
|
2073
|
+
...control.accept ? { accept: [...control.accept] } : {},
|
|
2074
|
+
...control.multiple ? { multiple: true } : {},
|
|
2038
2075
|
...control.options ? { options: toOptions(control.options) } : {}
|
|
2039
2076
|
}
|
|
2040
2077
|
};
|
|
@@ -2087,6 +2124,8 @@ const INTENTS = /* @__PURE__ */ new Set([
|
|
|
2087
2124
|
"download",
|
|
2088
2125
|
"refresh"
|
|
2089
2126
|
]);
|
|
2127
|
+
/** 去重靠指纹兜底,但重复调用本身也浪费一轮,所以先在提示词里劝阻(FR-21.5) */
|
|
2128
|
+
const NO_DUPLICATE_RENDER = "If a skill has already rendered a surface for this request, do not call render_ui again with the same content.";
|
|
2090
2129
|
function isIntent(value) {
|
|
2091
2130
|
return typeof value === "string" && INTENTS.has(value);
|
|
2092
2131
|
}
|
|
@@ -2167,7 +2206,7 @@ function createUiCatalogToolSource(options = {}) {
|
|
|
2167
2206
|
});
|
|
2168
2207
|
return {
|
|
2169
2208
|
kind: "ui-catalog",
|
|
2170
|
-
systemPrompt: () => Promise.resolve(catalog.toPrompt()),
|
|
2209
|
+
systemPrompt: () => Promise.resolve(`${catalog.toPrompt()}\n\n${NO_DUPLICATE_RENDER}`),
|
|
2171
2210
|
listToolSpecs: () => Promise.resolve(presets.length > 0 ? [renderTool(), presetTool()] : [renderTool()]),
|
|
2172
2211
|
canHandle: (name) => name === "render_ui" || presets.length > 0 && name === "describe_ui_preset",
|
|
2173
2212
|
call: (name, args) => {
|
|
@@ -2452,7 +2491,7 @@ function fromA2uiSpecAction(event) {
|
|
|
2452
2491
|
*/
|
|
2453
2492
|
async function loadWebSkillLitCatalog() {
|
|
2454
2493
|
try {
|
|
2455
|
-
const { webskillLitCatalog } = await import("./webskillLitCatalog-_mugzRHx-
|
|
2494
|
+
const { webskillLitCatalog } = await import("./webskillLitCatalog-_mugzRHx-B_54vxum.js");
|
|
2456
2495
|
return webskillLitCatalog();
|
|
2457
2496
|
} catch (cause) {
|
|
2458
2497
|
throw new WebSkillError("UI_UNAVAILABLE", "The WebSkill A2UI catalog is unavailable; install @a2ui/lit, @a2ui/web_core and lit to render catalog surfaces with A2UI", cause);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
|
|
3
|
-
//#region ../node/dist/env
|
|
3
|
+
//#region ../node/dist/env-8cY40DXB.js
|
|
4
4
|
/** 解析 .env(简单 KEY=VALUE 行解析,不引依赖);文件缺失返回 undefined */
|
|
5
5
|
function readEnvVars(dotenvPath) {
|
|
6
6
|
let raw;
|
|
@@ -23,15 +23,16 @@ function readEnvVars(dotenvPath) {
|
|
|
23
23
|
return vars;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
* 读取 LLM_BASE_URL / LLM_API_KEY / LLM_MODEL
|
|
27
|
-
*
|
|
26
|
+
* 读取 LLM_BASE_URL / LLM_API_KEY / LLM_MODEL;缺项返回 undefined 供测试 skip 判断。
|
|
27
|
+
* 0.6.0 FR-13.2 移除了旧的 `VITE_` 前缀回退:该前缀是 Vite 向**客户端 bundle** 注入变量的开关,
|
|
28
|
+
* 把 API key 放在它名下等于告诉使用者“这个 key 会被打进前端产物”。
|
|
28
29
|
*/
|
|
29
30
|
function loadLlmConfigFromEnv(dotenvPath = ".env") {
|
|
30
31
|
const vars = readEnvVars(dotenvPath);
|
|
31
32
|
if (!vars) return void 0;
|
|
32
|
-
const baseUrl = vars.get("LLM_BASE_URL")
|
|
33
|
-
const apiKey = vars.get("LLM_API_KEY")
|
|
34
|
-
const model = vars.get("LLM_MODEL")
|
|
33
|
+
const baseUrl = vars.get("LLM_BASE_URL");
|
|
34
|
+
const apiKey = vars.get("LLM_API_KEY");
|
|
35
|
+
const model = vars.get("LLM_MODEL");
|
|
35
36
|
if (!baseUrl || !apiKey || !model) return void 0;
|
|
36
37
|
return {
|
|
37
38
|
baseUrl,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../node/dist/env-
|
|
1
|
+
//#region ../node/dist/env-AK3cSMEA.d.ts
|
|
2
2
|
//#region src/env.d.ts
|
|
3
3
|
interface LlmEnvConfig {
|
|
4
4
|
baseUrl: string;
|
|
@@ -12,8 +12,9 @@ interface ProviderEnvConfig {
|
|
|
12
12
|
baseUrl?: string;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* 读取 LLM_BASE_URL / LLM_API_KEY / LLM_MODEL
|
|
16
|
-
*
|
|
15
|
+
* 读取 LLM_BASE_URL / LLM_API_KEY / LLM_MODEL;缺项返回 undefined 供测试 skip 判断。
|
|
16
|
+
* 0.6.0 FR-13.2 移除了旧的 `VITE_` 前缀回退:该前缀是 Vite 向**客户端 bundle** 注入变量的开关,
|
|
17
|
+
* 把 API key 放在它名下等于告诉使用者“这个 key 会被打进前端产物”。
|
|
17
18
|
*/
|
|
18
19
|
declare function loadLlmConfigFromEnv(dotenvPath?: string): LlmEnvConfig | undefined;
|
|
19
20
|
/** ANTHROPIC_API_KEY / ANTHROPIC_MODEL(可选 ANTHROPIC_BASE_URL);缺项返回 undefined */
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region ../governance/dist/eventTypes-DjIQpt8Y.js
|
|
2
|
+
/**
|
|
3
|
+
* 审计事件类型常量(FR-13.4)。
|
|
4
|
+
*
|
|
5
|
+
* 存在的理由是**消灭调用点的字面量**:写入点分散在 governance 与 console 的十来个文件里,
|
|
6
|
+
* 字面量拼错不会有任何编译期反馈,只会在审计里留下一条永远查不到的记录。
|
|
7
|
+
*
|
|
8
|
+
* `AuditEvent.type` 刻意**保持 `string`**、不收窄为 `AuditEventType`——
|
|
9
|
+
* 收窄会让外部写入方(插件、其它宿主)无法追加自定义类型,且会立刻产生快照差异。
|
|
10
|
+
*/
|
|
11
|
+
const AUDIT_EVENT_TYPES = {
|
|
12
|
+
skillEdited: "skill.edited",
|
|
13
|
+
skillRolledBack: "skill.rolled_back",
|
|
14
|
+
skillPublished: "skill.published",
|
|
15
|
+
skillRepairApplied: "skill.repair_applied",
|
|
16
|
+
skillQuarantined: "skill.quarantined",
|
|
17
|
+
skillPolicyDenied: "skill.policy_denied",
|
|
18
|
+
skillUninstalled: "skill.uninstalled",
|
|
19
|
+
skillInstalled: "skill.installed",
|
|
20
|
+
trustKeyAdded: "trust.key_added",
|
|
21
|
+
trustKeyRemoved: "trust.key_removed",
|
|
22
|
+
policyNetworkChanged: "policy.network_changed",
|
|
23
|
+
policyPrivacyChanged: "policy.privacy_changed",
|
|
24
|
+
mcpEndpointChanged: "mcp.endpoint_changed",
|
|
25
|
+
mcpPolicyRelaxed: "mcp.policy_relaxed",
|
|
26
|
+
providerChanged: "provider.changed"
|
|
27
|
+
};
|
|
28
|
+
/** 稳定展示序:筛选下拉与文档表格都从这里取,不各自维护一份顺序 */
|
|
29
|
+
const AUDIT_EVENT_TYPE_LIST = Object.values(AUDIT_EVENT_TYPES);
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { AUDIT_EVENT_TYPE_LIST as n, AUDIT_EVENT_TYPES as t };
|
package/dist/governance.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { _ as SkillVersion, a as AuditLog, c as CandidateFile, d as CandidateSource, f as CandidateStatus, g as SkillState, h as SKILL_VERSION_PAGE_SIZE, i as AuditEvent, l as CandidateRisk, m as CompositeApprovalPolicy, n as ApprovalDecision, o as AuditQueryFilter, p as CandidateStore, r as ApprovalPolicy, s as CANDIDATE_PAGE_SIZE, t as AlwaysHumanApprovalPolicy, u as CandidateSkill, v as SkillVersionStore, y as candidateToCatalogEntry } from "./skillVersionStore-
|
|
1
|
+
import { H as PageQuery, I as FileSystemProvider, V as Page, et as SkillCatalogEntry, f as LlmMessage, l as LlmClient, nt as SkillDocument, ot as SkillManagerPort, x as UiBridge } from "./types-CcxRLdJG-DCXyw1US.js";
|
|
2
|
+
import { H as IntegrityVerdict, Nt as SkillIntegrityGuard, Pt as SkillOutcomeReporter, Rt as SkillStateGuard, bt as RuntimeRun, ln as WebSkillRuntime } from "./index-DkbABR43.js";
|
|
3
|
+
import { _ as SkillVersion, a as AuditLog, c as CandidateFile, d as CandidateSource, f as CandidateStatus, g as SkillState, h as SKILL_VERSION_PAGE_SIZE, i as AuditEvent, l as CandidateRisk, m as CompositeApprovalPolicy, n as ApprovalDecision, o as AuditQueryFilter, p as CandidateStore, r as ApprovalPolicy, s as CANDIDATE_PAGE_SIZE, t as AlwaysHumanApprovalPolicy, u as CandidateSkill, v as SkillVersionStore, y as candidateToCatalogEntry } from "./skillVersionStore-Bl-ElD45-CWPvGvoq.js";
|
|
4
4
|
//#region ../governance/dist/index.d.ts
|
|
5
5
|
//#region src/candidate/candidateNormalizer.d.ts
|
|
6
6
|
/** 剥 markdown fence 与 <think> 块、截取首尾 {};非对象 → CANDIDATE_INVALID */
|
|
@@ -99,12 +99,29 @@ interface AuditChainVerification {
|
|
|
99
99
|
/** 首个断链位置(行号,0 起;ok 时 undefined) */
|
|
100
100
|
brokenAt?: number;
|
|
101
101
|
reason?: string;
|
|
102
|
+
/** 已扫描的记录总数(无论成败都给,便于判断断点在全链中的位置) */
|
|
103
|
+
total?: number;
|
|
104
|
+
/** 断点前一条的 ts(断点在首行时缺失) */
|
|
105
|
+
brokenBeforeTs?: string;
|
|
106
|
+
/** 断点所在记录的 ts(该行不可解析时缺失) */
|
|
107
|
+
brokenAfterTs?: string;
|
|
108
|
+
}
|
|
109
|
+
/** 带断链报告的分页结果(`tolerateBrokenChain` 打开时才可能带上后两个字段) */
|
|
110
|
+
interface AuditPage extends Page<AuditEvent> {
|
|
111
|
+
chainBrokenAt?: number;
|
|
112
|
+
chainReason?: string;
|
|
102
113
|
}
|
|
103
114
|
/**
|
|
104
115
|
* JSONL 追加式审计日志(<managedRoot>/.webskill/audit.jsonl):
|
|
105
|
-
* 真追加(fs.appendText,不整读改写)+ lastHash
|
|
116
|
+
* 真追加(fs.appendText,不整读改写)+ lastHash 缓存(仅当文件字节数未变时可用)。
|
|
106
117
|
* 语义:**tamper-evident, not tamper-proof**——verifyChain 能检出篡改/删除/换序,
|
|
107
118
|
* 但不阻止有写权限者直接改写文件;更强保证需要签名信任体系(未排期)。
|
|
119
|
+
*
|
|
120
|
+
* **并发边界**:追加的串行化只在**同一进程内**成立(模块级 mutex)。
|
|
121
|
+
* 跨进程 / 跨标签页靠的是「写前用 `stat().size` 重新确认链尾」:
|
|
122
|
+
* 外部写入会改变字节数,后写者因此会重读链尾而不会分叉——
|
|
123
|
+
* 除非两个进程落在同一个 stat/append 窗口内。真正的跨进程互斥需要文件锁,
|
|
124
|
+
* `FileSystemProvider` 不提供,不在本版承诺范围。
|
|
108
125
|
*/
|
|
109
126
|
declare class FsAuditLog implements AuditLog {
|
|
110
127
|
#private;
|
|
@@ -126,11 +143,42 @@ declare class FsAuditLog implements AuditLog {
|
|
|
126
143
|
* 任一处对不上以 `GOVERNANCE_FAILED` 报错。范围之外的断链不在本方法职责内——
|
|
127
144
|
* 那是 `verifyChain()` 的事(全量 O(N) 校验不该压在每次翻页上)。
|
|
128
145
|
*/
|
|
129
|
-
query(filter?: AuditQueryFilter & PageQuery): Promise<
|
|
130
|
-
/** hash 链完整性校验:逐行重算 hash 并核对 prevHash
|
|
146
|
+
query(filter?: AuditQueryFilter & PageQuery): Promise<AuditPage>;
|
|
147
|
+
/** hash 链完整性校验:逐行重算 hash 并核对 prevHash 链接。**只读**,绝不改写历史 */
|
|
131
148
|
verifyChain(): Promise<AuditChainVerification>;
|
|
132
149
|
}
|
|
133
150
|
//#endregion
|
|
151
|
+
//#region src/audit/eventTypes.d.ts
|
|
152
|
+
/**
|
|
153
|
+
* 审计事件类型常量(FR-13.4)。
|
|
154
|
+
*
|
|
155
|
+
* 存在的理由是**消灭调用点的字面量**:写入点分散在 governance 与 console 的十来个文件里,
|
|
156
|
+
* 字面量拼错不会有任何编译期反馈,只会在审计里留下一条永远查不到的记录。
|
|
157
|
+
*
|
|
158
|
+
* `AuditEvent.type` 刻意**保持 `string`**、不收窄为 `AuditEventType`——
|
|
159
|
+
* 收窄会让外部写入方(插件、其它宿主)无法追加自定义类型,且会立刻产生快照差异。
|
|
160
|
+
*/
|
|
161
|
+
declare const AUDIT_EVENT_TYPES: {
|
|
162
|
+
readonly skillEdited: "skill.edited";
|
|
163
|
+
readonly skillRolledBack: "skill.rolled_back";
|
|
164
|
+
readonly skillPublished: "skill.published";
|
|
165
|
+
readonly skillRepairApplied: "skill.repair_applied";
|
|
166
|
+
readonly skillQuarantined: "skill.quarantined";
|
|
167
|
+
readonly skillPolicyDenied: "skill.policy_denied";
|
|
168
|
+
readonly skillUninstalled: "skill.uninstalled";
|
|
169
|
+
readonly skillInstalled: "skill.installed";
|
|
170
|
+
readonly trustKeyAdded: "trust.key_added";
|
|
171
|
+
readonly trustKeyRemoved: "trust.key_removed";
|
|
172
|
+
readonly policyNetworkChanged: "policy.network_changed";
|
|
173
|
+
readonly policyPrivacyChanged: "policy.privacy_changed";
|
|
174
|
+
readonly mcpEndpointChanged: "mcp.endpoint_changed";
|
|
175
|
+
readonly mcpPolicyRelaxed: "mcp.policy_relaxed";
|
|
176
|
+
readonly providerChanged: "provider.changed";
|
|
177
|
+
};
|
|
178
|
+
type AuditEventType = (typeof AUDIT_EVENT_TYPES)[keyof typeof AUDIT_EVENT_TYPES];
|
|
179
|
+
/** 稳定展示序:筛选下拉与文档表格都从这里取,不各自维护一份顺序 */
|
|
180
|
+
declare const AUDIT_EVENT_TYPE_LIST: readonly AuditEventType[];
|
|
181
|
+
//#endregion
|
|
134
182
|
//#region src/repair/failureAnalyzer.d.ts
|
|
135
183
|
interface FailureDiagnosis {
|
|
136
184
|
cause: string;
|
|
@@ -173,6 +221,17 @@ declare class RepairPlanner {
|
|
|
173
221
|
}
|
|
174
222
|
//#endregion
|
|
175
223
|
//#region src/state/skillStatePolicy.d.ts
|
|
224
|
+
/**
|
|
225
|
+
* 用户策略主动拒绝的错误码(FR-12.4):这是配置生效的证据,不是技能有问题,不计入隔离阈值。
|
|
226
|
+
*
|
|
227
|
+
* 集中在这一份常量里而不散在条件判断里,是为了让「哪些码不计数」只有一个事实源。
|
|
228
|
+
*/
|
|
229
|
+
declare const POLICY_DENIAL_CODES: ReadonlySet<string>;
|
|
230
|
+
/** 自动隔离的原因判别式(FR-12.6);人工隔离仍写自由文本 */
|
|
231
|
+
declare const QUARANTINE_REASONS: {
|
|
232
|
+
readonly integrity: "integrity";
|
|
233
|
+
readonly failures: "failures";
|
|
234
|
+
};
|
|
176
235
|
/**
|
|
177
236
|
* 降级治理:states.json 持久化;失败达阈值 → quarantined;
|
|
178
237
|
* canRoute 仅 active;canExecute active|deprecated;disabled 执行抛 SKILL_DISABLED;
|
|
@@ -191,15 +250,22 @@ declare class SkillStatePolicy {
|
|
|
191
250
|
setState(skillName: string, state: SkillState, input: {
|
|
192
251
|
actor?: string;
|
|
193
252
|
reason?: string;
|
|
253
|
+
detail?: string;
|
|
194
254
|
}): Promise<void>;
|
|
195
255
|
/**
|
|
196
256
|
* 失败计数;达阈值(默认 3)→ quarantined + 审计。
|
|
197
257
|
*
|
|
198
|
-
*
|
|
258
|
+
* 计数是**连续**而非累计(0.7.0 FR-12.5):一次成功执行经 `clearFailures` 归零,
|
|
259
|
+
* `setState(name, 'active')` 同样清零。
|
|
199
260
|
*/
|
|
200
261
|
recordFailure(skillName: string, input?: {
|
|
201
262
|
actor?: string;
|
|
202
263
|
}): Promise<SkillState>;
|
|
264
|
+
/**
|
|
265
|
+
* 成功清零(FR-12.5)。不写审计(成功是常态,写了会把审计流淹掉),
|
|
266
|
+
* 也**不改变 state**——已隔离的技能不会因一次成功自动解除。
|
|
267
|
+
*/
|
|
268
|
+
clearFailures(skillName: string): Promise<void>;
|
|
203
269
|
canRoute(state: SkillState): boolean;
|
|
204
270
|
canExecute(state: SkillState): boolean;
|
|
205
271
|
/**
|
|
@@ -221,17 +287,18 @@ declare class SkillStatePolicy {
|
|
|
221
287
|
toSkillIntegrityGuard(verify: (skillName: string) => Promise<IntegrityVerdict>): SkillIntegrityGuard;
|
|
222
288
|
/**
|
|
223
289
|
* runtime `SkillOutcomeReporter` 适配(F1):一次真实的技能脚本执行失败 → `recordFailure`,
|
|
224
|
-
* 达阈值即自动 `quarantined` +
|
|
290
|
+
* 达阈值即自动 `quarantined` + 写审计;一次成功 → `clearFailures`。
|
|
225
291
|
*
|
|
226
292
|
* 0.4.0 之前 `recordFailure` 没有任何生产调用方——`states.json` 的失败计数只在单测里增长,
|
|
227
293
|
* 于是「失败达阈值自动隔离」在真实部署里从不触发,Console 上那个计数恒为 0。
|
|
228
294
|
* 这个适配器就是把那一段接上:runtime 不能反向依赖治理,装配点只能在宿主。
|
|
229
295
|
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
296
|
+
* 策略拒绝的分流放在这里而不是 `recordFailure`:后者是**治理动作**(管理员也可手工调用),
|
|
297
|
+
* 它不该知道运行时错误码;判定“这次失败算不算技能的错”是**上报侧**的语义。
|
|
232
298
|
*/
|
|
233
299
|
toSkillOutcomeReporter(input?: {
|
|
234
300
|
actor?: string;
|
|
301
|
+
policyDenialCodes?: ReadonlySet<string>;
|
|
235
302
|
}): SkillOutcomeReporter;
|
|
236
303
|
/** disabled → SKILL_DISABLED;quarantined → SKILL_QUARANTINED */
|
|
237
304
|
assertExecutable(skillName: string): Promise<void>;
|
|
@@ -405,4 +472,4 @@ declare function createMissHook(deps: {
|
|
|
405
472
|
*/
|
|
406
473
|
declare function completeText(llm: LlmClient, messages: LlmMessage[]): Promise<string>;
|
|
407
474
|
//#endregion
|
|
408
|
-
export { AUDIT_PAGE_SIZE, AlwaysHumanApprovalPolicy, type ApprovalDecision, type ApprovalPolicy, type AuditEvent, type AuditLog, type AuditQueryFilter, CANDIDATE_PAGE_SIZE, type CandidateFile, type CandidateRisk, type CandidateSink, type CandidateSinkOptions, type CandidateSkill, type CandidateSource, type CandidateStatus, CandidateStore, CompositeApprovalPolicy, DependencyGraph, DocumentSkillExtractor, type EvaluationReport, type EvaluationResult, EvaluationRunner, type EvaluationTask, FailureAnalyzer, type FailureDiagnosis, FsAuditLog, type GeneratedSkillSubmission, LlmCandidateGenerator, type RepairOption, RepairPlanner, SCORING_WEIGHTS, SKILL_VERSION_PAGE_SIZE, type ScoreInput, SimilarityDetector, SkillScorer, type SkillState, SkillStatePolicy, type SkillVersion, SkillVersionStore, type SourceDocument, candidateToCatalogEntry, completeText, createCandidateSink, createMissHook, jaccardSimilarity, normalizeCandidate, normalizeCandidateFiles, normalizeRisk, parseJsonObject, readDocument, sanitizeCandidateName, suggestFromFailedRun, validateCandidate };
|
|
475
|
+
export { AUDIT_EVENT_TYPES, AUDIT_EVENT_TYPE_LIST, AUDIT_PAGE_SIZE, AlwaysHumanApprovalPolicy, type ApprovalDecision, type ApprovalPolicy, type AuditChainVerification, type AuditEvent, type AuditEventType, type AuditLog, type AuditPage, type AuditQueryFilter, CANDIDATE_PAGE_SIZE, type CandidateFile, type CandidateRisk, type CandidateSink, type CandidateSinkOptions, type CandidateSkill, type CandidateSource, type CandidateStatus, CandidateStore, CompositeApprovalPolicy, DependencyGraph, DocumentSkillExtractor, type EvaluationReport, type EvaluationResult, EvaluationRunner, type EvaluationTask, FailureAnalyzer, type FailureDiagnosis, FsAuditLog, type GeneratedSkillSubmission, LlmCandidateGenerator, POLICY_DENIAL_CODES, QUARANTINE_REASONS, type RepairOption, RepairPlanner, SCORING_WEIGHTS, SKILL_VERSION_PAGE_SIZE, type ScoreInput, SimilarityDetector, SkillScorer, type SkillState, SkillStatePolicy, type SkillVersion, SkillVersionStore, type SourceDocument, candidateToCatalogEntry, completeText, createCandidateSink, createMissHook, jaccardSimilarity, normalizeCandidate, normalizeCandidateFiles, normalizeRisk, parseJsonObject, readDocument, sanitizeCandidateName, suggestFromFailedRun, validateCandidate };
|