@particle-academy/agent-integrations 0.34.0 → 0.36.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.
@@ -1,5 +1,5 @@
1
- import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-SJTLTITO.js';
2
- import { createSessionDescriptor, attachSseRelay } from './chunk-N6RLSLOF.js';
1
+ import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-ABP2THQV.js';
2
+ import { createSessionDescriptor, attachSseRelay } from './chunk-JDCB2NMM.js';
3
3
  import { attachInProcess } from './chunk-AFUULW5E.js';
4
4
  import { registerWhiteboardBridge } from './chunk-2U5JB6ZA.js';
5
5
  import './chunk-CT3LRNH7.js';
package/dist/index.cjs CHANGED
@@ -4093,7 +4093,15 @@ function registerDocBridge(host, options) {
4093
4093
  const disposers = [];
4094
4094
  ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
4095
4095
  let idSeq = 0;
4096
- const mintId = () => adapter.newId?.() ?? `${surface}-${idSeq += 1}`;
4096
+ const mintId = () => {
4097
+ if (adapter.newId) return adapter.newId();
4098
+ const taken = adapter.get().nodes;
4099
+ let id;
4100
+ do
4101
+ id = `${surface}-${idSeq += 1}`;
4102
+ while (taken[id]);
4103
+ return id;
4104
+ };
4097
4105
  const target = (elementId) => ({ kind: surface, screenId: adapter.screenId, elementId });
4098
4106
  const pending = /* @__PURE__ */ new Map();
4099
4107
  function commit(op, label, targetId) {
@@ -4112,10 +4120,10 @@ function registerDocBridge(host, options) {
4112
4120
  }
4113
4121
  function submit(op, label, targetId) {
4114
4122
  if (stage(op) === "confirm") {
4115
- const id = `${surface}-pending-${idSeq += 1}`;
4116
- pending.set(id, { op, label, targetId });
4117
- options.onPending?.({ id, op, label });
4118
- return { staged: true, id };
4123
+ const pendingId = `${surface}-pending-${idSeq += 1}`;
4124
+ pending.set(pendingId, { op, label, targetId });
4125
+ options.onPending?.({ id: pendingId, op, label });
4126
+ return { staged: true, id: targetId, pendingId };
4119
4127
  }
4120
4128
  commit(op, label, targetId);
4121
4129
  return { staged: false, id: targetId };
@@ -4198,18 +4206,26 @@ function registerDocBridge(host, options) {
4198
4206
  type: { type: "string", description: "Node type discriminant." },
4199
4207
  parent: { type: ["string", "null"], description: "Parent id, or null for a root." },
4200
4208
  props: { type: "object", description: "JSON props bag." },
4201
- order: { type: "string", description: "Fractional order key (default: append)." }
4209
+ order: { type: "string", description: "Fractional order key (default: append)." },
4210
+ id: {
4211
+ type: "string",
4212
+ description: "Id for the new node. Supply a meaningful one if you intend to address this node later; omitted means one is minted for you. Must not already exist."
4213
+ }
4202
4214
  },
4203
4215
  ["type"],
4204
4216
  (args) => {
4205
4217
  const tree = adapter.get();
4206
4218
  const parent = typeof args.parent === "string" ? args.parent : null;
4207
- const id = mintId();
4219
+ const requested = typeof args.id === "string" ? args.id : void 0;
4220
+ if (requested !== void 0 && tree.nodes[requested]) {
4221
+ throw new Error(`Node ${requested} already exists \u2014 pick a different id or update it instead`);
4222
+ }
4223
+ const id = requested ?? mintId();
4208
4224
  const order = typeof args.order === "string" ? args.order : fancyDocCommons.appendOrder(tree, parent);
4209
4225
  const props = args.props && typeof args.props === "object" ? args.props : {};
4210
4226
  const node = makeNode({ id, type: String(args.type), parent, order }, props);
4211
4227
  const res = submit({ t: "insert", node }, `add ${args.type} ${id}`, id);
4212
- return { ...res, _text: res.staged ? `staged add ${id}` : `added ${id}` };
4228
+ return { ...res, _text: res.staged ? `staged add ${id} \u2014 confirm ${res.pendingId}` : `added ${id}` };
4213
4229
  },
4214
4230
  true,
4215
4231
  (_args, result) => target(result.id)
@@ -4224,7 +4240,7 @@ function registerDocBridge(host, options) {
4224
4240
  if (!adapter.get().nodes[id]) throw new Error(`No node ${id}`);
4225
4241
  const patch = args.patch && typeof args.patch === "object" ? args.patch : {};
4226
4242
  const res = submit({ t: "set_props", id, patch }, `update ${id}`, id);
4227
- return { ...res, id, _text: res.staged ? `staged update ${id}` : `updated ${id}` };
4243
+ return { ...res, id, _text: res.staged ? `staged update ${id} \u2014 confirm ${res.pendingId}` : `updated ${id}` };
4228
4244
  },
4229
4245
  true,
4230
4246
  (args) => target(String(args.id))
@@ -4240,7 +4256,7 @@ function registerDocBridge(host, options) {
4240
4256
  if (!tree.nodes[id]) throw new Error(`No node ${id}`);
4241
4257
  const count = fancyDocCommons.descendantsOf(tree, id).length + 1;
4242
4258
  const res = submit({ t: "remove", id }, `remove ${id} (${count} node${count === 1 ? "" : "s"})`, id);
4243
- return { ...res, id, removed: count, _text: res.staged ? `staged remove ${id}` : `removed ${id}` };
4259
+ return { ...res, id, removed: count, _text: res.staged ? `staged remove ${id} \u2014 confirm ${res.pendingId}` : `removed ${id}` };
4244
4260
  },
4245
4261
  true,
4246
4262
  (args) => target(String(args.id))
@@ -4257,7 +4273,7 @@ function registerDocBridge(host, options) {
4257
4273
  const parent = args.parent === null ? null : typeof args.parent === "string" ? args.parent : tree.nodes[id].parent;
4258
4274
  const order = typeof args.order === "string" ? args.order : fancyDocCommons.appendOrder(tree, parent);
4259
4275
  const res = submit({ t: "move", id, parent, order }, `move ${id}`, id);
4260
- return { ...res, id, _text: res.staged ? `staged move ${id}` : `moved ${id}` };
4276
+ return { ...res, id, _text: res.staged ? `staged move ${id} \u2014 confirm ${res.pendingId}` : `moved ${id}` };
4261
4277
  },
4262
4278
  true,
4263
4279
  (args) => target(String(args.id))
@@ -4273,7 +4289,7 @@ function registerDocBridge(host, options) {
4273
4289
  if (built && typeof built === "object" && "error" in built) throw new Error(built.error);
4274
4290
  const tid = t.targetId?.(args);
4275
4291
  const res = submit(built, `${t.verb} ${tid ?? ""}`.trim(), tid);
4276
- return { ...res, id: tid, _text: res.staged ? `staged ${t.verb}` : t.verb };
4292
+ return { ...res, id: tid, _text: res.staged ? `staged ${t.verb} \u2014 confirm ${res.pendingId}` : t.verb };
4277
4293
  },
4278
4294
  true,
4279
4295
  (args) => target(t.targetId?.(args))
@@ -4281,8 +4297,8 @@ function registerDocBridge(host, options) {
4281
4297
  }
4282
4298
  reg(
4283
4299
  "confirm",
4284
- "Apply a staged op by its pending id (from a staged mutation).",
4285
- { id: { type: "string" } },
4300
+ "Apply a staged op. Pass the `pendingId` a staged mutation returned \u2014 not the node `id` it also returns.",
4301
+ { id: { type: "string", description: "The `pendingId` from a staged mutation." } },
4286
4302
  ["id"],
4287
4303
  (args) => {
4288
4304
  const id = String(args.id);
@@ -4297,8 +4313,8 @@ function registerDocBridge(host, options) {
4297
4313
  );
4298
4314
  reg(
4299
4315
  "reject",
4300
- "Discard a staged op by its pending id.",
4301
- { id: { type: "string" } },
4316
+ "Discard a staged op. Pass the `pendingId` a staged mutation returned \u2014 not the node `id` it also returns.",
4317
+ { id: { type: "string", description: "The `pendingId` from a staged mutation." } },
4302
4318
  ["id"],
4303
4319
  (args) => {
4304
4320
  const id = String(args.id);
@@ -4390,6 +4406,90 @@ function registerCmsBridge(host, options) {
4390
4406
  ]
4391
4407
  });
4392
4408
  }
4409
+ var SCREEN_TEXT_NODE_TYPE = "#text";
4410
+ function registerScreenDocBridge(host, options) {
4411
+ const { adapter } = options;
4412
+ const surface = options.surface ?? "screen";
4413
+ const setText = {
4414
+ verb: "set_text",
4415
+ description: "Replace the literal text of an element node \u2014 the natural way to change a label, heading or paragraph. Pass the ELEMENT's id, not the text node's.",
4416
+ properties: {
4417
+ id: { type: "string", description: "Id of the element whose text to set." },
4418
+ text: { type: "string" }
4419
+ },
4420
+ required: ["id", "text"],
4421
+ build: (args, tree) => {
4422
+ const id = String(args.id);
4423
+ const node = tree.nodes[id];
4424
+ if (!node) return { error: `No node ${id}` };
4425
+ if (node.type === SCREEN_TEXT_NODE_TYPE) {
4426
+ return { t: "set_props", id, patch: { value: String(args.text) } };
4427
+ }
4428
+ const texts = fancyDocCommons.childrenOf(tree, id).filter((c) => c.type === SCREEN_TEXT_NODE_TYPE);
4429
+ if (texts.length === 1) {
4430
+ return { t: "set_props", id: texts[0].id, patch: { value: String(args.text) } };
4431
+ }
4432
+ if (texts.length === 0) {
4433
+ return {
4434
+ t: "insert",
4435
+ node: {
4436
+ id: `${id}-text`,
4437
+ type: SCREEN_TEXT_NODE_TYPE,
4438
+ parent: id,
4439
+ order: fancyDocCommons.appendOrder(tree, id),
4440
+ props: { value: String(args.text) }
4441
+ }
4442
+ };
4443
+ }
4444
+ return {
4445
+ error: `Node ${id} has ${texts.length} text children (${texts.map((t) => t.id).join(", ")}) \u2014 set_text on the one you mean`
4446
+ };
4447
+ },
4448
+ targetId: (args) => String(args.id)
4449
+ };
4450
+ const bridge = registerDocBridge(host, {
4451
+ adapter,
4452
+ surface,
4453
+ agent: options.agent,
4454
+ stagePolicy: options.stagePolicy,
4455
+ onPending: options.onPending,
4456
+ // Anything the AGENT adds is authored by definition — it chose or was given
4457
+ // the id — so it must not inherit the synthetic flag from its neighbours.
4458
+ makeNode: ({ id, type, parent, order }, props) => ({ id, type, parent, order, props }),
4459
+ describeNode: (n) => ({
4460
+ id: n.id,
4461
+ type: n.type,
4462
+ parent: n.parent,
4463
+ ...n.synthetic ? { synthetic: true } : {},
4464
+ ...n.type === SCREEN_TEXT_NODE_TYPE ? { text: String(n.props?.value ?? "") } : { props: Object.keys(n.props ?? {}) }
4465
+ }),
4466
+ opTools: [setText]
4467
+ });
4468
+ const disposeAddressable = host.registerTool(
4469
+ {
4470
+ name: `${surface}_addressable`,
4471
+ description: "List the node ids that are safe to remember and use later. Ids NOT listed here were minted from a node's position: they resolve today and silently point at a different node once a sibling is inserted above them. Address those in the same turn you read them, and never store one.",
4472
+ inputSchema: { type: "object", properties: {}, required: [], additionalProperties: false }
4473
+ },
4474
+ (async () => {
4475
+ const nodes = Object.values(adapter.get().nodes);
4476
+ const authored = nodes.filter((n) => !n.synthetic).map((n) => ({ id: n.id, type: n.type }));
4477
+ const syntheticCount = nodes.length - authored.length;
4478
+ return textResult(
4479
+ authored.length ? `${authored.length} addressable, ${syntheticCount} positional` : `no addressable ids \u2014 all ${syntheticCount} nodes are positional`,
4480
+ { addressable: authored, syntheticCount }
4481
+ );
4482
+ })
4483
+ );
4484
+ return {
4485
+ id: surface,
4486
+ title: "Screen content",
4487
+ dispose: () => {
4488
+ disposeAddressable();
4489
+ bridge.dispose();
4490
+ }
4491
+ };
4492
+ }
4393
4493
 
4394
4494
  // src/sharing/token.ts
4395
4495
  var TOKEN_BYTES = 24;
@@ -4457,6 +4557,7 @@ var SseRelayTransport = class {
4457
4557
  this.listeners = /* @__PURE__ */ new Set();
4458
4558
  this.state = "idle";
4459
4559
  this.peers = /* @__PURE__ */ new Set();
4560
+ this.peerListeners = /* @__PURE__ */ new Set();
4460
4561
  this.opts = options;
4461
4562
  this.expectedToken = options.token;
4462
4563
  }
@@ -4517,6 +4618,8 @@ var SseRelayTransport = class {
4517
4618
  this.es?.close();
4518
4619
  this.es = void 0;
4519
4620
  this.connected = false;
4621
+ this.peers.clear();
4622
+ this.notifyPeers();
4520
4623
  this.setState("closed");
4521
4624
  }
4522
4625
  onStateChange(listener) {
@@ -4524,6 +4627,28 @@ var SseRelayTransport = class {
4524
4627
  listener(this.state);
4525
4628
  return () => this.listeners.delete(listener);
4526
4629
  }
4630
+ /** How many remote peers (agents) are currently attached to this session. */
4631
+ peerCount() {
4632
+ return this.peers.size;
4633
+ }
4634
+ /**
4635
+ * Subscribe to peer arrivals/departures. Fires immediately with the current
4636
+ * count.
4637
+ *
4638
+ * This is the ONLY honest answer to "is an agent actually here?".
4639
+ * `onStateChange` reports the BROWSER's own channel to the relay, which opens
4640
+ * the instant sharing starts — so a UI keyed on it announces "Agent is
4641
+ * driving" to a human who has not yet handed the link to anybody, and can
4642
+ * never tell them when one really arrives.
4643
+ */
4644
+ onPeersChange(listener) {
4645
+ this.peerListeners.add(listener);
4646
+ listener(this.peers.size);
4647
+ return () => this.peerListeners.delete(listener);
4648
+ }
4649
+ notifyPeers() {
4650
+ for (const l of this.peerListeners) l(this.peers.size);
4651
+ }
4527
4652
  /**
4528
4653
  * For relays that wrap each frame with auth metadata: hosts can call this
4529
4654
  * directly when a frame arrives via a non-SSE path. The transport will
@@ -4558,6 +4683,7 @@ var SseRelayTransport = class {
4558
4683
  if ("method" in message && message.method === "notifications/peer_joined") {
4559
4684
  const subscriberId = String(message.params?.subscriberId ?? "peer");
4560
4685
  this.peers.add(subscriberId);
4686
+ this.notifyPeers();
4561
4687
  fancyAutoCommon.emitActivity({
4562
4688
  agentId: "agent",
4563
4689
  agentName: "Agent",
@@ -4572,6 +4698,7 @@ var SseRelayTransport = class {
4572
4698
  if ("method" in message && message.method === "notifications/peer_left") {
4573
4699
  const subscriberId = String(message.params?.subscriberId ?? "peer");
4574
4700
  this.peers.delete(subscriberId);
4701
+ this.notifyPeers();
4575
4702
  if (this.peers.size === 0) {
4576
4703
  fancyAutoCommon.emitActivity({
4577
4704
  agentId: "agent",
@@ -4629,6 +4756,7 @@ function useCoBrowseSession(options) {
4629
4756
  const disposeBridge = react.useRef(null);
4630
4757
  const [session, setSession] = react.useState(null);
4631
4758
  const [relayState, setRelayState] = react.useState("idle");
4759
+ const [agentCount, setAgentCount] = react.useState(0);
4632
4760
  react.useEffect(() => {
4633
4761
  const server = new MicroMcpServer({
4634
4762
  info: options.info ?? { name: "fancy-co-browse", version: "0.1.0" },
@@ -4663,6 +4791,7 @@ function useCoBrowseSession(options) {
4663
4791
  }
4664
4792
  const relay = attachSseRelay(server, { baseUrl: relayBaseUrl, sessionId: descriptor.id, token: descriptor.token });
4665
4793
  relay.onStateChange(setRelayState);
4794
+ relay.onPeersChange(setAgentCount);
4666
4795
  relayRef.current = relay;
4667
4796
  setSession(descriptor);
4668
4797
  }, [relayBaseUrl, options]);
@@ -4671,6 +4800,7 @@ function useCoBrowseSession(options) {
4671
4800
  relayRef.current?.close();
4672
4801
  relayRef.current = null;
4673
4802
  setRelayState("idle");
4803
+ setAgentCount(0);
4674
4804
  setSession(null);
4675
4805
  if (current) {
4676
4806
  const csrf = options.csrfToken?.() ?? "";
@@ -4693,7 +4823,16 @@ function useCoBrowseSession(options) {
4693
4823
  meta: event
4694
4824
  });
4695
4825
  }, []);
4696
- return { server: serverRef.current, session, relayState, startShare, stopShare, observeUser };
4826
+ return {
4827
+ server: serverRef.current,
4828
+ session,
4829
+ relayState,
4830
+ agentConnected: agentCount > 0,
4831
+ agentCount,
4832
+ startShare,
4833
+ stopShare,
4834
+ observeUser
4835
+ };
4697
4836
  }
4698
4837
  function AgentPanel({ agent, activity, onSubmit, busy, actions, className, style }) {
4699
4838
  const scrollRef = react.useRef(null);
@@ -5416,10 +5555,12 @@ function ManualPopover({
5416
5555
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "fai-connect__copy-btn", onClick: onCopy, children: copied ? "Copied" : "Copy snippet" })
5417
5556
  ] });
5418
5557
  }
5558
+ var LIFECYCLE_ACTIONS = /* @__PURE__ */ new Set(["agent_connected", "agent_disconnected"]);
5419
5559
  function CoBrowsePresence({ session, connectUrl, shareBaseUrl, className }) {
5420
5560
  const { events } = useAgentActivity(void 0, { capacity: 40 });
5421
- const lastAgentAction = [...events].reverse().find((e) => (e.source ?? "agent") !== "user");
5422
- const connected = session.relayState === "open";
5561
+ const lastAgentAction = [...events].reverse().find((e) => (e.source ?? "agent") !== "user" && !LIFECYCLE_ACTIONS.has(e.action));
5562
+ const connected = session.agentConnected;
5563
+ const activity = react.useMemo(() => events.map(toPanelActivity), [events]);
5423
5564
  if (!session.session) {
5424
5565
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-co-browse-presence": "idle", children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void session.startShare(), "data-co-browse-start": true, children: "Let an agent drive" }) });
5425
5566
  }
@@ -5437,12 +5578,25 @@ function CoBrowsePresence({ session, connectUrl, shareBaseUrl, className }) {
5437
5578
  onStart: () => void session.startShare(),
5438
5579
  onStop: session.stopShare,
5439
5580
  status: session.relayState,
5581
+ agentConnected: connected,
5582
+ activity,
5440
5583
  shareBaseUrl
5441
5584
  }
5442
5585
  ),
5443
5586
  connectUrl && /* @__PURE__ */ jsxRuntime.jsx(ConnectorButtons, { serverName: "Fancy UI co-browse", mcpUrl: connectUrl })
5444
5587
  ] });
5445
5588
  }
5589
+ function toPanelActivity(event) {
5590
+ const who = (event.source ?? "agent") === "user" ? "You" : event.agentName ?? "Agent";
5591
+ return {
5592
+ id: `${event.timestamp}-${event.action}-${event.target?.elementId ?? event.target?.label ?? ""}`,
5593
+ at: event.timestamp,
5594
+ kind: LIFECYCLE_ACTIONS.has(event.action) ? "info" : "tool",
5595
+ source: who,
5596
+ text: event.target?.label ?? event.action,
5597
+ detail: event.meta
5598
+ };
5599
+ }
5446
5600
  CoBrowsePresence.displayName = "CoBrowsePresence";
5447
5601
  var CURSOR_EDGE_INSET = 24;
5448
5602
  var FLUID_CURSOR_SPEED_PX_PER_SECOND = 1050;
@@ -5461,19 +5615,26 @@ function fluidGlideDuration(from, to) {
5461
5615
  const distance = Math.hypot(to.x - from.x, to.y - from.y);
5462
5616
  return Math.round(Math.min(MAX_GLIDE_MS, Math.max(MIN_GLIDE_MS, distance / FLUID_CURSOR_SPEED_PX_PER_SECOND * 1e3)));
5463
5617
  }
5464
- function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
5618
+ var LIFECYCLE_ACTIONS2 = /* @__PURE__ */ new Set(["agent_connected", "agent_disconnected"]);
5619
+ function CoBrowseCursorLayer({
5620
+ active = true,
5621
+ zIndex = 2147483e3,
5622
+ idleAfterMs = 15e3
5623
+ }) {
5465
5624
  const { latest } = useAgentActivity(void 0, { capacity: 12 });
5466
5625
  const [cursor, setCursor] = react.useState(
5467
5626
  null
5468
5627
  );
5469
5628
  const [pulse, setPulse] = react.useState(null);
5629
+ const [lastActionAt, setLastActionAt] = react.useState(0);
5470
5630
  react.useEffect(() => {
5471
5631
  if (!latest || (latest.source ?? "agent") === "user") return;
5472
- if (latest.action === "agent_disconnected") {
5473
- setCursor((prev) => prev ? { ...prev, status: "Standing by", glideMs: 0 } : prev);
5632
+ if (LIFECYCLE_ACTIONS2.has(latest.action)) {
5633
+ setCursor((prev) => prev ? { ...prev, status: "Standing by", glideMs: 0 } : null);
5474
5634
  setPulse(null);
5475
5635
  return;
5476
5636
  }
5637
+ setLastActionAt(latest.timestamp);
5477
5638
  const color = latest.agentColor ?? "#a855f7";
5478
5639
  const name = latest.agentName ?? "Agent";
5479
5640
  const status = latest.target?.label ?? latest.action;
@@ -5495,6 +5656,14 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
5495
5656
  );
5496
5657
  }
5497
5658
  }, [latest?.timestamp]);
5659
+ react.useEffect(() => {
5660
+ if (!idleAfterMs || !lastActionAt) return;
5661
+ const timer = setTimeout(() => {
5662
+ setCursor(null);
5663
+ setPulse(null);
5664
+ }, idleAfterMs);
5665
+ return () => clearTimeout(timer);
5666
+ }, [lastActionAt, idleAfterMs]);
5498
5667
  if (!active || !cursor || typeof document === "undefined") return null;
5499
5668
  return reactDom.createPortal(
5500
5669
  /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-co-browse-cursor-layer": "", style: { position: "fixed", inset: 0, pointerEvents: "none", zIndex }, children: [
@@ -5842,6 +6011,7 @@ exports.MemoryHumanPlusEventStore = MemoryHumanPlusEventStore;
5842
6011
  exports.MicroMcpServer = MicroMcpServer;
5843
6012
  exports.PASSKEY_BRIDGE_TOOLS = PASSKEY_BRIDGE_TOOLS;
5844
6013
  exports.RelayTransport = RelayTransport;
6014
+ exports.SCREEN_TEXT_NODE_TYPE = SCREEN_TEXT_NODE_TYPE;
5845
6015
  exports.ScreensActivityBridge = ScreensActivityBridge;
5846
6016
  exports.ShareControls = ShareControls;
5847
6017
  exports.SimulateUsersButton = SimulateUsersButton;
@@ -5884,6 +6054,7 @@ exports.registerMapBridge = registerMapBridge;
5884
6054
  exports.registerNavigationBridge = registerNavigationBridge;
5885
6055
  exports.registerPasskeyBridge = registerPasskeyBridge;
5886
6056
  exports.registerSceneBridge = registerSceneBridge;
6057
+ exports.registerScreenDocBridge = registerScreenDocBridge;
5887
6058
  exports.registerScreensBridge = registerScreensBridge;
5888
6059
  exports.registerSheetsBridge = registerSheetsBridge;
5889
6060
  exports.registerSlidesBridge = registerSlidesBridge;