@matterfact/embed 0.9.0 → 0.10.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 +119 -0
- package/dist/{chunk-URGQBG4I.js → chunk-4AE5WINC.js} +209 -17
- package/dist/chunk-4AE5WINC.js.map +1 -0
- package/dist/{chunk-6EM7T2JV.js → chunk-CFDPCZO3.js} +208 -15
- package/dist/chunk-CFDPCZO3.js.map +1 -0
- package/dist/{chunk-BKKXHSYU.js → chunk-DXLHTFB4.js} +2 -2
- package/dist/chunk-RL6VIGWK.js +2 -0
- package/dist/chunk-TWMHQF7O.js +3 -0
- package/dist/chunk-TWMHQF7O.js.map +7 -0
- package/dist/{context-U2HJJN2S.js → context-HOOW63MO.js} +4 -2
- package/dist/context-SSQ4HUP3.js +3 -0
- package/dist/{context-ACFBWIFH.js.map → context-SSQ4HUP3.js.map} +1 -1
- package/dist/embed.js +1 -1
- package/dist/embed.js.map +2 -2
- package/dist/index.cjs +214 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +260 -15
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +124 -1
- package/dist/react.d.ts +124 -1
- package/dist/react.js +46 -3
- package/dist/react.js.map +1 -1
- package/dist/{snapshot-Y75SCGCM.js → snapshot-CRY2IBX6.js} +3 -3
- package/dist/{snapshot-Y75SCGCM.js.map → snapshot-CRY2IBX6.js.map} +1 -1
- package/dist/{snapshot-4GXT6PKZ.js → snapshot-EYRXPLRC.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-6EM7T2JV.js.map +0 -1
- package/dist/chunk-FEXG4LQJ.js +0 -3
- package/dist/chunk-FEXG4LQJ.js.map +0 -7
- package/dist/chunk-NWNMS34P.js +0 -2
- package/dist/chunk-URGQBG4I.js.map +0 -1
- package/dist/context-ACFBWIFH.js +0 -3
- /package/dist/{chunk-BKKXHSYU.js.map → chunk-DXLHTFB4.js.map} +0 -0
- /package/dist/{chunk-NWNMS34P.js.map → chunk-RL6VIGWK.js.map} +0 -0
- /package/dist/{context-U2HJJN2S.js.map → context-HOOW63MO.js.map} +0 -0
- /package/dist/{snapshot-4GXT6PKZ.js.map → snapshot-EYRXPLRC.js.map} +0 -0
package/dist/react.cjs
CHANGED
|
@@ -417,6 +417,156 @@ var init_hoist_runtime = __esm({
|
|
|
417
417
|
}
|
|
418
418
|
});
|
|
419
419
|
|
|
420
|
+
// src/adapters/registry.ts
|
|
421
|
+
function mfGlobal(win) {
|
|
422
|
+
return win?.matterfact ?? {};
|
|
423
|
+
}
|
|
424
|
+
function toolClass(name) {
|
|
425
|
+
if (name.startsWith("hoist.")) return "hoist";
|
|
426
|
+
if (name.startsWith("mf.")) return "mf";
|
|
427
|
+
return "app";
|
|
428
|
+
}
|
|
429
|
+
function emitToolEvent(win, e) {
|
|
430
|
+
const cb = mfGlobal(win).onToolEvent;
|
|
431
|
+
if (typeof cb !== "function") return;
|
|
432
|
+
try {
|
|
433
|
+
cb(e);
|
|
434
|
+
} catch {
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function mfTools(win) {
|
|
438
|
+
const { document: document2, artifact } = mfGlobal(win).resolve ?? {};
|
|
439
|
+
const out = [];
|
|
440
|
+
if (typeof document2 === "function") {
|
|
441
|
+
out.push({
|
|
442
|
+
name: "mf.resolveDocument",
|
|
443
|
+
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 a key (e.g. a ticker) when the site map shows the document lives on another route. 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.',
|
|
444
|
+
inputSchema: {
|
|
445
|
+
type: "object",
|
|
446
|
+
properties: {
|
|
447
|
+
doctype: { type: "string" },
|
|
448
|
+
key: { type: "string" }
|
|
449
|
+
},
|
|
450
|
+
required: ["doctype", "key"]
|
|
451
|
+
},
|
|
452
|
+
readOnly: true,
|
|
453
|
+
confirm: "auto"
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
if (typeof artifact === "function") {
|
|
457
|
+
out.push({
|
|
458
|
+
name: "mf.resolveArtifact",
|
|
459
|
+
description: 'Resolve a matterfact artifact (an interactive board) that is NOT co-embedded on the current page to a read grant. Call it with the artifact slug. Returns {id, owner, token, label}; the grant is applied for you. Cite the result inline as <MFRef kind="artifact" id="<id>" label="<label>" /> \u2014 it renders as a chip that opens the artifact in the side panel.',
|
|
460
|
+
inputSchema: {
|
|
461
|
+
type: "object",
|
|
462
|
+
properties: { slug: { type: "string" } },
|
|
463
|
+
required: ["slug"]
|
|
464
|
+
},
|
|
465
|
+
readOnly: true,
|
|
466
|
+
confirm: "auto"
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
return out;
|
|
470
|
+
}
|
|
471
|
+
function appName(name) {
|
|
472
|
+
return name.startsWith("app.") ? name : `app.${name}`;
|
|
473
|
+
}
|
|
474
|
+
function appTools(win) {
|
|
475
|
+
const defs = mfGlobal(win).tools;
|
|
476
|
+
if (!Array.isArray(defs)) return [];
|
|
477
|
+
const out = [];
|
|
478
|
+
for (const d of defs) {
|
|
479
|
+
const raw = (d?.name ?? "").trim();
|
|
480
|
+
if (!raw || typeof d.handler !== "function") continue;
|
|
481
|
+
const name = appName(raw);
|
|
482
|
+
if (!APP_NAME_RE.test(name)) continue;
|
|
483
|
+
out.push({
|
|
484
|
+
name,
|
|
485
|
+
description: String(d.description ?? `Run the host tool ${name}.`),
|
|
486
|
+
inputSchema: d.inputSchema ?? { type: "object", properties: {} },
|
|
487
|
+
readOnly: false,
|
|
488
|
+
confirm: d.confirm === "auto" ? "auto" : "required"
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
return out;
|
|
492
|
+
}
|
|
493
|
+
function advertise(win = typeof window !== "undefined" ? window : void 0) {
|
|
494
|
+
const merged = [];
|
|
495
|
+
const seen = /* @__PURE__ */ new Set();
|
|
496
|
+
const push = (tools) => {
|
|
497
|
+
for (const t of tools) {
|
|
498
|
+
if (seen.has(t.name)) continue;
|
|
499
|
+
seen.add(t.name);
|
|
500
|
+
merged.push(t);
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
try {
|
|
504
|
+
push(advertiseTools(win));
|
|
505
|
+
} catch {
|
|
506
|
+
}
|
|
507
|
+
try {
|
|
508
|
+
push(mfTools(win));
|
|
509
|
+
push(appTools(win));
|
|
510
|
+
} catch {
|
|
511
|
+
}
|
|
512
|
+
return merged.slice(0, MAX_TOOLS);
|
|
513
|
+
}
|
|
514
|
+
function timeout(ms) {
|
|
515
|
+
return new Promise(
|
|
516
|
+
(_, reject) => setTimeout(() => reject(new Error("host tool timed out")), ms)
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
function redactResult(value) {
|
|
520
|
+
if (value === void 0 || value === null) return value;
|
|
521
|
+
if (typeof value === "string") return redact(value);
|
|
522
|
+
try {
|
|
523
|
+
return JSON.parse(redact(JSON.stringify(value)));
|
|
524
|
+
} catch {
|
|
525
|
+
return redact(String(value));
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
async function execute(call, win = typeof window !== "undefined" ? window : void 0) {
|
|
529
|
+
const cls = toolClass(call.name);
|
|
530
|
+
try {
|
|
531
|
+
if (cls === "hoist") {
|
|
532
|
+
return executeHostTool(call, win);
|
|
533
|
+
}
|
|
534
|
+
const handler = resolveHandler(win, call.name);
|
|
535
|
+
if (!handler) return { ok: false, error: "unknown tool" };
|
|
536
|
+
const result = await Promise.race([
|
|
537
|
+
Promise.resolve(handler(call.args ?? {})),
|
|
538
|
+
timeout(HOST_HANDLER_TIMEOUT_MS)
|
|
539
|
+
]);
|
|
540
|
+
return { ok: true, result: redactResult(result) };
|
|
541
|
+
} catch (e) {
|
|
542
|
+
return {
|
|
543
|
+
ok: false,
|
|
544
|
+
error: redact(e instanceof Error ? e.message : "host tool failed")
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
function resolveHandler(win, name) {
|
|
549
|
+
const mf = mfGlobal(win);
|
|
550
|
+
if (name === "mf.resolveDocument") return mf.resolve?.document;
|
|
551
|
+
if (name === "mf.resolveArtifact") return mf.resolve?.artifact;
|
|
552
|
+
if (name.startsWith("app.")) {
|
|
553
|
+
const def = (mf.tools ?? []).find((d) => appName((d?.name ?? "").trim()) === name);
|
|
554
|
+
return def?.handler;
|
|
555
|
+
}
|
|
556
|
+
return void 0;
|
|
557
|
+
}
|
|
558
|
+
var MAX_TOOLS, HOST_HANDLER_TIMEOUT_MS, APP_NAME_RE;
|
|
559
|
+
var init_registry = __esm({
|
|
560
|
+
"src/adapters/registry.ts"() {
|
|
561
|
+
"use strict";
|
|
562
|
+
init_redact();
|
|
563
|
+
init_hoist_runtime();
|
|
564
|
+
MAX_TOOLS = 16;
|
|
565
|
+
HOST_HANDLER_TIMEOUT_MS = 3e4;
|
|
566
|
+
APP_NAME_RE = /^[A-Za-z0-9._-]+$/;
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
|
|
420
570
|
// src/dom/a11y.ts
|
|
421
571
|
function createStyleCache() {
|
|
422
572
|
const cache = /* @__PURE__ */ new WeakMap();
|
|
@@ -900,6 +1050,7 @@ __export(context_exports, {
|
|
|
900
1050
|
isPrivate: () => isPrivate,
|
|
901
1051
|
navigateHost: () => navigateHost,
|
|
902
1052
|
provideContext: () => provideContext,
|
|
1053
|
+
readDeclaredGrants: () => readDeclaredGrants,
|
|
903
1054
|
readPageContext: () => readPageContext,
|
|
904
1055
|
redact: () => redact,
|
|
905
1056
|
sendRegion: () => sendRegion,
|
|
@@ -1021,12 +1172,31 @@ function grantsFromIframeSrcs(srcs, origin) {
|
|
|
1021
1172
|
}
|
|
1022
1173
|
return out;
|
|
1023
1174
|
}
|
|
1175
|
+
function readDeclaredGrants() {
|
|
1176
|
+
const declared = window.matterfact?.artifacts;
|
|
1177
|
+
if (!Array.isArray(declared)) return [];
|
|
1178
|
+
const out = [];
|
|
1179
|
+
for (const a of declared) {
|
|
1180
|
+
const id = (a?.slug || "").trim();
|
|
1181
|
+
const owner = (a?.owner || "").trim();
|
|
1182
|
+
const token = (a?.token || "").trim();
|
|
1183
|
+
if (!id || !owner || !token) continue;
|
|
1184
|
+
if (out.some((g) => g.id === id)) continue;
|
|
1185
|
+
out.push({ id, owner, token });
|
|
1186
|
+
}
|
|
1187
|
+
return out;
|
|
1188
|
+
}
|
|
1024
1189
|
function readArtifactGrants() {
|
|
1025
1190
|
if (!widgetOrigin) return [];
|
|
1026
1191
|
const srcs = Array.from(document.querySelectorAll("iframe")).map(
|
|
1027
1192
|
(f) => f.getAttribute("src") || ""
|
|
1028
1193
|
);
|
|
1029
|
-
|
|
1194
|
+
const scanned = grantsFromIframeSrcs(srcs, widgetOrigin);
|
|
1195
|
+
const out = [...scanned];
|
|
1196
|
+
for (const g of readDeclaredGrants()) {
|
|
1197
|
+
if (!out.some((s) => s.id === g.id)) out.push(g);
|
|
1198
|
+
}
|
|
1199
|
+
return out;
|
|
1030
1200
|
}
|
|
1031
1201
|
function publishArtifactGrants() {
|
|
1032
1202
|
send?.({ type: "host.artifactGrants", grants: readArtifactGrants() });
|
|
@@ -1115,10 +1285,7 @@ function watchNavigation() {
|
|
|
1115
1285
|
void publishContext();
|
|
1116
1286
|
publishArtifactGrants();
|
|
1117
1287
|
publishSitemap();
|
|
1118
|
-
|
|
1119
|
-
type: "host.tools",
|
|
1120
|
-
tools: advertiseTools(typeof window !== "undefined" ? window : void 0)
|
|
1121
|
-
});
|
|
1288
|
+
publishTools();
|
|
1122
1289
|
};
|
|
1123
1290
|
navFire = fire;
|
|
1124
1291
|
for (const name of ["pushState", "replaceState"]) {
|
|
@@ -1223,10 +1390,24 @@ async function callTool(call, emit) {
|
|
|
1223
1390
|
});
|
|
1224
1391
|
return;
|
|
1225
1392
|
}
|
|
1226
|
-
const
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1393
|
+
const win = typeof window !== "undefined" ? window : void 0;
|
|
1394
|
+
const cls = toolClass(call.name);
|
|
1395
|
+
const startedAt = Date.now();
|
|
1396
|
+
emitToolEvent(win, {
|
|
1397
|
+
phase: "call",
|
|
1398
|
+
name: call.name,
|
|
1399
|
+
toolClass: cls,
|
|
1400
|
+
args: call.args
|
|
1401
|
+
});
|
|
1402
|
+
const r = await execute(call, win);
|
|
1403
|
+
emitToolEvent(win, {
|
|
1404
|
+
phase: "result",
|
|
1405
|
+
name: call.name,
|
|
1406
|
+
toolClass: cls,
|
|
1407
|
+
ok: r.ok,
|
|
1408
|
+
error: r.error,
|
|
1409
|
+
ms: Date.now() - startedAt
|
|
1410
|
+
});
|
|
1230
1411
|
emit({
|
|
1231
1412
|
type: "host.toolResult",
|
|
1232
1413
|
callId: call.callId,
|
|
@@ -1304,10 +1485,30 @@ function start(emit, origin, pageContext = true, provider) {
|
|
|
1304
1485
|
const theme = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
1305
1486
|
emit({ type: "host.theme", mode: theme });
|
|
1306
1487
|
if (pageContextOn) {
|
|
1307
|
-
const
|
|
1308
|
-
|
|
1309
|
-
)
|
|
1310
|
-
|
|
1488
|
+
const w = typeof window !== "undefined" ? window : void 0;
|
|
1489
|
+
const tools = advertise(w);
|
|
1490
|
+
if (tools.length) {
|
|
1491
|
+
emit({ type: "host.tools", tools });
|
|
1492
|
+
for (const t of tools) {
|
|
1493
|
+
emitToolEvent(w, {
|
|
1494
|
+
phase: "advertise",
|
|
1495
|
+
name: t.name,
|
|
1496
|
+
toolClass: toolClass(t.name)
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
function publishTools() {
|
|
1503
|
+
const win = typeof window !== "undefined" ? window : void 0;
|
|
1504
|
+
const tools = advertise(win);
|
|
1505
|
+
send?.({ type: "host.tools", tools });
|
|
1506
|
+
for (const t of tools) {
|
|
1507
|
+
emitToolEvent(win, {
|
|
1508
|
+
phase: "advertise",
|
|
1509
|
+
name: t.name,
|
|
1510
|
+
toolClass: toolClass(t.name)
|
|
1511
|
+
});
|
|
1311
1512
|
}
|
|
1312
1513
|
}
|
|
1313
1514
|
var widgetOrigin, MAX_ACTIVITY, send, activitySeq, activity, lastUrl, pageContextOn, contextProvider, navFire, origPushState, origReplaceState, snapshotModule, FORM_CONTROLS, ACTIONABLE, lastFocus, focusTimer, snapshotSeq;
|
|
@@ -1317,6 +1518,7 @@ var init_context = __esm({
|
|
|
1317
1518
|
init_redact();
|
|
1318
1519
|
init_hoist();
|
|
1319
1520
|
init_hoist_runtime();
|
|
1521
|
+
init_registry();
|
|
1320
1522
|
init_redact();
|
|
1321
1523
|
widgetOrigin = "";
|
|
1322
1524
|
MAX_ACTIVITY = 40;
|
|
@@ -2089,6 +2291,36 @@ function writeSitemapGlobal(sitemap) {
|
|
|
2089
2291
|
const w = window;
|
|
2090
2292
|
(w.matterfact ?? (w.matterfact = {})).sitemap = sitemap;
|
|
2091
2293
|
}
|
|
2294
|
+
function writeToolGlobals(artifacts, resolve, tools, onToolEvent) {
|
|
2295
|
+
if (typeof window === "undefined") return;
|
|
2296
|
+
const mf = window.matterfact ?? (window.matterfact = {});
|
|
2297
|
+
mf.artifacts = artifacts ?? [];
|
|
2298
|
+
mf.resolve = resolve ?? {};
|
|
2299
|
+
mf.tools = tools ?? [];
|
|
2300
|
+
mf.onToolEvent = onToolEvent;
|
|
2301
|
+
}
|
|
2302
|
+
function toolDescriptorKey(artifacts, resolve, tools) {
|
|
2303
|
+
return JSON.stringify({
|
|
2304
|
+
// Artifact identity is data (slug/owner/label), not a function.
|
|
2305
|
+
artifacts: (artifacts ?? []).map((a) => ({
|
|
2306
|
+
slug: a.slug,
|
|
2307
|
+
owner: a.owner,
|
|
2308
|
+
label: a.label
|
|
2309
|
+
})),
|
|
2310
|
+
// For resolvers, only WHICH contracts are present changes the advertised set.
|
|
2311
|
+
resolve: {
|
|
2312
|
+
document: typeof resolve?.document === "function",
|
|
2313
|
+
artifact: typeof resolve?.artifact === "function"
|
|
2314
|
+
},
|
|
2315
|
+
// For host tools, the advertised descriptor — never the handler.
|
|
2316
|
+
tools: (tools ?? []).map((t) => ({
|
|
2317
|
+
name: t.name,
|
|
2318
|
+
description: t.description,
|
|
2319
|
+
inputSchema: t.inputSchema,
|
|
2320
|
+
confirm: t.confirm
|
|
2321
|
+
}))
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2092
2324
|
function MatterfactAgent({
|
|
2093
2325
|
publishableKey,
|
|
2094
2326
|
widgetOrigin: widgetOrigin2,
|
|
@@ -2102,7 +2334,11 @@ function MatterfactAgent({
|
|
|
2102
2334
|
pageContext,
|
|
2103
2335
|
dev,
|
|
2104
2336
|
actions,
|
|
2105
|
-
sitemap
|
|
2337
|
+
sitemap,
|
|
2338
|
+
artifacts,
|
|
2339
|
+
resolve,
|
|
2340
|
+
tools,
|
|
2341
|
+
onToolEvent
|
|
2106
2342
|
}) {
|
|
2107
2343
|
const authRef = (0, import_react.useRef)(getAuthToken);
|
|
2108
2344
|
authRef.current = getAuthToken;
|
|
@@ -2116,10 +2352,15 @@ function MatterfactAgent({
|
|
|
2116
2352
|
(0, import_react.useEffect)(() => {
|
|
2117
2353
|
writeSitemapGlobal(sitemap);
|
|
2118
2354
|
}, [sitemapKey]);
|
|
2355
|
+
(0, import_react.useEffect)(() => {
|
|
2356
|
+
writeToolGlobals(artifacts, resolve, tools, onToolEvent);
|
|
2357
|
+
});
|
|
2358
|
+
const toolsKey = toolDescriptorKey(artifacts, resolve, tools);
|
|
2119
2359
|
(0, import_react.useEffect)(() => {
|
|
2120
2360
|
if (typeof window === "undefined") return;
|
|
2121
2361
|
if (inline && !slot.current) return;
|
|
2122
2362
|
writeActionsGlobal(actionsRef.current);
|
|
2363
|
+
writeToolGlobals(artifacts, resolve, tools, onToolEvent);
|
|
2123
2364
|
const config = {
|
|
2124
2365
|
publishableKey,
|
|
2125
2366
|
origin: widgetOrigin2 || DEFAULT_ORIGIN,
|
|
@@ -2150,7 +2391,11 @@ function MatterfactAgent({
|
|
|
2150
2391
|
inline,
|
|
2151
2392
|
pageContext,
|
|
2152
2393
|
dev,
|
|
2153
|
-
actionsKey
|
|
2394
|
+
actionsKey,
|
|
2395
|
+
// A change to the advertised tool SHAPE remounts so start() re-advertises under it;
|
|
2396
|
+
// a change to only a handler body or callback identity does not (see toolDescriptorKey).
|
|
2397
|
+
toolsKey
|
|
2398
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2154
2399
|
]);
|
|
2155
2400
|
if (!inline) return null;
|
|
2156
2401
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|