@matterfact/embed 0.9.0 → 0.11.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 +122 -0
- package/dist/{chunk-6EM7T2JV.js → chunk-AANODHBV.js} +217 -15
- package/dist/chunk-AANODHBV.js.map +1 -0
- package/dist/{chunk-URGQBG4I.js → chunk-CTZEDOH7.js} +218 -17
- package/dist/chunk-CTZEDOH7.js.map +1 -0
- package/dist/{chunk-BKKXHSYU.js → chunk-JO3GWFMJ.js} +2 -2
- package/dist/chunk-SKJFF7RD.js +2 -0
- package/dist/chunk-Y7I25VHL.js +3 -0
- package/dist/chunk-Y7I25VHL.js.map +7 -0
- package/dist/context-FR7VFENN.js +3 -0
- package/dist/{context-ACFBWIFH.js.map → context-FR7VFENN.js.map} +1 -1
- package/dist/{context-U2HJJN2S.js → context-IK5MECUW.js} +4 -2
- package/dist/embed.js +1 -1
- package/dist/embed.js.map +3 -3
- package/dist/index.cjs +247 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -1
- package/dist/index.d.ts +88 -1
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +302 -15
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +174 -2
- package/dist/react.d.ts +174 -2
- package/dist/react.js +79 -3
- package/dist/react.js.map +1 -1
- package/dist/{snapshot-4GXT6PKZ.js → snapshot-2V5SDSH2.js} +2 -2
- package/dist/{snapshot-Y75SCGCM.js → snapshot-Y5BF2UJR.js} +3 -3
- package/dist/{snapshot-Y75SCGCM.js.map → snapshot-Y5BF2UJR.js.map} +1 -1
- package/examples/embed-demo/README.md +22 -0
- package/examples/embed-demo/src/App.tsx +105 -2
- package/examples/embed-demo/src/styles.css +29 -0
- 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-JO3GWFMJ.js.map} +0 -0
- /package/dist/{chunk-NWNMS34P.js.map → chunk-SKJFF7RD.js.map} +0 -0
- /package/dist/{context-U2HJJN2S.js.map → context-IK5MECUW.js.map} +0 -0
- /package/dist/{snapshot-4GXT6PKZ.js.map → snapshot-2V5SDSH2.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -403,6 +403,164 @@ var init_hoist_runtime = __esm({
|
|
|
403
403
|
init_redact();
|
|
404
404
|
}
|
|
405
405
|
});
|
|
406
|
+
|
|
407
|
+
// src/adapters/registry.ts
|
|
408
|
+
function mfGlobal(win) {
|
|
409
|
+
return win?.matterfact ?? {};
|
|
410
|
+
}
|
|
411
|
+
function toolClass(name) {
|
|
412
|
+
if (name.startsWith("hoist.")) return "hoist";
|
|
413
|
+
if (name.startsWith("mf.")) return "mf";
|
|
414
|
+
return "app";
|
|
415
|
+
}
|
|
416
|
+
function emitEvent(win, e) {
|
|
417
|
+
const cb = mfGlobal(win).onEvent;
|
|
418
|
+
if (typeof cb !== "function") return;
|
|
419
|
+
try {
|
|
420
|
+
cb(e);
|
|
421
|
+
} catch {
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
function emitToolEvent(win, e) {
|
|
425
|
+
emitEvent(win, { type: "tool", ...e });
|
|
426
|
+
const cb = mfGlobal(win).onToolEvent;
|
|
427
|
+
if (typeof cb !== "function") return;
|
|
428
|
+
try {
|
|
429
|
+
cb(e);
|
|
430
|
+
} catch {
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function mfTools(win) {
|
|
434
|
+
const { document: document2, artifact } = mfGlobal(win).resolve ?? {};
|
|
435
|
+
const out = [];
|
|
436
|
+
if (typeof document2 === "function") {
|
|
437
|
+
out.push({
|
|
438
|
+
name: "mf.resolveDocument",
|
|
439
|
+
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.',
|
|
440
|
+
inputSchema: {
|
|
441
|
+
type: "object",
|
|
442
|
+
properties: {
|
|
443
|
+
doctype: { type: "string" },
|
|
444
|
+
key: { type: "string" }
|
|
445
|
+
},
|
|
446
|
+
required: ["doctype", "key"]
|
|
447
|
+
},
|
|
448
|
+
readOnly: true,
|
|
449
|
+
confirm: "auto"
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
if (typeof artifact === "function") {
|
|
453
|
+
out.push({
|
|
454
|
+
name: "mf.resolveArtifact",
|
|
455
|
+
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.',
|
|
456
|
+
inputSchema: {
|
|
457
|
+
type: "object",
|
|
458
|
+
properties: { slug: { type: "string" } },
|
|
459
|
+
required: ["slug"]
|
|
460
|
+
},
|
|
461
|
+
readOnly: true,
|
|
462
|
+
confirm: "auto"
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
return out;
|
|
466
|
+
}
|
|
467
|
+
function appName(name) {
|
|
468
|
+
return name.startsWith("app.") ? name : `app.${name}`;
|
|
469
|
+
}
|
|
470
|
+
function appTools(win) {
|
|
471
|
+
const defs = mfGlobal(win).tools;
|
|
472
|
+
if (!Array.isArray(defs)) return [];
|
|
473
|
+
const out = [];
|
|
474
|
+
for (const d of defs) {
|
|
475
|
+
const raw = (d?.name ?? "").trim();
|
|
476
|
+
if (!raw || typeof d.handler !== "function") continue;
|
|
477
|
+
const name = appName(raw);
|
|
478
|
+
if (!APP_NAME_RE.test(name)) continue;
|
|
479
|
+
out.push({
|
|
480
|
+
name,
|
|
481
|
+
description: String(d.description ?? `Run the host tool ${name}.`),
|
|
482
|
+
inputSchema: d.inputSchema ?? { type: "object", properties: {} },
|
|
483
|
+
readOnly: false,
|
|
484
|
+
confirm: d.confirm === "auto" ? "auto" : "required"
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
return out;
|
|
488
|
+
}
|
|
489
|
+
function advertise(win = typeof window !== "undefined" ? window : void 0) {
|
|
490
|
+
const merged = [];
|
|
491
|
+
const seen = /* @__PURE__ */ new Set();
|
|
492
|
+
const push = (tools) => {
|
|
493
|
+
for (const t of tools) {
|
|
494
|
+
if (seen.has(t.name)) continue;
|
|
495
|
+
seen.add(t.name);
|
|
496
|
+
merged.push(t);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
try {
|
|
500
|
+
push(advertiseTools(win));
|
|
501
|
+
} catch {
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
push(mfTools(win));
|
|
505
|
+
push(appTools(win));
|
|
506
|
+
} catch {
|
|
507
|
+
}
|
|
508
|
+
return merged.slice(0, MAX_TOOLS);
|
|
509
|
+
}
|
|
510
|
+
function timeout(ms) {
|
|
511
|
+
return new Promise(
|
|
512
|
+
(_, reject) => setTimeout(() => reject(new Error("host tool timed out")), ms)
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
function redactResult(value) {
|
|
516
|
+
if (value === void 0 || value === null) return value;
|
|
517
|
+
if (typeof value === "string") return redact(value);
|
|
518
|
+
try {
|
|
519
|
+
return JSON.parse(redact(JSON.stringify(value)));
|
|
520
|
+
} catch {
|
|
521
|
+
return redact(String(value));
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
async function execute(call, win = typeof window !== "undefined" ? window : void 0) {
|
|
525
|
+
const cls = toolClass(call.name);
|
|
526
|
+
try {
|
|
527
|
+
if (cls === "hoist") {
|
|
528
|
+
return executeHostTool(call, win);
|
|
529
|
+
}
|
|
530
|
+
const handler = resolveHandler(win, call.name);
|
|
531
|
+
if (!handler) return { ok: false, error: "unknown tool" };
|
|
532
|
+
const result = await Promise.race([
|
|
533
|
+
Promise.resolve(handler(call.args ?? {})),
|
|
534
|
+
timeout(HOST_HANDLER_TIMEOUT_MS)
|
|
535
|
+
]);
|
|
536
|
+
return { ok: true, result: redactResult(result) };
|
|
537
|
+
} catch (e) {
|
|
538
|
+
return {
|
|
539
|
+
ok: false,
|
|
540
|
+
error: redact(e instanceof Error ? e.message : "host tool failed")
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
function resolveHandler(win, name) {
|
|
545
|
+
const mf = mfGlobal(win);
|
|
546
|
+
if (name === "mf.resolveDocument") return mf.resolve?.document;
|
|
547
|
+
if (name === "mf.resolveArtifact") return mf.resolve?.artifact;
|
|
548
|
+
if (name.startsWith("app.")) {
|
|
549
|
+
const def = (mf.tools ?? []).find((d) => appName((d?.name ?? "").trim()) === name);
|
|
550
|
+
return def?.handler;
|
|
551
|
+
}
|
|
552
|
+
return void 0;
|
|
553
|
+
}
|
|
554
|
+
var MAX_TOOLS, HOST_HANDLER_TIMEOUT_MS, APP_NAME_RE;
|
|
555
|
+
var init_registry = __esm({
|
|
556
|
+
"src/adapters/registry.ts"() {
|
|
557
|
+
init_redact();
|
|
558
|
+
init_hoist_runtime();
|
|
559
|
+
MAX_TOOLS = 16;
|
|
560
|
+
HOST_HANDLER_TIMEOUT_MS = 3e4;
|
|
561
|
+
APP_NAME_RE = /^[A-Za-z0-9._-]+$/;
|
|
562
|
+
}
|
|
563
|
+
});
|
|
406
564
|
function createStyleCache() {
|
|
407
565
|
const cache = /* @__PURE__ */ new WeakMap();
|
|
408
566
|
return ((el, pseudo) => {
|
|
@@ -880,6 +1038,7 @@ __export(context_exports, {
|
|
|
880
1038
|
isPrivate: () => isPrivate,
|
|
881
1039
|
navigateHost: () => navigateHost,
|
|
882
1040
|
provideContext: () => provideContext,
|
|
1041
|
+
readDeclaredGrants: () => readDeclaredGrants,
|
|
883
1042
|
readPageContext: () => readPageContext,
|
|
884
1043
|
redact: () => redact,
|
|
885
1044
|
sendRegion: () => sendRegion,
|
|
@@ -1001,12 +1160,31 @@ function grantsFromIframeSrcs(srcs, origin) {
|
|
|
1001
1160
|
}
|
|
1002
1161
|
return out;
|
|
1003
1162
|
}
|
|
1163
|
+
function readDeclaredGrants() {
|
|
1164
|
+
const declared = window.matterfact?.artifacts;
|
|
1165
|
+
if (!Array.isArray(declared)) return [];
|
|
1166
|
+
const out = [];
|
|
1167
|
+
for (const a of declared) {
|
|
1168
|
+
const id = (a?.slug || "").trim();
|
|
1169
|
+
const owner = (a?.owner || "").trim();
|
|
1170
|
+
const token = (a?.token || "").trim();
|
|
1171
|
+
if (!id || !owner || !token) continue;
|
|
1172
|
+
if (out.some((g) => g.id === id)) continue;
|
|
1173
|
+
out.push({ id, owner, token });
|
|
1174
|
+
}
|
|
1175
|
+
return out;
|
|
1176
|
+
}
|
|
1004
1177
|
function readArtifactGrants() {
|
|
1005
1178
|
if (!widgetOrigin) return [];
|
|
1006
1179
|
const srcs = Array.from(document.querySelectorAll("iframe")).map(
|
|
1007
1180
|
(f) => f.getAttribute("src") || ""
|
|
1008
1181
|
);
|
|
1009
|
-
|
|
1182
|
+
const scanned = grantsFromIframeSrcs(srcs, widgetOrigin);
|
|
1183
|
+
const out = [...scanned];
|
|
1184
|
+
for (const g of readDeclaredGrants()) {
|
|
1185
|
+
if (!out.some((s) => s.id === g.id)) out.push(g);
|
|
1186
|
+
}
|
|
1187
|
+
return out;
|
|
1010
1188
|
}
|
|
1011
1189
|
function publishArtifactGrants() {
|
|
1012
1190
|
send?.({ type: "host.artifactGrants", grants: readArtifactGrants() });
|
|
@@ -1095,10 +1273,7 @@ function watchNavigation() {
|
|
|
1095
1273
|
void publishContext();
|
|
1096
1274
|
publishArtifactGrants();
|
|
1097
1275
|
publishSitemap();
|
|
1098
|
-
|
|
1099
|
-
type: "host.tools",
|
|
1100
|
-
tools: advertiseTools(typeof window !== "undefined" ? window : void 0)
|
|
1101
|
-
});
|
|
1276
|
+
publishTools();
|
|
1102
1277
|
};
|
|
1103
1278
|
navFire = fire;
|
|
1104
1279
|
for (const name of ["pushState", "replaceState"]) {
|
|
@@ -1202,10 +1377,24 @@ async function callTool(call, emit) {
|
|
|
1202
1377
|
});
|
|
1203
1378
|
return;
|
|
1204
1379
|
}
|
|
1205
|
-
const
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1380
|
+
const win = typeof window !== "undefined" ? window : void 0;
|
|
1381
|
+
const cls = toolClass(call.name);
|
|
1382
|
+
const startedAt = Date.now();
|
|
1383
|
+
emitToolEvent(win, {
|
|
1384
|
+
phase: "call",
|
|
1385
|
+
name: call.name,
|
|
1386
|
+
toolClass: cls,
|
|
1387
|
+
args: call.args
|
|
1388
|
+
});
|
|
1389
|
+
const r = await execute(call, win);
|
|
1390
|
+
emitToolEvent(win, {
|
|
1391
|
+
phase: "result",
|
|
1392
|
+
name: call.name,
|
|
1393
|
+
toolClass: cls,
|
|
1394
|
+
ok: r.ok,
|
|
1395
|
+
error: r.error,
|
|
1396
|
+
ms: Date.now() - startedAt
|
|
1397
|
+
});
|
|
1209
1398
|
emit({
|
|
1210
1399
|
type: "host.toolResult",
|
|
1211
1400
|
callId: call.callId,
|
|
@@ -1283,10 +1472,30 @@ function start(emit, origin, pageContext = true, provider) {
|
|
|
1283
1472
|
const theme = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
1284
1473
|
emit({ type: "host.theme", mode: theme });
|
|
1285
1474
|
if (pageContextOn) {
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
)
|
|
1289
|
-
|
|
1475
|
+
const w = typeof window !== "undefined" ? window : void 0;
|
|
1476
|
+
const tools = advertise(w);
|
|
1477
|
+
if (tools.length) {
|
|
1478
|
+
emit({ type: "host.tools", tools });
|
|
1479
|
+
for (const t of tools) {
|
|
1480
|
+
emitToolEvent(w, {
|
|
1481
|
+
phase: "advertise",
|
|
1482
|
+
name: t.name,
|
|
1483
|
+
toolClass: toolClass(t.name)
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
function publishTools() {
|
|
1490
|
+
const win = typeof window !== "undefined" ? window : void 0;
|
|
1491
|
+
const tools = advertise(win);
|
|
1492
|
+
send?.({ type: "host.tools", tools });
|
|
1493
|
+
for (const t of tools) {
|
|
1494
|
+
emitToolEvent(win, {
|
|
1495
|
+
phase: "advertise",
|
|
1496
|
+
name: t.name,
|
|
1497
|
+
toolClass: toolClass(t.name)
|
|
1498
|
+
});
|
|
1290
1499
|
}
|
|
1291
1500
|
}
|
|
1292
1501
|
var widgetOrigin, MAX_ACTIVITY, send, activitySeq, activity, lastUrl, pageContextOn, contextProvider, navFire, origPushState, origReplaceState, snapshotModule, FORM_CONTROLS, ACTIONABLE, lastFocus, focusTimer, snapshotSeq;
|
|
@@ -1295,6 +1504,7 @@ var init_context = __esm({
|
|
|
1295
1504
|
init_redact();
|
|
1296
1505
|
init_hoist();
|
|
1297
1506
|
init_hoist_runtime();
|
|
1507
|
+
init_registry();
|
|
1298
1508
|
init_redact();
|
|
1299
1509
|
widgetOrigin = "";
|
|
1300
1510
|
MAX_ACTIVITY = 40;
|
|
@@ -1713,6 +1923,21 @@ var EmbedHost = class {
|
|
|
1713
1923
|
__testHandle(msg) {
|
|
1714
1924
|
this.handle(msg);
|
|
1715
1925
|
}
|
|
1926
|
+
/**
|
|
1927
|
+
* The eager stub's own emit-and-swallow for the host's `onEvent` telemetry hook.
|
|
1928
|
+
* Deliberately does NOT import the registry's `emitEvent`: pulling the lazy ./context
|
|
1929
|
+
* chunk (where the registry lives) into the size-budgeted stub would blow it, so this
|
|
1930
|
+
* ~5-line duplication across the bundle boundary is intentional. Host telemetry is
|
|
1931
|
+
* host code — a throw here must never break the widget.
|
|
1932
|
+
*/
|
|
1933
|
+
emit(e) {
|
|
1934
|
+
const cb = globalThis.matterfact?.onEvent;
|
|
1935
|
+
if (typeof cb !== "function") return;
|
|
1936
|
+
try {
|
|
1937
|
+
cb(e);
|
|
1938
|
+
} catch {
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1716
1941
|
handle(msg) {
|
|
1717
1942
|
switch (msg.type) {
|
|
1718
1943
|
case "widget.ready":
|
|
@@ -1725,8 +1950,10 @@ var EmbedHost = class {
|
|
|
1725
1950
|
this.send({ type: "host.theme", mode: this.themeMode() });
|
|
1726
1951
|
this.flush();
|
|
1727
1952
|
if (this.inline) void this.loadContext();
|
|
1953
|
+
this.emit({ type: "ready" });
|
|
1728
1954
|
break;
|
|
1729
1955
|
case "widget.setOpen":
|
|
1956
|
+
this.emit({ type: msg.open ? "open" : "close" });
|
|
1730
1957
|
if (this.inline) break;
|
|
1731
1958
|
this.open = msg.open;
|
|
1732
1959
|
this.place();
|
|
@@ -1914,11 +2141,16 @@ var EmbedHost = class {
|
|
|
1914
2141
|
if (this.hostEl) this.hostEl.style.display = "none";
|
|
1915
2142
|
break;
|
|
1916
2143
|
case "widget.needsAuth":
|
|
2144
|
+
this.emit({ type: "auth", phase: "required" });
|
|
1917
2145
|
void this.provideAuth();
|
|
1918
2146
|
break;
|
|
1919
2147
|
case "widget.navigate":
|
|
2148
|
+
this.emit({ type: "navigate", href: msg.href });
|
|
1920
2149
|
void this.loadContext().then((m) => m.navigateHost(msg.href));
|
|
1921
2150
|
break;
|
|
2151
|
+
case "widget.chat":
|
|
2152
|
+
this.emit({ type: "chat", phase: msg.phase, chatId: msg.chatId });
|
|
2153
|
+
break;
|
|
1922
2154
|
}
|
|
1923
2155
|
}
|
|
1924
2156
|
/**
|
|
@@ -2031,7 +2263,9 @@ var EmbedHost = class {
|
|
|
2031
2263
|
try {
|
|
2032
2264
|
const token = await provider();
|
|
2033
2265
|
if (token) this.send({ type: "host.auth", token, expiresAt: 0 });
|
|
2266
|
+
this.emit({ type: "auth", phase: token ? "granted" : "failed" });
|
|
2034
2267
|
} catch {
|
|
2268
|
+
this.emit({ type: "auth", phase: "failed" });
|
|
2035
2269
|
}
|
|
2036
2270
|
}
|
|
2037
2271
|
loadContext() {
|