@webskill/sdk 0.6.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 +217 -27
- package/dist/browser.d.ts +30 -4
- package/dist/browser.js +196 -12
- package/dist/{catalogComponents-Dr5dFMAb-Dacibl1e.js → catalogComponents-Dr5dFMAb-DKH_7VPI.js} +723 -931
- package/dist/{dist-DusANsrn.js → dist-D0qW6e40.js} +246 -39
- package/dist/eventTypes-DjIQpt8Y-Bj3vghj4.js +32 -0
- package/dist/governance.d.ts +78 -11
- package/dist/governance.js +172 -49
- package/dist/{index-BuTpBMzr.d.ts → index-Ba3xFtfz.d.ts} +156 -5
- package/dist/{index-BMocOEi0.d.ts → index-BwsK9lGk.d.ts} +2 -2
- package/dist/{index-C-KFAZoF.d.ts → index-DkbABR43.d.ts} +40 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/mcp.d.ts +123 -6
- package/dist/mcp.js +224 -27
- package/dist/node.d.ts +3 -3
- package/dist/node.js +3 -2
- package/dist/{openUiLibrary-Bdrji9qK-DzAxRlTY.js → openUiLibrary-Bdrji9qK-D2LxmM-a.js} +1 -1
- package/dist/{skillVersionStore-BzLbzFOL-CxdAFWO2.d.ts → skillVersionStore-Bl-ElD45-CWPvGvoq.d.ts} +8 -2
- package/dist/testing.d.ts +1 -1
- package/dist/{types-4pg-qp_I-Gq63X8Oa.d.ts → types-CcxRLdJG-DCXyw1US.d.ts} +31 -4
- package/dist/ui-react.d.ts +5 -3
- package/dist/ui-react.js +9 -27
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui.d.ts +3 -3
- package/dist/ui.js +1 -1
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as parseSkillMarkdown, B as unzipWithLimits, H as verifyManifest, L as resolveInsideRoot, M as readResponseWithLimit, N as readSkillSignature, O as messageOf, T as isValidSkillName, U as verifySkillSignature, V as validateSkills, _ as atomicWriteText, f as SkillDiscovery, h as assertRemoteUrlAllowed, j as parseSkillPackManifest, m as WebSkillError, o as SKILLS_LOCKFILE, r as MANIFEST_EXCLUDED_FILES, s as SKILL_MANIFEST_FILE, u as SKILL_PACK_FILE, v as buildCatalog, w as exportSkills, y as buildManifest } from "./dist-8oQRa8Xz.js";
|
|
2
|
-
import {
|
|
2
|
+
import { B as bridgeError, C as ProgressiveRouter, S as OpenAiCompatibleClient, U as createWebSkillApi, a as AgentLoop, b as GoogleGenAiClient, c as CapabilityApproval, ct as normalizeToolError, g as FsRunSnapshotStore, h as FsMemoryStore, it as networkPolicyLibSource, lt as parseBridgeRequest, m as FsArtifactStore, nt as mergeCatalogEntries, o as AnthropicClient, st as normalizeToolContent } from "./dist-D0qW6e40.js";
|
|
3
3
|
import { n as MockLlmClient } from "./testing-CYTFqkDm.js";
|
|
4
4
|
|
|
5
5
|
//#region ../browser/dist/index.js
|
|
@@ -1615,8 +1615,20 @@ function describeError(e) {
|
|
|
1615
1615
|
if (e instanceof TypeError) return "the request was blocked, most likely by CORS";
|
|
1616
1616
|
return e instanceof Error ? e.message : String(e);
|
|
1617
1617
|
}
|
|
1618
|
-
/** 值可能是凭据的输入类型:即便宿主忘了写进 exclude
|
|
1618
|
+
/** 值可能是凭据的输入类型:即便宿主忘了写进 exclude 也不读值。操作侧复用同一份,不另写 */
|
|
1619
1619
|
const SECRET_INPUT_TYPES = /* @__PURE__ */ new Set(["password", "hidden"]);
|
|
1620
|
+
/** 可被操作的角色:只给这些节点发句柄,其余节点模型连提都提不出来 */
|
|
1621
|
+
const ACTIONABLE_ROLES = /* @__PURE__ */ new Set([
|
|
1622
|
+
"button",
|
|
1623
|
+
"checkbox",
|
|
1624
|
+
"combobox",
|
|
1625
|
+
"form",
|
|
1626
|
+
"link",
|
|
1627
|
+
"radio",
|
|
1628
|
+
"searchbox",
|
|
1629
|
+
"switch",
|
|
1630
|
+
"textbox"
|
|
1631
|
+
]);
|
|
1620
1632
|
/** tag → 可访问性角色的最小映射;命中不了就退到 generic,不猜 */
|
|
1621
1633
|
const ROLE_BY_TAG = {
|
|
1622
1634
|
A: "link",
|
|
@@ -1654,7 +1666,7 @@ const clip = (text) => {
|
|
|
1654
1666
|
const normalized = text.replace(/\s+/g, " ").trim();
|
|
1655
1667
|
return normalized.length > MAX_TEXT ? `${normalized.slice(0, MAX_TEXT)}…` : normalized;
|
|
1656
1668
|
};
|
|
1657
|
-
function roleOf(element) {
|
|
1669
|
+
function roleOf$1(element) {
|
|
1658
1670
|
const explicit = element.getAttribute("role");
|
|
1659
1671
|
if (explicit !== null && explicit.trim() !== "") return explicit.trim();
|
|
1660
1672
|
if (element.tagName === "INPUT") {
|
|
@@ -1700,7 +1712,7 @@ function valueOf(element) {
|
|
|
1700
1712
|
* 隐藏节点不进结果:屏幕上看不见的东西,用户没有机会发现它被读走了。
|
|
1701
1713
|
* jsdom 里 `getComputedStyle` 可用但布局是假的,因此只看显式声明,不看尺寸。
|
|
1702
1714
|
*/
|
|
1703
|
-
function hidden(element, view) {
|
|
1715
|
+
function hidden$1(element, view) {
|
|
1704
1716
|
if (element.hasAttribute("hidden")) return true;
|
|
1705
1717
|
if (element.getAttribute("aria-hidden") === "true") return true;
|
|
1706
1718
|
const inlineStyle = element.getAttribute("style") ?? "";
|
|
@@ -1718,18 +1730,18 @@ const SKIPPED_TAGS = /* @__PURE__ */ new Set([
|
|
|
1718
1730
|
"NOSCRIPT",
|
|
1719
1731
|
"TEMPLATE"
|
|
1720
1732
|
]);
|
|
1721
|
-
function describe(element, excluded, doc, view, targets) {
|
|
1733
|
+
function describe(element, excluded, doc, view, targets, handles) {
|
|
1722
1734
|
if (excluded.has(element)) return void 0;
|
|
1723
1735
|
if (SKIPPED_TAGS.has(element.tagName)) return void 0;
|
|
1724
|
-
if (hidden(element, view)) return void 0;
|
|
1736
|
+
if (hidden$1(element, view)) return void 0;
|
|
1725
1737
|
const children = [];
|
|
1726
1738
|
for (const child of element.children) {
|
|
1727
|
-
const node = describe(child, excluded, doc, view, targets);
|
|
1739
|
+
const node = describe(child, excluded, doc, view, targets, handles);
|
|
1728
1740
|
if (node !== void 0) children.push(node);
|
|
1729
1741
|
}
|
|
1730
1742
|
const name = nameOf(element, doc);
|
|
1731
1743
|
const value = valueOf(element);
|
|
1732
|
-
const role = roleOf(element);
|
|
1744
|
+
const role = roleOf$1(element);
|
|
1733
1745
|
if (role === "generic" && name === void 0 && value === void 0 && children.length === 0) return void 0;
|
|
1734
1746
|
const node = {
|
|
1735
1747
|
role,
|
|
@@ -1737,6 +1749,8 @@ function describe(element, excluded, doc, view, targets) {
|
|
|
1737
1749
|
...value !== void 0 ? { value } : {},
|
|
1738
1750
|
...children.length > 0 ? { children } : {}
|
|
1739
1751
|
};
|
|
1752
|
+
const ref = handles?.issue(element, role);
|
|
1753
|
+
if (ref !== void 0) node.ref = ref;
|
|
1740
1754
|
if (targets !== void 0 && isCapturableElement(element)) targets.push({
|
|
1741
1755
|
element,
|
|
1742
1756
|
node
|
|
@@ -1744,6 +1758,31 @@ function describe(element, excluded, doc, view, targets) {
|
|
|
1744
1758
|
return node;
|
|
1745
1759
|
}
|
|
1746
1760
|
/**
|
|
1761
|
+
* 句柄发放与解析。表在 reader 实例内、每次 `read()` 整体替换:
|
|
1762
|
+
* 全局表是第二套状态且会跨会话泄漏;不替换则页面变了还能用旧句柄点到别的东西。
|
|
1763
|
+
*/
|
|
1764
|
+
var HandleIssuer = class {
|
|
1765
|
+
#table = /* @__PURE__ */ new Map();
|
|
1766
|
+
#actionable;
|
|
1767
|
+
#excluded;
|
|
1768
|
+
constructor(actionable, excluded) {
|
|
1769
|
+
this.#actionable = actionable;
|
|
1770
|
+
this.#excluded = excluded;
|
|
1771
|
+
}
|
|
1772
|
+
issue(element, role) {
|
|
1773
|
+
if (!this.#actionable.has(element) || this.#excluded.has(element)) return void 0;
|
|
1774
|
+
if (!ACTIONABLE_ROLES.has(role)) return void 0;
|
|
1775
|
+
const bytes = /* @__PURE__ */ new Uint8Array(8);
|
|
1776
|
+
crypto.getRandomValues(bytes);
|
|
1777
|
+
const ref = [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1778
|
+
this.#table.set(ref, element);
|
|
1779
|
+
return ref;
|
|
1780
|
+
}
|
|
1781
|
+
get table() {
|
|
1782
|
+
return this.#table;
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
/**
|
|
1747
1786
|
* DOM 遍历实现(设计 09 §2 的「实现层」)。产出只有角色 / 名称 / 值,
|
|
1748
1787
|
* **不含任何 HTML 标记、class、data 属性或注释**(FR-10.4)。
|
|
1749
1788
|
*
|
|
@@ -1752,17 +1791,43 @@ function describe(element, excluded, doc, view, targets) {
|
|
|
1752
1791
|
* @experimental
|
|
1753
1792
|
*/
|
|
1754
1793
|
function createDomPerceptionReader(options = {}) {
|
|
1794
|
+
let handles;
|
|
1795
|
+
const resolveDocument = () => options.document ?? globalThis.document;
|
|
1796
|
+
/** 按当前 DOM 重算一次可操作集合;发句柄与执行前各算一次 */
|
|
1797
|
+
const actionSets = (doc) => {
|
|
1798
|
+
const actionable = /* @__PURE__ */ new Set();
|
|
1799
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
1800
|
+
const scope = options.actionScope;
|
|
1801
|
+
if (scope === void 0 || scope.include.length === 0) return {
|
|
1802
|
+
actionable,
|
|
1803
|
+
excluded
|
|
1804
|
+
};
|
|
1805
|
+
for (const selector of scope.include) for (const root of doc.querySelectorAll(selector)) {
|
|
1806
|
+
actionable.add(root);
|
|
1807
|
+
for (const descendant of root.querySelectorAll("*")) actionable.add(descendant);
|
|
1808
|
+
}
|
|
1809
|
+
for (const selector of scope.exclude ?? []) for (const root of doc.querySelectorAll(selector)) {
|
|
1810
|
+
excluded.add(root);
|
|
1811
|
+
for (const descendant of root.querySelectorAll("*")) excluded.add(descendant);
|
|
1812
|
+
}
|
|
1813
|
+
return {
|
|
1814
|
+
actionable,
|
|
1815
|
+
excluded
|
|
1816
|
+
};
|
|
1817
|
+
};
|
|
1755
1818
|
function collect(scope, targets) {
|
|
1756
|
-
const doc =
|
|
1819
|
+
const doc = resolveDocument();
|
|
1757
1820
|
if (doc === void 0 || scope.include.length === 0) return [];
|
|
1758
1821
|
const view = doc.defaultView;
|
|
1822
|
+
const sets = actionSets(doc);
|
|
1823
|
+
handles = new HandleIssuer(sets.actionable, sets.excluded);
|
|
1759
1824
|
const excluded = /* @__PURE__ */ new Set();
|
|
1760
1825
|
for (const selector of scope.exclude ?? []) for (const element of doc.querySelectorAll(selector)) excluded.add(element);
|
|
1761
1826
|
const roots = [];
|
|
1762
1827
|
for (const selector of scope.include) for (const element of doc.querySelectorAll(selector)) if (!roots.includes(element)) roots.push(element);
|
|
1763
1828
|
const nodes = [];
|
|
1764
1829
|
for (const root of roots) {
|
|
1765
|
-
const node = describe(root, excluded, doc, view, targets);
|
|
1830
|
+
const node = describe(root, excluded, doc, view, targets, handles);
|
|
1766
1831
|
if (node !== void 0) nodes.push(node);
|
|
1767
1832
|
}
|
|
1768
1833
|
return nodes;
|
|
@@ -1804,7 +1869,126 @@ function createDomPerceptionReader(options = {}) {
|
|
|
1804
1869
|
if (!capture.images || capture.maxImages <= 0) return Promise.resolve({ nodes: collect(scope, void 0) });
|
|
1805
1870
|
return readWithImages(scope, capture);
|
|
1806
1871
|
}
|
|
1807
|
-
return {
|
|
1872
|
+
return {
|
|
1873
|
+
read,
|
|
1874
|
+
resolve: (ref) => handles?.table.get(ref),
|
|
1875
|
+
inActionScope: (element) => {
|
|
1876
|
+
const doc = resolveDocument();
|
|
1877
|
+
if (doc === void 0) return false;
|
|
1878
|
+
const sets = actionSets(doc);
|
|
1879
|
+
return sets.actionable.has(element) && !sets.excluded.has(element);
|
|
1880
|
+
}
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
const FILLABLE_TAGS = /* @__PURE__ */ new Set(["INPUT", "TEXTAREA"]);
|
|
1884
|
+
/** 只看显式声明,不看尺寸:jsdom 有 getComputedStyle 但没有布局 */
|
|
1885
|
+
function hidden(element) {
|
|
1886
|
+
if (element.hasAttribute("hidden")) return true;
|
|
1887
|
+
if (element.getAttribute("aria-hidden") === "true") return true;
|
|
1888
|
+
const inlineStyle = element.getAttribute("style") ?? "";
|
|
1889
|
+
if (/display\s*:\s*none|visibility\s*:\s*hidden/i.test(inlineStyle)) return true;
|
|
1890
|
+
const view = element.ownerDocument.defaultView;
|
|
1891
|
+
if (view !== null) {
|
|
1892
|
+
const computed = view.getComputedStyle(element);
|
|
1893
|
+
if (computed.display === "none" || computed.visibility === "hidden") return true;
|
|
1894
|
+
}
|
|
1895
|
+
return false;
|
|
1896
|
+
}
|
|
1897
|
+
const inputType = (element) => (element.getAttribute("type") ?? "text").toLowerCase();
|
|
1898
|
+
const isSecret = (element) => element.tagName === "INPUT" && SECRET_INPUT_TYPES.has(inputType(element));
|
|
1899
|
+
function accessibleName(element) {
|
|
1900
|
+
const label = element.getAttribute("aria-label");
|
|
1901
|
+
if (label !== null && label.trim() !== "") return label.trim();
|
|
1902
|
+
const text = element.textContent?.replace(/\s+/g, " ").trim() ?? "";
|
|
1903
|
+
if (text !== "") return text;
|
|
1904
|
+
const placeholder = element.getAttribute("placeholder");
|
|
1905
|
+
return placeholder !== null && placeholder.trim() !== "" ? placeholder.trim() : void 0;
|
|
1906
|
+
}
|
|
1907
|
+
function roleOf(element) {
|
|
1908
|
+
const explicit = element.getAttribute("role");
|
|
1909
|
+
if (explicit !== null && explicit.trim() !== "") return explicit.trim();
|
|
1910
|
+
if (element.tagName === "INPUT") {
|
|
1911
|
+
const type = inputType(element);
|
|
1912
|
+
return type === "checkbox" || type === "radio" ? type : type === "button" || type === "submit" ? "button" : "textbox";
|
|
1913
|
+
}
|
|
1914
|
+
if (element.tagName === "BUTTON") return "button";
|
|
1915
|
+
if (element.tagName === "A") return "link";
|
|
1916
|
+
if (element.tagName === "TEXTAREA") return "textbox";
|
|
1917
|
+
if (element.tagName === "SELECT") return "combobox";
|
|
1918
|
+
if (element.tagName === "FORM") return "form";
|
|
1919
|
+
return "generic";
|
|
1920
|
+
}
|
|
1921
|
+
const describeElement = (element) => {
|
|
1922
|
+
const name = accessibleName(element);
|
|
1923
|
+
return {
|
|
1924
|
+
role: roleOf(element),
|
|
1925
|
+
...name !== void 0 ? { name } : {},
|
|
1926
|
+
...isSecret(element) ? { secret: true } : {}
|
|
1927
|
+
};
|
|
1928
|
+
};
|
|
1929
|
+
/**
|
|
1930
|
+
* 受控组件必须收到 `input` / `change`:直接写 `.value` 在 React 上会被下一次渲染覆盖,
|
|
1931
|
+
* 表现为「填了又没了」。原生 setter 是绕过 React value 劫持的唯一办法。
|
|
1932
|
+
*/
|
|
1933
|
+
function fillValue(element, value) {
|
|
1934
|
+
const prototype = element.tagName === "INPUT" ? HTMLInputElement.prototype : HTMLTextAreaElement.prototype;
|
|
1935
|
+
const setter = Object.getOwnPropertyDescriptor(prototype, "value")?.set;
|
|
1936
|
+
if (setter) setter.call(element, value);
|
|
1937
|
+
else element.value = value;
|
|
1938
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1939
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1940
|
+
}
|
|
1941
|
+
/** @experimental */
|
|
1942
|
+
function createDomPageActionExecutor(options) {
|
|
1943
|
+
const { reader } = options;
|
|
1944
|
+
const describe = (ref) => {
|
|
1945
|
+
const element = reader.resolve(ref);
|
|
1946
|
+
return element === void 0 ? void 0 : describeElement(element);
|
|
1947
|
+
};
|
|
1948
|
+
const execute = (request) => {
|
|
1949
|
+
const element = reader.resolve(request.ref);
|
|
1950
|
+
if (element === void 0) return {
|
|
1951
|
+
ok: false,
|
|
1952
|
+
target: { role: "generic" },
|
|
1953
|
+
reason: "The element reference is unknown or expired."
|
|
1954
|
+
};
|
|
1955
|
+
const target = describeElement(element);
|
|
1956
|
+
const fail = (reason) => ({
|
|
1957
|
+
ok: false,
|
|
1958
|
+
target,
|
|
1959
|
+
reason
|
|
1960
|
+
});
|
|
1961
|
+
if (!reader.inActionScope(element)) return fail("The element is no longer inside the actionable scope.");
|
|
1962
|
+
if (hidden(element)) return fail("The element is not visible.");
|
|
1963
|
+
if (element.hasAttribute("disabled")) return fail("The element is disabled.");
|
|
1964
|
+
if (request.action === "click") {
|
|
1965
|
+
element.click();
|
|
1966
|
+
return {
|
|
1967
|
+
ok: true,
|
|
1968
|
+
target
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
if (request.action === "fill") {
|
|
1972
|
+
if (!FILLABLE_TAGS.has(element.tagName)) return fail("The element is not a text control.");
|
|
1973
|
+
if (element.hasAttribute("readonly")) return fail("The element is read-only.");
|
|
1974
|
+
fillValue(element, request.value ?? "");
|
|
1975
|
+
return {
|
|
1976
|
+
ok: true,
|
|
1977
|
+
target
|
|
1978
|
+
};
|
|
1979
|
+
}
|
|
1980
|
+
const form = element.tagName === "FORM" ? element : element.form;
|
|
1981
|
+
if (!form) return fail("The element does not belong to a form.");
|
|
1982
|
+
form.requestSubmit();
|
|
1983
|
+
return {
|
|
1984
|
+
ok: true,
|
|
1985
|
+
target
|
|
1986
|
+
};
|
|
1987
|
+
};
|
|
1988
|
+
return {
|
|
1989
|
+
execute,
|
|
1990
|
+
describe
|
|
1991
|
+
};
|
|
1808
1992
|
}
|
|
1809
1993
|
const isRecord = (v) => typeof v === "object" && v !== null;
|
|
1810
1994
|
const isNonEmptyString = (v) => typeof v === "string" && v !== "";
|
|
@@ -2488,4 +2672,4 @@ async function deleteMemoryEncryptionKey(name = "user-profile") {
|
|
|
2488
2672
|
}
|
|
2489
2673
|
|
|
2490
2674
|
//#endregion
|
|
2491
|
-
export { BrowserSkillManager, BrowserWorkerScriptExecutor, ChromeBuiltinLlmClient, IframeWorkerLike, OpfsProvider, TsTranspiler, WORKER_BOOTSTRAP_SOURCE, WorkerRuntimeClient, WorkerUiBridge, bridgeError, captureElementImage, checkDictationAvailability, compressImageToBudget, createDomPerceptionReader, createEncryptedMemoryStore, createIframeWorker, createLlmClient, deleteMemoryEncryptionKey, extractZipWeb, generateMemoryEncryptionKey, installWebSkillNavigator, isCapturableElement, isCaptureFailure, isEncryptedMemoryValue, isOpfsAvailable, openMemoryEncryptionKey, parseBridgeRequest, parseMainMessage, parseWorkerEvent, probeChromeBuiltinAvailability, sha256HexWeb, startDictation, startWorkerRuntimeHost };
|
|
2675
|
+
export { BrowserSkillManager, BrowserWorkerScriptExecutor, ChromeBuiltinLlmClient, IframeWorkerLike, OpfsProvider, TsTranspiler, WORKER_BOOTSTRAP_SOURCE, WorkerRuntimeClient, WorkerUiBridge, bridgeError, captureElementImage, checkDictationAvailability, compressImageToBudget, createDomPageActionExecutor, createDomPerceptionReader, createEncryptedMemoryStore, createIframeWorker, createLlmClient, deleteMemoryEncryptionKey, extractZipWeb, generateMemoryEncryptionKey, installWebSkillNavigator, isCapturableElement, isCaptureFailure, isEncryptedMemoryValue, isOpfsAvailable, openMemoryEncryptionKey, parseBridgeRequest, parseMainMessage, parseWorkerEvent, probeChromeBuiltinAvailability, sha256HexWeb, startDictation, startWorkerRuntimeHost };
|