@arbidocs/blocks 0.5.127 → 0.5.128

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,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkJVLOIIA7_cjs = require('../chunk-JVLOIIA7.cjs');
4
+ var chunkZQNTYINE_cjs = require('../chunk-ZQNTYINE.cjs');
5
5
  require('../chunk-JITYC4OS.cjs');
6
6
  require('../chunk-WVZLAAIZ.cjs');
7
7
  require('../chunk-X7ALF4MP.cjs');
@@ -10,7 +10,7 @@ var chunkPL7HUTM3_cjs = require('../chunk-PL7HUTM3.cjs');
10
10
  require('../chunk-QWVUBTW3.cjs');
11
11
  require('../chunk-JVEDKKNO.cjs');
12
12
  require('../chunk-ADDQKZ5I.cjs');
13
- require('../chunk-KXIRVKCJ.cjs');
13
+ require('../chunk-ERRXU2HL.cjs');
14
14
  require('../chunk-5QERK4PK.cjs');
15
15
  require('../chunk-T73BHNQX.cjs');
16
16
  require('../chunk-HYUKPHCT.cjs');
@@ -94,7 +94,7 @@ require('../chunk-PLIF5CUV.cjs');
94
94
 
95
95
  Object.defineProperty(exports, "ConnectedDocumentViewer", {
96
96
  enumerable: true,
97
- get: function () { return chunkJVLOIIA7_cjs.ConnectedDocumentViewer; }
97
+ get: function () { return chunkZQNTYINE_cjs.ConnectedDocumentViewer; }
98
98
  });
99
99
  Object.defineProperty(exports, "ConnectedDocumentToolsProvider", {
100
100
  enumerable: true,
@@ -1,7 +1,10 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useState, useEffect, useId } from "react";
4
+ import { Download } from "lucide-react";
5
+ import { Button } from "@arbidocs/react/ui";
4
6
  import { normalizeMermaidGraph } from "../../chat/mermaid-normalize.js";
7
+ import { downloadMermaidSvg } from "./download-mermaid.js";
5
8
  let mermaidInstance = null;
6
9
  let mermaidLoadPromise = null;
7
10
  async function getMermaid() {
@@ -89,12 +92,18 @@ function MermaidDiagram({ chart }) {
89
92
  }
90
93
  );
91
94
  }
92
- return /* @__PURE__ */ jsx(
95
+ return /* @__PURE__ */ jsxs(
93
96
  "div",
94
97
  {
95
98
  className: "mermaid-diagram my-4 overflow-x-auto rounded-md border border-border bg-background p-4",
96
99
  "data-testid": "mermaid-diagram",
97
- dangerouslySetInnerHTML: { __html: svg }
100
+ children: [
101
+ /* @__PURE__ */ jsx("div", { className: "mb-2 flex justify-end", children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: () => downloadMermaidSvg(svg), children: [
102
+ /* @__PURE__ */ jsx(Download, { className: "mr-2 size-4", "aria-hidden": "true" }),
103
+ "Download SVG"
104
+ ] }) }),
105
+ /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: svg } })
106
+ ]
98
107
  }
99
108
  );
100
109
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/connection/conversation/MermaidDiagram.tsx"],
4
- "sourcesContent": ["/**\n * MermaidDiagram Component\n *\n * Renders a Mermaid diagram from source code.\n * Used inside MarkdownRenderer to handle ```mermaid code blocks.\n * Lazy-loads the mermaid library to avoid bloating the initial bundle.\n */\n\nimport { useState, useEffect, useId } from 'react'\nimport { normalizeMermaidGraph } from '../../chat/mermaid-normalize'\n\ninterface MermaidDiagramProps {\n /** Mermaid diagram source code */\n chart: string\n}\n\n// Lazy-load and initialize mermaid once\nlet mermaidInstance: typeof import('mermaid').default | null = null\nlet mermaidLoadPromise: Promise<typeof import('mermaid').default> | null = null\n\nasync function getMermaid() {\n if (mermaidInstance) return mermaidInstance\n if (!mermaidLoadPromise) {\n mermaidLoadPromise = import('mermaid').then((mod) => {\n const m = mod.default\n m.initialize({\n startOnLoad: false,\n theme: 'default',\n securityLevel: 'strict',\n flowchart: { useMaxWidth: true, curve: 'basis' },\n })\n mermaidInstance = m\n return m\n })\n }\n return mermaidLoadPromise\n}\n\nexport function MermaidDiagram({ chart }: MermaidDiagramProps) {\n const [svg, setSvg] = useState<string | null>(null)\n const [error, setError] = useState<string | null>(null)\n const uniqueId = useId().replace(/:/g, '-')\n\n useEffect(() => {\n let cancelled = false\n\n async function render() {\n const mermaid = await getMermaid()\n const diagramId = `mermaid${uniqueId}`\n\n // Validate with parse() before render(). In Mermaid v11 a render() with\n // bad source can return a \"Syntax error in text\" bomb SVG instead of\n // throwing \u2014 and it appends DOM side-effects of its own \u2014 so a try/catch\n // around render() doesn't reliably catch failures and the bomb leaks\n // into the page (especially under React StrictMode where effects run\n // twice). parse() throws cleanly with no DOM side-effects.\n //\n // Defensive rescue: some LLMs emit single-line `graph`/`flowchart`\n // source. If the original parse fails, try a normalized variant. The\n // normalizer is a no-op on already-multi-line source and on non-graph\n // diagram types, so this only helps the bad-source case and never\n // corrupts valid input.\n let validSource: string | null = null\n let firstErr: unknown\n try {\n await mermaid.parse(chart)\n validSource = chart\n } catch (err) {\n firstErr = err\n const normalized = normalizeMermaidGraph(chart)\n if (normalized !== chart) {\n try {\n await mermaid.parse(normalized)\n validSource = normalized\n } catch (retryErr) {\n console.warn('Mermaid normalized parse also failed', retryErr)\n }\n }\n }\n\n if (cancelled) return\n\n if (!validSource) {\n console.warn('Mermaid parse failed, showing source', firstErr)\n setError('Failed to render diagram')\n setSvg(null)\n return\n }\n\n try {\n const { svg: renderedSvg } = await mermaid.render(diagramId, validSource)\n if (!cancelled) {\n setSvg(renderedSvg)\n setError(null)\n }\n } catch (renderErr) {\n if (!cancelled) {\n console.warn('Mermaid render failed despite parse success', renderErr)\n setError('Failed to render diagram')\n setSvg(null)\n }\n }\n }\n\n render()\n return () => {\n cancelled = true\n }\n }, [chart, uniqueId])\n\n if (error) {\n // Fall back to showing the raw source in a code block\n return (\n <div className=\"code-block\" data-testid=\"mermaid-error\">\n <div className=\"text-sm text-muted-foreground mb-1\">{error}</div>\n <code className=\"language-mermaid\">{chart}</code>\n </div>\n )\n }\n\n if (!svg) {\n return (\n <div\n className=\"flex items-center justify-center py-8 text-muted-foreground text-sm\"\n data-testid=\"mermaid-loading\"\n >\n Rendering diagram...\n </div>\n )\n }\n\n return (\n <div\n className=\"mermaid-diagram my-4 overflow-x-auto rounded-md border border-border bg-background p-4\"\n data-testid=\"mermaid-diagram\"\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n )\n}\n"],
5
- "mappings": ";AAiHM,SACE,KADF;AAzGN,SAAS,UAAU,WAAW,aAAa;AAC3C,SAAS,6BAA6B;AAQtC,IAAI,kBAA2D;AAC/D,IAAI,qBAAuE;AAE3E,eAAe,aAAa;AAC1B,MAAI,gBAAiB,QAAO;AAC5B,MAAI,CAAC,oBAAoB;AACvB,yBAAqB,OAAO,SAAS,EAAE,KAAK,CAAC,QAAQ;AACnD,YAAM,IAAI,IAAI;AACd,QAAE,WAAW;AAAA,QACX,aAAa;AAAA,QACb,OAAO;AAAA,QACP,eAAe;AAAA,QACf,WAAW,EAAE,aAAa,MAAM,OAAO,QAAQ;AAAA,MACjD,CAAC;AACD,wBAAkB;AAClB,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEO,SAAS,eAAe,EAAE,MAAM,GAAwB;AAC7D,QAAM,CAAC,KAAK,MAAM,IAAI,SAAwB,IAAI;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,WAAW,MAAM,EAAE,QAAQ,MAAM,GAAG;AAE1C,YAAU,MAAM;AACd,QAAI,YAAY;AAEhB,mBAAe,SAAS;AACtB,YAAM,UAAU,MAAM,WAAW;AACjC,YAAM,YAAY,UAAU,QAAQ;AAcpC,UAAI,cAA6B;AACjC,UAAI;AACJ,UAAI;AACF,cAAM,QAAQ,MAAM,KAAK;AACzB,sBAAc;AAAA,MAChB,SAAS,KAAK;AACZ,mBAAW;AACX,cAAM,aAAa,sBAAsB,KAAK;AAC9C,YAAI,eAAe,OAAO;AACxB,cAAI;AACF,kBAAM,QAAQ,MAAM,UAAU;AAC9B,0BAAc;AAAA,UAChB,SAAS,UAAU;AACjB,oBAAQ,KAAK,wCAAwC,QAAQ;AAAA,UAC/D;AAAA,QACF;AAAA,MACF;AAEA,UAAI,UAAW;AAEf,UAAI,CAAC,aAAa;AAChB,gBAAQ,KAAK,wCAAwC,QAAQ;AAC7D,iBAAS,0BAA0B;AACnC,eAAO,IAAI;AACX;AAAA,MACF;AAEA,UAAI;AACF,cAAM,EAAE,KAAK,YAAY,IAAI,MAAM,QAAQ,OAAO,WAAW,WAAW;AACxE,YAAI,CAAC,WAAW;AACd,iBAAO,WAAW;AAClB,mBAAS,IAAI;AAAA,QACf;AAAA,MACF,SAAS,WAAW;AAClB,YAAI,CAAC,WAAW;AACd,kBAAQ,KAAK,+CAA+C,SAAS;AACrE,mBAAS,0BAA0B;AACnC,iBAAO,IAAI;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AACP,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,MAAI,OAAO;AAET,WACE,qBAAC,SAAI,WAAU,cAAa,eAAY,iBACtC;AAAA,0BAAC,SAAI,WAAU,sCAAsC,iBAAM;AAAA,MAC3D,oBAAC,UAAK,WAAU,oBAAoB,iBAAM;AAAA,OAC5C;AAAA,EAEJ;AAEA,MAAI,CAAC,KAAK;AACR,WACE;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAY;AAAA,QACb;AAAA;AAAA,IAED;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,eAAY;AAAA,MACZ,yBAAyB,EAAE,QAAQ,IAAI;AAAA;AAAA,EACzC;AAEJ;",
4
+ "sourcesContent": ["/**\n * MermaidDiagram Component\n *\n * Renders a Mermaid diagram from source code.\n * Used inside MarkdownRenderer to handle ```mermaid code blocks.\n * Lazy-loads the mermaid library to avoid bloating the initial bundle.\n */\n\nimport { useState, useEffect, useId } from 'react'\nimport { Download } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { normalizeMermaidGraph } from '../../chat/mermaid-normalize'\nimport { downloadMermaidSvg } from './download-mermaid'\n\ninterface MermaidDiagramProps {\n /** Mermaid diagram source code */\n chart: string\n}\n\n// Lazy-load and initialize mermaid once\nlet mermaidInstance: typeof import('mermaid').default | null = null\nlet mermaidLoadPromise: Promise<typeof import('mermaid').default> | null = null\n\nasync function getMermaid() {\n if (mermaidInstance) return mermaidInstance\n if (!mermaidLoadPromise) {\n mermaidLoadPromise = import('mermaid').then((mod) => {\n const m = mod.default\n m.initialize({\n startOnLoad: false,\n theme: 'default',\n securityLevel: 'strict',\n flowchart: { useMaxWidth: true, curve: 'basis' },\n })\n mermaidInstance = m\n return m\n })\n }\n return mermaidLoadPromise\n}\n\nexport function MermaidDiagram({ chart }: MermaidDiagramProps) {\n const [svg, setSvg] = useState<string | null>(null)\n const [error, setError] = useState<string | null>(null)\n const uniqueId = useId().replace(/:/g, '-')\n\n useEffect(() => {\n let cancelled = false\n\n async function render() {\n const mermaid = await getMermaid()\n const diagramId = `mermaid${uniqueId}`\n\n // Validate with parse() before render(). In Mermaid v11 a render() with\n // bad source can return a \"Syntax error in text\" bomb SVG instead of\n // throwing \u2014 and it appends DOM side-effects of its own \u2014 so a try/catch\n // around render() doesn't reliably catch failures and the bomb leaks\n // into the page (especially under React StrictMode where effects run\n // twice). parse() throws cleanly with no DOM side-effects.\n //\n // Defensive rescue: some LLMs emit single-line `graph`/`flowchart`\n // source. If the original parse fails, try a normalized variant. The\n // normalizer is a no-op on already-multi-line source and on non-graph\n // diagram types, so this only helps the bad-source case and never\n // corrupts valid input.\n let validSource: string | null = null\n let firstErr: unknown\n try {\n await mermaid.parse(chart)\n validSource = chart\n } catch (err) {\n firstErr = err\n const normalized = normalizeMermaidGraph(chart)\n if (normalized !== chart) {\n try {\n await mermaid.parse(normalized)\n validSource = normalized\n } catch (retryErr) {\n console.warn('Mermaid normalized parse also failed', retryErr)\n }\n }\n }\n\n if (cancelled) return\n\n if (!validSource) {\n console.warn('Mermaid parse failed, showing source', firstErr)\n setError('Failed to render diagram')\n setSvg(null)\n return\n }\n\n try {\n const { svg: renderedSvg } = await mermaid.render(diagramId, validSource)\n if (!cancelled) {\n setSvg(renderedSvg)\n setError(null)\n }\n } catch (renderErr) {\n if (!cancelled) {\n console.warn('Mermaid render failed despite parse success', renderErr)\n setError('Failed to render diagram')\n setSvg(null)\n }\n }\n }\n\n render()\n return () => {\n cancelled = true\n }\n }, [chart, uniqueId])\n\n if (error) {\n // Fall back to showing the raw source in a code block\n return (\n <div className=\"code-block\" data-testid=\"mermaid-error\">\n <div className=\"text-sm text-muted-foreground mb-1\">{error}</div>\n <code className=\"language-mermaid\">{chart}</code>\n </div>\n )\n }\n\n if (!svg) {\n return (\n <div\n className=\"flex items-center justify-center py-8 text-muted-foreground text-sm\"\n data-testid=\"mermaid-loading\"\n >\n Rendering diagram...\n </div>\n )\n }\n\n return (\n <div\n className=\"mermaid-diagram my-4 overflow-x-auto rounded-md border border-border bg-background p-4\"\n data-testid=\"mermaid-diagram\"\n >\n <div className=\"mb-2 flex justify-end\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => downloadMermaidSvg(svg)}>\n <Download className=\"mr-2 size-4\" aria-hidden=\"true\" />\n Download SVG\n </Button>\n </div>\n <div dangerouslySetInnerHTML={{ __html: svg }} />\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,2 @@
1
+ /** Save the rendered graphic, including Mermaid's styles, as a standalone image. */
2
+ export declare function downloadMermaidSvg(rendered: string): void;
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ function downloadMermaidSvg(rendered) {
3
+ const doc = new DOMParser().parseFromString(rendered, "image/svg+xml");
4
+ const svg = doc.documentElement;
5
+ if (svg.localName !== "svg" || doc.querySelector("parsererror"))
6
+ throw new Error("The diagram did not produce a valid SVG image");
7
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
8
+ const box = svg.getAttribute("viewBox")?.trim().split(/[\s,]+/).map(Number);
9
+ if (box?.length === 4 && box.every(Number.isFinite) && box[2] > 0 && box[3] > 0) {
10
+ svg.setAttribute("width", String(Math.ceil(box[2])));
11
+ svg.setAttribute("height", String(Math.ceil(box[3])));
12
+ }
13
+ const blob = new Blob([new XMLSerializer().serializeToString(svg)], { type: "image/svg+xml" });
14
+ const url = URL.createObjectURL(blob);
15
+ const link = document.createElement("a");
16
+ link.href = url;
17
+ link.download = "diagram.svg";
18
+ document.body.append(link);
19
+ try {
20
+ link.click();
21
+ } finally {
22
+ link.remove();
23
+ setTimeout(() => URL.revokeObjectURL(url), 1e3);
24
+ }
25
+ }
26
+ export {
27
+ downloadMermaidSvg
28
+ };
29
+ //# sourceMappingURL=download-mermaid.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/connection/conversation/download-mermaid.ts"],
4
+ "sourcesContent": ["/** Save the rendered graphic, including Mermaid's styles, as a standalone image. */\nexport function downloadMermaidSvg(rendered: string): void {\n const doc = new DOMParser().parseFromString(rendered, 'image/svg+xml')\n const svg = doc.documentElement\n if (svg.localName !== 'svg' || doc.querySelector('parsererror'))\n throw new Error('The diagram did not produce a valid SVG image')\n svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg')\n const box = svg\n .getAttribute('viewBox')\n ?.trim()\n .split(/[\\s,]+/)\n .map(Number)\n if (box?.length === 4 && box.every(Number.isFinite) && box[2] > 0 && box[3] > 0) {\n svg.setAttribute('width', String(Math.ceil(box[2])))\n svg.setAttribute('height', String(Math.ceil(box[3])))\n }\n const blob = new Blob([new XMLSerializer().serializeToString(svg)], { type: 'image/svg+xml' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = 'diagram.svg'\n document.body.append(link)\n try {\n link.click()\n } finally {\n link.remove()\n // Let the browser consume the download before releasing the image URL.\n setTimeout(() => URL.revokeObjectURL(url), 1000)\n }\n}\n"],
5
+ "mappings": ";AACO,SAAS,mBAAmB,UAAwB;AACzD,QAAM,MAAM,IAAI,UAAU,EAAE,gBAAgB,UAAU,eAAe;AACrE,QAAM,MAAM,IAAI;AAChB,MAAI,IAAI,cAAc,SAAS,IAAI,cAAc,aAAa;AAC5D,UAAM,IAAI,MAAM,+CAA+C;AACjE,MAAI,aAAa,SAAS,4BAA4B;AACtD,QAAM,MAAM,IACT,aAAa,SAAS,GACrB,KAAK,EACN,MAAM,QAAQ,EACd,IAAI,MAAM;AACb,MAAI,KAAK,WAAW,KAAK,IAAI,MAAM,OAAO,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,GAAG;AAC/E,QAAI,aAAa,SAAS,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;AACnD,QAAI,aAAa,UAAU,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,EACtD;AACA,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,cAAc,EAAE,kBAAkB,GAAG,CAAC,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC7F,QAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,QAAM,OAAO,SAAS,cAAc,GAAG;AACvC,OAAK,OAAO;AACZ,OAAK,WAAW;AAChB,WAAS,KAAK,OAAO,IAAI;AACzB,MAAI;AACF,SAAK,MAAM;AAAA,EACb,UAAE;AACA,SAAK,OAAO;AAEZ,eAAW,MAAM,IAAI,gBAAgB,GAAG,GAAG,GAAI;AAAA,EACjD;AACF;",
6
+ "names": []
7
+ }
@@ -18,7 +18,7 @@ const screenRuntimes = /* @__PURE__ */ new WeakMap();
18
18
  function screenRuntime(session) {
19
19
  let runtime = screenRuntimes.get(session);
20
20
  if (!runtime) {
21
- runtime = { sharing: createScreenSharing(), generation: 0, setup: "" };
21
+ runtime = { sharing: createScreenSharing(), generation: 0, setup: "", opening: false };
22
22
  screenRuntimes.set(session, runtime);
23
23
  }
24
24
  return runtime;
@@ -29,6 +29,7 @@ function stopScreen(session) {
29
29
  runtime.generation++;
30
30
  runtime.sharing.stop();
31
31
  runtime.setup = "";
32
+ runtime.opening = false;
32
33
  const actions = remoteControlActions(session);
33
34
  if (remoteControlStateOf(session.getState()).sharing) actions.setSharing(false);
34
35
  }
@@ -61,12 +62,14 @@ function createRemoteControl(session, guided, screenTransport) {
61
62
  actions.setControllingAgent({ name: req.agentName, extId: req.agentExtId });
62
63
  try {
63
64
  if (!runtime.sharing.active) {
65
+ runtime.opening = true;
64
66
  await runtime.sharing.start(disable);
65
67
  if (!current()) {
66
68
  runtime.sharing.stop();
67
69
  await reply(req, "stopped");
68
70
  return;
69
71
  }
72
+ runtime.opening = false;
70
73
  actions.setSharing(true);
71
74
  if (screenTransport.diagnose)
72
75
  runtime.setup = await screenTransport.diagnose().catch(() => "Setup checks unavailable.");
@@ -91,7 +94,9 @@ ${runtime.setup}`.slice(0, 24e3)
91
94
  if (current()) disable();
92
95
  } finally {
93
96
  if (current()) {
94
- actions.setControllingAgent(null);
97
+ const currentAgent = state().controllingAgent;
98
+ if (currentAgent?.name === req.agentName && currentAgent.extId === req.agentExtId)
99
+ actions.setControllingAgent(null);
95
100
  if (!keepSharing) disable();
96
101
  }
97
102
  }
@@ -197,6 +202,17 @@ function useRemoteControlSessionReset() {
197
202
  ];
198
203
  return () => off.forEach((unsubscribe) => unsubscribe?.());
199
204
  }, [arbi, session]);
205
+ useEffect(
206
+ () => session.subscribe(() => {
207
+ const permission = remoteControlStateOf(session.getState());
208
+ const runtime = screenRuntimes.get(session);
209
+ if (runtime && (runtime.sharing.active || runtime.opening) && !permission.enabled && !permission.controllingAgent) {
210
+ stopScreen(session);
211
+ cancelGuidedRun();
212
+ }
213
+ }),
214
+ [session]
215
+ );
200
216
  const lastUser = useRef(userId);
201
217
  useEffect(() => {
202
218
  if (lastUser.current === userId) return;
@@ -218,7 +234,7 @@ function useRemoteControlHandlers() {
218
234
  remoteControlActions(session).setEnabled(false);
219
235
  cancelGuidedRun();
220
236
  },
221
- [session, workspaceId]
237
+ [session, workspaceId, remoteControl]
222
238
  );
223
239
  return useMemo(
224
240
  () => remoteControl ? {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/connection/remote-control/remoteControl.ts"],
4
- "sourcesContent": ["/**\n * Remote-control orchestration \u2014 the frontend side of \"a backend agent drives the UI over the\n * websocket\" (the message and the session state: `@arbidocs/react`'s remote-control module).\n *\n * This is the SEPARATE, gated entry point for websocket-arriving runs. It is deliberately distinct\n * from a site's `GuidedRuns.run` so that local \"Show me\" tips (which run directly) are NEVER gated\n * by consent \u2014 GUARANTEE #4. Only runs that arrive here, from the socket, pass through the gate.\n *\n * Gate logic (`handleMessage`):\n * - the site has not turned remote control on (`guided.remoteControl`), or the consent prompt or\n * the guided cursor is not on screen \u2192 refuse: nothing runs, nothing is asked.\n * - remote control `enabled` this session \u2192 run immediately.\n * - otherwise \u2192 stash the request in `pending` (the consent prompt opens); run NOTHING until the\n * user grants (GUARANTEE #2).\n *\n * What a remote command can run: a `sequence_id` the site registered (`GuidedRuns.isSequenceId`)\n * or inline `steps` whose every step has a target, through the one guided runner \u2014 nothing else\n * (no action dispatch). In a remote run the runner acts only on what the user can see, caps waits\n * and pauses at 5 s, and never acts inside an off-limits surface (remote control's own controls,\n * so a one-off grant cannot grant itself the session; credential and endpoint forms) nor on a\n * label whose control is inside one; no guided run types into a secret field.\n *\n * Every sign-in, sign-out, session expiry and change of user drops the grant, any pending request\n * and the run in flight (`useRemoteControlSessionReset`, mounted with the handler and the cursor),\n * so nothing carries over to the next person in the tab.\n *\n * While a run executes, `controllingAgent` is set (labels the pill) and cleared afterwards.\n * Turning remote control off (`disable`) cancels any in-flight run immediately (GUARANTEE #5).\n */\nimport { useEffect, useMemo, useRef } from 'react'\nimport { logger } from '@arbidocs/client'\nimport {\n remoteControlActions,\n remoteControlStateOf,\n toRemoteControlRequest,\n useArbiHost,\n useArbiSession,\n useArbiSessionStore,\n useArbiSessionState,\n type ArbiWsHandlers,\n type GuidedStep,\n type RemoteControlMessage,\n type RemoteControlRequest,\n type RemoteControlSession,\n} from '@arbidocs/react'\nimport { cancelGuidedRun } from '../../guided/runner'\nimport type { GuidedRuns } from '../../guided/sequences'\nimport { useGuidedRuns } from '../../guided/useGuidedRuns'\nimport { isSurfaceMounted } from '../../guided/surfaces'\nimport { createScreenSharing, type ScreenSharing } from './screen-sharing'\n\nexport interface RemoteControl {\n /** The websocket entry point, for a `remote_control` message. Gated (see the file header). */\n handleMessage(msg: RemoteControlMessage): void\n /**\n * Grant the pending consent and run it. `forSession: true` keeps remote control enabled so\n * later websocket runs go without re-prompting; `false` runs the one pending run and leaves it\n * disabled (\"just this once\").\n */\n grantAndRun(opts: { forSession: boolean }): void\n /** Deny the pending consent \u2014 clears it and runs nothing. */\n deny(): void\n /**\n * Turn remote control OFF and revoke immediately (GUARANTEE #5): clears the enabled flag, the\n * pending prompt and the pill, and cancels any in-flight run so the guided cursor stops at once.\n */\n disable(): void\n /** Turn remote control ON directly \u2014 the user's own explicit choice. Runs nothing by itself. */\n enable(): void\n}\n\nexport interface ScreenTransport {\n reply(\n requestId: string,\n result: {\n status: 'captured' | 'denied' | 'stopped' | 'unavailable' | 'action_finished'\n screenshot_png?: string\n diagnostics?: string\n }\n ): Promise<void>\n diagnose?(): Promise<string>\n}\nconst screenRuntimes = new WeakMap<\n RemoteControlSession,\n { sharing: ScreenSharing; generation: number; setup: string }\n>()\nfunction screenRuntime(session: RemoteControlSession) {\n let runtime = screenRuntimes.get(session)\n if (!runtime) {\n runtime = { sharing: createScreenSharing(), generation: 0, setup: '' }\n screenRuntimes.set(session, runtime)\n }\n return runtime\n}\nfunction stopScreen(session: RemoteControlSession) {\n const runtime = screenRuntimes.get(session)\n if (!runtime) return\n runtime.generation++\n runtime.sharing.stop()\n runtime.setup = ''\n const actions = remoteControlActions(session)\n if (remoteControlStateOf(session.getState()).sharing) actions.setSharing(false)\n}\n\n/** Remote control on a session's state, running the site's guided runs. */\nexport function createRemoteControl(\n session: RemoteControlSession,\n guided: Pick<GuidedRuns, 'isSequenceId' | 'run' | 'remoteControl'>,\n screenTransport?: ScreenTransport\n): RemoteControl {\n const actions = remoteControlActions(session)\n const state = () => remoteControlStateOf(session.getState())\n\n const runtime = screenRuntime(session)\n const reply = async (\n req: RemoteControlRequest,\n status: 'denied' | 'stopped' | 'unavailable' | 'action_finished'\n ) => {\n if ((req.screenRequestId || req.actionRequestId) && screenTransport) {\n await screenTransport\n .reply((req.screenRequestId || req.actionRequestId)!, { status })\n .catch(() => {})\n }\n }\n const disable = () => {\n const pending = state().pending\n if (pending) void reply(pending, 'stopped')\n stopScreen(session)\n actions.setEnabled(false)\n cancelGuidedRun()\n }\n const inspect = async (req: RemoteControlRequest, keepSharing: boolean) => {\n if (!req.screenRequestId || !screenTransport) return\n const workspace = session.getState().workspaceId\n if (workspace !== req.workspaceExtId) {\n await reply(req, 'unavailable')\n return\n }\n const token = runtime.generation\n const current = () =>\n token === runtime.generation && session.getState().workspaceId === workspace\n actions.setControllingAgent({ name: req.agentName, extId: req.agentExtId })\n try {\n if (!runtime.sharing.active) {\n // Called directly from the consent button: getDisplayMedia needs this user gesture.\n await runtime.sharing.start(disable)\n if (!current()) {\n runtime.sharing.stop()\n await reply(req, 'stopped')\n return\n }\n actions.setSharing(true)\n if (screenTransport.diagnose)\n runtime.setup = await screenTransport.diagnose().catch(() => 'Setup checks unavailable.')\n }\n if (!current()) {\n await reply(req, 'stopped')\n return\n }\n const frame = await runtime.sharing.frame()\n if (!current()) {\n await reply(req, 'stopped')\n return\n }\n await screenTransport.reply(req.screenRequestId, {\n status: 'captured',\n ...frame,\n diagnostics: `${frame.diagnostics}\\n${runtime.setup}`.slice(0, 24000),\n })\n } catch {\n await reply(req, current() ? 'unavailable' : 'stopped')\n if (current()) disable()\n } finally {\n if (current()) {\n actions.setControllingAgent(null)\n if (!keepSharing) disable()\n }\n }\n }\n\n /** Resolve a request to the concrete run input for the runner. */\n const resolveRun = (req: RemoteControlRequest): string | GuidedStep[] | null => {\n if (req.steps && req.steps.length > 0) return req.steps\n if (req.sequenceId && guided.isSequenceId(req.sequenceId)) return req.sequenceId\n return null\n }\n\n /** Execute a request, labelling the pill for its duration. The ONLY place a websocket-arriving\n * run reaches the runner. */\n const runRemoteRequest = async (\n req: RemoteControlRequest,\n keepSharing = state().enabled\n ): Promise<void> => {\n if (req.screenRequestId) {\n await inspect(req, keepSharing)\n return\n }\n const run = resolveRun(req)\n if (!run) return\n const token = runtime.generation\n actions.setControllingAgent({ name: req.agentName, extId: req.agentExtId })\n try {\n await guided.run(run, { remote: true })\n if (req.actionRequestId)\n await reply(req, token === runtime.generation ? 'action_finished' : 'stopped')\n } catch {\n await reply(req, 'unavailable')\n } finally {\n // Only clear the pill if THIS run is still the active one \u2014 a newer run or a disable will\n // have replaced/cleared it already.\n const current = state().controllingAgent\n if (current && current.name === req.agentName && current.extId === req.agentExtId) {\n actions.setControllingAgent(null)\n }\n }\n }\n\n return {\n handleMessage(msg) {\n if (!guided.remoteControl) {\n logger.warn('[RemoteControl] Off on this site \u2014 ignoring a request')\n return\n }\n if (!isSurfaceMounted('consent') || !isSurfaceMounted('cursor')) {\n logger.warn('[RemoteControl] No consent prompt or cursor on screen \u2014 ignoring a request')\n return\n }\n const req = toRemoteControlRequest(msg, guided.isSequenceId)\n if (!req) return\n if (\n (req.screenRequestId || req.actionRequestId) &&\n (!screenTransport || session.getState().workspaceId !== req.workspaceExtId)\n ) {\n void reply(req, 'unavailable')\n return\n }\n if (state().enabled && (!req.screenRequestId || runtime.sharing.active)) {\n logger.info('[RemoteControl] Enabled \u2014 running requested action from', req.agentName)\n void runRemoteRequest(req)\n return\n }\n logger.info('[RemoteControl] Consent required \u2014 prompting for', req.agentName)\n if (state().pending) void reply(state().pending!, 'denied')\n actions.request(req)\n },\n grantAndRun(opts) {\n const pending = state().pending\n const keepSharing = opts.forSession || state().enabled\n actions.grant(opts)\n if (pending) void runRemoteRequest(pending, keepSharing)\n },\n deny: () => {\n const pending = state().pending\n actions.deny()\n if (pending) void reply(pending, 'denied')\n },\n disable,\n enable: () => actions.setEnabled(true),\n }\n}\n\n/** Remote control on the host's session and guided runs. */\nexport function useRemoteControlActions(): RemoteControl {\n const session = useArbiSessionStore()\n const guided = useGuidedRuns()\n const { arbi } = useArbiHost()\n return useMemo(\n () =>\n createRemoteControl(\n session,\n guided,\n arbi\n ? {\n reply: (id, result) => arbi.remoteControl.replyScreen(id, result),\n diagnose: async () => JSON.stringify(await arbi.diagnose()),\n }\n : undefined\n ),\n [session, guided, arbi]\n )\n}\n\n/**\n * Drop remote control's grant, its pending request and the guided run in flight on every sign-in,\n * sign-out and session expiry of the host's `Arbi`, and whenever the signed-in user changes (a\n * host that signs in its own way), so nothing carries over to the next person in the tab.\n */\nexport function useRemoteControlSessionReset(): void {\n const session = useArbiSessionStore()\n const { arbi } = useArbiHost()\n const userId = useArbiSession().user?.external_id ?? null\n useEffect(() => {\n const reset = () => {\n stopScreen(session)\n remoteControlActions(session).reset()\n cancelGuidedRun()\n }\n if (!arbi) return\n // A host's stand-in `Arbi` (a demo, a test) may lack some of them.\n const off = [\n arbi.onSigningOut?.(reset),\n arbi.onSessionExpired?.(reset),\n arbi.onSignedIn?.(reset),\n ]\n return () => off.forEach((unsubscribe) => unsubscribe?.())\n }, [arbi, session])\n const lastUser = useRef(userId)\n useEffect(() => {\n if (lastUser.current === userId) return\n lastUser.current = userId\n stopScreen(session)\n remoteControlActions(session).reset()\n cancelGuidedRun()\n }, [userId, session])\n}\n\n/**\n * The live connection's handler for remote control (`ArbiWebSocketProvider` `handlers`): an\n * `agt-\u2026` agent asking to drive the UI goes to the consent-gated entry point. None while the\n * site has not turned remote control on (`guided.remoteControl`). It also drops the grant and\n * the run in flight at every sign-in and sign-out (`useRemoteControlSessionReset`).\n */\nexport function useRemoteControlHandlers(): ArbiWsHandlers {\n useRemoteControlSessionReset()\n const remote = useRemoteControlActions()\n const { remoteControl } = useGuidedRuns()\n const session = useArbiSessionStore()\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n // The handler owns the stream lifecycle. A route/auth host teardown always stops sharing.\n useEffect(\n () => () => {\n stopScreen(session)\n remoteControlActions(session).setEnabled(false)\n cancelGuidedRun()\n },\n [session, workspaceId]\n )\n return useMemo(\n () =>\n remoteControl\n ? {\n remote_control: (message) =>\n remote.handleMessage(message as unknown as RemoteControlMessage),\n }\n : {},\n [remote, remoteControl]\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Remote-control orchestration \u2014 the frontend side of \"a backend agent drives the UI over the\n * websocket\" (the message and the session state: `@arbidocs/react`'s remote-control module).\n *\n * This is the SEPARATE, gated entry point for websocket-arriving runs. It is deliberately distinct\n * from a site's `GuidedRuns.run` so that local \"Show me\" tips (which run directly) are NEVER gated\n * by consent \u2014 GUARANTEE #4. Only runs that arrive here, from the socket, pass through the gate.\n *\n * Gate logic (`handleMessage`):\n * - the site has not turned remote control on (`guided.remoteControl`), or the consent prompt or\n * the guided cursor is not on screen \u2192 refuse: nothing runs, nothing is asked.\n * - remote control `enabled` this session \u2192 run immediately.\n * - otherwise \u2192 stash the request in `pending` (the consent prompt opens); run NOTHING until the\n * user grants (GUARANTEE #2).\n *\n * What a remote command can run: a `sequence_id` the site registered (`GuidedRuns.isSequenceId`)\n * or inline `steps` whose every step has a target, through the one guided runner \u2014 nothing else\n * (no action dispatch). In a remote run the runner acts only on what the user can see, caps waits\n * and pauses at 5 s, and never acts inside an off-limits surface (remote control's own controls,\n * so a one-off grant cannot grant itself the session; credential and endpoint forms) nor on a\n * label whose control is inside one; no guided run types into a secret field.\n *\n * Every sign-in, sign-out, session expiry and change of user drops the grant, any pending request\n * and the run in flight (`useRemoteControlSessionReset`, mounted with the handler and the cursor),\n * so nothing carries over to the next person in the tab.\n *\n * While a run executes, `controllingAgent` is set (labels the pill) and cleared afterwards.\n * Turning remote control off (`disable`) cancels any in-flight run immediately (GUARANTEE #5).\n */\nimport { useEffect, useMemo, useRef } from 'react'\nimport { logger } from '@arbidocs/client'\nimport {\n remoteControlActions,\n remoteControlStateOf,\n toRemoteControlRequest,\n useArbiHost,\n useArbiSession,\n useArbiSessionStore,\n useArbiSessionState,\n type ArbiWsHandlers,\n type GuidedStep,\n type RemoteControlMessage,\n type RemoteControlRequest,\n type RemoteControlSession,\n} from '@arbidocs/react'\nimport { cancelGuidedRun } from '../../guided/runner'\nimport type { GuidedRuns } from '../../guided/sequences'\nimport { useGuidedRuns } from '../../guided/useGuidedRuns'\nimport { isSurfaceMounted } from '../../guided/surfaces'\nimport { createScreenSharing, type ScreenSharing } from './screen-sharing'\n\nexport interface RemoteControl {\n /** The websocket entry point, for a `remote_control` message. Gated (see the file header). */\n handleMessage(msg: RemoteControlMessage): void\n /**\n * Grant the pending consent and run it. `forSession: true` keeps remote control enabled so\n * later websocket runs go without re-prompting; `false` runs the one pending run and leaves it\n * disabled (\"just this once\").\n */\n grantAndRun(opts: { forSession: boolean }): void\n /** Deny the pending consent \u2014 clears it and runs nothing. */\n deny(): void\n /**\n * Turn remote control OFF and revoke immediately (GUARANTEE #5): clears the enabled flag, the\n * pending prompt and the pill, and cancels any in-flight run so the guided cursor stops at once.\n */\n disable(): void\n /** Turn remote control ON directly \u2014 the user's own explicit choice. Runs nothing by itself. */\n enable(): void\n}\n\nexport interface ScreenTransport {\n reply(\n requestId: string,\n result: {\n status: 'captured' | 'denied' | 'stopped' | 'unavailable' | 'action_finished'\n screenshot_png?: string\n diagnostics?: string\n }\n ): Promise<void>\n diagnose?(): Promise<string>\n}\nconst screenRuntimes = new WeakMap<\n RemoteControlSession,\n { sharing: ScreenSharing; generation: number; setup: string; opening: boolean }\n>()\nfunction screenRuntime(session: RemoteControlSession) {\n let runtime = screenRuntimes.get(session)\n if (!runtime) {\n runtime = { sharing: createScreenSharing(), generation: 0, setup: '', opening: false }\n screenRuntimes.set(session, runtime)\n }\n return runtime\n}\nfunction stopScreen(session: RemoteControlSession) {\n const runtime = screenRuntimes.get(session)\n if (!runtime) return\n runtime.generation++\n runtime.sharing.stop()\n runtime.setup = ''\n runtime.opening = false\n const actions = remoteControlActions(session)\n if (remoteControlStateOf(session.getState()).sharing) actions.setSharing(false)\n}\n\n/** Remote control on a session's state, running the site's guided runs. */\nexport function createRemoteControl(\n session: RemoteControlSession,\n guided: Pick<GuidedRuns, 'isSequenceId' | 'run' | 'remoteControl'>,\n screenTransport?: ScreenTransport\n): RemoteControl {\n const actions = remoteControlActions(session)\n const state = () => remoteControlStateOf(session.getState())\n\n const runtime = screenRuntime(session)\n const reply = async (\n req: RemoteControlRequest,\n status: 'denied' | 'stopped' | 'unavailable' | 'action_finished'\n ) => {\n if ((req.screenRequestId || req.actionRequestId) && screenTransport) {\n await screenTransport\n .reply((req.screenRequestId || req.actionRequestId)!, { status })\n .catch(() => {})\n }\n }\n const disable = () => {\n const pending = state().pending\n if (pending) void reply(pending, 'stopped')\n stopScreen(session)\n actions.setEnabled(false)\n cancelGuidedRun()\n }\n const inspect = async (req: RemoteControlRequest, keepSharing: boolean) => {\n if (!req.screenRequestId || !screenTransport) return\n const workspace = session.getState().workspaceId\n if (workspace !== req.workspaceExtId) {\n await reply(req, 'unavailable')\n return\n }\n const token = runtime.generation\n const current = () =>\n token === runtime.generation && session.getState().workspaceId === workspace\n actions.setControllingAgent({ name: req.agentName, extId: req.agentExtId })\n try {\n if (!runtime.sharing.active) {\n // Called directly from the consent button: getDisplayMedia needs this user gesture.\n runtime.opening = true\n await runtime.sharing.start(disable)\n if (!current()) {\n runtime.sharing.stop()\n await reply(req, 'stopped')\n return\n }\n runtime.opening = false\n actions.setSharing(true)\n if (screenTransport.diagnose)\n runtime.setup = await screenTransport.diagnose().catch(() => 'Setup checks unavailable.')\n }\n if (!current()) {\n await reply(req, 'stopped')\n return\n }\n const frame = await runtime.sharing.frame()\n if (!current()) {\n await reply(req, 'stopped')\n return\n }\n await screenTransport.reply(req.screenRequestId, {\n status: 'captured',\n ...frame,\n diagnostics: `${frame.diagnostics}\\n${runtime.setup}`.slice(0, 24000),\n })\n } catch {\n await reply(req, current() ? 'unavailable' : 'stopped')\n if (current()) disable()\n } finally {\n if (current()) {\n const currentAgent = state().controllingAgent\n if (currentAgent?.name === req.agentName && currentAgent.extId === req.agentExtId)\n actions.setControllingAgent(null)\n if (!keepSharing) disable()\n }\n }\n }\n\n /** Resolve a request to the concrete run input for the runner. */\n const resolveRun = (req: RemoteControlRequest): string | GuidedStep[] | null => {\n if (req.steps && req.steps.length > 0) return req.steps\n if (req.sequenceId && guided.isSequenceId(req.sequenceId)) return req.sequenceId\n return null\n }\n\n /** Execute a request, labelling the pill for its duration. The ONLY place a websocket-arriving\n * run reaches the runner. */\n const runRemoteRequest = async (\n req: RemoteControlRequest,\n keepSharing = state().enabled\n ): Promise<void> => {\n if (req.screenRequestId) {\n await inspect(req, keepSharing)\n return\n }\n const run = resolveRun(req)\n if (!run) return\n const token = runtime.generation\n actions.setControllingAgent({ name: req.agentName, extId: req.agentExtId })\n try {\n await guided.run(run, { remote: true })\n if (req.actionRequestId)\n await reply(req, token === runtime.generation ? 'action_finished' : 'stopped')\n } catch {\n await reply(req, 'unavailable')\n } finally {\n // Only clear the pill if THIS run is still the active one \u2014 a newer run or a disable will\n // have replaced/cleared it already.\n const current = state().controllingAgent\n if (current && current.name === req.agentName && current.extId === req.agentExtId) {\n actions.setControllingAgent(null)\n }\n }\n }\n\n return {\n handleMessage(msg) {\n if (!guided.remoteControl) {\n logger.warn('[RemoteControl] Off on this site \u2014 ignoring a request')\n return\n }\n if (!isSurfaceMounted('consent') || !isSurfaceMounted('cursor')) {\n logger.warn('[RemoteControl] No consent prompt or cursor on screen \u2014 ignoring a request')\n return\n }\n const req = toRemoteControlRequest(msg, guided.isSequenceId)\n if (!req) return\n if (\n (req.screenRequestId || req.actionRequestId) &&\n (!screenTransport || session.getState().workspaceId !== req.workspaceExtId)\n ) {\n void reply(req, 'unavailable')\n return\n }\n if (state().enabled && (!req.screenRequestId || runtime.sharing.active)) {\n logger.info('[RemoteControl] Enabled \u2014 running requested action from', req.agentName)\n void runRemoteRequest(req)\n return\n }\n logger.info('[RemoteControl] Consent required \u2014 prompting for', req.agentName)\n if (state().pending) void reply(state().pending!, 'denied')\n actions.request(req)\n },\n grantAndRun(opts) {\n const pending = state().pending\n const keepSharing = opts.forSession || state().enabled\n actions.grant(opts)\n if (pending) void runRemoteRequest(pending, keepSharing)\n },\n deny: () => {\n const pending = state().pending\n actions.deny()\n if (pending) void reply(pending, 'denied')\n },\n disable,\n enable: () => actions.setEnabled(true),\n }\n}\n\n/** Remote control on the host's session and guided runs. */\nexport function useRemoteControlActions(): RemoteControl {\n const session = useArbiSessionStore()\n const guided = useGuidedRuns()\n const { arbi } = useArbiHost()\n return useMemo(\n () =>\n createRemoteControl(\n session,\n guided,\n arbi\n ? {\n reply: (id, result) => arbi.remoteControl.replyScreen(id, result),\n diagnose: async () => JSON.stringify(await arbi.diagnose()),\n }\n : undefined\n ),\n [session, guided, arbi]\n )\n}\n\n/**\n * Drop remote control's grant, its pending request and the guided run in flight on every sign-in,\n * sign-out and session expiry of the host's `Arbi`, and whenever the signed-in user changes (a\n * host that signs in its own way), so nothing carries over to the next person in the tab.\n */\nexport function useRemoteControlSessionReset(): void {\n const session = useArbiSessionStore()\n const { arbi } = useArbiHost()\n const userId = useArbiSession().user?.external_id ?? null\n useEffect(() => {\n const reset = () => {\n stopScreen(session)\n remoteControlActions(session).reset()\n cancelGuidedRun()\n }\n if (!arbi) return\n // A host's stand-in `Arbi` (a demo, a test) may lack some of them.\n const off = [\n arbi.onSigningOut?.(reset),\n arbi.onSessionExpired?.(reset),\n arbi.onSignedIn?.(reset),\n ]\n return () => off.forEach((unsubscribe) => unsubscribe?.())\n }, [arbi, session])\n // A layout/session reset can drop the transient grant without calling the UI's disable action.\n // Close the native stream (including an unresolved browser picker) when that happens.\n useEffect(\n () =>\n session.subscribe(() => {\n const permission = remoteControlStateOf(session.getState())\n const runtime = screenRuntimes.get(session)\n if (\n runtime &&\n (runtime.sharing.active || runtime.opening) &&\n !permission.enabled &&\n !permission.controllingAgent\n ) {\n stopScreen(session)\n cancelGuidedRun()\n }\n }),\n [session]\n )\n const lastUser = useRef(userId)\n useEffect(() => {\n if (lastUser.current === userId) return\n lastUser.current = userId\n stopScreen(session)\n remoteControlActions(session).reset()\n cancelGuidedRun()\n }, [userId, session])\n}\n\n/**\n * The live connection's handler for remote control (`ArbiWebSocketProvider` `handlers`): an\n * `agt-\u2026` agent asking to drive the UI goes to the consent-gated entry point. None while the\n * site has not turned remote control on (`guided.remoteControl`). It also drops the grant and\n * the run in flight at every sign-in and sign-out (`useRemoteControlSessionReset`).\n */\nexport function useRemoteControlHandlers(): ArbiWsHandlers {\n useRemoteControlSessionReset()\n const remote = useRemoteControlActions()\n const { remoteControl } = useGuidedRuns()\n const session = useArbiSessionStore()\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n // The handler owns the stream lifecycle. A route/auth host teardown always stops sharing.\n useEffect(\n () => () => {\n stopScreen(session)\n remoteControlActions(session).setEnabled(false)\n cancelGuidedRun()\n },\n [session, workspaceId, remoteControl]\n )\n return useMemo(\n () =>\n remoteControl\n ? {\n remote_control: (message) =>\n remote.handleMessage(message as unknown as RemoteControlMessage),\n }\n : {},\n [remote, remoteControl]\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunk2SU37RZA_cjs = require('../chunk-2SU37RZA.cjs');
4
+ var chunkIWMHQTVL_cjs = require('../chunk-IWMHQTVL.cjs');
5
5
  require('../chunk-XF355M7O.cjs');
6
6
  require('../chunk-2F57IO7S.cjs');
7
7
  require('../chunk-7NLO7ASW.cjs');
@@ -9,7 +9,7 @@ require('../chunk-7PN3YENO.cjs');
9
9
  require('../chunk-UFT22LAB.cjs');
10
10
  require('../chunk-TJY7XPDE.cjs');
11
11
  require('../chunk-XNW62J54.cjs');
12
- require('../chunk-KXIRVKCJ.cjs');
12
+ require('../chunk-ERRXU2HL.cjs');
13
13
  require('../chunk-5QERK4PK.cjs');
14
14
  require('../chunk-T73BHNQX.cjs');
15
15
  require('../chunk-HYUKPHCT.cjs');
@@ -86,27 +86,27 @@ require('../chunk-PLIF5CUV.cjs');
86
86
 
87
87
  Object.defineProperty(exports, "ArbiChat", {
88
88
  enumerable: true,
89
- get: function () { return chunk2SU37RZA_cjs.ArbiChat; }
89
+ get: function () { return chunkIWMHQTVL_cjs.ArbiChat; }
90
90
  });
91
91
  Object.defineProperty(exports, "ConnectedCompactLogin", {
92
92
  enumerable: true,
93
- get: function () { return chunk2SU37RZA_cjs.ConnectedCompactLogin; }
93
+ get: function () { return chunkIWMHQTVL_cjs.ConnectedCompactLogin; }
94
94
  });
95
95
  Object.defineProperty(exports, "ConnectedEmbeddedChat", {
96
96
  enumerable: true,
97
- get: function () { return chunk2SU37RZA_cjs.ConnectedEmbeddedChat; }
97
+ get: function () { return chunkIWMHQTVL_cjs.ConnectedEmbeddedChat; }
98
98
  });
99
99
  Object.defineProperty(exports, "ConnectedLoginPage", {
100
100
  enumerable: true,
101
- get: function () { return chunk2SU37RZA_cjs.ConnectedLoginPage; }
101
+ get: function () { return chunkIWMHQTVL_cjs.ConnectedLoginPage; }
102
102
  });
103
103
  Object.defineProperty(exports, "EmbeddedChatPanel", {
104
104
  enumerable: true,
105
- get: function () { return chunk2SU37RZA_cjs.EmbeddedChatPanel; }
105
+ get: function () { return chunkIWMHQTVL_cjs.EmbeddedChatPanel; }
106
106
  });
107
107
  Object.defineProperty(exports, "defaultHost", {
108
108
  enumerable: true,
109
- get: function () { return chunk2SU37RZA_cjs.defaultHost; }
109
+ get: function () { return chunkIWMHQTVL_cjs.defaultHost; }
110
110
  });
111
111
  Object.defineProperty(exports, "useConnection", {
112
112
  enumerable: true,