@matterfact/embed 0.11.3 → 0.13.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/README.md +41 -0
- package/dist/chunk-C7DXO37G.js +2 -0
- package/dist/{chunk-CTZEDOH7.js → chunk-JLJG3MDX.js} +101 -51
- package/dist/chunk-JLJG3MDX.js.map +1 -0
- package/dist/chunk-QZCUQZJK.js +3 -0
- package/dist/chunk-QZCUQZJK.js.map +7 -0
- package/dist/{chunk-AANODHBV.js → chunk-S6OT47DL.js} +100 -49
- package/dist/chunk-S6OT47DL.js.map +1 -0
- package/dist/{chunk-JO3GWFMJ.js → chunk-UA4Y2O64.js} +2 -2
- package/dist/{context-FR7VFENN.js → context-DAXACLSP.js} +3 -3
- package/dist/{context-FR7VFENN.js.map → context-DAXACLSP.js.map} +1 -1
- package/dist/{context-IK5MECUW.js → context-IJK345PN.js} +4 -2
- package/dist/embed.js +1 -1
- package/dist/embed.js.map +3 -3
- package/dist/index.cjs +167 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -10
- package/dist/index.d.ts +83 -10
- package/dist/index.js +63 -6
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +159 -52
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +29 -2
- package/dist/react.d.ts +29 -2
- package/dist/react.js +54 -5
- package/dist/react.js.map +1 -1
- package/dist/{snapshot-2V5SDSH2.js → snapshot-EVBNVVCT.js} +2 -2
- package/dist/{snapshot-Y5BF2UJR.js → snapshot-P5SVKSPB.js} +3 -3
- package/dist/{snapshot-Y5BF2UJR.js.map → snapshot-P5SVKSPB.js.map} +1 -1
- package/examples/embed-demo/.env.example +7 -3
- package/examples/embed-demo/README.md +25 -4
- package/examples/embed-demo/src/App.tsx +67 -7
- package/examples/embed-demo/src/styles.css +52 -0
- package/examples/embed-demo/vite.config.ts +3 -2
- package/package.json +1 -1
- package/dist/chunk-AANODHBV.js.map +0 -1
- package/dist/chunk-CTZEDOH7.js.map +0 -1
- package/dist/chunk-SKJFF7RD.js +0 -2
- package/dist/chunk-Y7I25VHL.js +0 -3
- package/dist/chunk-Y7I25VHL.js.map +0 -7
- /package/dist/{chunk-SKJFF7RD.js.map → chunk-C7DXO37G.js.map} +0 -0
- /package/dist/{chunk-JO3GWFMJ.js.map → chunk-UA4Y2O64.js.map} +0 -0
- /package/dist/{context-IK5MECUW.js.map → context-IJK345PN.js.map} +0 -0
- /package/dist/{snapshot-2V5SDSH2.js.map → snapshot-EVBNVVCT.js.map} +0 -0
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
// src/pageContextMode.ts
|
|
4
|
+
var RANK = {
|
|
5
|
+
off: 0,
|
|
6
|
+
declared: 1,
|
|
7
|
+
full: 2
|
|
8
|
+
};
|
|
9
|
+
function parsePageContextMode(value) {
|
|
10
|
+
if (typeof value === "boolean") return value ? "full" : "off";
|
|
11
|
+
if (value == null) return "full";
|
|
12
|
+
const s = String(value).trim().toLowerCase();
|
|
13
|
+
if (s === "full" || s === "declared" || s === "off") return s;
|
|
14
|
+
if (s === "true" || s === "on" || s === "1" || s === "yes") return "full";
|
|
15
|
+
if (s === "false" || s === "0" || s === "no") return "off";
|
|
16
|
+
return "full";
|
|
17
|
+
}
|
|
18
|
+
function clampPageContextMode(adminMax, hostRequest) {
|
|
19
|
+
return RANK[adminMax] <= RANK[hostRequest] ? adminMax : hostRequest;
|
|
20
|
+
}
|
|
21
|
+
function allowsDeclared(mode) {
|
|
22
|
+
return mode !== "off";
|
|
23
|
+
}
|
|
24
|
+
function allowsAuto(mode) {
|
|
25
|
+
return mode === "full";
|
|
26
|
+
}
|
|
27
|
+
|
|
3
28
|
// src/redact.ts
|
|
4
29
|
var PII = [
|
|
5
30
|
/\b[\w.+-]+@[\w-]+\.[\w.]{2,}\b/g,
|
|
@@ -410,7 +435,7 @@ function mfTools(win) {
|
|
|
410
435
|
if (typeof document2 === "function") {
|
|
411
436
|
out.push({
|
|
412
437
|
name: "mf.resolveDocument",
|
|
413
|
-
description:
|
|
438
|
+
description: `Resolve a matterfact document (dossier, report, briefing) that is NOT on the current page to a concrete id. Call it with the document type and the subject's key, when the site map shows the document lives on another route. For the key, use the current route parameter VERBATIM when the page context states one (e.g. ticker = BP~+LN+Equity \u2192 key "BP~+LN+Equity"): it is the host's own identifier and often differs from the ticker or name a person would write. Do not normalise, decode or re-spell it, and do not substitute what the user typed. Returns {id, label, href}. Cite the result inline as <MFRef kind="document" id="<id>" label="<label>" /> \u2014 it renders as a chip that opens the document in the side panel; href is its "open on page" deeplink.`,
|
|
414
439
|
inputSchema: {
|
|
415
440
|
type: "object",
|
|
416
441
|
properties: {
|
|
@@ -534,7 +559,14 @@ var send = null;
|
|
|
534
559
|
var activitySeq = 0;
|
|
535
560
|
var activity = [];
|
|
536
561
|
var lastUrl = "";
|
|
537
|
-
var
|
|
562
|
+
var hostPageContextMode = "full";
|
|
563
|
+
var adminPageContextMax = "full";
|
|
564
|
+
function effectivePageContextMode() {
|
|
565
|
+
return clampPageContextMode(adminPageContextMax, hostPageContextMode);
|
|
566
|
+
}
|
|
567
|
+
function pageContextOn() {
|
|
568
|
+
return allowsDeclared(effectivePageContextMode());
|
|
569
|
+
}
|
|
538
570
|
var contextProvider;
|
|
539
571
|
var navFire = null;
|
|
540
572
|
var origPushState = null;
|
|
@@ -626,8 +658,9 @@ async function resolveDeclaredContext() {
|
|
|
626
658
|
return mf?.context ?? {};
|
|
627
659
|
}
|
|
628
660
|
async function publishContext() {
|
|
629
|
-
if (!pageContextOn) return;
|
|
661
|
+
if (!pageContextOn()) return;
|
|
630
662
|
const declared = await resolveDeclaredContext();
|
|
663
|
+
if (!pageContextOn()) return;
|
|
631
664
|
send?.({ type: "host.context", context: buildPageContext(declared) });
|
|
632
665
|
}
|
|
633
666
|
function provideContext() {
|
|
@@ -688,7 +721,7 @@ function readSitemap2() {
|
|
|
688
721
|
return Array.isArray(s) ? s : [];
|
|
689
722
|
}
|
|
690
723
|
function publishSitemap() {
|
|
691
|
-
if (!pageContextOn) return;
|
|
724
|
+
if (!pageContextOn()) return;
|
|
692
725
|
const sitemap = readSitemap2();
|
|
693
726
|
if (sitemap.length) send?.({ type: "host.sitemap", sitemap });
|
|
694
727
|
}
|
|
@@ -705,6 +738,7 @@ function navigateHost(href) {
|
|
|
705
738
|
location.assign(target.href);
|
|
706
739
|
}
|
|
707
740
|
function pushActivity(e) {
|
|
741
|
+
if (!allowsAuto(effectivePageContextMode())) return;
|
|
708
742
|
activity.push({ ...e, seq: ++activitySeq, ts: Date.now() });
|
|
709
743
|
if (activity.length > MAX_ACTIVITY) activity.shift();
|
|
710
744
|
send?.({ type: "host.activity", events: [activity[activity.length - 1]] });
|
|
@@ -771,6 +805,7 @@ function watchNavigation() {
|
|
|
771
805
|
publishSitemap();
|
|
772
806
|
publishTools();
|
|
773
807
|
};
|
|
808
|
+
if (navFire) return;
|
|
774
809
|
navFire = fire;
|
|
775
810
|
for (const name of ["pushState", "replaceState"]) {
|
|
776
811
|
const orig = history[name];
|
|
@@ -813,7 +848,7 @@ function describeControl(el) {
|
|
|
813
848
|
return describe(el);
|
|
814
849
|
}
|
|
815
850
|
async function loadSnapshotModule() {
|
|
816
|
-
const m = await import("./snapshot-
|
|
851
|
+
const m = await import("./snapshot-EVBNVVCT.js");
|
|
817
852
|
snapshotModule = m;
|
|
818
853
|
return m;
|
|
819
854
|
}
|
|
@@ -828,7 +863,7 @@ function scheduleFocus() {
|
|
|
828
863
|
}
|
|
829
864
|
var snapshotSeq = 0;
|
|
830
865
|
async function sendSnapshot(emit) {
|
|
831
|
-
if (!
|
|
866
|
+
if (!allowsAuto(effectivePageContextMode())) return;
|
|
832
867
|
const hoist = detectHoist(() => readHoistRuntime());
|
|
833
868
|
if (hoist) {
|
|
834
869
|
const { rows } = readHoistConfig(
|
|
@@ -844,6 +879,7 @@ async function sendSnapshot(emit) {
|
|
|
844
879
|
return;
|
|
845
880
|
}
|
|
846
881
|
const { snapshot } = await loadSnapshotModule();
|
|
882
|
+
if (!allowsAuto(effectivePageContextMode())) return;
|
|
847
883
|
const { yaml, truncated, visibleRefs } = snapshot();
|
|
848
884
|
emit({
|
|
849
885
|
type: "host.snapshot",
|
|
@@ -853,8 +889,9 @@ async function sendSnapshot(emit) {
|
|
|
853
889
|
emit({ type: "host.focus", focus: lastFocus });
|
|
854
890
|
}
|
|
855
891
|
async function sendRegion(ref, emit) {
|
|
856
|
-
if (!
|
|
892
|
+
if (!allowsAuto(effectivePageContextMode())) return;
|
|
857
893
|
const { snapshotRegion, resolveRef } = await loadSnapshotModule();
|
|
894
|
+
if (!allowsAuto(effectivePageContextMode())) return;
|
|
858
895
|
const el = resolveRef(ref);
|
|
859
896
|
if (!el) {
|
|
860
897
|
emit({
|
|
@@ -868,15 +905,6 @@ async function sendRegion(ref, emit) {
|
|
|
868
905
|
emit({ type: "host.region", ref, yaml: redact(yaml) });
|
|
869
906
|
}
|
|
870
907
|
async function callTool(call, emit) {
|
|
871
|
-
if (!pageContextOn) {
|
|
872
|
-
emit({
|
|
873
|
-
type: "host.toolResult",
|
|
874
|
-
callId: call.callId,
|
|
875
|
-
ok: false,
|
|
876
|
-
error: "host tools are disabled"
|
|
877
|
-
});
|
|
878
|
-
return;
|
|
879
|
-
}
|
|
880
908
|
const win = typeof window !== "undefined" ? window : void 0;
|
|
881
909
|
const cls = toolClass(call.name);
|
|
882
910
|
const startedAt = Date.now();
|
|
@@ -903,13 +931,39 @@ async function callTool(call, emit) {
|
|
|
903
931
|
error: r.error
|
|
904
932
|
});
|
|
905
933
|
}
|
|
906
|
-
function
|
|
934
|
+
function installAutoObservers() {
|
|
935
|
+
document.addEventListener("click", onClick, { capture: true, passive: true });
|
|
936
|
+
document.addEventListener("submit", onSubmit, {
|
|
937
|
+
capture: true,
|
|
938
|
+
passive: true
|
|
939
|
+
});
|
|
940
|
+
document.addEventListener("change", onChange, {
|
|
941
|
+
capture: true,
|
|
942
|
+
passive: true
|
|
943
|
+
});
|
|
944
|
+
document.addEventListener("selectionchange", scheduleFocus, { passive: true });
|
|
945
|
+
document.addEventListener("focusin", scheduleFocus, {
|
|
946
|
+
capture: true,
|
|
947
|
+
passive: true
|
|
948
|
+
});
|
|
949
|
+
window.addEventListener("scroll", scheduleFocus, {
|
|
950
|
+
capture: true,
|
|
951
|
+
passive: true
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
function removeAutoObservers() {
|
|
907
955
|
document.removeEventListener("click", onClick, { capture: true });
|
|
908
956
|
document.removeEventListener("submit", onSubmit, { capture: true });
|
|
909
957
|
document.removeEventListener("change", onChange, { capture: true });
|
|
910
958
|
document.removeEventListener("selectionchange", scheduleFocus);
|
|
911
959
|
document.removeEventListener("focusin", scheduleFocus, { capture: true });
|
|
912
960
|
window.removeEventListener("scroll", scheduleFocus, { capture: true });
|
|
961
|
+
if (focusTimer) {
|
|
962
|
+
clearTimeout(focusTimer);
|
|
963
|
+
focusTimer = null;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
function unwatchNavigation() {
|
|
913
967
|
if (navFire) {
|
|
914
968
|
window.removeEventListener("popstate", navFire);
|
|
915
969
|
navFire = null;
|
|
@@ -922,10 +976,10 @@ function stop() {
|
|
|
922
976
|
history.replaceState = origReplaceState;
|
|
923
977
|
origReplaceState = null;
|
|
924
978
|
}
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
979
|
+
}
|
|
980
|
+
function stop() {
|
|
981
|
+
removeAutoObservers();
|
|
982
|
+
unwatchNavigation();
|
|
929
983
|
send = null;
|
|
930
984
|
contextProvider = void 0;
|
|
931
985
|
activity.length = 0;
|
|
@@ -933,45 +987,41 @@ function stop() {
|
|
|
933
987
|
widgetOrigin = "";
|
|
934
988
|
snapshotModule?.clearRefs();
|
|
935
989
|
}
|
|
990
|
+
function setPageContextMax(max) {
|
|
991
|
+
adminPageContextMax = parsePageContextMode(max);
|
|
992
|
+
applyObservation();
|
|
993
|
+
}
|
|
994
|
+
function applyObservation() {
|
|
995
|
+
const mode = effectivePageContextMode();
|
|
996
|
+
if (allowsAuto(mode)) {
|
|
997
|
+
installAutoObservers();
|
|
998
|
+
} else {
|
|
999
|
+
removeAutoObservers();
|
|
1000
|
+
activity.length = 0;
|
|
1001
|
+
lastFocus = {};
|
|
1002
|
+
}
|
|
1003
|
+
if (allowsDeclared(mode)) {
|
|
1004
|
+
watchNavigation();
|
|
1005
|
+
} else {
|
|
1006
|
+
unwatchNavigation();
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
936
1009
|
function start(emit, origin, pageContext = true, provider) {
|
|
937
1010
|
stop();
|
|
938
1011
|
send = emit;
|
|
939
1012
|
widgetOrigin = origin || "";
|
|
940
1013
|
lastUrl = location.pathname;
|
|
941
|
-
|
|
1014
|
+
hostPageContextMode = parsePageContextMode(pageContext);
|
|
942
1015
|
contextProvider = provider;
|
|
943
|
-
if (
|
|
1016
|
+
if (allowsDeclared(effectivePageContextMode())) {
|
|
944
1017
|
void publishContext();
|
|
945
1018
|
publishArtifactGrants();
|
|
946
1019
|
publishSitemap();
|
|
947
|
-
watchNavigation();
|
|
948
|
-
document.addEventListener("click", onClick, {
|
|
949
|
-
capture: true,
|
|
950
|
-
passive: true
|
|
951
|
-
});
|
|
952
|
-
document.addEventListener("submit", onSubmit, {
|
|
953
|
-
capture: true,
|
|
954
|
-
passive: true
|
|
955
|
-
});
|
|
956
|
-
document.addEventListener("change", onChange, {
|
|
957
|
-
capture: true,
|
|
958
|
-
passive: true
|
|
959
|
-
});
|
|
960
|
-
document.addEventListener("selectionchange", scheduleFocus, {
|
|
961
|
-
passive: true
|
|
962
|
-
});
|
|
963
|
-
document.addEventListener("focusin", scheduleFocus, {
|
|
964
|
-
capture: true,
|
|
965
|
-
passive: true
|
|
966
|
-
});
|
|
967
|
-
window.addEventListener("scroll", scheduleFocus, {
|
|
968
|
-
capture: true,
|
|
969
|
-
passive: true
|
|
970
|
-
});
|
|
971
1020
|
}
|
|
1021
|
+
applyObservation();
|
|
972
1022
|
const theme = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
973
1023
|
emit({ type: "host.theme", mode: theme });
|
|
974
|
-
|
|
1024
|
+
{
|
|
975
1025
|
const w = typeof window !== "undefined" ? window : void 0;
|
|
976
1026
|
const tools = advertise(w);
|
|
977
1027
|
if (tools.length) {
|
|
@@ -1013,6 +1063,7 @@ export {
|
|
|
1013
1063
|
sendRegion,
|
|
1014
1064
|
callTool,
|
|
1015
1065
|
stop,
|
|
1066
|
+
setPageContextMax,
|
|
1016
1067
|
start
|
|
1017
1068
|
};
|
|
1018
|
-
//# sourceMappingURL=chunk-
|
|
1069
|
+
//# sourceMappingURL=chunk-S6OT47DL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pageContextMode.ts","../src/redact.ts","../src/adapters/hoist.ts","../src/adapters/hoist-runtime.ts","../src/adapters/registry.ts","../src/context.ts"],"sourcesContent":["/** Page-context observation modes (embed host + admin max). */\n\nexport type PageContextMode = 'full' | 'declared' | 'off';\n\nconst RANK: Record<PageContextMode, number> = {\n off: 0,\n declared: 1,\n full: 2,\n};\n\n/** Coerce host/config/bootstrap values. Bool aliases: true→full, false→off. */\nexport function parsePageContextMode(value: unknown): PageContextMode {\n if (typeof value === 'boolean') return value ? 'full' : 'off';\n if (value == null) return 'full';\n const s = String(value).trim().toLowerCase();\n if (s === 'full' || s === 'declared' || s === 'off') return s;\n if (s === 'true' || s === 'on' || s === '1' || s === 'yes') return 'full';\n if (s === 'false' || s === '0' || s === 'no') return 'off';\n return 'full';\n}\n\n/** Effective mode = more restrictive of admin max and host request. */\nexport function clampPageContextMode(\n adminMax: PageContextMode,\n hostRequest: PageContextMode,\n): PageContextMode {\n return RANK[adminMax] <= RANK[hostRequest] ? adminMax : hostRequest;\n}\n\nexport function allowsDeclared(mode: PageContextMode): boolean {\n return mode !== 'off';\n}\n\nexport function allowsAuto(mode: PageContextMode): boolean {\n return mode === 'full';\n}\n","/**\n * Redaction, split out of context.ts so it can be imported by both context.ts\n * (the DOM-walking eye) and the Hoist adapter (adapters/hoist.ts) without the\n * latter creating an import cycle back into context.ts.\n *\n * Re-exported from context.ts (`export { redact } from './redact'`) so every\n * existing importer of `redact` from `./context` keeps working unchanged.\n */\n\nconst PII = [\n /\\b[\\w.+-]+@[\\w-]+\\.[\\w.]{2,}\\b/g, // email\n /\\b(?:\\d[ -]?){13,19}\\b/g, // card-ish\n /\\b\\d{3}[- ]?\\d{2}[- ]?\\d{4}\\b/g, // ssn — dashed, spaced, OR bare 9 digits\n /\\b\\d{9,}\\b/g, // long bare digit runs: account / MRN / routing numbers\n /(?:\\+?\\d{1,2}[\\s.-]?)?\\(?\\d{3}\\)?[\\s.-]\\d{3}[\\s.-]\\d{4}\\b/g, // us phone\n /\\b(?:sk|pk|rk|ak)_(?:live|test)_[A-Za-z0-9]{8,}\\b/g, // stripe-style api keys\n /\\beyJ[\\w-]+\\.[\\w-]+\\.[\\w-]+\\b/g, // jwt\n];\n\n/**\n * Scrub before anything leaves the page — not after it arrives.\n *\n * A compromised widget, or a bug in ours, must not be able to retroactively obtain\n * a customer's users' email addresses. The only way to guarantee that is to never\n * put them on the wire.\n */\nexport function redact(text: string): string {\n let out = text;\n for (const re of PII) out = out.replace(re, '[redacted]');\n return out;\n}\n","/**\n * The Hoist adapter — a pure transform from a `HoistRuntime` (already read out of\n * `window.XH` by hoist-runtime.ts) into the context/snapshot shapes context.ts sends\n * over the bridge.\n *\n * This file never touches `window` or `XH` itself — see hoist-runtime.ts for the only\n * code that does — so every function here is a plain, fully unit-testable transform\n * against a plain object. That split is what keeps this file degrade-safe: it can be\n * exhaustively tested without a real Hoist app, and hoist-runtime.ts's own try/catch\n * (via detectHoist) is the one place a live-model surprise can ever throw.\n */\n\n// From ./redact, not ./context: context.ts (Task 7) imports THIS module, so importing\n// from ./context here would be a cycle. redact.ts holds no other context.ts state, so\n// this is the clean fix rather than a same-cycle-but-runtime-safe workaround. context.ts\n// still re-exports `redact`, so every pre-existing importer is unaffected.\nimport { redact } from '../redact';\nimport type { HostTool, PageContext } from '../protocol';\n\nexport interface HoistRoute {\n name: string;\n path: string;\n params: Record<string, unknown>;\n}\nexport interface HoistColumn {\n field: string;\n header: string;\n}\nexport type HoistRow = Record<string, unknown>;\nexport interface HoistGrid {\n id: string;\n title: string;\n columns: HoistColumn[];\n selected: HoistRow[];\n rows: HoistRow[];\n totalCount: number;\n}\nexport interface HoistChart {\n id: string;\n title: string;\n series: { name: string; data: number[] }[];\n}\n/** A navigable destination in the host app: a human label + a deep-link path. */\nexport interface HoistDestination {\n label: string;\n path: string;\n /**\n * The fully-qualified router route name (e.g. `default.company.ticker.ownership`) —\n * what `hoist.navigate` actually hands `XH.navigate`/`XH.router.navigate`. The LABEL\n * is what the agent sees and picks from (the tool arg is `destination`, a label); the\n * name is resolved from it internally, never exposed as an arg the model fills in.\n */\n name: string;\n /** True for the destination the user is currently on (per nav level). */\n current?: boolean;\n}\n/** One level of site navigation (a Hoist TabContainer): the top app tabs, the\n * per-section sidebar, etc. */\nexport interface HoistNavGroup {\n label: string;\n items: HoistDestination[];\n}\nexport interface HoistRuntime {\n route: HoistRoute;\n grids: HoistGrid[];\n charts: HoistChart[];\n /** The site map — navigable destinations, grouped by nav level. */\n nav: HoistNavGroup[];\n}\n\n/** Read the runtime through `read`, but never let a Hoist-side error reach context.ts.\n * Returns null when there is nothing worth sending, so the caller falls back to the\n * generic DOM walker. */\nexport function detectHoist(\n read: () => HoistRuntime | null,\n): HoistRuntime | null {\n let rt: HoistRuntime | null;\n try {\n rt = read();\n } catch {\n return null;\n }\n if (!rt) return null;\n const worthwhile =\n !!rt.route.name ||\n rt.grids.length > 0 ||\n rt.charts.length > 0 ||\n rt.nav.length > 0;\n return worthwhile ? rt : null;\n}\n\n/* ─────────────────────────── grid rendering ────────────────────────────── */\n\n/** Collapse whitespace, then redact, then truncate, then escape — in that order.\n * The order matches dom/snapshot.ts's `sanitize()`: truncate first and a value\n * containing PII can be cut through the middle of it, the regex no longer\n * matches, and the fragment before the cut ships unredacted. Collapsing\n * whitespace first also means an embedded newline can never survive into the\n * YAML as a fabricated sibling line. */\nfunction quote(s: string, max = 120): string {\n const clean = redact(s.replace(/\\s+/g, ' ').trim());\n const capped = clean.length > max ? `${clean.slice(0, max - 1)}…` : clean;\n return `\"${capped.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n}\n\n/** One field value → a short, redacted, quoted cell string. */\nfunction cell(value: unknown): string {\n const s = value == null ? '' : String(value);\n return `- cell ${quote(s)}`;\n}\n\nfunction pushRow(\n row: HoistRow,\n cols: HoistColumn[],\n out: string[],\n pad: string,\n): void {\n out.push(`${pad}- row:`);\n for (const c of cols) out.push(`${pad} ${cell(row[c.field])}`);\n}\n\nexport function renderGrid(\n grid: HoistGrid,\n rowCap: number,\n out: string[],\n depth: number,\n): void {\n const pad = ' '.repeat(depth);\n out.push(`${pad}- table ${quote(grid.title || 'grid')}:`);\n\n out.push(`${pad} - rowgroup \"columns\":`);\n for (const c of grid.columns)\n out.push(`${pad} - columnheader ${quote(c.header || c.field)}`);\n\n if (grid.selected.length) {\n out.push(`${pad} - rowgroup \"selected\":`);\n for (const r of grid.selected) pushRow(r, grid.columns, out, `${pad} `);\n }\n\n const shown = grid.rows.slice(0, Math.max(0, rowCap));\n out.push(`${pad} - rowgroup \"rows\":`);\n for (const r of shown) pushRow(r, grid.columns, out, `${pad} `);\n\n out.push(\n `${pad} - text: ${quote(`showing ${shown.length} of ${grid.totalCount} rows`)}`,\n );\n}\n\n/* ─────────────────────────── chart rendering ───────────────────────────── */\n\nfunction seriesSummary(name: string, data: number[]): string {\n if (!data.length) return `series ${name}: 0 points`;\n // Looped, not Math.min(...data)/Math.max(...data): spreading a large series into\n // call arguments hits the engine's argument-count ceiling (RangeError) well within\n // the size of a normal intraday/tick series. See adapters/hoist.test.ts's 200k-point\n // case.\n let min = data[0];\n let max = data[0];\n for (const n of data) {\n if (n < min) min = n;\n if (n > max) max = n;\n }\n const last = data[data.length - 1];\n return `series ${name}: ${data.length} points, min ${min}, max ${max}, last ${last}`;\n}\n\nexport function renderChart(\n chart: HoistChart,\n out: string[],\n depth: number,\n): void {\n const pad = ' '.repeat(depth);\n out.push(`${pad}- figure ${quote(chart.title || 'chart')}:`);\n for (const s of chart.series) {\n out.push(`${pad} - text: ${quote(seriesSummary(s.name, s.data))}`);\n }\n}\n\n/* ─────────────────────────── site-map rendering ────────────────────────── */\n\nexport function renderNav(\n groups: HoistNavGroup[],\n out: string[],\n depth: number,\n): void {\n const pad = ' '.repeat(depth);\n for (const g of groups) {\n if (!g.items.length) continue;\n out.push(`${pad}- navigation ${quote(g.label)}:`);\n for (const d of g.items) {\n const mark = d.current ? ' [current]' : '';\n // The path is a deep-link the agent can hand the user. Redact it like any value,\n // but leave it after the arrow rather than as a quoted YAML name.\n out.push(`${pad} - link ${quote(d.label)}${mark} → ${redact(d.path)}`);\n }\n }\n}\n\n/* ─────────────────────────── navigate tool (Layer 3) ───────────────────── */\n\n/** The host's policy for agent-driven actions, keyed by tool family. Read from\n * `window.matterfact.hoist.actions` by hoist-runtime.ts's `readActionsConfig`\n * (the `<MatterfactAgent actions>` React prop is sugar that writes that same\n * global — see react.tsx's `writeActionsGlobal`); `'off'` is the default — the\n * tool is opt-in, never advertised unless a host turns it on. */\nexport interface HoistActionsConfig {\n navigate: 'off' | 'confirm' | 'auto';\n}\n\n/** Every destination across every nav level, flattened — the universe `hoist.navigate`\n * is bounded to (its enum) and what `executeHostTool` looks the agent's chosen label\n * up against. */\nexport function flattenDestinations(rt: HoistRuntime): HoistDestination[] {\n return rt.nav.flatMap((g) => g.items);\n}\n\n/**\n * The `hoist.navigate` tool: lets the agent send the user to a destination in the\n * CURRENT site map. The arg is `destination` — the human LABEL the agent already sees\n * in the sitemap (e.g. \"Ownership\"), never a raw route name; the loader resolves the\n * label to a route name internally (see executeHostTool). The enum is exactly the\n * labels `readSitemap` found on THIS page, so the model cannot name a destination that\n * doesn't exist here — the injection bound this tool relies on.\n */\nexport function buildNavigateTool(\n rt: HoistRuntime,\n policy: 'confirm' | 'auto',\n): HostTool {\n const destinations = flattenDestinations(rt);\n const bySection = rt.nav\n .filter((g) => g.items.length)\n .map((g) => `${g.label} (${g.items.map((d) => d.label).join(', ')})`)\n .join('; ');\n return {\n name: 'hoist.navigate',\n description: redact(\n 'Navigate the user to a destination in the app. \"destination\" must be one of ' +\n `the destinations currently available, grouped by section: ${bySection || '(none available)'}.`,\n ),\n inputSchema: {\n type: 'object',\n properties: {\n destination: {\n type: 'string',\n enum: destinations.map((d) => d.label),\n },\n params: { type: 'object' },\n },\n required: ['destination'],\n },\n readOnly: false,\n // 'confirm' policy ⇒ the widget must show a confirm card every call; 'auto' ⇒ it\n // may call without asking. See the confirm field's doc comment on HostTool.\n confirm: policy === 'auto' ? 'auto' : 'required',\n };\n}\n\n/* ─────────────────────────── top-level transforms ──────────────────────── */\n\nexport function buildHoistContext(rt: HoistRuntime): PageContext {\n const selected = rt.grids.reduce((n, g) => n + g.selected.length, 0);\n const view = rt.route.name || rt.route.path || 'this view';\n const bits = [`Viewing ${view}`];\n if (selected) bits.push(`${selected} selected`);\n if (rt.grids.length) bits.push(`${rt.grids.length} grid(s)`);\n if (rt.charts.length) bits.push(`${rt.charts.length} chart(s)`);\n return {\n route: rt.route.name ? redact(rt.route.name) : undefined,\n description: redact(`${bits.join(', ')}.`),\n };\n}\n\nexport function renderHoistSnapshot(\n rt: HoistRuntime,\n rowCap: number,\n): { yaml: string; truncated: boolean } {\n const out: string[] = [];\n // Nav LEADS. It's the most stable part of the page — it barely changes as the user\n // works within a view — so emitting it first keeps the snapshot's prefix stable\n // across turns (better prompt caching) and orients the agent before the volatile\n // grid/chart data.\n renderNav(rt.nav, out, 0);\n let truncated = false;\n for (const g of rt.grids) {\n if (g.rows.length > rowCap) truncated = true;\n renderGrid(g, rowCap, out, 0);\n }\n for (const c of rt.charts) renderChart(c, out, 0);\n return { yaml: out.join('\\n'), truncated };\n}\n","/**\n * The only module that touches `window.XH`.\n *\n * Everything here is defensive by construction: every field read is optional-chained\n * and falls back to an empty/zero value, so a Hoist version whose shape drifts from\n * what's confirmed below degrades to missing fields rather than a thrown error. The\n * one place a genuine surprise (e.g. `XH` itself being a stub) could still throw is\n * caught one layer up, by `detectHoist()` in ./hoist — this module does not try/catch.\n *\n * The accessors below are CONFIRMED against a live ActivistHub instance (see\n * adapters/HOIST-CONTRACT.md). Two findings shaped this file:\n * 1. Model discovery uses the global `XH.getModels(className)` lookup, NOT the\n * Inspector — `XH.inspectorService.activeInstances` is empty unless the dev\n * Inspector UI is toggled on, so it's useless as an ambient source.\n * 2. Grid columns can be GROUPED: `gridModel.columns` holds ColumnGroups (no field,\n * a `.children` array) whose leaves carry the real `colId`. We read the flat leaf\n * set via `getVisibleLeafColumns()` and prefix each leaf's header with its group\n * (\"5Y\" group + \"Value\" leaf -> \"5Y Value\") so the columns aren't ambiguous.\n */\n\nimport type {\n HoistRuntime,\n HoistGrid,\n HoistChart,\n HoistColumn,\n HoistRow,\n HoistNavGroup,\n HoistDestination,\n HoistActionsConfig,\n} from './hoist';\nimport { buildNavigateTool, flattenDestinations } from './hoist';\nimport type { HostTool, ToolCall } from '../protocol';\nimport { redact } from '../redact';\n\nexport function readHoistConfig(win: unknown): {\n rows: number;\n excludeModels: string[];\n} {\n const cfg = (\n win as {\n matterfact?: { hoist?: { rows?: number; excludeModels?: string[] } };\n }\n )?.matterfact?.hoist;\n const ex = cfg?.excludeModels;\n return {\n rows: typeof cfg?.rows === 'number' && cfg.rows >= 0 ? cfg.rows : 50,\n excludeModels: Array.isArray(ex) ? ex : [],\n };\n}\n\n// ── model discovery ──────────────────────────────────────────────────────────\n// Confirmed: `XH.getModels(className)` returns every mounted model of that class\n// (a native Hoist ModelSelector form). It also returns empty / off-view grids that\n// happen to be mounted — those are dropped by `hasContent` in readHoistRuntime.\nfunction getModelsByClass(XH: any, name: string): any[] {\n const models = typeof XH?.getModels === 'function' ? XH.getModels(name) : [];\n return Array.isArray(models) ? models : [];\n}\n\nfunction className(m: any): string {\n return m?.constructor?.name ?? '';\n}\n\nfunction modelId(m: any): string {\n return String(m?.xhId ?? m?.id ?? m?.modelId ?? '');\n}\n\nfunction headerOf(c: any): string {\n return String(c?.headerName ?? c?.displayName ?? c?.field ?? c?.colId ?? '');\n}\n\n// Walk the full column tree (a ColumnGroup has a `.children` array and no field) to\n// map each leaf colId -> its group-qualified header, so a leaf headed \"Value\" under a\n// \"5Y\" group reads as \"5Y Value\" rather than an ambiguous bare \"Value\".\nfunction collectHeaders(\n cols: any[],\n prefix: string[],\n out: Map<string, string>,\n): void {\n for (const c of Array.isArray(cols) ? cols : []) {\n const children = c?.children;\n if (Array.isArray(children) && children.length) {\n collectHeaders(children, [...prefix, headerOf(c)], out);\n } else {\n const id = String(c?.colId ?? c?.field ?? '');\n if (id) out.set(id, [...prefix, headerOf(c)].filter(Boolean).join(' '));\n }\n }\n}\n\n// Prefer getVisibleLeafColumns() — flat, hidden-aware, real colIds — over the raw\n// `columns` tree (which contains groups without fields). Falls back to `columns` for\n// a Hoist without that method.\nfunction readColumns(g: any): HoistColumn[] {\n const leaves =\n typeof g?.getVisibleLeafColumns === 'function'\n ? g.getVisibleLeafColumns()\n : Array.isArray(g?.columns)\n ? g.columns\n : [];\n const headers = new Map<string, string>();\n collectHeaders(Array.isArray(g?.columns) ? g.columns : [], [], headers);\n return (Array.isArray(leaves) ? leaves : [])\n .map((c: any) => {\n const field = String(c?.colId ?? c?.field ?? '');\n return { field, header: headers.get(field) || headerOf(c) };\n })\n .filter((c: HoistColumn) => c.field);\n}\n\nfunction readRow(rec: any, cols: HoistColumn[]): HoistRow {\n const row: HoistRow = {};\n for (const c of cols)\n row[c.field] =\n typeof rec?.get === 'function' ? rec.get(c.field) : rec?.data?.[c.field];\n return row;\n}\n\nfunction readGrid(g: any): HoistGrid {\n const columns = readColumns(g);\n const records = Array.isArray(g?.store?.records) ? g.store.records : [];\n return {\n id: modelId(g),\n title: String(g?.title ?? ''),\n columns,\n selected: (Array.isArray(g?.selectedRecords) ? g.selectedRecords : []).map(\n (r: any) => readRow(r, columns),\n ),\n rows: records.map((r: any) => readRow(r, columns)),\n totalCount:\n typeof g?.store?.allCount === 'number'\n ? g.store.allCount\n : records.length,\n };\n}\n\n// An off-view / not-yet-loaded grid (no rows AND nothing selected) is one that\n// XH.getModels still returns but that carries no page-context value — drop it.\nfunction hasContent(g: HoistGrid): boolean {\n return g.totalCount > 0 || g.selected.length > 0;\n}\n\nfunction readChart(c: any): HoistChart {\n // Confirmed: series data points can be [timestamp, value] tuples (not bare numbers) —\n // extract the value (`d[1]` / `d.y`) so min/max/last summarise values, not timestamps.\n const series = c?.series ?? c?.highchartsConfig?.series ?? [];\n return {\n id: modelId(c),\n title: String(c?.title ?? c?.highchartsConfig?.title?.text ?? ''),\n series: (Array.isArray(series) ? series : []).map((s: any) => ({\n name: String(s?.name ?? ''),\n data: (Array.isArray(s?.data) ? s.data : [])\n .map((d: any) => (typeof d === 'number' ? d : Number(d?.y ?? d?.[1])))\n .filter((n: number) => Number.isFinite(n)),\n })),\n };\n}\n\n/* ─────────────────────────────── site map ──────────────────────────────── */\n\nfunction humanize(seg: string): string {\n return seg\n .replace(/[_-]+/g, ' ')\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/\\b\\w/g, (c) => c.toUpperCase())\n .trim();\n}\n\nfunction childrenOf(node: any): any[] {\n const k = node?.children;\n return k ? (Array.isArray(k) ? k : Array.from(k)) : [];\n}\n\n// Map each route's LAST segment -> { path, fully-qualified name }, by walking the\n// router5 tree and building a deep-link path for each with the current params.\nfunction routeIndex(\n XH: any,\n params: Record<string, unknown>,\n): Map<string, { path: string; name: string }> {\n const router = XH?.router;\n const root = router?.rootNode ?? router?.config?.rootNode;\n const out = new Map<string, { path: string; name: string }>();\n if (!router || typeof router.buildPath !== 'function' || !root) return out;\n const walk = (node: any, prefix: string) => {\n for (const c of childrenOf(node)) {\n const seg = String(c?.name ?? '');\n if (!seg) continue;\n const name = prefix ? `${prefix}.${seg}` : seg;\n let path = '';\n try {\n path = router.buildPath(name, params);\n } catch {\n path = '';\n }\n if (path && !out.has(seg)) out.set(seg, { path, name });\n walk(c, name);\n }\n };\n walk(root, '');\n return out;\n}\n\n// The site map: each Hoist TabContainerModel is one nav level (top app tabs, the\n// per-section sidebar, …). Its tabs give the exact human labels + the active tab;\n// the router gives each tab id its deep-link path. Route names ≠ display labels\n// (e.g. `governanceScorecard` shows as \"Governance Risk\"), so the tab TITLE wins.\nfunction readSitemap(\n XH: any,\n excluded: (m: any) => boolean,\n origin: string,\n): HoistNavGroup[] {\n const params = (XH?.routerState?.params ?? {}) as Record<string, unknown>;\n const currentName = String(XH?.routerState?.name ?? '');\n const routes = routeIndex(XH, params);\n if (!routes.size) return [];\n\n const groups: HoistNavGroup[] = [];\n for (const tc of getModelsByClass(XH, 'TabContainerModel')) {\n if (excluded(tc)) continue;\n const tabs = Array.isArray(tc?.tabs) ? tc.tabs : [];\n const activeTabId = String(tc?.activeTabId ?? '');\n const items: HoistDestination[] = [];\n let companyScoped = false;\n for (const t of tabs) {\n const id = String(t?.id ?? '');\n const r = routes.get(id);\n if (!id || !r) continue;\n if (r.name.includes('.company.ticker.')) companyScoped = true;\n items.push({\n // Redact HERE, at the source — not in a downstream renderer. This is the\n // one place a Hoist tab TITLE (host-page text, so potentially PII-shaped)\n // becomes a `HoistDestination.label`, and that label is what EVERY\n // consumer uses verbatim: renderNav's YAML, buildNavigateTool's\n // description AND its inputSchema.enum, and executeHostTool's\n // `.find(d => d.label === destination)` lookup. Redacting once here keeps\n // all of them consistent by construction — an enum built from an\n // ALREADY-redacted label can never leak PII a sibling renderer scrubbed\n // (see Important #1), and a destination arg matching the redacted string\n // (the only thing the agent ever saw) still resolves.\n label: redact(String(t?.title ?? '') || humanize(id)),\n // ABSOLUTE, against the HOST page's origin — not the router's bare path.\n // This path's only job is to be a link the agent can hand the user, and\n // the agent's answer renders inside our widget iframe, which is on OUR\n // origin: a bare \"/research\" there resolves to app.matterfact.com/research\n // (a dead link to the wrong app), which is exactly what shipped before.\n // The adapter runs in the host page, so its own origin is the right one.\n path: origin && r.path.startsWith('/') ? origin + r.path : r.path,\n // The fully-qualified route name — what hoist.navigate hands XH.navigate.\n // Always present: `r` only exists here because routes.get(id) resolved.\n name: r.name,\n current: id === activeTabId || r.name === currentName,\n });\n }\n if (!items.length) continue;\n const ticker = String(params.ticker ?? '');\n const label = companyScoped\n ? ticker\n ? `Company · ${ticker}`\n : 'Company'\n : 'Site';\n groups.push({ label, items });\n }\n return groups;\n}\n\nexport function readHoistRuntime(\n win: unknown = typeof window !== 'undefined' ? window : undefined,\n): HoistRuntime | null {\n const XH = (win as { XH?: any })?.XH;\n if (!XH) return null;\n const { excludeModels } = readHoistConfig(win);\n const excluded = (m: any) =>\n excludeModels.includes(className(m)) || excludeModels.includes(modelId(m));\n\n const rs = XH.routerState ?? {};\n return {\n route: {\n name: String(rs.name ?? ''),\n path: String(rs.path ?? ''),\n params: rs.params ?? {},\n },\n grids: getModelsByClass(XH, 'GridModel')\n .filter((m) => !excluded(m))\n .map(readGrid)\n .filter(hasContent),\n charts: getModelsByClass(XH, 'ChartModel')\n .filter((m) => !excluded(m))\n .map(readChart)\n .filter((c) => c.series.length > 0),\n nav: readSitemap(\n XH,\n excluded,\n String(\n (win as { location?: { origin?: string } })?.location?.origin ?? '',\n ),\n ),\n };\n}\n\n/* ─────────────────────────── actions / tools (Layer 3) ─────────────────── */\n\n/** Read the host's action policy from `window.matterfact.hoist.actions`. Defaults to\n * `{navigate:'off'}` — agent-driven navigation is opt-in, and any value other than\n * the two known policies degrades to `'off'` rather than advertising a tool under an\n * unrecognized policy. */\nexport function readActionsConfig(win: unknown): HoistActionsConfig {\n const navigate = (\n win as {\n matterfact?: { hoist?: { actions?: { navigate?: unknown } } };\n }\n )?.matterfact?.hoist?.actions?.navigate;\n return {\n navigate: navigate === 'confirm' || navigate === 'auto' ? navigate : 'off',\n };\n}\n\n/**\n * The tools this page currently offers the agent — today, just `hoist.navigate` when\n * a Hoist app is detected and the host has turned navigation on via\n * `window.matterfact.hoist.actions` (`readActionsConfig` above) — the SAME read\n * `executeHostTool` re-checks at call time, so advertise and execute can never\n * disagree about the current policy.\n *\n * Degrade-safe by construction: no `window.XH`, `navigate:'off'` (the default), no\n * detectable runtime, or a `getModels`/router surprise ⇒ `[]`, never a throw — so a\n * caller can call this unconditionally without its own try/catch.\n */\nexport function advertiseTools(\n win: unknown = typeof window !== 'undefined' ? window : undefined,\n): HostTool[] {\n try {\n const XH = (win as { XH?: unknown })?.XH;\n if (!XH) return [];\n const { navigate } = readActionsConfig(win);\n if (navigate === 'off') return [];\n const rt = readHoistRuntime(win);\n if (!rt) return [];\n return [buildNavigateTool(rt, navigate)];\n } catch {\n return [];\n }\n}\n\n/**\n * Run a host tool call. Two enforcement points, both re-checked fresh on every call —\n * never against anything the widget claims was advertised earlier, which a\n * compromised or merely-stale widget could lie about:\n *\n * 1. the host's CURRENT action policy (`readActionsConfig`) — a widget that cached\n * an advertisement from before the host flipped `actions.navigate` to `'off'`\n * (e.g. entering a regulated flow) must be refused, not just un-advertised;\n * 2. the destination, against the LIVE current sitemap.\n *\n * That is the \"loader route-bound\" guarantee the confirm card (Wave 2) sits on top\n * of, not a substitute for it.\n *\n * Degrade-safe and NEVER throws: any surprise (bad args, XH/router missing or\n * throwing) becomes `{ok:false, error}`, never an exception into context.ts. The\n * error text itself is redacted too — a thrown Error can plausibly embed host-page\n * detail, same as the success path's `result`.\n */\nexport function executeHostTool(\n call: ToolCall,\n win: unknown = typeof window !== 'undefined' ? window : undefined,\n): { ok: boolean; result?: unknown; error?: string } {\n try {\n if (call.name !== 'hoist.navigate') {\n return { ok: false, error: 'unknown tool' };\n }\n // Execute-time policy re-check (defense-in-depth): `advertiseTools` already\n // gates on this at advertise time, but that is not an access-control decision\n // this function may assume still holds — the widget calling in is exactly the\n // thing this whole module treats as untrustworthy. See the doc comment above.\n if (readActionsConfig(win).navigate === 'off') {\n return { ok: false, error: 'navigation is disabled' };\n }\n\n const destination = String(call.args?.destination ?? '');\n const rt = readHoistRuntime(win);\n const item = rt\n ? flattenDestinations(rt).find((d) => d.label === destination)\n : undefined;\n if (!item) return { ok: false, error: 'unknown destination' };\n\n const XH = (win as { XH?: any })?.XH;\n // Merge: the CURRENT route's params first, then whatever the agent explicitly\n // supplied on top. A company subroute (e.g. Ownership) needs the current\n // `ticker` param to resolve correctly even though the agent never saw or passed\n // it; an agent-supplied key still wins on conflict (spread order).\n const params = {\n ...(XH?.routerState?.params ?? {}),\n ...((call.args?.params as Record<string, unknown> | undefined) ?? {}),\n };\n if (typeof XH?.navigate === 'function') {\n XH.navigate(item.name, params);\n } else if (typeof XH?.router?.navigate === 'function') {\n XH.router.navigate(item.name, params);\n } else {\n return { ok: false, error: 'navigation unavailable' };\n }\n return { ok: true, result: redact(`navigated to ${destination}`) };\n } catch (e) {\n return {\n ok: false,\n error: redact(e instanceof Error ? e.message : 'navigate failed'),\n };\n }\n}\n","/**\n * The host-tool registry — the ONE place the three tool classes are merged into the\n * single list the widget advertises, and the ONE execution path for calling any of\n * them.\n *\n * Three classes, distinguished by who owns the contract and who runs the code:\n *\n * - `hoist.*` matterfact-defined, matterfact-implemented. The loader adapter runs\n * them (today: `hoist.navigate`). Gated on `window.XH` + the host's\n * `hoist.actions` policy. See `hoist-runtime.ts`.\n * - `mf.*` matterfact-defined, HOST-implemented. WE fix the name, schema and\n * agent semantics (the description is authored HERE, not per\n * integration); the host supplies the function via `resolve.*`. Today:\n * `mf.resolveDocument`, `mf.resolveArtifact`.\n * - `app.*` host-defined, host-implemented. Anything the host advertises via\n * `tools`. Normalised into the `app.` namespace so it can never shadow\n * ours.\n *\n * Everything downstream (the widget's confirm gate, the backend dispatcher) is already\n * generic over \"a tool with a name/schema/confirm and a call round-trip\" — this module\n * is purely the loader-side composition + dispatch, so `hoist-runtime.ts` stays one\n * adapter rather than the whole surface.\n *\n * SECURITY: `mf.*`/`app.*` handlers are HOST code. Their results and error strings pass\n * through `redact()` before leaving the page, exactly like the hoist adapter's; a\n * handler that throws or hangs becomes a normal `{ok:false}` result, never an exception\n * into `context.ts`. And the SERVER decides which of these an app may actually expose\n * (the `host_tools` policy) — advertising here is necessary but not sufficient.\n */\nimport type { HostTool, MatterfactEvent, ToolCall, ToolEvent } from '../protocol';\nimport { redact } from '../redact';\nimport { advertiseTools, executeHostTool } from './hoist-runtime';\n\n/** Advertised metadata rides EVERY turn's model context and is host-supplied. Bound\n * the count; the backend caps it too (defense in depth). */\nexport const MAX_TOOLS = 16;\n\n/** A host `mf.*`/`app.*` handler is host code — bound it so a hung promise surfaces as\n * a normal declined result INSIDE the backend's own ~60s wait, never eating it. */\nexport const HOST_HANDLER_TIMEOUT_MS = 30_000;\n\nexport type ToolClass = 'hoist' | 'mf' | 'app';\n\n/** A host-supplied resolver: matterfact fixes the contract, the host implements it. */\nexport interface HostResolvers {\n document?: (args: {\n doctype: string;\n key: string;\n }) => Promise<{ id: string; label: string; href?: string }>;\n artifact?: (args: {\n slug: string;\n }) => Promise<{ id: string; owner: string; token: string; label: string }>;\n}\n\n/** A host-defined tool (the `tools` prop): a WebMCP-shaped descriptor plus its handler. */\nexport interface HostToolDef {\n name: string;\n description: string;\n inputSchema?: Record<string, unknown>;\n confirm?: 'auto' | 'required';\n handler: (args: Record<string, unknown>) => unknown | Promise<unknown>;\n}\n\ninterface MatterfactGlobal {\n resolve?: HostResolvers;\n tools?: HostToolDef[];\n onToolEvent?: (e: ToolEvent) => void;\n onEvent?: (e: MatterfactEvent) => void;\n}\n\nfunction mfGlobal(win: unknown): MatterfactGlobal {\n return (\n (win as { matterfact?: MatterfactGlobal } | undefined)?.matterfact ?? {}\n );\n}\n\nexport function toolClass(name: string): ToolClass {\n if (name.startsWith('hoist.')) return 'hoist';\n if (name.startsWith('mf.')) return 'mf';\n return 'app';\n}\n\n/** Fire the host's unified `onEvent` telemetry hook, swallowing any throw. A host\n * telemetry callback is host code: a throw here must not fail a call, advertise, or\n * anything else on the path. */\nexport function emitEvent(win: unknown, e: MatterfactEvent): void {\n const cb = mfGlobal(win).onEvent;\n if (typeof cb !== 'function') return;\n try {\n cb(e);\n } catch {\n /* a host telemetry callback must never break the call path */\n }\n}\n\n/** Fire tool telemetry on BOTH the unified `onEvent` (tagged `type:'tool'`) and the\n * legacy `onToolEvent` shim (untagged). Each is independently throw-guarded, so a\n * throwing hook on one never starves the other or the call path. */\nexport function emitToolEvent(win: unknown, e: ToolEvent): void {\n emitEvent(win, { type: 'tool', ...e });\n const cb = mfGlobal(win).onToolEvent;\n if (typeof cb !== 'function') return;\n try {\n cb(e);\n } catch {\n /* legacy shim: a host telemetry callback must never break the call path */\n }\n}\n\n/* ───────────────────────────── mf.* contracts ──────────────────────────── */\n\n/**\n * The `mf.*` tool descriptors. Authored HERE so the agent's understanding of them is\n * ours and lives in one place — an integration spends no instruction budget teaching\n * what they mean. Only advertised for the resolvers the host actually supplied.\n */\nfunction mfTools(win: unknown): HostTool[] {\n const { document, artifact } = mfGlobal(win).resolve ?? {};\n const out: HostTool[] = [];\n if (typeof document === 'function') {\n out.push({\n name: 'mf.resolveDocument',\n description:\n 'Resolve a matterfact document (dossier, report, briefing) that is NOT on the ' +\n 'current page to a concrete id. Call it with the document type and the ' +\n \"subject's key, when the site map shows the document lives on another route. \" +\n 'For the key, use the current route parameter VERBATIM when the page context ' +\n 'states one (e.g. ticker = BP~+LN+Equity → key \"BP~+LN+Equity\"): it is the ' +\n \"host's own identifier and often differs from the ticker or name a person \" +\n 'would write. Do not normalise, decode or re-spell it, and do not substitute ' +\n 'what the user typed. Returns ' +\n '{id, label, href}. Cite the result inline as ' +\n '<MFRef kind=\"document\" id=\"<id>\" label=\"<label>\" /> — it renders as a chip that ' +\n 'opens the document in the side panel; href is its \"open on page\" deeplink.',\n inputSchema: {\n type: 'object',\n properties: {\n doctype: { type: 'string' },\n key: { type: 'string' },\n },\n required: ['doctype', 'key'],\n },\n readOnly: true,\n confirm: 'auto',\n });\n }\n if (typeof artifact === 'function') {\n out.push({\n name: 'mf.resolveArtifact',\n description:\n 'Resolve a matterfact artifact (an interactive board) that is NOT co-embedded on ' +\n 'the current page to a read grant. Call it with the artifact slug. Returns ' +\n '{id, owner, token, label}; the grant is applied for you. Cite the result inline ' +\n 'as <MFRef kind=\"artifact\" id=\"<id>\" label=\"<label>\" /> — it renders as a chip ' +\n 'that opens the artifact in the side panel.',\n inputSchema: {\n type: 'object',\n properties: { slug: { type: 'string' } },\n required: ['slug'],\n },\n readOnly: true,\n confirm: 'auto',\n });\n }\n return out;\n}\n\n/* ───────────────────────────── app.* host tools ────────────────────────── */\n\nconst APP_NAME_RE = /^[A-Za-z0-9._-]+$/;\n\n/** Normalise a host tool name into the `app.` namespace so it can never collide with\n * `hoist.*`/`mf.*`. A name already prefixed `app.` is kept; anything else is prefixed.\n * Names outside the safe charset are dropped by the caller. */\nfunction appName(name: string): string {\n return name.startsWith('app.') ? name : `app.${name}`;\n}\n\nfunction appTools(win: unknown): HostTool[] {\n const defs = mfGlobal(win).tools;\n if (!Array.isArray(defs)) return [];\n const out: HostTool[] = [];\n for (const d of defs) {\n const raw = (d?.name ?? '').trim();\n if (!raw || typeof d.handler !== 'function') continue;\n const name = appName(raw);\n if (!APP_NAME_RE.test(name)) continue;\n out.push({\n name,\n description: String(d.description ?? `Run the host tool ${name}.`),\n inputSchema: d.inputSchema ?? { type: 'object', properties: {} },\n readOnly: false,\n confirm: d.confirm === 'auto' ? 'auto' : 'required',\n });\n }\n return out;\n}\n\n/* ───────────────────────────── advertise ───────────────────────────────── */\n\n/**\n * The merged tool list this page offers the agent: hoist adapter tools, then the\n * `mf.*` contracts for supplied resolvers, then host `app.*` tools. matterfact-defined\n * names win on collision (an `app.*` normalisation can't produce one, but a host that\n * literally named a tool `mf.foo` in `app.` space still can't shadow a real `mf.*`).\n * Deduped by name, first-wins, capped at MAX_TOOLS.\n *\n * Degrade-safe: any surprise ⇒ the entries built so far, never a throw — a caller can\n * call this unconditionally.\n */\nexport function advertise(\n win: unknown = typeof window !== 'undefined' ? window : undefined,\n): HostTool[] {\n const merged: HostTool[] = [];\n const seen = new Set<string>();\n const push = (tools: HostTool[]) => {\n for (const t of tools) {\n if (seen.has(t.name)) continue;\n seen.add(t.name);\n merged.push(t);\n }\n };\n try {\n push(advertiseTools(win));\n } catch {\n /* hoist adapter already degrade-safe; belt and suspenders */\n }\n try {\n push(mfTools(win));\n push(appTools(win));\n } catch {\n /* fall through with whatever merged so far */\n }\n return merged.slice(0, MAX_TOOLS);\n}\n\n/* ───────────────────────────── execute ─────────────────────────────────── */\n\nfunction timeout(ms: number): Promise<never> {\n return new Promise((_, reject) =>\n setTimeout(() => reject(new Error('host tool timed out')), ms),\n );\n}\n\n/** Redact anything a host handler returns before it can leave the page. Strings are\n * scrubbed directly; structured results are JSON round-tripped through the scrubber so\n * an email tucked in a field can't ride out. */\nfunction redactResult(value: unknown): unknown {\n if (value === undefined || value === null) return value;\n if (typeof value === 'string') return redact(value);\n try {\n return JSON.parse(redact(JSON.stringify(value)));\n } catch {\n return redact(String(value));\n }\n}\n\n/**\n * Run one host tool call. Dispatches by class:\n * - `hoist.*` → the existing adapter (keeps its OWN execute-time policy + route\n * re-checks — this module does not second-guess it);\n * - `mf.*` → the matching `resolve.*` function;\n * - `app.*` → the matching host `tools[].handler`.\n *\n * Handlers are read FRESH off the global on every call (so a host swapping a handler\n * body never needs a remount) and bounded at HOST_HANDLER_TIMEOUT_MS. NEVER throws:\n * any surprise becomes `{ok:false, error}`, redacted.\n */\nexport async function execute(\n call: ToolCall,\n win: unknown = typeof window !== 'undefined' ? window : undefined,\n): Promise<{ ok: boolean; result?: unknown; error?: string }> {\n const cls = toolClass(call.name);\n try {\n if (cls === 'hoist') {\n // Synchronous adapter; keep its result/redaction exactly as-is.\n return executeHostTool(call, win);\n }\n\n const handler = resolveHandler(win, call.name);\n if (!handler) return { ok: false, error: 'unknown tool' };\n\n const result = await Promise.race([\n Promise.resolve(handler(call.args ?? {})),\n timeout(HOST_HANDLER_TIMEOUT_MS),\n ]);\n return { ok: true, result: redactResult(result) };\n } catch (e) {\n return {\n ok: false,\n error: redact(e instanceof Error ? e.message : 'host tool failed'),\n };\n }\n}\n\n/** The host function backing an `mf.*`/`app.*` name, or undefined. */\nfunction resolveHandler(\n win: unknown,\n name: string,\n): ((args: Record<string, unknown>) => unknown) | undefined {\n const mf = mfGlobal(win);\n if (name === 'mf.resolveDocument') return mf.resolve?.document as never;\n if (name === 'mf.resolveArtifact') return mf.resolve?.artifact as never;\n if (name.startsWith('app.')) {\n const def = (mf.tools ?? []).find((d) => appName((d?.name ?? '').trim()) === name);\n return def?.handler;\n }\n return undefined;\n}\n","import type {\n ActivityEvent,\n FocusContext,\n HostToWidget,\n PageContext,\n PageEntity,\n SiteMapEntry,\n ToolCall,\n} from './protocol';\nimport {\n allowsAuto,\n allowsDeclared,\n clampPageContextMode,\n parsePageContextMode,\n type PageContextMode,\n} from './pageContextMode';\nimport { redact } from './redact';\nimport {\n detectHoist,\n buildHoistContext,\n renderHoistSnapshot,\n} from './adapters/hoist';\nimport {\n readHoistRuntime,\n readHoistConfig,\n} from './adapters/hoist-runtime';\n// The registry composes the hoist adapter with the mf.*/app.* tool sources and is the\n// single advertise/execute surface — context.ts talks to it, not to the hoist adapter\n// directly. See adapters/registry.ts.\nimport { advertise, execute, emitToolEvent, toolClass } from './adapters/registry';\n\n// Re-exported so every existing importer of `redact` from `./context` (e.g.\n// dom/snapshot.ts) keeps working unchanged — see redact.ts for why the\n// definition itself lives in its own module.\nexport { redact } from './redact';\n\n/** The origin serving our chat — how we tell OUR embedded content from the host's own\n * iframes. Set by start(); empty until then, which just means we spot nothing. */\nlet widgetOrigin = '';\n\n/**\n * The eye.\n *\n * Everything in this module can see the customer's page. It is a SEPARATE CHUNK,\n * loaded only when someone actually opens the chat — so a page whose visitors never\n * click the widget pays nothing for any of it, and a security reviewer can read\n * exactly one file to know what we look at.\n *\n * The rules, which are not negotiable:\n *\n * NEVER captured — no config enables it: the value of any <input>, <textarea> or\n * contenteditable; anything inside a password field; cookies; localStorage;\n * sessionStorage; the raw DOM; screenshots; network traffic; anything inside an\n * element marked `data-mf-private`.\n *\n * The agent never gets a selector and never touches the DOM. It gets refs. A ref\n * is resolved to an element HERE, in the page, by us.\n */\n\ntype Send = (msg: HostToWidget) => void;\n\nconst MAX_ACTIVITY = 40;\n\nlet send: Send | null = null;\nlet activitySeq = 0;\nconst activity: ActivityEvent[] = [];\nlet lastUrl = '';\n/** Host-requested mode (before admin clamp). Set by `start()`. */\nlet hostPageContextMode: PageContextMode = 'full';\n/** Admin max from bootstrap (`widget.pageContextMax`); defaults to full. */\nlet adminPageContextMax: PageContextMode = 'full';\n\nfunction effectivePageContextMode(): PageContextMode {\n return clampPageContextMode(adminPageContextMax, hostPageContextMode);\n}\n\n/** @deprecated Prefer allowsDeclared/allowsAuto — true when any observation is on. */\nfunction pageContextOn(): boolean {\n return allowsDeclared(effectivePageContextMode());\n}\n\n/**\n * A host callback that returns the DECLARED page context on demand — the pull-based\n * counterpart to the static `window.matterfact.context` global. Symmetric with\n * `AuthTokenProvider`: the React `<MatterfactAgent getPageContext>` prop supplies it; the\n * `<script>` loader uses `window.matterfact.getPageContext` instead (see resolveDeclaredContext).\n */\nexport type PageContextProvider = () =>\n | PageContext\n | null\n | undefined\n | Promise<PageContext | null | undefined>;\n/** The programmatic pull callback, set by `start()`. Read fresh on every publish. */\nlet contextProvider: PageContextProvider | undefined;\n\n/* ─────────────────────────── teardown state ───────────────────────────── */\n\n/**\n * Everything below is module-global bookkeeping so `stop()` (see `start()`, bottom of\n * file) can undo exactly what `start()`/`watchNavigation()` installed — remove every\n * listener, restore `history` to what it was before we wrapped it, and forget any\n * DOM-walk module we pulled in. All of this outlives a single `EmbedHost`; see\n * `stop()`'s doc comment for why that's the bug this exists to close.\n */\n\n/** The `fire` closure `watchNavigation()` handed to `popstate` — the only handle we\n * have to remove that listener again. */\nlet navFire: (() => void) | null = null;\n/** The `history.pushState`/`replaceState` this module wrapped, captured so `stop()`\n * can restore them EXACTLY rather than re-wrapping (which is how the old code\n * double-fired navigation on a second `start()`). */\nlet origPushState: History['pushState'] | null = null;\nlet origReplaceState: History['replaceState'] | null = null;\n/** Set once `sendSnapshot`/`sendRegion`/`readFocus` actually pull in the DOM-walk\n * chunk (`./dom/snapshot`) — never imported eagerly, so `stop()` doesn't pay for a\n * chunk that a host who only ever opted out (and never opened a snapshot) never\n * loaded in the first place. */\nlet snapshotModule: { clearRefs: () => void } | null = null;\n\n/* ─────────────────────────── redaction ────────────────────────────────── */\n// redact() now lives in ./redact — see that file's doc comment. Re-exported\n// above; imported here for local use throughout this module.\n\n/** Anything the host has marked private, or that is inherently sensitive, is out. */\nexport function isPrivate(el: Element): boolean {\n if (el.closest('[data-mf-private]')) return true;\n const tag = el.tagName;\n if (tag === 'INPUT') {\n const t = (el as HTMLInputElement).type;\n if (t === 'password' || t === 'hidden') return true;\n }\n return false;\n}\n\n/* ───────────────────────── page context ───────────────────────────────── */\n\n/**\n * What the page says about itself.\n *\n * A host that declares nothing still gets URL + title, which is what every other\n * embeddable assistant on the market offers in total. The interesting fields\n * (`route`, `description`, `entities`) are host-declared, because only the host\n * knows that `/o/8813` is \"the Acme Corp order, 3 items, unpaid\".\n *\n * Declared via a global the host sets before we load:\n * window.matterfact = { context: { route: '/orders/:id', description: '...', entities: [...] } }\n */\n/**\n * matterfact content embedded IN the host page — today, artifact iframes.\n *\n * A cross-origin iframe is opaque: `contentDocument` throws, so the DOM snapshot walks\n * straight past an embedded artifact and the agent is blind to the very thing the page\n * is built around. It reads the page as empty and asks which URL you mean.\n *\n * We don't need to see inside, and shouldn't want to. The artifact's ID is right there\n * in the src, and the agent can already resolve `artifacts/<id>/` in its session — the\n * same path an `@`-mention uses. So we report the ID and let the backend fetch the real\n * thing, which beats scraping a rendering of it: it gets the data, not the picture.\n *\n * Matched by ORIGIN, not by path shape: a customer is perfectly entitled to their own\n * /artifacts/ route, and it isn't ours.\n */\n/** The artifact slug from a matterfact artifact path, or null. Matches both the\n * chrome-free embed route (/embed/artifacts/<slug>) and the bare /artifacts/<slug>. */\nexport function artifactIdFromPath(pathname: string): string | null {\n const m = pathname.match(/^\\/(?:embed\\/)?artifacts\\/(.+?)\\/?$/);\n return m ? decodeURIComponent(m[1]) : null;\n}\n\nfunction embeddedMatterfactEntities(): PageEntity[] {\n if (!widgetOrigin) return [];\n const out: PageEntity[] = [];\n for (const frame of Array.from(document.querySelectorAll('iframe'))) {\n let u: URL;\n try {\n u = new URL(frame.getAttribute('src') || '', location.href);\n } catch {\n continue;\n }\n if (u.origin !== widgetOrigin) continue;\n const id = artifactIdFromPath(u.pathname);\n if (!id) continue;\n if (out.some((e) => e.id === id)) continue; // same artifact twice = once\n // No url field: the agent reaches an artifact by ID (`artifacts/<id>/`), never by\n // fetching the page, and an artifact URL can carry a share token we've no business\n // forwarding. The id is the whole useful payload.\n out.push({\n kind: 'artifact',\n id,\n label: redact(frame.getAttribute('title') || '') || id,\n });\n }\n return out;\n}\n\n/**\n * Frames we can see the existence of but nothing inside — someone else's cross-origin\n * embed. Worth one line: \"there is a thing here I cannot read\" is a true and useful\n * statement, and much better than the agent confidently describing a page while missing\n * the widget the user is actually asking about.\n */\nfunction opaqueFrameCount(): number {\n return Array.from(document.querySelectorAll('iframe')).filter((f) => {\n try {\n const u = new URL(f.getAttribute('src') || '', location.href);\n return u.origin !== location.origin && u.origin !== widgetOrigin;\n } catch {\n return false;\n }\n }).length;\n}\n\n/**\n * Merge the host's DECLARED context with what we auto-detect. Auto-detected fields\n * (url/path/title/locale, co-embedded artifact entities, opaque-frame count) are additive:\n * a declared value wins where they overlap (the `...declared` spread), and found entities\n * append to declared ones.\n */\nexport function buildPageContext(declared: PageContext): PageContext {\n const found = embeddedMatterfactEntities();\n const opaque = opaqueFrameCount();\n\n return {\n // Path only. A query string is where session ids, tokens and email addresses\n // live; it is not ours to take.\n url: location.origin + location.pathname,\n path: location.pathname,\n title: redact(document.title),\n locale: document.documentElement.lang || undefined,\n ...declared,\n // After the spread: what we FOUND is additive to what the host DECLARED, never a\n // replacement. A host that declares its own entities still gets the artifacts we\n // spotted, and vice versa.\n entities: [...(declared.entities ?? []), ...found],\n data: {\n ...(declared.data ?? {}),\n ...(opaque ? { opaque_frames: opaque } : {}),\n },\n };\n}\n\n/** Back-compat: build context from the static `window.matterfact.context` global only (sync). */\nexport function readPageContext(): PageContext {\n return buildPageContext(\n (window as { matterfact?: { context?: PageContext } }).matterfact\n ?.context ?? {},\n );\n}\n\n/**\n * Resolve the host's DECLARED context, preferring a pull callback over the static global so\n * a virtualized SPA can hand us fresh context per turn. First non-null wins:\n * 1. the programmatic `getPageContext` provider (React `<MatterfactAgent getPageContext>`),\n * 2. the `<script>`-loader global `window.matterfact.getPageContext()`,\n * 3. the static `window.matterfact.context`.\n */\nasync function resolveDeclaredContext(): Promise<PageContext> {\n const mf = (\n window as {\n matterfact?: {\n context?: PageContext;\n getPageContext?: PageContextProvider;\n };\n }\n ).matterfact;\n if (contextProvider) {\n const c = await contextProvider();\n if (c) return c;\n }\n if (mf?.getPageContext) {\n const c = await mf.getPageContext();\n if (c) return c;\n }\n // Hoist auto-detection: a framework-shaped context source, below explicit host\n // declarations but above the static global. Degrade-safe (detectHoist swallows).\n const hoist = detectHoist(() => readHoistRuntime());\n if (hoist) return buildHoistContext(hoist);\n return mf?.context ?? {};\n}\n\n/**\n * Publish the current declared+detected context as `host.context`. Async because the pull\n * callback may be (a host might read a store). Rapid calls just re-publish — for idempotent\n * context, last-writer-wins is fine. No-op when the host opted out of page observation.\n */\nasync function publishContext() {\n if (!pageContextOn()) return;\n const declared = await resolveDeclaredContext();\n // Re-check AFTER the await, not just before it. The host's getPageContext can take\n // arbitrarily long, and the admin clamp (`setPageContextMax`) can land inside that\n // window — start() kicks off exactly this call, and the bootstrap that carries the\n // ceiling resolves moments later. Gating only on entry would let a publish that was\n // legal when it began complete against a mode that now forbids it.\n if (!pageContextOn()) return;\n send?.({ type: 'host.context', context: buildPageContext(declared) });\n}\n\n/**\n * Answer a `widget.requestContext` (the pull path): publish context AND the site map NOW,\n * so a turn assembled right after carries both as they are — not as of the last route\n * change. The site map matters here as much as the context: the loader's nav hook fires\n * synchronously during `pushState`, BEFORE a React host has re-rendered with the new\n * route's map, so a nav-time push can be a render stale. Re-publishing at turn-assembly\n * (after the host has settled) is what makes it fresh. No-op when page observation is off.\n */\nexport function provideContext() {\n void publishContext();\n publishSitemap();\n}\n\n/* ─────────────────────── artifact grants (backend-only) ────────────────── */\n\nexport interface ArtifactGrantSrc {\n id: string;\n owner: string;\n token: string;\n}\n\n/** Read-only capability grants from co-embedded artifact iframes, for the backend to\n * materialize their data. Separate from entities on purpose: the token must never ride\n * ambient (rendered) context, only this backend-only channel. */\nexport function grantsFromIframeSrcs(\n srcs: string[],\n origin: string,\n): ArtifactGrantSrc[] {\n const out: ArtifactGrantSrc[] = [];\n for (const raw of srcs) {\n let u: URL;\n try {\n u = new URL(raw || '', location.href);\n } catch {\n continue;\n }\n if (u.origin !== origin) continue;\n const id = artifactIdFromPath(u.pathname);\n if (!id) continue;\n const owner = u.searchParams.get('owner') || '';\n const token = u.searchParams.get('t') || '';\n if (!owner || !token) continue;\n if (out.some((g) => g.id === id)) continue;\n out.push({ id, owner, token });\n }\n return out;\n}\n\n/**\n * Grants DECLARED by the host — `window.matterfact.artifacts` (the\n * `<MatterfactAgent artifacts>` prop mirrors onto it). Same wire shape as a scanned\n * iframe grant, so a board is reachable from a route where its iframe isn't mounted\n * WITHOUT hidden zero-size iframes smuggling the token into the DOM. Degrade-safe:\n * anything malformed is skipped, never thrown.\n */\nexport function readDeclaredGrants(): ArtifactGrantSrc[] {\n const declared = (\n window as {\n matterfact?: {\n artifacts?: Array<{ slug?: string; owner?: string; token?: string }>;\n };\n }\n ).matterfact?.artifacts;\n if (!Array.isArray(declared)) return [];\n const out: ArtifactGrantSrc[] = [];\n for (const a of declared) {\n const id = (a?.slug || '').trim();\n const owner = (a?.owner || '').trim();\n const token = (a?.token || '').trim();\n if (!id || !owner || !token) continue;\n if (out.some((g) => g.id === id)) continue;\n out.push({ id, owner, token });\n }\n return out;\n}\n\nfunction readArtifactGrants(): ArtifactGrantSrc[] {\n if (!widgetOrigin) return [];\n const srcs = Array.from(document.querySelectorAll('iframe')).map(\n (f) => f.getAttribute('src') || '',\n );\n const scanned = grantsFromIframeSrcs(srcs, widgetOrigin);\n // A live co-embedded iframe on THIS page wins over a declared grant for the same\n // slug (its token is the one the visible board is actually spending); declared\n // grants fill in the boards that aren't mounted here.\n const out = [...scanned];\n for (const g of readDeclaredGrants()) {\n if (!out.some((s) => s.id === g.id)) out.push(g);\n }\n return out;\n}\n\nfunction publishArtifactGrants() {\n send?.({ type: 'host.artifactGrants', grants: readArtifactGrants() });\n}\n\n/* ─────────────────────────── site map ─────────────────────────────────── */\n\n/**\n * The host's DECLARED site map — its routes, annotated with a content class so the\n * agent knows which carry matterfact content and of what kind. Read from the\n * `window.matterfact.sitemap` global; the React `<MatterfactAgent sitemap>` prop writes\n * it there, symmetric with `context`/`actions`. Classification only — no per-instance\n * ids, never a capability token (those ride `host.context`/`host.artifactGrants`).\n */\nfunction readSitemap(): SiteMapEntry[] {\n const s = (window as { matterfact?: { sitemap?: SiteMapEntry[] } }).matterfact\n ?.sitemap;\n return Array.isArray(s) ? s : [];\n}\n\nfunction publishSitemap() {\n if (!pageContextOn()) return;\n const sitemap = readSitemap();\n // Omit an empty map rather than send `[]` on every load — most hosts declare none.\n if (sitemap.length) send?.({ type: 'host.sitemap', sitemap });\n}\n\n/**\n * Navigate the HOST page to one of its OWN routes — the \"open on page\" deeplink from\n * a co-embedded document's side-panel viewer. The widget is a cross-origin iframe and\n * can't navigate the top window itself, so it asks us (via `widget.navigate`).\n *\n * Guarded to the host's OWN origin: resolve the href against the host location and\n * refuse anything on a different origin or a non-http(s) scheme. The href originates\n * in page context the host itself declared, so this is defense-in-depth — the widget\n * must never be able to send the host off-site. Lives in this lazy chunk (not the\n * eager loader stub) to stay off the every-page budget.\n */\nexport function navigateHost(href: unknown): void {\n if (typeof href !== 'string' || !href) return;\n let target: URL;\n try {\n target = new URL(href, location.href);\n } catch {\n return;\n }\n if (target.protocol !== 'http:' && target.protocol !== 'https:') return;\n if (target.origin !== location.origin) return;\n location.assign(target.href);\n}\n\n/* ────────────────────────── activity ──────────────────────────────────── */\n\nfunction pushActivity(e: Omit<ActivityEvent, 'seq' | 'ts'>) {\n // The activity trail is AUTO observation. Gating here rather than only at the\n // listener install is what covers the nav trail: `declared` still watches\n // navigation (a route change makes the declared context and site map stale), so\n // without this check a clamped app would keep narrating where the user went.\n if (!allowsAuto(effectivePageContextMode())) return;\n activity.push({ ...e, seq: ++activitySeq, ts: Date.now() });\n if (activity.length > MAX_ACTIVITY) activity.shift();\n send?.({ type: 'host.activity', events: [activity[activity.length - 1]] });\n}\n\n/**\n * A short, human-readable label for what got clicked.\n *\n * Shaped after PostHog's autocapture, not after a session-replay frame: rrweb would\n * give us `{source:2, type:2, id:417, x:210, y:88}` — no text, no role, no href,\n * meaningless to a model without the full DOM snapshot it deltas against. One line\n * of \"clicked button 'Export CSV'\" is worth more and costs less.\n */\n/**\n * The accessible NAME of a form control — never its value.\n *\n * A control has no `innerText`, so the generic path below misses it. We look where a\n * control's name actually lives: `aria-label`, then a `<label for>` or a wrapping\n * `<label>`, then `placeholder`. `placeholder` is a LABEL, not a value — it is the\n * hint shown when the field is empty (\"Order number or customer\"), so it is safe.\n */\nfunction controlLabel(el: Element): string {\n const aria = el.getAttribute('aria-label');\n if (aria) return aria;\n\n const id = el.id;\n if (id) {\n const forLabel = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n const t = forLabel?.textContent?.trim();\n if (t) return t;\n }\n const wrapping = el.closest('label')?.textContent?.trim();\n if (wrapping) return wrapping;\n\n const placeholder = el.getAttribute('placeholder');\n if (placeholder) return placeholder;\n\n return '';\n}\n\nconst FORM_CONTROLS = new Set(['INPUT', 'SELECT', 'TEXTAREA']);\n\nfunction describe(el: Element): string {\n const role = el.getAttribute('role') || el.tagName.toLowerCase();\n const label =\n el.getAttribute('aria-label') ||\n (FORM_CONTROLS.has(el.tagName)\n ? controlLabel(el)\n : (el as HTMLElement).innerText?.trim().slice(0, 60)) ||\n el.getAttribute('title') ||\n '';\n return label ? `${role} \"${redact(label)}\"` : role;\n}\n\n/**\n * Elements a click is worth recording. Deliberately tight: the point of the activity\n * stream is INTENT (\"the user chose to export\"), and a click on a heading, a label,\n * a card gutter, or blank page is not intent, it is noise. We only log a click that\n * lands on something actionable.\n */\nconst ACTIONABLE =\n 'a[href],button,input,select,textarea,summary,' +\n '[role=\"button\"],[role=\"link\"],[role=\"menuitem\"],[role=\"tab\"],[role=\"option\"],' +\n '[role=\"checkbox\"],[role=\"switch\"],[role=\"radio\"],[onclick],[tabindex]';\n\nfunction onClick(ev: Event) {\n const target = ev.target as Element | null;\n if (!target || !(target instanceof Element)) return;\n\n // Clicking a <label> operates the control it labels — record THAT, not \"clicked\n // label\", so the event reads as the user's actual intent.\n const label = target.closest('label');\n const labelled = label\n ? (label.getAttribute('for') &&\n document.getElementById(label.getAttribute('for')!)) ||\n label.querySelector('input,select,textarea')\n : null;\n\n const actionable = labelled ?? target.closest(ACTIONABLE);\n // No actionable target — a click on text, a gutter, or blank space. That is not an\n // action; dropping it is the whole fix for the click-log noise.\n if (!actionable || isPrivate(actionable)) return;\n\n pushActivity({ type: 'click', summary: `clicked ${describe(actionable)}` });\n}\n\nfunction onSubmit(ev: Event) {\n const el = ev.target as Element | null;\n if (!el || isPrivate(el)) return;\n // The FORM was submitted — never its values.\n pushActivity({ type: 'submit', summary: `submitted ${describe(el)}` });\n}\n\n/**\n * A form field changed.\n *\n * The rule is the same as everywhere else and the temptation here is sharpest:\n * record THAT a field changed and WHICH field (its label), never WHAT it was\n * changed to. `change` fires on exactly the elements whose values are off-limits.\n *\n * One safe exception: a <select>, a checkbox, or a radio chose from a fixed, visible\n * set of options the agent can already see in the snapshot — \"Unpaid\", \"Shipped\".\n * That is a user *choice*, not typed data, so the chosen option's LABEL is fair to\n * include and is the useful part (\"filtered status to Shipped\"). Free-text and\n * numeric inputs get their label only.\n */\nfunction onChange(ev: Event) {\n const el = ev.target as (HTMLElement & { type?: string }) | null;\n if (!el || !(el instanceof Element) || isPrivate(el)) return;\n\n const tag = el.tagName;\n const type = (el as HTMLInputElement).type;\n\n // Never a password/hidden field, and isPrivate already covered data-mf-private.\n if (tag === 'INPUT' && (type === 'password' || type === 'hidden')) return;\n\n let summary = `changed ${describe(el)}`;\n\n if (tag === 'SELECT') {\n const opt = (el as HTMLSelectElement).selectedOptions[0]?.text;\n if (opt) summary = `${describe(el)} → \"${redact(opt)}\"`;\n } else if (type === 'checkbox' || type === 'radio') {\n summary = `${(el as HTMLInputElement).checked ? 'checked' : 'unchecked'} ${describe(el)}`;\n }\n\n pushActivity({ type: 'input', summary });\n}\n\n/**\n * SPA navigation. There is no event for `pushState`, so we wrap it — a 20-line job\n * that no library does better.\n */\nfunction watchNavigation() {\n const fire = () => {\n const url = location.pathname;\n if (url === lastUrl) return;\n lastUrl = url;\n pushActivity({ type: 'nav', summary: `navigated to ${url}` });\n void publishContext();\n publishArtifactGrants();\n // The site map can change without a reload (a virtualized SPA) and `current`\n // moves with the route, so re-publish it on navigation like context/grants.\n publishSitemap();\n // Re-advertise host.tools too (Minor #2): the enum `hoist.navigate` carries is\n // bound to the CURRENT sitemap, and start() only ever advertised it ONCE. A\n // route that gained or lost destinations must not leave the widget holding a\n // stale enum forever. Unlike start()'s one-shot emit (gated on tools.length),\n // this fires even when the result is `[]` — the whole point is to CLEAR a\n // tool the widget cached from before this navigation, not just to add one.\n publishTools();\n };\n // Captured so stop() can remove exactly this listener, and so history.pushState/\n // replaceState get restored to what they were before we wrapped them — never\n // re-wrapped on top of an existing wrap (that was the pre-existing bug: a second\n // start() used to wrap the ALREADY-wrapped methods, double-firing every nav).\n // Already watching ⇒ nothing to do. applyObservation() calls this on every\n // reconcile, so this guard is what keeps a clamp from re-wrapping history.\n if (navFire) return;\n navFire = fire;\n\n for (const name of ['pushState', 'replaceState'] as const) {\n const orig = history[name];\n if (name === 'pushState') origPushState = orig as History['pushState'];\n else origReplaceState = orig as History['replaceState'];\n history[name] = function (\n this: History,\n ...args: Parameters<History['pushState']>\n ) {\n const r = orig.apply(this, args);\n fire();\n return r;\n } as History[typeof name];\n }\n window.addEventListener('popstate', fire);\n}\n\n/* ─────────────────────────── focal context ────────────────────────────── */\n\n/**\n * Where the user's attention is, right now.\n *\n * This is the \"knows what you're doing\" layer, and it is deliberately small so it can\n * ride on every turn — where the full snapshot cannot. It is also the most sensitive:\n * `selection` is whatever the user highlighted, which could be their own email, so it\n * is redacted and respects data-mf-private like everything else. Focus and the\n * viewport are labels and refs — never a value.\n *\n * Held so the last-known focus can travel with a turn even between the (throttled)\n * push updates.\n */\nlet lastFocus: FocusContext = {};\n\nasync function readFocus(): Promise<FocusContext> {\n const focus: FocusContext = {};\n\n // Selection — the single strongest \"this is what I'm asking about\" signal.\n const sel = window.getSelection?.();\n if (sel && !sel.isCollapsed) {\n const anchor = sel.anchorNode?.parentElement ?? null;\n // Don't lift a selection out of a private region, and cap it — a user can select\n // the whole page.\n if (!anchor || !anchor.closest('[data-mf-private]')) {\n const text = sel.toString().trim().slice(0, 500);\n if (text) focus.selection = redact(text);\n }\n }\n\n // The control they're working in — its label, never its contents.\n const active = document.activeElement;\n if (\n active &&\n active !== document.body &&\n !isPrivate(active) &&\n !active.closest('[data-mf-private]')\n ) {\n const { snapshot } = await loadSnapshotModule();\n void snapshot; // ensure the chunk that owns refFor is loaded before we describe\n focus.focused = {\n label: redact(describeControl(active)),\n role: active.getAttribute('role') || active.tagName.toLowerCase(),\n };\n }\n\n const doc = document.documentElement;\n const scrollable = doc.scrollHeight - doc.clientHeight;\n focus.scroll =\n scrollable > 0 ? Math.round((doc.scrollTop / scrollable) * 100) / 100 : 0;\n\n return focus;\n}\n\n/** A label for whatever is focused, reusing the same value-blind rules as activity. */\nfunction describeControl(el: Element): string {\n return describe(el);\n}\n\n/** The one place any of the three call sites below reach into the DOM-walk chunk —\n * so `stop()` has a single `snapshotModule` to check without importing anything\n * itself (see the teardown-state block above). */\nasync function loadSnapshotModule() {\n const m = await import('./dom/snapshot');\n snapshotModule = m;\n return m;\n}\n\nlet focusTimer: ReturnType<typeof setTimeout> | null = null;\n\n/** Coalesce a burst of selection/focus/scroll events into one push. */\nfunction scheduleFocus() {\n if (focusTimer) return;\n focusTimer = setTimeout(async () => {\n focusTimer = null;\n lastFocus = await readFocus();\n send?.({ type: 'host.focus', focus: lastFocus });\n }, 250);\n}\n\n/* ───────────────────────────── snapshot ───────────────────────────────── */\n\nlet snapshotSeq = 0;\n\nexport async function sendSnapshot(emit: Send) {\n // Auto observation only — `declared` keeps getPageContext but skips DOM crawl.\n if (!allowsAuto(effectivePageContextMode())) return;\n\n // Hoist-first: on an XH Hoist SPA, the live models are a richer and cheaper source\n // of truth than scraping role-less div soup. detectHoist() is degrade-safe (never\n // throws here), so an absent/broken window.XH falls straight through to the\n // generic a11y walk below, unchanged.\n const hoist = detectHoist(() => readHoistRuntime());\n if (hoist) {\n const { rows } = readHoistConfig(\n typeof window !== 'undefined' ? window : undefined,\n );\n const { yaml, truncated } = renderHoistSnapshot(hoist, rows);\n emit({\n type: 'host.snapshot',\n snapshot: { yaml: redact(yaml), seq: ++snapshotSeq, truncated },\n });\n // Refs are out of scope for Layer 1 (they arrive with the interactive channel in\n // Layer 3) — a Hoist snapshot never mints [ref=eN] handles, so nothing is visible\n // by ref.\n lastFocus = { ...lastFocus, visibleRefs: [] };\n emit({ type: 'host.focus', focus: lastFocus });\n return;\n }\n\n // The a11y walk is itself lazily imported: a host that only ever declares\n // PageContext and never lets the agent look at the page never downloads it.\n const { snapshot } = await loadSnapshotModule();\n // Re-check across the await — the admin clamp can land while the chunk is still\n // loading (the loader asks for a snapshot on a cold start, before the widget has\n // finished bootstrapping). Crawling the host's whole page and posting it against a\n // mode that now forbids it is the single worst version of this leak, so bail BEFORE\n // walking the DOM rather than merely before emitting.\n if (!allowsAuto(effectivePageContextMode())) return;\n const { yaml, truncated, visibleRefs } = snapshot();\n emit({\n type: 'host.snapshot',\n snapshot: { yaml: redact(yaml), seq: ++snapshotSeq, truncated },\n });\n // The viewport slice rides with the focus context so the agent can tell the few\n // things on screen from the whole tree it just received.\n lastFocus = { ...lastFocus, visibleRefs };\n emit({ type: 'host.focus', focus: lastFocus });\n}\n\n/**\n * Zoom in on one ref — the pull half of the model. The agent asks; we resolve the ref\n * to a live element and return just its sub-tree.\n */\nexport async function sendRegion(ref: string, emit: Send) {\n // Auto observation only (same gate as sendSnapshot).\n if (!allowsAuto(effectivePageContextMode())) return;\n const { snapshotRegion, resolveRef } = await loadSnapshotModule();\n // Same across-the-await re-check as sendSnapshot — a region read is a smaller crawl,\n // not a different rule.\n if (!allowsAuto(effectivePageContextMode())) return;\n const el = resolveRef(ref);\n if (!el) {\n emit({\n type: 'host.region',\n ref,\n yaml: '(this element is no longer on the page)',\n });\n return;\n }\n const { yaml } = snapshotRegion(el);\n emit({ type: 'host.region', ref, yaml: redact(yaml) });\n}\n\n/* ───────────────────────────── tools ──────────────────────────────────── */\n\n/**\n * Tools the page's ADAPTER (today: Hoist) exposes to the agent, and the sole\n * execution path for calling one.\n *\n * The page's content is untrusted — text on it can try to instruct the agent — and\n * the moment the agent can act, a bad answer becomes a bad ACTION. Several things\n * hold that line, and all of them live HERE (in the page, where we control what\n * actually happens), not in the widget, which can be lied to:\n *\n * - a tool is only ever ADVERTISED (`advertiseTools`) when the HOST opted in via\n * `window.matterfact.hoist.actions` — default 'off';\n * - host tools are independent of page-context mode (admin host-tool allowlist);\n * - `executeHostTool` (adapters/hoist-runtime.ts) RE-CHECKS the host's current\n * action policy AND re-validates the destination against the LIVE page state,\n * on every call — never trusting what the widget claims was advertised, or\n * that the policy it was advertised UNDER still holds. A tool not marked\n * `readOnly` also carries a `confirm` policy the widget must gate on — see\n * HostTool's doc comment in protocol.ts.\n */\nexport async function callTool(call: ToolCall, emit: Send) {\n const win = typeof window !== 'undefined' ? window : undefined;\n const cls = toolClass(call.name);\n const startedAt = Date.now();\n emitToolEvent(win, {\n phase: 'call',\n name: call.name,\n toolClass: cls,\n args: call.args,\n });\n const r = await execute(call, win);\n emitToolEvent(win, {\n phase: 'result',\n name: call.name,\n toolClass: cls,\n ok: r.ok,\n error: r.error,\n ms: Date.now() - startedAt,\n });\n emit({\n type: 'host.toolResult',\n callId: call.callId,\n ok: r.ok,\n result: r.result,\n error: r.error,\n });\n}\n\n/* ───────────────────────────── stop / start ───────────────────────────── */\n\n/**\n * The AUTO half of observation — click/submit/change activity and focal context.\n * Split out of `start()` so `setPageContextMax` can take it back down without a\n * remount (see there). `addEventListener` de-dupes on (type, fn, capture), so\n * calling this twice installs one set.\n */\nfunction installAutoObservers(): void {\n // Passive + capture: we observe, we never interfere with the host's own handling.\n document.addEventListener('click', onClick, { capture: true, passive: true });\n document.addEventListener('submit', onSubmit, {\n capture: true,\n passive: true,\n });\n // `change` fires on blur/commit for text inputs and immediately for select/\n // checkbox/radio — not on every keystroke, which is what we want: a settled\n // choice, not a stream of partial values.\n document.addEventListener('change', onChange, {\n capture: true,\n passive: true,\n });\n\n // Focal context: what the user is attending to. Coalesced (scheduleFocus), because\n // selectionchange and scroll fire in torrents.\n document.addEventListener('selectionchange', scheduleFocus, { passive: true });\n document.addEventListener('focusin', scheduleFocus, {\n capture: true,\n passive: true,\n });\n window.addEventListener('scroll', scheduleFocus, {\n capture: true,\n passive: true,\n });\n}\n\n/** Remove what `installAutoObservers` added, and drop what it had already buffered —\n * a pending focus timer would otherwise fire one last reading after the clamp. */\nfunction removeAutoObservers(): void {\n document.removeEventListener('click', onClick, { capture: true });\n document.removeEventListener('submit', onSubmit, { capture: true });\n document.removeEventListener('change', onChange, { capture: true });\n document.removeEventListener('selectionchange', scheduleFocus);\n document.removeEventListener('focusin', scheduleFocus, { capture: true });\n window.removeEventListener('scroll', scheduleFocus, { capture: true });\n\n if (focusTimer) {\n clearTimeout(focusTimer);\n focusTimer = null;\n }\n}\n\n/** Undo `watchNavigation`: drop the popstate listener and put history.pushState /\n * replaceState back to what they were before we wrapped them. Restore, don't\n * re-wrap — that is what stops a repeated start() from wrapping an already-wrapped\n * pushState (the old double-fire-per-nav bug). */\nfunction unwatchNavigation(): void {\n if (navFire) {\n window.removeEventListener('popstate', navFire);\n navFire = null;\n }\n if (origPushState) {\n history.pushState = origPushState;\n origPushState = null;\n }\n if (origReplaceState) {\n history.replaceState = origReplaceState;\n origReplaceState = null;\n }\n}\n\n/**\n * The opposite number of `start()` — remove every listener it (or `watchNavigation`)\n * installed, restore `history.pushState`/`replaceState` to what they were before we\n * wrapped them, and forget the module-level `send`/`activity`/focus state. Nothing\n * here is a filter over what gets sent afterward — there is simply nothing left\n * installed to send anything.\n *\n * Distinct from `applyObservation()`, which reconciles the same listeners against a\n * changed mode: this one also drops `send`, so the widget is disconnected outright.\n * A clamp must never take this path — an app dialled to `off` still has a working\n * chat and working host tools.\n *\n * Why this has to exist at all: everything `start()` installs is MODULE-GLOBAL, and\n * this module outlives any single `EmbedHost`. React remounts `EmbedHost` whenever\n * ANY of its identity-defining props change (react.tsx's effect deps: publishableKey,\n * widgetOrigin, surface, theme, inline, pageContext, dev) — including just a theme\n * swap, not only a deliberate opt-out. Before this fix, a remount's `start()` call\n * only ever ADDED listeners; the previous mount's were still attached and kept firing\n * into the module `send`, which the new `start()` had just repointed at the NEW\n * widget. Net effect: open once with pageContext on, then remount for any reason\n * (including `pageContext: false`) and the new widget silently keeps receiving\n * clicks/nav/focus collected by the old mount's still-live listeners.\n *\n * Called from two places: the top of `start()` (idempotency — a second `start()`\n * never doubles up, which also fixes the pre-existing double history-wrap /\n * double-`fire()`-per-navigation bug), and `EmbedHost.destroy()` in loader.ts (a\n * plain unmount with no remount still has to stop, not just wait for a `start()`\n * that may never come).\n */\nexport function stop(): void {\n removeAutoObservers();\n unwatchNavigation();\n\n send = null;\n contextProvider = undefined;\n activity.length = 0;\n lastFocus = {};\n widgetOrigin = '';\n\n // Belt-and-suspenders alongside sendRegion's own pageContextOn check (see above):\n // an old ref minted while observation was on must not stay resolvable afterward.\n // Only touches the DOM-walk chunk if it was ever actually loaded — see\n // loadSnapshotModule's doc comment.\n snapshotModule?.clearRefs();\n}\n\n/**\n * Admin max from bootstrap — clamps effective mode without requiring a remount.\n * Host request (from `start`) is unchanged; effective = min(admin, host).\n *\n * This ALWAYS lands after `start()`: the loader mounts the iframe (and starts\n * observing under the host's requested mode) before the widget inside it has\n * round-tripped `/session/bootstrap` to learn the admin max. So recording the value\n * is not enough — the observers `start()` already installed have to come back down,\n * or an app dialed to `declared`/`off` keeps collecting and posting exactly what the\n * setting says it may not. Reconciling is the main path here, not a corner case.\n */\nexport function setPageContextMax(max: unknown): void {\n adminPageContextMax = parsePageContextMode(max);\n applyObservation();\n}\n\n/**\n * Bring what's installed in line with the CURRENT effective mode. Idempotent, so\n * `start()` and a later clamp can both just call it.\n *\n * Only ever reconciles observation — never `send`, so a clamp (even to `off`) leaves\n * the widget connected and host tools working; those are governed by the app's own\n * tool allowlist, not by page-context mode.\n */\nfunction applyObservation(): void {\n const mode = effectivePageContextMode();\n\n if (allowsAuto(mode)) {\n installAutoObservers();\n } else {\n removeAutoObservers();\n // Drop what was collected while the mode was wider. A buffered click trail from\n // before the clamp is exactly the data the clamp says we may not hold.\n activity.length = 0;\n lastFocus = {};\n }\n\n if (allowsDeclared(mode)) {\n watchNavigation();\n } else {\n unwatchNavigation();\n }\n}\n\n/**\n * @param pageContext Observation mode. Default `full` (`true`). `declared` keeps\n * getPageContext / host sitemap; `off`/`false` disables all page context.\n * Auto DOM/focus/activity requires `full`.\n */\nexport function start(\n emit: Send,\n origin?: string,\n pageContext: boolean | PageContextMode = true,\n provider?: PageContextProvider,\n) {\n // Idempotent: undo whatever a PREVIOUS start() installed before this one installs\n // anything. Without this, a remount (see stop()'s doc comment) leaves the old\n // mount's listeners live, writing into the `send` this call is about to reassign.\n stop();\n\n send = emit;\n widgetOrigin = origin || '';\n lastUrl = location.pathname;\n hostPageContextMode = parsePageContextMode(pageContext);\n contextProvider = provider;\n\n if (allowsDeclared(effectivePageContextMode())) {\n void publishContext();\n publishArtifactGrants();\n publishSitemap();\n }\n // Installs exactly what this mode allows — and is the same call a later\n // `setPageContextMax` makes to take it back down again.\n applyObservation();\n\n const theme = matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light';\n emit({ type: 'host.theme', mode: theme });\n\n // Host tools are independent of page-context mode (admin allowlist + host actions).\n {\n const w = typeof window !== 'undefined' ? window : undefined;\n const tools = advertise(w);\n if (tools.length) {\n emit({ type: 'host.tools', tools });\n for (const t of tools) {\n emitToolEvent(w, {\n phase: 'advertise',\n name: t.name,\n toolClass: toolClass(t.name),\n });\n }\n }\n }\n}\n\n/** Advertise the merged tool list on the wire and fire the host's onToolEvent so its\n * telemetry (and the dev panel) sees the current set. Shared by start()'s first emit's\n * navigation re-advertisement; fires even on `[]` to CLEAR a tool cached before a nav. */\nfunction publishTools() {\n const win = typeof window !== 'undefined' ? window : undefined;\n const tools = advertise(win);\n send?.({ type: 'host.tools', tools });\n for (const t of tools) {\n emitToolEvent(win, {\n phase: 'advertise',\n name: t.name,\n toolClass: toolClass(t.name),\n });\n }\n}\n"],"mappings":";;;AAIA,IAAM,OAAwC;AAAA,EAC5C,KAAK;AAAA,EACL,UAAU;AAAA,EACV,MAAM;AACR;AAGO,SAAS,qBAAqB,OAAiC;AACpE,MAAI,OAAO,UAAU,UAAW,QAAO,QAAQ,SAAS;AACxD,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,IAAI,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY;AAC3C,MAAI,MAAM,UAAU,MAAM,cAAc,MAAM,MAAO,QAAO;AAC5D,MAAI,MAAM,UAAU,MAAM,QAAQ,MAAM,OAAO,MAAM,MAAO,QAAO;AACnE,MAAI,MAAM,WAAW,MAAM,OAAO,MAAM,KAAM,QAAO;AACrD,SAAO;AACT;AAGO,SAAS,qBACd,UACA,aACiB;AACjB,SAAO,KAAK,QAAQ,KAAK,KAAK,WAAW,IAAI,WAAW;AAC1D;AAEO,SAAS,eAAe,MAAgC;AAC7D,SAAO,SAAS;AAClB;AAEO,SAAS,WAAW,MAAgC;AACzD,SAAO,SAAS;AAClB;;;AC1BA,IAAM,MAAM;AAAA,EACV;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AASO,SAAS,OAAO,MAAsB;AAC3C,MAAI,MAAM;AACV,aAAW,MAAM,IAAK,OAAM,IAAI,QAAQ,IAAI,YAAY;AACxD,SAAO;AACT;;;AC2CO,SAAS,YACd,MACqB;AACrB,MAAI;AACJ,MAAI;AACF,SAAK,KAAK;AAAA,EACZ,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,aACJ,CAAC,CAAC,GAAG,MAAM,QACX,GAAG,MAAM,SAAS,KAClB,GAAG,OAAO,SAAS,KACnB,GAAG,IAAI,SAAS;AAClB,SAAO,aAAa,KAAK;AAC3B;AAUA,SAAS,MAAM,GAAW,MAAM,KAAa;AAC3C,QAAM,QAAQ,OAAO,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK,CAAC;AAClD,QAAM,SAAS,MAAM,SAAS,MAAM,GAAG,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,WAAM;AACpE,SAAO,IAAI,OAAO,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK,CAAC;AAC/D;AAGA,SAAS,KAAK,OAAwB;AACpC,QAAM,IAAI,SAAS,OAAO,KAAK,OAAO,KAAK;AAC3C,SAAO,UAAU,MAAM,CAAC,CAAC;AAC3B;AAEA,SAAS,QACP,KACA,MACA,KACA,KACM;AACN,MAAI,KAAK,GAAG,GAAG,QAAQ;AACvB,aAAW,KAAK,KAAM,KAAI,KAAK,GAAG,GAAG,KAAK,KAAK,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE;AAChE;AAEO,SAAS,WACd,MACA,QACA,KACA,OACM;AACN,QAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,MAAI,KAAK,GAAG,GAAG,WAAW,MAAM,KAAK,SAAS,MAAM,CAAC,GAAG;AAExD,MAAI,KAAK,GAAG,GAAG,yBAAyB;AACxC,aAAW,KAAK,KAAK;AACnB,QAAI,KAAK,GAAG,GAAG,sBAAsB,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE;AAEnE,MAAI,KAAK,SAAS,QAAQ;AACxB,QAAI,KAAK,GAAG,GAAG,0BAA0B;AACzC,eAAW,KAAK,KAAK,SAAU,SAAQ,GAAG,KAAK,SAAS,KAAK,GAAG,GAAG,MAAM;AAAA,EAC3E;AAEA,QAAM,QAAQ,KAAK,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AACpD,MAAI,KAAK,GAAG,GAAG,sBAAsB;AACrC,aAAW,KAAK,MAAO,SAAQ,GAAG,KAAK,SAAS,KAAK,GAAG,GAAG,MAAM;AAEjE,MAAI;AAAA,IACF,GAAG,GAAG,aAAa,MAAM,WAAW,MAAM,MAAM,OAAO,KAAK,UAAU,OAAO,CAAC;AAAA,EAChF;AACF;AAIA,SAAS,cAAc,MAAc,MAAwB;AAC3D,MAAI,CAAC,KAAK,OAAQ,QAAO,UAAU,IAAI;AAKvC,MAAI,MAAM,KAAK,CAAC;AAChB,MAAI,MAAM,KAAK,CAAC;AAChB,aAAW,KAAK,MAAM;AACpB,QAAI,IAAI,IAAK,OAAM;AACnB,QAAI,IAAI,IAAK,OAAM;AAAA,EACrB;AACA,QAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,SAAO,UAAU,IAAI,KAAK,KAAK,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,IAAI;AACpF;AAEO,SAAS,YACd,OACA,KACA,OACM;AACN,QAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,MAAI,KAAK,GAAG,GAAG,YAAY,MAAM,MAAM,SAAS,OAAO,CAAC,GAAG;AAC3D,aAAW,KAAK,MAAM,QAAQ;AAC5B,QAAI,KAAK,GAAG,GAAG,aAAa,MAAM,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE;AAAA,EACpE;AACF;AAIO,SAAS,UACd,QACA,KACA,OACM;AACN,QAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,aAAW,KAAK,QAAQ;AACtB,QAAI,CAAC,EAAE,MAAM,OAAQ;AACrB,QAAI,KAAK,GAAG,GAAG,gBAAgB,MAAM,EAAE,KAAK,CAAC,GAAG;AAChD,eAAW,KAAK,EAAE,OAAO;AACvB,YAAM,OAAO,EAAE,UAAU,eAAe;AAGxC,UAAI,KAAK,GAAG,GAAG,YAAY,MAAM,EAAE,KAAK,CAAC,GAAG,IAAI,WAAM,OAAO,EAAE,IAAI,CAAC,EAAE;AAAA,IACxE;AAAA,EACF;AACF;AAgBO,SAAS,oBAAoB,IAAsC;AACxE,SAAO,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,KAAK;AACtC;AAUO,SAAS,kBACd,IACA,QACU;AACV,QAAM,eAAe,oBAAoB,EAAE;AAC3C,QAAM,YAAY,GAAG,IAClB,OAAO,CAAC,MAAM,EAAE,MAAM,MAAM,EAC5B,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,GAAG,EACnE,KAAK,IAAI;AACZ,SAAO;AAAA,IACL,MAAM;AAAA,IACN,aAAa;AAAA,MACX,yIAC+D,aAAa,kBAAkB;AAAA,IAChG;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,aAAa;AAAA,UACX,MAAM;AAAA,UACN,MAAM,aAAa,IAAI,CAAC,MAAM,EAAE,KAAK;AAAA,QACvC;AAAA,QACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MAC3B;AAAA,MACA,UAAU,CAAC,aAAa;AAAA,IAC1B;AAAA,IACA,UAAU;AAAA;AAAA;AAAA,IAGV,SAAS,WAAW,SAAS,SAAS;AAAA,EACxC;AACF;AAIO,SAAS,kBAAkB,IAA+B;AAC/D,QAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,SAAS,QAAQ,CAAC;AACnE,QAAM,OAAO,GAAG,MAAM,QAAQ,GAAG,MAAM,QAAQ;AAC/C,QAAM,OAAO,CAAC,WAAW,IAAI,EAAE;AAC/B,MAAI,SAAU,MAAK,KAAK,GAAG,QAAQ,WAAW;AAC9C,MAAI,GAAG,MAAM,OAAQ,MAAK,KAAK,GAAG,GAAG,MAAM,MAAM,UAAU;AAC3D,MAAI,GAAG,OAAO,OAAQ,MAAK,KAAK,GAAG,GAAG,OAAO,MAAM,WAAW;AAC9D,SAAO;AAAA,IACL,OAAO,GAAG,MAAM,OAAO,OAAO,GAAG,MAAM,IAAI,IAAI;AAAA,IAC/C,aAAa,OAAO,GAAG,KAAK,KAAK,IAAI,CAAC,GAAG;AAAA,EAC3C;AACF;AAEO,SAAS,oBACd,IACA,QACsC;AACtC,QAAM,MAAgB,CAAC;AAKvB,YAAU,GAAG,KAAK,KAAK,CAAC;AACxB,MAAI,YAAY;AAChB,aAAW,KAAK,GAAG,OAAO;AACxB,QAAI,EAAE,KAAK,SAAS,OAAQ,aAAY;AACxC,eAAW,GAAG,QAAQ,KAAK,CAAC;AAAA,EAC9B;AACA,aAAW,KAAK,GAAG,OAAQ,aAAY,GAAG,KAAK,CAAC;AAChD,SAAO,EAAE,MAAM,IAAI,KAAK,IAAI,GAAG,UAAU;AAC3C;;;AC/PO,SAAS,gBAAgB,KAG9B;AACA,QAAM,MACJ,KAGC,YAAY;AACf,QAAM,KAAK,KAAK;AAChB,SAAO;AAAA,IACL,MAAM,OAAO,KAAK,SAAS,YAAY,IAAI,QAAQ,IAAI,IAAI,OAAO;AAAA,IAClE,eAAe,MAAM,QAAQ,EAAE,IAAI,KAAK,CAAC;AAAA,EAC3C;AACF;AAMA,SAAS,iBAAiB,IAAS,MAAqB;AACtD,QAAM,SAAS,OAAO,IAAI,cAAc,aAAa,GAAG,UAAU,IAAI,IAAI,CAAC;AAC3E,SAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC;AAC3C;AAEA,SAAS,UAAU,GAAgB;AACjC,SAAO,GAAG,aAAa,QAAQ;AACjC;AAEA,SAAS,QAAQ,GAAgB;AAC/B,SAAO,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,EAAE;AACpD;AAEA,SAAS,SAAS,GAAgB;AAChC,SAAO,OAAO,GAAG,cAAc,GAAG,eAAe,GAAG,SAAS,GAAG,SAAS,EAAE;AAC7E;AAKA,SAAS,eACP,MACA,QACA,KACM;AACN,aAAW,KAAK,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,GAAG;AAC/C,UAAM,WAAW,GAAG;AACpB,QAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,QAAQ;AAC9C,qBAAe,UAAU,CAAC,GAAG,QAAQ,SAAS,CAAC,CAAC,GAAG,GAAG;AAAA,IACxD,OAAO;AACL,YAAM,KAAK,OAAO,GAAG,SAAS,GAAG,SAAS,EAAE;AAC5C,UAAI,GAAI,KAAI,IAAI,IAAI,CAAC,GAAG,QAAQ,SAAS,CAAC,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAAC;AAAA,IACxE;AAAA,EACF;AACF;AAKA,SAAS,YAAY,GAAuB;AAC1C,QAAM,SACJ,OAAO,GAAG,0BAA0B,aAChC,EAAE,sBAAsB,IACxB,MAAM,QAAQ,GAAG,OAAO,IACtB,EAAE,UACF,CAAC;AACT,QAAM,UAAU,oBAAI,IAAoB;AACxC,iBAAe,MAAM,QAAQ,GAAG,OAAO,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,GAAG,OAAO;AACtE,UAAQ,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,GACvC,IAAI,CAAC,MAAW;AACf,UAAM,QAAQ,OAAO,GAAG,SAAS,GAAG,SAAS,EAAE;AAC/C,WAAO,EAAE,OAAO,QAAQ,QAAQ,IAAI,KAAK,KAAK,SAAS,CAAC,EAAE;AAAA,EAC5D,CAAC,EACA,OAAO,CAAC,MAAmB,EAAE,KAAK;AACvC;AAEA,SAAS,QAAQ,KAAU,MAA+B;AACxD,QAAM,MAAgB,CAAC;AACvB,aAAW,KAAK;AACd,QAAI,EAAE,KAAK,IACT,OAAO,KAAK,QAAQ,aAAa,IAAI,IAAI,EAAE,KAAK,IAAI,KAAK,OAAO,EAAE,KAAK;AAC3E,SAAO;AACT;AAEA,SAAS,SAAS,GAAmB;AACnC,QAAM,UAAU,YAAY,CAAC;AAC7B,QAAM,UAAU,MAAM,QAAQ,GAAG,OAAO,OAAO,IAAI,EAAE,MAAM,UAAU,CAAC;AACtE,SAAO;AAAA,IACL,IAAI,QAAQ,CAAC;AAAA,IACb,OAAO,OAAO,GAAG,SAAS,EAAE;AAAA,IAC5B;AAAA,IACA,WAAW,MAAM,QAAQ,GAAG,eAAe,IAAI,EAAE,kBAAkB,CAAC,GAAG;AAAA,MACrE,CAAC,MAAW,QAAQ,GAAG,OAAO;AAAA,IAChC;AAAA,IACA,MAAM,QAAQ,IAAI,CAAC,MAAW,QAAQ,GAAG,OAAO,CAAC;AAAA,IACjD,YACE,OAAO,GAAG,OAAO,aAAa,WAC1B,EAAE,MAAM,WACR,QAAQ;AAAA,EAChB;AACF;AAIA,SAAS,WAAW,GAAuB;AACzC,SAAO,EAAE,aAAa,KAAK,EAAE,SAAS,SAAS;AACjD;AAEA,SAAS,UAAU,GAAoB;AAGrC,QAAM,SAAS,GAAG,UAAU,GAAG,kBAAkB,UAAU,CAAC;AAC5D,SAAO;AAAA,IACL,IAAI,QAAQ,CAAC;AAAA,IACb,OAAO,OAAO,GAAG,SAAS,GAAG,kBAAkB,OAAO,QAAQ,EAAE;AAAA,IAChE,SAAS,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAC,OAAY;AAAA,MAC7D,MAAM,OAAO,GAAG,QAAQ,EAAE;AAAA,MAC1B,OAAO,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,OAAO,CAAC,GACvC,IAAI,CAAC,MAAY,OAAO,MAAM,WAAW,IAAI,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAE,EACpE,OAAO,CAAC,MAAc,OAAO,SAAS,CAAC,CAAC;AAAA,IAC7C,EAAE;AAAA,EACJ;AACF;AAIA,SAAS,SAAS,KAAqB;AACrC,SAAO,IACJ,QAAQ,UAAU,GAAG,EACrB,QAAQ,sBAAsB,OAAO,EACrC,QAAQ,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,EACvC,KAAK;AACV;AAEA,SAAS,WAAW,MAAkB;AACpC,QAAM,IAAI,MAAM;AAChB,SAAO,IAAK,MAAM,QAAQ,CAAC,IAAI,IAAI,MAAM,KAAK,CAAC,IAAK,CAAC;AACvD;AAIA,SAAS,WACP,IACA,QAC6C;AAC7C,QAAM,SAAS,IAAI;AACnB,QAAM,OAAO,QAAQ,YAAY,QAAQ,QAAQ;AACjD,QAAM,MAAM,oBAAI,IAA4C;AAC5D,MAAI,CAAC,UAAU,OAAO,OAAO,cAAc,cAAc,CAAC,KAAM,QAAO;AACvE,QAAM,OAAO,CAAC,MAAW,WAAmB;AAC1C,eAAW,KAAK,WAAW,IAAI,GAAG;AAChC,YAAM,MAAM,OAAO,GAAG,QAAQ,EAAE;AAChC,UAAI,CAAC,IAAK;AACV,YAAM,OAAO,SAAS,GAAG,MAAM,IAAI,GAAG,KAAK;AAC3C,UAAI,OAAO;AACX,UAAI;AACF,eAAO,OAAO,UAAU,MAAM,MAAM;AAAA,MACtC,QAAQ;AACN,eAAO;AAAA,MACT;AACA,UAAI,QAAQ,CAAC,IAAI,IAAI,GAAG,EAAG,KAAI,IAAI,KAAK,EAAE,MAAM,KAAK,CAAC;AACtD,WAAK,GAAG,IAAI;AAAA,IACd;AAAA,EACF;AACA,OAAK,MAAM,EAAE;AACb,SAAO;AACT;AAMA,SAAS,YACP,IACA,UACA,QACiB;AACjB,QAAM,SAAU,IAAI,aAAa,UAAU,CAAC;AAC5C,QAAM,cAAc,OAAO,IAAI,aAAa,QAAQ,EAAE;AACtD,QAAM,SAAS,WAAW,IAAI,MAAM;AACpC,MAAI,CAAC,OAAO,KAAM,QAAO,CAAC;AAE1B,QAAM,SAA0B,CAAC;AACjC,aAAW,MAAM,iBAAiB,IAAI,mBAAmB,GAAG;AAC1D,QAAI,SAAS,EAAE,EAAG;AAClB,UAAM,OAAO,MAAM,QAAQ,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC;AAClD,UAAM,cAAc,OAAO,IAAI,eAAe,EAAE;AAChD,UAAM,QAA4B,CAAC;AACnC,QAAI,gBAAgB;AACpB,eAAW,KAAK,MAAM;AACpB,YAAM,KAAK,OAAO,GAAG,MAAM,EAAE;AAC7B,YAAM,IAAI,OAAO,IAAI,EAAE;AACvB,UAAI,CAAC,MAAM,CAAC,EAAG;AACf,UAAI,EAAE,KAAK,SAAS,kBAAkB,EAAG,iBAAgB;AACzD,YAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWT,OAAO,OAAO,OAAO,GAAG,SAAS,EAAE,KAAK,SAAS,EAAE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOpD,MAAM,UAAU,EAAE,KAAK,WAAW,GAAG,IAAI,SAAS,EAAE,OAAO,EAAE;AAAA;AAAA;AAAA,QAG7D,MAAM,EAAE;AAAA,QACR,SAAS,OAAO,eAAe,EAAE,SAAS;AAAA,MAC5C,CAAC;AAAA,IACH;AACA,QAAI,CAAC,MAAM,OAAQ;AACnB,UAAM,SAAS,OAAO,OAAO,UAAU,EAAE;AACzC,UAAM,QAAQ,gBACV,SACE,gBAAa,MAAM,KACnB,YACF;AACJ,WAAO,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,EAC9B;AACA,SAAO;AACT;AAEO,SAAS,iBACd,MAAe,OAAO,WAAW,cAAc,SAAS,QACnC;AACrB,QAAM,KAAM,KAAsB;AAClC,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,EAAE,cAAc,IAAI,gBAAgB,GAAG;AAC7C,QAAM,WAAW,CAAC,MAChB,cAAc,SAAS,UAAU,CAAC,CAAC,KAAK,cAAc,SAAS,QAAQ,CAAC,CAAC;AAE3E,QAAM,KAAK,GAAG,eAAe,CAAC;AAC9B,SAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM,OAAO,GAAG,QAAQ,EAAE;AAAA,MAC1B,MAAM,OAAO,GAAG,QAAQ,EAAE;AAAA,MAC1B,QAAQ,GAAG,UAAU,CAAC;AAAA,IACxB;AAAA,IACA,OAAO,iBAAiB,IAAI,WAAW,EACpC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAC1B,IAAI,QAAQ,EACZ,OAAO,UAAU;AAAA,IACpB,QAAQ,iBAAiB,IAAI,YAAY,EACtC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAC1B,IAAI,SAAS,EACb,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS,CAAC;AAAA,IACpC,KAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,QACG,KAA4C,UAAU,UAAU;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACF;AAQO,SAAS,kBAAkB,KAAkC;AAClE,QAAM,WACJ,KAGC,YAAY,OAAO,SAAS;AAC/B,SAAO;AAAA,IACL,UAAU,aAAa,aAAa,aAAa,SAAS,WAAW;AAAA,EACvE;AACF;AAaO,SAAS,eACd,MAAe,OAAO,WAAW,cAAc,SAAS,QAC5C;AACZ,MAAI;AACF,UAAM,KAAM,KAA0B;AACtC,QAAI,CAAC,GAAI,QAAO,CAAC;AACjB,UAAM,EAAE,SAAS,IAAI,kBAAkB,GAAG;AAC1C,QAAI,aAAa,MAAO,QAAO,CAAC;AAChC,UAAM,KAAK,iBAAiB,GAAG;AAC/B,QAAI,CAAC,GAAI,QAAO,CAAC;AACjB,WAAO,CAAC,kBAAkB,IAAI,QAAQ,CAAC;AAAA,EACzC,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAoBO,SAAS,gBACd,MACA,MAAe,OAAO,WAAW,cAAc,SAAS,QACL;AACnD,MAAI;AACF,QAAI,KAAK,SAAS,kBAAkB;AAClC,aAAO,EAAE,IAAI,OAAO,OAAO,eAAe;AAAA,IAC5C;AAKA,QAAI,kBAAkB,GAAG,EAAE,aAAa,OAAO;AAC7C,aAAO,EAAE,IAAI,OAAO,OAAO,yBAAyB;AAAA,IACtD;AAEA,UAAM,cAAc,OAAO,KAAK,MAAM,eAAe,EAAE;AACvD,UAAM,KAAK,iBAAiB,GAAG;AAC/B,UAAM,OAAO,KACT,oBAAoB,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,WAAW,IAC3D;AACJ,QAAI,CAAC,KAAM,QAAO,EAAE,IAAI,OAAO,OAAO,sBAAsB;AAE5D,UAAM,KAAM,KAAsB;AAKlC,UAAM,SAAS;AAAA,MACb,GAAI,IAAI,aAAa,UAAU,CAAC;AAAA,MAChC,GAAK,KAAK,MAAM,UAAkD,CAAC;AAAA,IACrE;AACA,QAAI,OAAO,IAAI,aAAa,YAAY;AACtC,SAAG,SAAS,KAAK,MAAM,MAAM;AAAA,IAC/B,WAAW,OAAO,IAAI,QAAQ,aAAa,YAAY;AACrD,SAAG,OAAO,SAAS,KAAK,MAAM,MAAM;AAAA,IACtC,OAAO;AACL,aAAO,EAAE,IAAI,OAAO,OAAO,yBAAyB;AAAA,IACtD;AACA,WAAO,EAAE,IAAI,MAAM,QAAQ,OAAO,gBAAgB,WAAW,EAAE,EAAE;AAAA,EACnE,SAAS,GAAG;AACV,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,OAAO,aAAa,QAAQ,EAAE,UAAU,iBAAiB;AAAA,IAClE;AAAA,EACF;AACF;;;ACpXO,IAAM,YAAY;AAIlB,IAAM,0BAA0B;AA+BvC,SAAS,SAAS,KAAgC;AAChD,SACG,KAAuD,cAAc,CAAC;AAE3E;AAEO,SAAS,UAAU,MAAyB;AACjD,MAAI,KAAK,WAAW,QAAQ,EAAG,QAAO;AACtC,MAAI,KAAK,WAAW,KAAK,EAAG,QAAO;AACnC,SAAO;AACT;AAKO,SAAS,UAAU,KAAc,GAA0B;AAChE,QAAM,KAAK,SAAS,GAAG,EAAE;AACzB,MAAI,OAAO,OAAO,WAAY;AAC9B,MAAI;AACF,OAAG,CAAC;AAAA,EACN,QAAQ;AAAA,EAER;AACF;AAKO,SAAS,cAAc,KAAc,GAAoB;AAC9D,YAAU,KAAK,EAAE,MAAM,QAAQ,GAAG,EAAE,CAAC;AACrC,QAAM,KAAK,SAAS,GAAG,EAAE;AACzB,MAAI,OAAO,OAAO,WAAY;AAC9B,MAAI;AACF,OAAG,CAAC;AAAA,EACN,QAAQ;AAAA,EAER;AACF;AASA,SAAS,QAAQ,KAA0B;AACzC,QAAM,EAAE,UAAAA,WAAU,SAAS,IAAI,SAAS,GAAG,EAAE,WAAW,CAAC;AACzD,QAAM,MAAkB,CAAC;AACzB,MAAI,OAAOA,cAAa,YAAY;AAClC,QAAI,KAAK;AAAA,MACP,MAAM;AAAA,MACN,aACE;AAAA,MAWF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS,EAAE,MAAM,SAAS;AAAA,UAC1B,KAAK,EAAE,MAAM,SAAS;AAAA,QACxB;AAAA,QACA,UAAU,CAAC,WAAW,KAAK;AAAA,MAC7B;AAAA,MACA,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,MAAI,OAAO,aAAa,YAAY;AAClC,QAAI,KAAK;AAAA,MACP,MAAM;AAAA,MACN,aACE;AAAA,MAKF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE;AAAA,QACvC,UAAU,CAAC,MAAM;AAAA,MACnB;AAAA,MACA,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAIA,IAAM,cAAc;AAKpB,SAAS,QAAQ,MAAsB;AACrC,SAAO,KAAK,WAAW,MAAM,IAAI,OAAO,OAAO,IAAI;AACrD;AAEA,SAAS,SAAS,KAA0B;AAC1C,QAAM,OAAO,SAAS,GAAG,EAAE;AAC3B,MAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,QAAO,CAAC;AAClC,QAAM,MAAkB,CAAC;AACzB,aAAW,KAAK,MAAM;AACpB,UAAM,OAAO,GAAG,QAAQ,IAAI,KAAK;AACjC,QAAI,CAAC,OAAO,OAAO,EAAE,YAAY,WAAY;AAC7C,UAAM,OAAO,QAAQ,GAAG;AACxB,QAAI,CAAC,YAAY,KAAK,IAAI,EAAG;AAC7B,QAAI,KAAK;AAAA,MACP;AAAA,MACA,aAAa,OAAO,EAAE,eAAe,qBAAqB,IAAI,GAAG;AAAA,MACjE,aAAa,EAAE,eAAe,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,MAC/D,UAAU;AAAA,MACV,SAAS,EAAE,YAAY,SAAS,SAAS;AAAA,IAC3C,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAcO,SAAS,UACd,MAAe,OAAO,WAAW,cAAc,SAAS,QAC5C;AACZ,QAAM,SAAqB,CAAC;AAC5B,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,OAAO,CAAC,UAAsB;AAClC,eAAW,KAAK,OAAO;AACrB,UAAI,KAAK,IAAI,EAAE,IAAI,EAAG;AACtB,WAAK,IAAI,EAAE,IAAI;AACf,aAAO,KAAK,CAAC;AAAA,IACf;AAAA,EACF;AACA,MAAI;AACF,SAAK,eAAe,GAAG,CAAC;AAAA,EAC1B,QAAQ;AAAA,EAER;AACA,MAAI;AACF,SAAK,QAAQ,GAAG,CAAC;AACjB,SAAK,SAAS,GAAG,CAAC;AAAA,EACpB,QAAQ;AAAA,EAER;AACA,SAAO,OAAO,MAAM,GAAG,SAAS;AAClC;AAIA,SAAS,QAAQ,IAA4B;AAC3C,SAAO,IAAI;AAAA,IAAQ,CAAC,GAAG,WACrB,WAAW,MAAM,OAAO,IAAI,MAAM,qBAAqB,CAAC,GAAG,EAAE;AAAA,EAC/D;AACF;AAKA,SAAS,aAAa,OAAyB;AAC7C,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK;AAClD,MAAI;AACF,WAAO,KAAK,MAAM,OAAO,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,EACjD,QAAQ;AACN,WAAO,OAAO,OAAO,KAAK,CAAC;AAAA,EAC7B;AACF;AAaA,eAAsB,QACpB,MACA,MAAe,OAAO,WAAW,cAAc,SAAS,QACI;AAC5D,QAAM,MAAM,UAAU,KAAK,IAAI;AAC/B,MAAI;AACF,QAAI,QAAQ,SAAS;AAEnB,aAAO,gBAAgB,MAAM,GAAG;AAAA,IAClC;AAEA,UAAM,UAAU,eAAe,KAAK,KAAK,IAAI;AAC7C,QAAI,CAAC,QAAS,QAAO,EAAE,IAAI,OAAO,OAAO,eAAe;AAExD,UAAM,SAAS,MAAM,QAAQ,KAAK;AAAA,MAChC,QAAQ,QAAQ,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,MACxC,QAAQ,uBAAuB;AAAA,IACjC,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,QAAQ,aAAa,MAAM,EAAE;AAAA,EAClD,SAAS,GAAG;AACV,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,OAAO,aAAa,QAAQ,EAAE,UAAU,kBAAkB;AAAA,IACnE;AAAA,EACF;AACF;AAGA,SAAS,eACP,KACA,MAC0D;AAC1D,QAAM,KAAK,SAAS,GAAG;AACvB,MAAI,SAAS,qBAAsB,QAAO,GAAG,SAAS;AACtD,MAAI,SAAS,qBAAsB,QAAO,GAAG,SAAS;AACtD,MAAI,KAAK,WAAW,MAAM,GAAG;AAC3B,UAAM,OAAO,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,MAAM,SAAS,GAAG,QAAQ,IAAI,KAAK,CAAC,MAAM,IAAI;AACjF,WAAO,KAAK;AAAA,EACd;AACA,SAAO;AACT;;;AC9QA,IAAI,eAAe;AAuBnB,IAAM,eAAe;AAErB,IAAI,OAAoB;AACxB,IAAI,cAAc;AAClB,IAAM,WAA4B,CAAC;AACnC,IAAI,UAAU;AAEd,IAAI,sBAAuC;AAE3C,IAAI,sBAAuC;AAE3C,SAAS,2BAA4C;AACnD,SAAO,qBAAqB,qBAAqB,mBAAmB;AACtE;AAGA,SAAS,gBAAyB;AAChC,SAAO,eAAe,yBAAyB,CAAC;AAClD;AAcA,IAAI;AAcJ,IAAI,UAA+B;AAInC,IAAI,gBAA6C;AACjD,IAAI,mBAAmD;AAKvD,IAAI,iBAAmD;AAOhD,SAAS,UAAU,IAAsB;AAC9C,MAAI,GAAG,QAAQ,mBAAmB,EAAG,QAAO;AAC5C,QAAM,MAAM,GAAG;AACf,MAAI,QAAQ,SAAS;AACnB,UAAM,IAAK,GAAwB;AACnC,QAAI,MAAM,cAAc,MAAM,SAAU,QAAO;AAAA,EACjD;AACA,SAAO;AACT;AAgCO,SAAS,mBAAmB,UAAiC;AAClE,QAAM,IAAI,SAAS,MAAM,qCAAqC;AAC9D,SAAO,IAAI,mBAAmB,EAAE,CAAC,CAAC,IAAI;AACxC;AAEA,SAAS,6BAA2C;AAClD,MAAI,CAAC,aAAc,QAAO,CAAC;AAC3B,QAAM,MAAoB,CAAC;AAC3B,aAAW,SAAS,MAAM,KAAK,SAAS,iBAAiB,QAAQ,CAAC,GAAG;AACnE,QAAI;AACJ,QAAI;AACF,UAAI,IAAI,IAAI,MAAM,aAAa,KAAK,KAAK,IAAI,SAAS,IAAI;AAAA,IAC5D,QAAQ;AACN;AAAA,IACF;AACA,QAAI,EAAE,WAAW,aAAc;AAC/B,UAAM,KAAK,mBAAmB,EAAE,QAAQ;AACxC,QAAI,CAAC,GAAI;AACT,QAAI,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAG;AAIlC,QAAI,KAAK;AAAA,MACP,MAAM;AAAA,MACN;AAAA,MACA,OAAO,OAAO,MAAM,aAAa,OAAO,KAAK,EAAE,KAAK;AAAA,IACtD,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAQA,SAAS,mBAA2B;AAClC,SAAO,MAAM,KAAK,SAAS,iBAAiB,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM;AACnE,QAAI;AACF,YAAM,IAAI,IAAI,IAAI,EAAE,aAAa,KAAK,KAAK,IAAI,SAAS,IAAI;AAC5D,aAAO,EAAE,WAAW,SAAS,UAAU,EAAE,WAAW;AAAA,IACtD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC,EAAE;AACL;AAQO,SAAS,iBAAiB,UAAoC;AACnE,QAAM,QAAQ,2BAA2B;AACzC,QAAM,SAAS,iBAAiB;AAEhC,SAAO;AAAA;AAAA;AAAA,IAGL,KAAK,SAAS,SAAS,SAAS;AAAA,IAChC,MAAM,SAAS;AAAA,IACf,OAAO,OAAO,SAAS,KAAK;AAAA,IAC5B,QAAQ,SAAS,gBAAgB,QAAQ;AAAA,IACzC,GAAG;AAAA;AAAA;AAAA;AAAA,IAIH,UAAU,CAAC,GAAI,SAAS,YAAY,CAAC,GAAI,GAAG,KAAK;AAAA,IACjD,MAAM;AAAA,MACJ,GAAI,SAAS,QAAQ,CAAC;AAAA,MACtB,GAAI,SAAS,EAAE,eAAe,OAAO,IAAI,CAAC;AAAA,IAC5C;AAAA,EACF;AACF;AAGO,SAAS,kBAA+B;AAC7C,SAAO;AAAA,IACJ,OAAsD,YACnD,WAAW,CAAC;AAAA,EAClB;AACF;AASA,eAAe,yBAA+C;AAC5D,QAAM,KACJ,OAMA;AACF,MAAI,iBAAiB;AACnB,UAAM,IAAI,MAAM,gBAAgB;AAChC,QAAI,EAAG,QAAO;AAAA,EAChB;AACA,MAAI,IAAI,gBAAgB;AACtB,UAAM,IAAI,MAAM,GAAG,eAAe;AAClC,QAAI,EAAG,QAAO;AAAA,EAChB;AAGA,QAAM,QAAQ,YAAY,MAAM,iBAAiB,CAAC;AAClD,MAAI,MAAO,QAAO,kBAAkB,KAAK;AACzC,SAAO,IAAI,WAAW,CAAC;AACzB;AAOA,eAAe,iBAAiB;AAC9B,MAAI,CAAC,cAAc,EAAG;AACtB,QAAM,WAAW,MAAM,uBAAuB;AAM9C,MAAI,CAAC,cAAc,EAAG;AACtB,SAAO,EAAE,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ,EAAE,CAAC;AACtE;AAUO,SAAS,iBAAiB;AAC/B,OAAK,eAAe;AACpB,iBAAe;AACjB;AAaO,SAAS,qBACd,MACA,QACoB;AACpB,QAAM,MAA0B,CAAC;AACjC,aAAW,OAAO,MAAM;AACtB,QAAI;AACJ,QAAI;AACF,UAAI,IAAI,IAAI,OAAO,IAAI,SAAS,IAAI;AAAA,IACtC,QAAQ;AACN;AAAA,IACF;AACA,QAAI,EAAE,WAAW,OAAQ;AACzB,UAAM,KAAK,mBAAmB,EAAE,QAAQ;AACxC,QAAI,CAAC,GAAI;AACT,UAAM,QAAQ,EAAE,aAAa,IAAI,OAAO,KAAK;AAC7C,UAAM,QAAQ,EAAE,aAAa,IAAI,GAAG,KAAK;AACzC,QAAI,CAAC,SAAS,CAAC,MAAO;AACtB,QAAI,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAG;AAClC,QAAI,KAAK,EAAE,IAAI,OAAO,MAAM,CAAC;AAAA,EAC/B;AACA,SAAO;AACT;AASO,SAAS,qBAAyC;AACvD,QAAM,WACJ,OAKA,YAAY;AACd,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO,CAAC;AACtC,QAAM,MAA0B,CAAC;AACjC,aAAW,KAAK,UAAU;AACxB,UAAM,MAAM,GAAG,QAAQ,IAAI,KAAK;AAChC,UAAM,SAAS,GAAG,SAAS,IAAI,KAAK;AACpC,UAAM,SAAS,GAAG,SAAS,IAAI,KAAK;AACpC,QAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAO;AAC7B,QAAI,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAG;AAClC,QAAI,KAAK,EAAE,IAAI,OAAO,MAAM,CAAC;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,qBAAyC;AAChD,MAAI,CAAC,aAAc,QAAO,CAAC;AAC3B,QAAM,OAAO,MAAM,KAAK,SAAS,iBAAiB,QAAQ,CAAC,EAAE;AAAA,IAC3D,CAAC,MAAM,EAAE,aAAa,KAAK,KAAK;AAAA,EAClC;AACA,QAAM,UAAU,qBAAqB,MAAM,YAAY;AAIvD,QAAM,MAAM,CAAC,GAAG,OAAO;AACvB,aAAW,KAAK,mBAAmB,GAAG;AACpC,QAAI,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,EAAG,KAAI,KAAK,CAAC;AAAA,EACjD;AACA,SAAO;AACT;AAEA,SAAS,wBAAwB;AAC/B,SAAO,EAAE,MAAM,uBAAuB,QAAQ,mBAAmB,EAAE,CAAC;AACtE;AAWA,SAASC,eAA8B;AACrC,QAAM,IAAK,OAAyD,YAChE;AACJ,SAAO,MAAM,QAAQ,CAAC,IAAI,IAAI,CAAC;AACjC;AAEA,SAAS,iBAAiB;AACxB,MAAI,CAAC,cAAc,EAAG;AACtB,QAAM,UAAUA,aAAY;AAE5B,MAAI,QAAQ,OAAQ,QAAO,EAAE,MAAM,gBAAgB,QAAQ,CAAC;AAC9D;AAaO,SAAS,aAAa,MAAqB;AAChD,MAAI,OAAO,SAAS,YAAY,CAAC,KAAM;AACvC,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,MAAM,SAAS,IAAI;AAAA,EACtC,QAAQ;AACN;AAAA,EACF;AACA,MAAI,OAAO,aAAa,WAAW,OAAO,aAAa,SAAU;AACjE,MAAI,OAAO,WAAW,SAAS,OAAQ;AACvC,WAAS,OAAO,OAAO,IAAI;AAC7B;AAIA,SAAS,aAAa,GAAsC;AAK1D,MAAI,CAAC,WAAW,yBAAyB,CAAC,EAAG;AAC7C,WAAS,KAAK,EAAE,GAAG,GAAG,KAAK,EAAE,aAAa,IAAI,KAAK,IAAI,EAAE,CAAC;AAC1D,MAAI,SAAS,SAAS,aAAc,UAAS,MAAM;AACnD,SAAO,EAAE,MAAM,iBAAiB,QAAQ,CAAC,SAAS,SAAS,SAAS,CAAC,CAAC,EAAE,CAAC;AAC3E;AAkBA,SAAS,aAAa,IAAqB;AACzC,QAAM,OAAO,GAAG,aAAa,YAAY;AACzC,MAAI,KAAM,QAAO;AAEjB,QAAM,KAAK,GAAG;AACd,MAAI,IAAI;AACN,UAAM,WAAW,SAAS,cAAc,cAAc,IAAI,OAAO,EAAE,CAAC,IAAI;AACxE,UAAM,IAAI,UAAU,aAAa,KAAK;AACtC,QAAI,EAAG,QAAO;AAAA,EAChB;AACA,QAAM,WAAW,GAAG,QAAQ,OAAO,GAAG,aAAa,KAAK;AACxD,MAAI,SAAU,QAAO;AAErB,QAAM,cAAc,GAAG,aAAa,aAAa;AACjD,MAAI,YAAa,QAAO;AAExB,SAAO;AACT;AAEA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,SAAS,UAAU,UAAU,CAAC;AAE7D,SAAS,SAAS,IAAqB;AACrC,QAAM,OAAO,GAAG,aAAa,MAAM,KAAK,GAAG,QAAQ,YAAY;AAC/D,QAAM,QACJ,GAAG,aAAa,YAAY,MAC3B,cAAc,IAAI,GAAG,OAAO,IACzB,aAAa,EAAE,IACd,GAAmB,WAAW,KAAK,EAAE,MAAM,GAAG,EAAE,MACrD,GAAG,aAAa,OAAO,KACvB;AACF,SAAO,QAAQ,GAAG,IAAI,KAAK,OAAO,KAAK,CAAC,MAAM;AAChD;AAQA,IAAM,aACJ;AAIF,SAAS,QAAQ,IAAW;AAC1B,QAAM,SAAS,GAAG;AAClB,MAAI,CAAC,UAAU,EAAE,kBAAkB,SAAU;AAI7C,QAAM,QAAQ,OAAO,QAAQ,OAAO;AACpC,QAAM,WAAW,QACZ,MAAM,aAAa,KAAK,KACvB,SAAS,eAAe,MAAM,aAAa,KAAK,CAAE,KACpD,MAAM,cAAc,uBAAuB,IAC3C;AAEJ,QAAM,aAAa,YAAY,OAAO,QAAQ,UAAU;AAGxD,MAAI,CAAC,cAAc,UAAU,UAAU,EAAG;AAE1C,eAAa,EAAE,MAAM,SAAS,SAAS,WAAW,SAAS,UAAU,CAAC,GAAG,CAAC;AAC5E;AAEA,SAAS,SAAS,IAAW;AAC3B,QAAM,KAAK,GAAG;AACd,MAAI,CAAC,MAAM,UAAU,EAAE,EAAG;AAE1B,eAAa,EAAE,MAAM,UAAU,SAAS,aAAa,SAAS,EAAE,CAAC,GAAG,CAAC;AACvE;AAeA,SAAS,SAAS,IAAW;AAC3B,QAAM,KAAK,GAAG;AACd,MAAI,CAAC,MAAM,EAAE,cAAc,YAAY,UAAU,EAAE,EAAG;AAEtD,QAAM,MAAM,GAAG;AACf,QAAM,OAAQ,GAAwB;AAGtC,MAAI,QAAQ,YAAY,SAAS,cAAc,SAAS,UAAW;AAEnE,MAAI,UAAU,WAAW,SAAS,EAAE,CAAC;AAErC,MAAI,QAAQ,UAAU;AACpB,UAAM,MAAO,GAAyB,gBAAgB,CAAC,GAAG;AAC1D,QAAI,IAAK,WAAU,GAAG,SAAS,EAAE,CAAC,YAAO,OAAO,GAAG,CAAC;AAAA,EACtD,WAAW,SAAS,cAAc,SAAS,SAAS;AAClD,cAAU,GAAI,GAAwB,UAAU,YAAY,WAAW,IAAI,SAAS,EAAE,CAAC;AAAA,EACzF;AAEA,eAAa,EAAE,MAAM,SAAS,QAAQ,CAAC;AACzC;AAMA,SAAS,kBAAkB;AACzB,QAAM,OAAO,MAAM;AACjB,UAAM,MAAM,SAAS;AACrB,QAAI,QAAQ,QAAS;AACrB,cAAU;AACV,iBAAa,EAAE,MAAM,OAAO,SAAS,gBAAgB,GAAG,GAAG,CAAC;AAC5D,SAAK,eAAe;AACpB,0BAAsB;AAGtB,mBAAe;AAOf,iBAAa;AAAA,EACf;AAOA,MAAI,QAAS;AACb,YAAU;AAEV,aAAW,QAAQ,CAAC,aAAa,cAAc,GAAY;AACzD,UAAM,OAAO,QAAQ,IAAI;AACzB,QAAI,SAAS,YAAa,iBAAgB;AAAA,QACrC,oBAAmB;AACxB,YAAQ,IAAI,IAAI,YAEX,MACH;AACA,YAAM,IAAI,KAAK,MAAM,MAAM,IAAI;AAC/B,WAAK;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,iBAAiB,YAAY,IAAI;AAC1C;AAgBA,IAAI,YAA0B,CAAC;AAE/B,eAAe,YAAmC;AAChD,QAAM,QAAsB,CAAC;AAG7B,QAAM,MAAM,OAAO,eAAe;AAClC,MAAI,OAAO,CAAC,IAAI,aAAa;AAC3B,UAAM,SAAS,IAAI,YAAY,iBAAiB;AAGhD,QAAI,CAAC,UAAU,CAAC,OAAO,QAAQ,mBAAmB,GAAG;AACnD,YAAM,OAAO,IAAI,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG;AAC/C,UAAI,KAAM,OAAM,YAAY,OAAO,IAAI;AAAA,IACzC;AAAA,EACF;AAGA,QAAM,SAAS,SAAS;AACxB,MACE,UACA,WAAW,SAAS,QACpB,CAAC,UAAU,MAAM,KACjB,CAAC,OAAO,QAAQ,mBAAmB,GACnC;AACA,UAAM,EAAE,SAAS,IAAI,MAAM,mBAAmB;AAC9C,SAAK;AACL,UAAM,UAAU;AAAA,MACd,OAAO,OAAO,gBAAgB,MAAM,CAAC;AAAA,MACrC,MAAM,OAAO,aAAa,MAAM,KAAK,OAAO,QAAQ,YAAY;AAAA,IAClE;AAAA,EACF;AAEA,QAAM,MAAM,SAAS;AACrB,QAAM,aAAa,IAAI,eAAe,IAAI;AAC1C,QAAM,SACJ,aAAa,IAAI,KAAK,MAAO,IAAI,YAAY,aAAc,GAAG,IAAI,MAAM;AAE1E,SAAO;AACT;AAGA,SAAS,gBAAgB,IAAqB;AAC5C,SAAO,SAAS,EAAE;AACpB;AAKA,eAAe,qBAAqB;AAClC,QAAM,IAAI,MAAM,OAAO,wBAAgB;AACvC,mBAAiB;AACjB,SAAO;AACT;AAEA,IAAI,aAAmD;AAGvD,SAAS,gBAAgB;AACvB,MAAI,WAAY;AAChB,eAAa,WAAW,YAAY;AAClC,iBAAa;AACb,gBAAY,MAAM,UAAU;AAC5B,WAAO,EAAE,MAAM,cAAc,OAAO,UAAU,CAAC;AAAA,EACjD,GAAG,GAAG;AACR;AAIA,IAAI,cAAc;AAElB,eAAsB,aAAa,MAAY;AAE7C,MAAI,CAAC,WAAW,yBAAyB,CAAC,EAAG;AAM7C,QAAM,QAAQ,YAAY,MAAM,iBAAiB,CAAC;AAClD,MAAI,OAAO;AACT,UAAM,EAAE,KAAK,IAAI;AAAA,MACf,OAAO,WAAW,cAAc,SAAS;AAAA,IAC3C;AACA,UAAM,EAAE,MAAAC,OAAM,WAAAC,WAAU,IAAI,oBAAoB,OAAO,IAAI;AAC3D,SAAK;AAAA,MACH,MAAM;AAAA,MACN,UAAU,EAAE,MAAM,OAAOD,KAAI,GAAG,KAAK,EAAE,aAAa,WAAAC,WAAU;AAAA,IAChE,CAAC;AAID,gBAAY,EAAE,GAAG,WAAW,aAAa,CAAC,EAAE;AAC5C,SAAK,EAAE,MAAM,cAAc,OAAO,UAAU,CAAC;AAC7C;AAAA,EACF;AAIA,QAAM,EAAE,SAAS,IAAI,MAAM,mBAAmB;AAM9C,MAAI,CAAC,WAAW,yBAAyB,CAAC,EAAG;AAC7C,QAAM,EAAE,MAAM,WAAW,YAAY,IAAI,SAAS;AAClD,OAAK;AAAA,IACH,MAAM;AAAA,IACN,UAAU,EAAE,MAAM,OAAO,IAAI,GAAG,KAAK,EAAE,aAAa,UAAU;AAAA,EAChE,CAAC;AAGD,cAAY,EAAE,GAAG,WAAW,YAAY;AACxC,OAAK,EAAE,MAAM,cAAc,OAAO,UAAU,CAAC;AAC/C;AAMA,eAAsB,WAAW,KAAa,MAAY;AAExD,MAAI,CAAC,WAAW,yBAAyB,CAAC,EAAG;AAC7C,QAAM,EAAE,gBAAgB,WAAW,IAAI,MAAM,mBAAmB;AAGhE,MAAI,CAAC,WAAW,yBAAyB,CAAC,EAAG;AAC7C,QAAM,KAAK,WAAW,GAAG;AACzB,MAAI,CAAC,IAAI;AACP,SAAK;AAAA,MACH,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR,CAAC;AACD;AAAA,EACF;AACA,QAAM,EAAE,KAAK,IAAI,eAAe,EAAE;AAClC,OAAK,EAAE,MAAM,eAAe,KAAK,MAAM,OAAO,IAAI,EAAE,CAAC;AACvD;AAuBA,eAAsB,SAAS,MAAgB,MAAY;AACzD,QAAM,MAAM,OAAO,WAAW,cAAc,SAAS;AACrD,QAAM,MAAM,UAAU,KAAK,IAAI;AAC/B,QAAM,YAAY,KAAK,IAAI;AAC3B,gBAAc,KAAK;AAAA,IACjB,OAAO;AAAA,IACP,MAAM,KAAK;AAAA,IACX,WAAW;AAAA,IACX,MAAM,KAAK;AAAA,EACb,CAAC;AACD,QAAM,IAAI,MAAM,QAAQ,MAAM,GAAG;AACjC,gBAAc,KAAK;AAAA,IACjB,OAAO;AAAA,IACP,MAAM,KAAK;AAAA,IACX,WAAW;AAAA,IACX,IAAI,EAAE;AAAA,IACN,OAAO,EAAE;AAAA,IACT,IAAI,KAAK,IAAI,IAAI;AAAA,EACnB,CAAC;AACD,OAAK;AAAA,IACH,MAAM;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,IAAI,EAAE;AAAA,IACN,QAAQ,EAAE;AAAA,IACV,OAAO,EAAE;AAAA,EACX,CAAC;AACH;AAUA,SAAS,uBAA6B;AAEpC,WAAS,iBAAiB,SAAS,SAAS,EAAE,SAAS,MAAM,SAAS,KAAK,CAAC;AAC5E,WAAS,iBAAiB,UAAU,UAAU;AAAA,IAC5C,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAID,WAAS,iBAAiB,UAAU,UAAU;AAAA,IAC5C,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAID,WAAS,iBAAiB,mBAAmB,eAAe,EAAE,SAAS,KAAK,CAAC;AAC7E,WAAS,iBAAiB,WAAW,eAAe;AAAA,IAClD,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACD,SAAO,iBAAiB,UAAU,eAAe;AAAA,IAC/C,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACH;AAIA,SAAS,sBAA4B;AACnC,WAAS,oBAAoB,SAAS,SAAS,EAAE,SAAS,KAAK,CAAC;AAChE,WAAS,oBAAoB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;AAClE,WAAS,oBAAoB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;AAClE,WAAS,oBAAoB,mBAAmB,aAAa;AAC7D,WAAS,oBAAoB,WAAW,eAAe,EAAE,SAAS,KAAK,CAAC;AACxE,SAAO,oBAAoB,UAAU,eAAe,EAAE,SAAS,KAAK,CAAC;AAErE,MAAI,YAAY;AACd,iBAAa,UAAU;AACvB,iBAAa;AAAA,EACf;AACF;AAMA,SAAS,oBAA0B;AACjC,MAAI,SAAS;AACX,WAAO,oBAAoB,YAAY,OAAO;AAC9C,cAAU;AAAA,EACZ;AACA,MAAI,eAAe;AACjB,YAAQ,YAAY;AACpB,oBAAgB;AAAA,EAClB;AACA,MAAI,kBAAkB;AACpB,YAAQ,eAAe;AACvB,uBAAmB;AAAA,EACrB;AACF;AA+BO,SAAS,OAAa;AAC3B,sBAAoB;AACpB,oBAAkB;AAElB,SAAO;AACP,oBAAkB;AAClB,WAAS,SAAS;AAClB,cAAY,CAAC;AACb,iBAAe;AAMf,kBAAgB,UAAU;AAC5B;AAaO,SAAS,kBAAkB,KAAoB;AACpD,wBAAsB,qBAAqB,GAAG;AAC9C,mBAAiB;AACnB;AAUA,SAAS,mBAAyB;AAChC,QAAM,OAAO,yBAAyB;AAEtC,MAAI,WAAW,IAAI,GAAG;AACpB,yBAAqB;AAAA,EACvB,OAAO;AACL,wBAAoB;AAGpB,aAAS,SAAS;AAClB,gBAAY,CAAC;AAAA,EACf;AAEA,MAAI,eAAe,IAAI,GAAG;AACxB,oBAAgB;AAAA,EAClB,OAAO;AACL,sBAAkB;AAAA,EACpB;AACF;AAOO,SAAS,MACd,MACA,QACA,cAAyC,MACzC,UACA;AAIA,OAAK;AAEL,SAAO;AACP,iBAAe,UAAU;AACzB,YAAU,SAAS;AACnB,wBAAsB,qBAAqB,WAAW;AACtD,oBAAkB;AAElB,MAAI,eAAe,yBAAyB,CAAC,GAAG;AAC9C,SAAK,eAAe;AACpB,0BAAsB;AACtB,mBAAe;AAAA,EACjB;AAGA,mBAAiB;AAEjB,QAAM,QAAQ,WAAW,8BAA8B,EAAE,UACrD,SACA;AACJ,OAAK,EAAE,MAAM,cAAc,MAAM,MAAM,CAAC;AAGxC;AACE,UAAM,IAAI,OAAO,WAAW,cAAc,SAAS;AACnD,UAAM,QAAQ,UAAU,CAAC;AACzB,QAAI,MAAM,QAAQ;AAChB,WAAK,EAAE,MAAM,cAAc,MAAM,CAAC;AAClC,iBAAW,KAAK,OAAO;AACrB,sBAAc,GAAG;AAAA,UACf,OAAO;AAAA,UACP,MAAM,EAAE;AAAA,UACR,WAAW,UAAU,EAAE,IAAI;AAAA,QAC7B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,eAAe;AACtB,QAAM,MAAM,OAAO,WAAW,cAAc,SAAS;AACrD,QAAM,QAAQ,UAAU,GAAG;AAC3B,SAAO,EAAE,MAAM,cAAc,MAAM,CAAC;AACpC,aAAW,KAAK,OAAO;AACrB,kBAAc,KAAK;AAAA,MACjB,OAAO;AAAA,MACP,MAAM,EAAE;AAAA,MACR,WAAW,UAAU,EAAE,IAAI;AAAA,IAC7B,CAAC;AAAA,EACH;AACF;","names":["document","readSitemap","yaml","truncated"]}
|