@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/react.d.cts CHANGED
@@ -61,6 +61,38 @@ interface SiteMapEntry {
61
61
  content?: ContentClass;
62
62
  current?: boolean;
63
63
  }
64
+ /**
65
+ * A DECLARED artifact grant — the `<MatterfactAgent artifacts>` prop (or
66
+ * `window.matterfact.artifacts`). Same wire shape as a grant discovered by scanning
67
+ * co-embedded `<MatterfactArtifact>` iframes, plus an optional `label`; it feeds the
68
+ * SAME `host.artifactGrants` channel. This is how a host makes a board reachable from
69
+ * a route where its iframe ISN'T mounted, without hidden zero-size iframes smuggling
70
+ * the token into the DOM. The token stays in the grant channel, never in message text.
71
+ */
72
+ interface DeclaredArtifact {
73
+ slug: string;
74
+ owner: string;
75
+ token: string;
76
+ label?: string;
77
+ }
78
+ /**
79
+ * One host-tool lifecycle event, surfaced to the host via `onToolEvent` (and the dev
80
+ * panel) — the host's own telemetry hook. Fired loader-side; a throwing or slow
81
+ * callback here NEVER blocks or breaks the call path.
82
+ *
83
+ * - `advertise` — the merged tool list changed (fired with the new set's names).
84
+ * - `call` — a tool call is about to run (`args` present).
85
+ * - `result` — the call settled (`ok`/`error`/`ms`).
86
+ */
87
+ interface ToolEvent {
88
+ phase: 'advertise' | 'call' | 'result';
89
+ name: string;
90
+ toolClass: 'hoist' | 'mf' | 'app';
91
+ args?: unknown;
92
+ ok?: boolean;
93
+ error?: string;
94
+ ms?: number;
95
+ }
64
96
 
65
97
  /**
66
98
  * The Hoist adapter — a pure transform from a `HoistRuntime` (already read out of
@@ -83,6 +115,64 @@ interface HoistActionsConfig {
83
115
  navigate: 'off' | 'confirm' | 'auto';
84
116
  }
85
117
 
118
+ /**
119
+ * The host-tool registry — the ONE place the three tool classes are merged into the
120
+ * single list the widget advertises, and the ONE execution path for calling any of
121
+ * them.
122
+ *
123
+ * Three classes, distinguished by who owns the contract and who runs the code:
124
+ *
125
+ * - `hoist.*` matterfact-defined, matterfact-implemented. The loader adapter runs
126
+ * them (today: `hoist.navigate`). Gated on `window.XH` + the host's
127
+ * `hoist.actions` policy. See `hoist-runtime.ts`.
128
+ * - `mf.*` matterfact-defined, HOST-implemented. WE fix the name, schema and
129
+ * agent semantics (the description is authored HERE, not per
130
+ * integration); the host supplies the function via `resolve.*`. Today:
131
+ * `mf.resolveDocument`, `mf.resolveArtifact`.
132
+ * - `app.*` host-defined, host-implemented. Anything the host advertises via
133
+ * `tools`. Normalised into the `app.` namespace so it can never shadow
134
+ * ours.
135
+ *
136
+ * Everything downstream (the widget's confirm gate, the backend dispatcher) is already
137
+ * generic over "a tool with a name/schema/confirm and a call round-trip" — this module
138
+ * is purely the loader-side composition + dispatch, so `hoist-runtime.ts` stays one
139
+ * adapter rather than the whole surface.
140
+ *
141
+ * SECURITY: `mf.*`/`app.*` handlers are HOST code. Their results and error strings pass
142
+ * through `redact()` before leaving the page, exactly like the hoist adapter's; a
143
+ * handler that throws or hangs becomes a normal `{ok:false}` result, never an exception
144
+ * into `context.ts`. And the SERVER decides which of these an app may actually expose
145
+ * (the `host_tools` policy) — advertising here is necessary but not sufficient.
146
+ */
147
+
148
+ /** A host-supplied resolver: matterfact fixes the contract, the host implements it. */
149
+ interface HostResolvers {
150
+ document?: (args: {
151
+ doctype: string;
152
+ key: string;
153
+ }) => Promise<{
154
+ id: string;
155
+ label: string;
156
+ href?: string;
157
+ }>;
158
+ artifact?: (args: {
159
+ slug: string;
160
+ }) => Promise<{
161
+ id: string;
162
+ owner: string;
163
+ token: string;
164
+ label: string;
165
+ }>;
166
+ }
167
+ /** A host-defined tool (the `tools` prop): a WebMCP-shaped descriptor plus its handler. */
168
+ interface HostToolDef {
169
+ name: string;
170
+ description: string;
171
+ inputSchema?: Record<string, unknown>;
172
+ confirm?: 'auto' | 'required';
173
+ handler: (args: Record<string, unknown>) => unknown | Promise<unknown>;
174
+ }
175
+
86
176
  interface MatterfactAgentProps {
87
177
  /** Publishable key (`pk_…`) identifying this embed app. Public, origin-scoped. */
88
178
  publishableKey: string;
@@ -156,8 +246,41 @@ interface MatterfactAgentProps {
156
246
  * on load and on navigation.
157
247
  */
158
248
  sitemap?: SiteMapEntry[];
249
+ /**
250
+ * Declared artifact grants — make a board reachable from ANY route, even ones where
251
+ * its `<MatterfactArtifact>` iframe isn't mounted. Replaces the pattern of mounting
252
+ * hidden zero-size iframes purely to smuggle a read token into the DOM. The token
253
+ * rides the grant channel, never message text. Sugar over `window.matterfact.artifacts`.
254
+ */
255
+ artifacts?: DeclaredArtifact[];
256
+ /**
257
+ * matterfact-defined resolver contracts the HOST implements. matterfact fixes the tool
258
+ * name, schema and agent semantics (so an integration spends no instruction budget on
259
+ * them); you supply the function.
260
+ *
261
+ * - `document({doctype, key})` → `{id, label, href?}` — resolve an off-page matterfact
262
+ * document (dossier/report) to its id, e.g. via your own content-location lookup.
263
+ * - `artifact({slug})` → `{id, owner, token, label}` — resolve an artifact to a read grant.
264
+ *
265
+ * The agent calls these when the site map shows the content lives on another route, and
266
+ * renders the result as an `<MFRef>` chip. Sugar over `window.matterfact.resolve`.
267
+ */
268
+ resolve?: HostResolvers;
269
+ /**
270
+ * Host-defined tools (`app.*`): your own functions, offered to the agent WebMCP-style.
271
+ * Each is `{name, description, inputSchema?, confirm?, handler}`; the name is normalised
272
+ * into the `app.` namespace. A tool is only actually exposed if this app's server-side
273
+ * policy allows it. Sugar over `window.matterfact.tools`.
274
+ */
275
+ tools?: HostToolDef[];
276
+ /**
277
+ * Host telemetry hook: fired on every host-tool advertise/call/result so you can pipe
278
+ * calls into your own observability. Never blocks or breaks the call path — a throw here
279
+ * is swallowed. Sugar over `window.matterfact.onToolEvent`.
280
+ */
281
+ onToolEvent?: (e: ToolEvent) => void;
159
282
  }
160
- declare function MatterfactAgent({ publishableKey, widgetOrigin, surface, theme, getAuthToken, getPageContext, inline, className, style, pageContext, dev, actions, sitemap, }: MatterfactAgentProps): react_jsx_runtime.JSX.Element | null;
283
+ declare function MatterfactAgent({ publishableKey, widgetOrigin, surface, theme, getAuthToken, getPageContext, inline, className, style, pageContext, dev, actions, sitemap, artifacts, resolve, tools, onToolEvent, }: MatterfactAgentProps): react_jsx_runtime.JSX.Element | null;
161
284
  interface MatterfactArtifactProps {
162
285
  /** The artifact's slug/name. */
163
286
  slug: string;
package/dist/react.d.ts CHANGED
@@ -61,6 +61,38 @@ interface SiteMapEntry {
61
61
  content?: ContentClass;
62
62
  current?: boolean;
63
63
  }
64
+ /**
65
+ * A DECLARED artifact grant — the `<MatterfactAgent artifacts>` prop (or
66
+ * `window.matterfact.artifacts`). Same wire shape as a grant discovered by scanning
67
+ * co-embedded `<MatterfactArtifact>` iframes, plus an optional `label`; it feeds the
68
+ * SAME `host.artifactGrants` channel. This is how a host makes a board reachable from
69
+ * a route where its iframe ISN'T mounted, without hidden zero-size iframes smuggling
70
+ * the token into the DOM. The token stays in the grant channel, never in message text.
71
+ */
72
+ interface DeclaredArtifact {
73
+ slug: string;
74
+ owner: string;
75
+ token: string;
76
+ label?: string;
77
+ }
78
+ /**
79
+ * One host-tool lifecycle event, surfaced to the host via `onToolEvent` (and the dev
80
+ * panel) — the host's own telemetry hook. Fired loader-side; a throwing or slow
81
+ * callback here NEVER blocks or breaks the call path.
82
+ *
83
+ * - `advertise` — the merged tool list changed (fired with the new set's names).
84
+ * - `call` — a tool call is about to run (`args` present).
85
+ * - `result` — the call settled (`ok`/`error`/`ms`).
86
+ */
87
+ interface ToolEvent {
88
+ phase: 'advertise' | 'call' | 'result';
89
+ name: string;
90
+ toolClass: 'hoist' | 'mf' | 'app';
91
+ args?: unknown;
92
+ ok?: boolean;
93
+ error?: string;
94
+ ms?: number;
95
+ }
64
96
 
65
97
  /**
66
98
  * The Hoist adapter — a pure transform from a `HoistRuntime` (already read out of
@@ -83,6 +115,64 @@ interface HoistActionsConfig {
83
115
  navigate: 'off' | 'confirm' | 'auto';
84
116
  }
85
117
 
118
+ /**
119
+ * The host-tool registry — the ONE place the three tool classes are merged into the
120
+ * single list the widget advertises, and the ONE execution path for calling any of
121
+ * them.
122
+ *
123
+ * Three classes, distinguished by who owns the contract and who runs the code:
124
+ *
125
+ * - `hoist.*` matterfact-defined, matterfact-implemented. The loader adapter runs
126
+ * them (today: `hoist.navigate`). Gated on `window.XH` + the host's
127
+ * `hoist.actions` policy. See `hoist-runtime.ts`.
128
+ * - `mf.*` matterfact-defined, HOST-implemented. WE fix the name, schema and
129
+ * agent semantics (the description is authored HERE, not per
130
+ * integration); the host supplies the function via `resolve.*`. Today:
131
+ * `mf.resolveDocument`, `mf.resolveArtifact`.
132
+ * - `app.*` host-defined, host-implemented. Anything the host advertises via
133
+ * `tools`. Normalised into the `app.` namespace so it can never shadow
134
+ * ours.
135
+ *
136
+ * Everything downstream (the widget's confirm gate, the backend dispatcher) is already
137
+ * generic over "a tool with a name/schema/confirm and a call round-trip" — this module
138
+ * is purely the loader-side composition + dispatch, so `hoist-runtime.ts` stays one
139
+ * adapter rather than the whole surface.
140
+ *
141
+ * SECURITY: `mf.*`/`app.*` handlers are HOST code. Their results and error strings pass
142
+ * through `redact()` before leaving the page, exactly like the hoist adapter's; a
143
+ * handler that throws or hangs becomes a normal `{ok:false}` result, never an exception
144
+ * into `context.ts`. And the SERVER decides which of these an app may actually expose
145
+ * (the `host_tools` policy) — advertising here is necessary but not sufficient.
146
+ */
147
+
148
+ /** A host-supplied resolver: matterfact fixes the contract, the host implements it. */
149
+ interface HostResolvers {
150
+ document?: (args: {
151
+ doctype: string;
152
+ key: string;
153
+ }) => Promise<{
154
+ id: string;
155
+ label: string;
156
+ href?: string;
157
+ }>;
158
+ artifact?: (args: {
159
+ slug: string;
160
+ }) => Promise<{
161
+ id: string;
162
+ owner: string;
163
+ token: string;
164
+ label: string;
165
+ }>;
166
+ }
167
+ /** A host-defined tool (the `tools` prop): a WebMCP-shaped descriptor plus its handler. */
168
+ interface HostToolDef {
169
+ name: string;
170
+ description: string;
171
+ inputSchema?: Record<string, unknown>;
172
+ confirm?: 'auto' | 'required';
173
+ handler: (args: Record<string, unknown>) => unknown | Promise<unknown>;
174
+ }
175
+
86
176
  interface MatterfactAgentProps {
87
177
  /** Publishable key (`pk_…`) identifying this embed app. Public, origin-scoped. */
88
178
  publishableKey: string;
@@ -156,8 +246,41 @@ interface MatterfactAgentProps {
156
246
  * on load and on navigation.
157
247
  */
158
248
  sitemap?: SiteMapEntry[];
249
+ /**
250
+ * Declared artifact grants — make a board reachable from ANY route, even ones where
251
+ * its `<MatterfactArtifact>` iframe isn't mounted. Replaces the pattern of mounting
252
+ * hidden zero-size iframes purely to smuggle a read token into the DOM. The token
253
+ * rides the grant channel, never message text. Sugar over `window.matterfact.artifacts`.
254
+ */
255
+ artifacts?: DeclaredArtifact[];
256
+ /**
257
+ * matterfact-defined resolver contracts the HOST implements. matterfact fixes the tool
258
+ * name, schema and agent semantics (so an integration spends no instruction budget on
259
+ * them); you supply the function.
260
+ *
261
+ * - `document({doctype, key})` → `{id, label, href?}` — resolve an off-page matterfact
262
+ * document (dossier/report) to its id, e.g. via your own content-location lookup.
263
+ * - `artifact({slug})` → `{id, owner, token, label}` — resolve an artifact to a read grant.
264
+ *
265
+ * The agent calls these when the site map shows the content lives on another route, and
266
+ * renders the result as an `<MFRef>` chip. Sugar over `window.matterfact.resolve`.
267
+ */
268
+ resolve?: HostResolvers;
269
+ /**
270
+ * Host-defined tools (`app.*`): your own functions, offered to the agent WebMCP-style.
271
+ * Each is `{name, description, inputSchema?, confirm?, handler}`; the name is normalised
272
+ * into the `app.` namespace. A tool is only actually exposed if this app's server-side
273
+ * policy allows it. Sugar over `window.matterfact.tools`.
274
+ */
275
+ tools?: HostToolDef[];
276
+ /**
277
+ * Host telemetry hook: fired on every host-tool advertise/call/result so you can pipe
278
+ * calls into your own observability. Never blocks or breaks the call path — a throw here
279
+ * is swallowed. Sugar over `window.matterfact.onToolEvent`.
280
+ */
281
+ onToolEvent?: (e: ToolEvent) => void;
159
282
  }
160
- declare function MatterfactAgent({ publishableKey, widgetOrigin, surface, theme, getAuthToken, getPageContext, inline, className, style, pageContext, dev, actions, sitemap, }: MatterfactAgentProps): react_jsx_runtime.JSX.Element | null;
283
+ declare function MatterfactAgent({ publishableKey, widgetOrigin, surface, theme, getAuthToken, getPageContext, inline, className, style, pageContext, dev, actions, sitemap, artifacts, resolve, tools, onToolEvent, }: MatterfactAgentProps): react_jsx_runtime.JSX.Element | null;
161
284
  interface MatterfactArtifactProps {
162
285
  /** The artifact's slug/name. */
163
286
  slug: string;
package/dist/react.js CHANGED
@@ -694,7 +694,7 @@ var EmbedHost = class {
694
694
  }
695
695
  }
696
696
  loadContext() {
697
- this.context ?? (this.context = import("./context-U2HJJN2S.js").then((m) => {
697
+ this.context ?? (this.context = import("./context-HOOW63MO.js").then((m) => {
698
698
  m.start(
699
699
  this.send,
700
700
  this.config.origin,
@@ -747,6 +747,36 @@ function writeSitemapGlobal(sitemap) {
747
747
  const w = window;
748
748
  (w.matterfact ?? (w.matterfact = {})).sitemap = sitemap;
749
749
  }
750
+ function writeToolGlobals(artifacts, resolve, tools, onToolEvent) {
751
+ if (typeof window === "undefined") return;
752
+ const mf = window.matterfact ?? (window.matterfact = {});
753
+ mf.artifacts = artifacts ?? [];
754
+ mf.resolve = resolve ?? {};
755
+ mf.tools = tools ?? [];
756
+ mf.onToolEvent = onToolEvent;
757
+ }
758
+ function toolDescriptorKey(artifacts, resolve, tools) {
759
+ return JSON.stringify({
760
+ // Artifact identity is data (slug/owner/label), not a function.
761
+ artifacts: (artifacts ?? []).map((a) => ({
762
+ slug: a.slug,
763
+ owner: a.owner,
764
+ label: a.label
765
+ })),
766
+ // For resolvers, only WHICH contracts are present changes the advertised set.
767
+ resolve: {
768
+ document: typeof resolve?.document === "function",
769
+ artifact: typeof resolve?.artifact === "function"
770
+ },
771
+ // For host tools, the advertised descriptor — never the handler.
772
+ tools: (tools ?? []).map((t) => ({
773
+ name: t.name,
774
+ description: t.description,
775
+ inputSchema: t.inputSchema,
776
+ confirm: t.confirm
777
+ }))
778
+ });
779
+ }
750
780
  function MatterfactAgent({
751
781
  publishableKey,
752
782
  widgetOrigin,
@@ -760,7 +790,11 @@ function MatterfactAgent({
760
790
  pageContext,
761
791
  dev,
762
792
  actions,
763
- sitemap
793
+ sitemap,
794
+ artifacts,
795
+ resolve,
796
+ tools,
797
+ onToolEvent
764
798
  }) {
765
799
  const authRef = useRef(getAuthToken);
766
800
  authRef.current = getAuthToken;
@@ -774,10 +808,15 @@ function MatterfactAgent({
774
808
  useEffect(() => {
775
809
  writeSitemapGlobal(sitemap);
776
810
  }, [sitemapKey]);
811
+ useEffect(() => {
812
+ writeToolGlobals(artifacts, resolve, tools, onToolEvent);
813
+ });
814
+ const toolsKey = toolDescriptorKey(artifacts, resolve, tools);
777
815
  useEffect(() => {
778
816
  if (typeof window === "undefined") return;
779
817
  if (inline && !slot.current) return;
780
818
  writeActionsGlobal(actionsRef.current);
819
+ writeToolGlobals(artifacts, resolve, tools, onToolEvent);
781
820
  const config = {
782
821
  publishableKey,
783
822
  origin: widgetOrigin || DEFAULT_ORIGIN,
@@ -808,7 +847,11 @@ function MatterfactAgent({
808
847
  inline,
809
848
  pageContext,
810
849
  dev,
811
- actionsKey
850
+ actionsKey,
851
+ // A change to the advertised tool SHAPE remounts so start() re-advertises under it;
852
+ // a change to only a handler body or callback identity does not (see toolDescriptorKey).
853
+ toolsKey
854
+ // eslint-disable-next-line react-hooks/exhaustive-deps
812
855
  ]);
813
856
  if (!inline) return null;
814
857
  return /* @__PURE__ */ jsx(