@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.
Files changed (40) hide show
  1. package/README.md +119 -0
  2. package/dist/{chunk-URGQBG4I.js → chunk-4AE5WINC.js} +209 -17
  3. package/dist/chunk-4AE5WINC.js.map +1 -0
  4. package/dist/{chunk-6EM7T2JV.js → chunk-CFDPCZO3.js} +208 -15
  5. package/dist/chunk-CFDPCZO3.js.map +1 -0
  6. package/dist/{chunk-BKKXHSYU.js → chunk-DXLHTFB4.js} +2 -2
  7. package/dist/chunk-RL6VIGWK.js +2 -0
  8. package/dist/chunk-TWMHQF7O.js +3 -0
  9. package/dist/chunk-TWMHQF7O.js.map +7 -0
  10. package/dist/{context-U2HJJN2S.js → context-HOOW63MO.js} +4 -2
  11. package/dist/context-SSQ4HUP3.js +3 -0
  12. package/dist/{context-ACFBWIFH.js.map → context-SSQ4HUP3.js.map} +1 -1
  13. package/dist/embed.js +1 -1
  14. package/dist/embed.js.map +2 -2
  15. package/dist/index.cjs +214 -13
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +33 -1
  18. package/dist/index.d.ts +33 -1
  19. package/dist/index.js +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/react.cjs +260 -15
  22. package/dist/react.cjs.map +1 -1
  23. package/dist/react.d.cts +124 -1
  24. package/dist/react.d.ts +124 -1
  25. package/dist/react.js +46 -3
  26. package/dist/react.js.map +1 -1
  27. package/dist/{snapshot-Y75SCGCM.js → snapshot-CRY2IBX6.js} +3 -3
  28. package/dist/{snapshot-Y75SCGCM.js.map → snapshot-CRY2IBX6.js.map} +1 -1
  29. package/dist/{snapshot-4GXT6PKZ.js → snapshot-EYRXPLRC.js} +2 -2
  30. package/package.json +1 -1
  31. package/dist/chunk-6EM7T2JV.js.map +0 -1
  32. package/dist/chunk-FEXG4LQJ.js +0 -3
  33. package/dist/chunk-FEXG4LQJ.js.map +0 -7
  34. package/dist/chunk-NWNMS34P.js +0 -2
  35. package/dist/chunk-URGQBG4I.js.map +0 -1
  36. package/dist/context-ACFBWIFH.js +0 -3
  37. /package/dist/{chunk-BKKXHSYU.js.map → chunk-DXLHTFB4.js.map} +0 -0
  38. /package/dist/{chunk-NWNMS34P.js.map → chunk-RL6VIGWK.js.map} +0 -0
  39. /package/dist/{context-U2HJJN2S.js.map → context-HOOW63MO.js.map} +0 -0
  40. /package/dist/{snapshot-4GXT6PKZ.js.map → snapshot-EYRXPLRC.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -403,6 +403,155 @@ 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 emitToolEvent(win, e) {
417
+ const cb = mfGlobal(win).onToolEvent;
418
+ if (typeof cb !== "function") return;
419
+ try {
420
+ cb(e);
421
+ } catch {
422
+ }
423
+ }
424
+ function mfTools(win) {
425
+ const { document: document2, artifact } = mfGlobal(win).resolve ?? {};
426
+ const out = [];
427
+ if (typeof document2 === "function") {
428
+ out.push({
429
+ name: "mf.resolveDocument",
430
+ 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.',
431
+ inputSchema: {
432
+ type: "object",
433
+ properties: {
434
+ doctype: { type: "string" },
435
+ key: { type: "string" }
436
+ },
437
+ required: ["doctype", "key"]
438
+ },
439
+ readOnly: true,
440
+ confirm: "auto"
441
+ });
442
+ }
443
+ if (typeof artifact === "function") {
444
+ out.push({
445
+ name: "mf.resolveArtifact",
446
+ 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.',
447
+ inputSchema: {
448
+ type: "object",
449
+ properties: { slug: { type: "string" } },
450
+ required: ["slug"]
451
+ },
452
+ readOnly: true,
453
+ confirm: "auto"
454
+ });
455
+ }
456
+ return out;
457
+ }
458
+ function appName(name) {
459
+ return name.startsWith("app.") ? name : `app.${name}`;
460
+ }
461
+ function appTools(win) {
462
+ const defs = mfGlobal(win).tools;
463
+ if (!Array.isArray(defs)) return [];
464
+ const out = [];
465
+ for (const d of defs) {
466
+ const raw = (d?.name ?? "").trim();
467
+ if (!raw || typeof d.handler !== "function") continue;
468
+ const name = appName(raw);
469
+ if (!APP_NAME_RE.test(name)) continue;
470
+ out.push({
471
+ name,
472
+ description: String(d.description ?? `Run the host tool ${name}.`),
473
+ inputSchema: d.inputSchema ?? { type: "object", properties: {} },
474
+ readOnly: false,
475
+ confirm: d.confirm === "auto" ? "auto" : "required"
476
+ });
477
+ }
478
+ return out;
479
+ }
480
+ function advertise(win = typeof window !== "undefined" ? window : void 0) {
481
+ const merged = [];
482
+ const seen = /* @__PURE__ */ new Set();
483
+ const push = (tools) => {
484
+ for (const t of tools) {
485
+ if (seen.has(t.name)) continue;
486
+ seen.add(t.name);
487
+ merged.push(t);
488
+ }
489
+ };
490
+ try {
491
+ push(advertiseTools(win));
492
+ } catch {
493
+ }
494
+ try {
495
+ push(mfTools(win));
496
+ push(appTools(win));
497
+ } catch {
498
+ }
499
+ return merged.slice(0, MAX_TOOLS);
500
+ }
501
+ function timeout(ms) {
502
+ return new Promise(
503
+ (_, reject) => setTimeout(() => reject(new Error("host tool timed out")), ms)
504
+ );
505
+ }
506
+ function redactResult(value) {
507
+ if (value === void 0 || value === null) return value;
508
+ if (typeof value === "string") return redact(value);
509
+ try {
510
+ return JSON.parse(redact(JSON.stringify(value)));
511
+ } catch {
512
+ return redact(String(value));
513
+ }
514
+ }
515
+ async function execute(call, win = typeof window !== "undefined" ? window : void 0) {
516
+ const cls = toolClass(call.name);
517
+ try {
518
+ if (cls === "hoist") {
519
+ return executeHostTool(call, win);
520
+ }
521
+ const handler = resolveHandler(win, call.name);
522
+ if (!handler) return { ok: false, error: "unknown tool" };
523
+ const result = await Promise.race([
524
+ Promise.resolve(handler(call.args ?? {})),
525
+ timeout(HOST_HANDLER_TIMEOUT_MS)
526
+ ]);
527
+ return { ok: true, result: redactResult(result) };
528
+ } catch (e) {
529
+ return {
530
+ ok: false,
531
+ error: redact(e instanceof Error ? e.message : "host tool failed")
532
+ };
533
+ }
534
+ }
535
+ function resolveHandler(win, name) {
536
+ const mf = mfGlobal(win);
537
+ if (name === "mf.resolveDocument") return mf.resolve?.document;
538
+ if (name === "mf.resolveArtifact") return mf.resolve?.artifact;
539
+ if (name.startsWith("app.")) {
540
+ const def = (mf.tools ?? []).find((d) => appName((d?.name ?? "").trim()) === name);
541
+ return def?.handler;
542
+ }
543
+ return void 0;
544
+ }
545
+ var MAX_TOOLS, HOST_HANDLER_TIMEOUT_MS, APP_NAME_RE;
546
+ var init_registry = __esm({
547
+ "src/adapters/registry.ts"() {
548
+ init_redact();
549
+ init_hoist_runtime();
550
+ MAX_TOOLS = 16;
551
+ HOST_HANDLER_TIMEOUT_MS = 3e4;
552
+ APP_NAME_RE = /^[A-Za-z0-9._-]+$/;
553
+ }
554
+ });
406
555
  function createStyleCache() {
407
556
  const cache = /* @__PURE__ */ new WeakMap();
408
557
  return ((el, pseudo) => {
@@ -880,6 +1029,7 @@ __export(context_exports, {
880
1029
  isPrivate: () => isPrivate,
881
1030
  navigateHost: () => navigateHost,
882
1031
  provideContext: () => provideContext,
1032
+ readDeclaredGrants: () => readDeclaredGrants,
883
1033
  readPageContext: () => readPageContext,
884
1034
  redact: () => redact,
885
1035
  sendRegion: () => sendRegion,
@@ -1001,12 +1151,31 @@ function grantsFromIframeSrcs(srcs, origin) {
1001
1151
  }
1002
1152
  return out;
1003
1153
  }
1154
+ function readDeclaredGrants() {
1155
+ const declared = window.matterfact?.artifacts;
1156
+ if (!Array.isArray(declared)) return [];
1157
+ const out = [];
1158
+ for (const a of declared) {
1159
+ const id = (a?.slug || "").trim();
1160
+ const owner = (a?.owner || "").trim();
1161
+ const token = (a?.token || "").trim();
1162
+ if (!id || !owner || !token) continue;
1163
+ if (out.some((g) => g.id === id)) continue;
1164
+ out.push({ id, owner, token });
1165
+ }
1166
+ return out;
1167
+ }
1004
1168
  function readArtifactGrants() {
1005
1169
  if (!widgetOrigin) return [];
1006
1170
  const srcs = Array.from(document.querySelectorAll("iframe")).map(
1007
1171
  (f) => f.getAttribute("src") || ""
1008
1172
  );
1009
- return grantsFromIframeSrcs(srcs, widgetOrigin);
1173
+ const scanned = grantsFromIframeSrcs(srcs, widgetOrigin);
1174
+ const out = [...scanned];
1175
+ for (const g of readDeclaredGrants()) {
1176
+ if (!out.some((s) => s.id === g.id)) out.push(g);
1177
+ }
1178
+ return out;
1010
1179
  }
1011
1180
  function publishArtifactGrants() {
1012
1181
  send?.({ type: "host.artifactGrants", grants: readArtifactGrants() });
@@ -1095,10 +1264,7 @@ function watchNavigation() {
1095
1264
  void publishContext();
1096
1265
  publishArtifactGrants();
1097
1266
  publishSitemap();
1098
- send?.({
1099
- type: "host.tools",
1100
- tools: advertiseTools(typeof window !== "undefined" ? window : void 0)
1101
- });
1267
+ publishTools();
1102
1268
  };
1103
1269
  navFire = fire;
1104
1270
  for (const name of ["pushState", "replaceState"]) {
@@ -1202,10 +1368,24 @@ async function callTool(call, emit) {
1202
1368
  });
1203
1369
  return;
1204
1370
  }
1205
- const r = executeHostTool(
1206
- call,
1207
- typeof window !== "undefined" ? window : void 0
1208
- );
1371
+ const win = typeof window !== "undefined" ? window : void 0;
1372
+ const cls = toolClass(call.name);
1373
+ const startedAt = Date.now();
1374
+ emitToolEvent(win, {
1375
+ phase: "call",
1376
+ name: call.name,
1377
+ toolClass: cls,
1378
+ args: call.args
1379
+ });
1380
+ const r = await execute(call, win);
1381
+ emitToolEvent(win, {
1382
+ phase: "result",
1383
+ name: call.name,
1384
+ toolClass: cls,
1385
+ ok: r.ok,
1386
+ error: r.error,
1387
+ ms: Date.now() - startedAt
1388
+ });
1209
1389
  emit({
1210
1390
  type: "host.toolResult",
1211
1391
  callId: call.callId,
@@ -1283,10 +1463,30 @@ function start(emit, origin, pageContext = true, provider) {
1283
1463
  const theme = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
1284
1464
  emit({ type: "host.theme", mode: theme });
1285
1465
  if (pageContextOn) {
1286
- const tools = advertiseTools(
1287
- typeof window !== "undefined" ? window : void 0
1288
- );
1289
- if (tools.length) emit({ type: "host.tools", tools });
1466
+ const w = typeof window !== "undefined" ? window : void 0;
1467
+ const tools = advertise(w);
1468
+ if (tools.length) {
1469
+ emit({ type: "host.tools", tools });
1470
+ for (const t of tools) {
1471
+ emitToolEvent(w, {
1472
+ phase: "advertise",
1473
+ name: t.name,
1474
+ toolClass: toolClass(t.name)
1475
+ });
1476
+ }
1477
+ }
1478
+ }
1479
+ }
1480
+ function publishTools() {
1481
+ const win = typeof window !== "undefined" ? window : void 0;
1482
+ const tools = advertise(win);
1483
+ send?.({ type: "host.tools", tools });
1484
+ for (const t of tools) {
1485
+ emitToolEvent(win, {
1486
+ phase: "advertise",
1487
+ name: t.name,
1488
+ toolClass: toolClass(t.name)
1489
+ });
1290
1490
  }
1291
1491
  }
1292
1492
  var widgetOrigin, MAX_ACTIVITY, send, activitySeq, activity, lastUrl, pageContextOn, contextProvider, navFire, origPushState, origReplaceState, snapshotModule, FORM_CONTROLS, ACTIONABLE, lastFocus, focusTimer, snapshotSeq;
@@ -1295,6 +1495,7 @@ var init_context = __esm({
1295
1495
  init_redact();
1296
1496
  init_hoist();
1297
1497
  init_hoist_runtime();
1498
+ init_registry();
1298
1499
  init_redact();
1299
1500
  widgetOrigin = "";
1300
1501
  MAX_ACTIVITY = 40;