@particle-academy/agent-integrations 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridges/artboard.d.cts +3 -3
- package/dist/bridges/artboard.d.ts +3 -3
- package/dist/bridges/catalog.d.cts +3 -3
- package/dist/bridges/catalog.d.ts +3 -3
- package/dist/bridges/charts.d.cts +3 -3
- package/dist/bridges/charts.d.ts +3 -3
- package/dist/bridges/cms.d.cts +50 -0
- package/dist/bridges/cms.d.ts +50 -0
- package/dist/bridges/code.d.cts +3 -3
- package/dist/bridges/code.d.ts +3 -3
- package/dist/bridges/doc.d.cts +68 -0
- package/dist/bridges/doc.d.ts +68 -0
- package/dist/bridges/features.d.cts +3 -3
- package/dist/bridges/features.d.ts +3 -3
- package/dist/bridges/files.d.cts +3 -3
- package/dist/bridges/files.d.ts +3 -3
- package/dist/bridges/flow.d.cts +3 -3
- package/dist/bridges/flow.d.ts +3 -3
- package/dist/bridges/forms.d.cts +3 -3
- package/dist/bridges/forms.d.ts +3 -3
- package/dist/bridges/map.d.cts +3 -3
- package/dist/bridges/map.d.ts +3 -3
- package/dist/bridges/scene.d.cts +3 -3
- package/dist/bridges/scene.d.ts +3 -3
- package/dist/bridges/screens.d.cts +3 -3
- package/dist/bridges/screens.d.ts +3 -3
- package/dist/bridges/sheets.d.cts +3 -3
- package/dist/bridges/sheets.d.ts +3 -3
- package/dist/bridges/slides.d.cts +3 -3
- package/dist/bridges/slides.d.ts +3 -3
- package/dist/bridges/terminal.d.cts +3 -3
- package/dist/bridges/terminal.d.ts +3 -3
- package/dist/bridges/whiteboard.d.cts +3 -3
- package/dist/bridges/whiteboard.d.ts +3 -3
- package/dist/bridges-artboard.js +1 -1
- package/dist/bridges-catalog.js +2 -2
- package/dist/bridges-charts.js +2 -2
- package/dist/bridges-cms.cjs +437 -0
- package/dist/bridges-cms.cjs.map +1 -0
- package/dist/bridges-cms.js +8 -0
- package/dist/bridges-cms.js.map +1 -0
- package/dist/bridges-code.js +2 -2
- package/dist/bridges-doc.cjs +364 -0
- package/dist/bridges-doc.cjs.map +1 -0
- package/dist/bridges-doc.js +7 -0
- package/dist/bridges-doc.js.map +1 -0
- package/dist/bridges-features.js +2 -2
- package/dist/bridges-files.js +2 -2
- package/dist/bridges-flow.js +1 -1
- package/dist/bridges-forms.js +2 -2
- package/dist/bridges-map.js +2 -2
- package/dist/bridges-scene.js +2 -2
- package/dist/bridges-screens.js +2 -2
- package/dist/bridges-sheets.js +2 -2
- package/dist/bridges-slides.js +2 -2
- package/dist/bridges-terminal.js +2 -2
- package/dist/bridges-whiteboard.js +2 -2
- package/dist/{chunk-HKQBG2HZ.js → chunk-5KLUYF4D.js} +3 -3
- package/dist/{chunk-HKQBG2HZ.js.map → chunk-5KLUYF4D.js.map} +1 -1
- package/dist/{chunk-YMX7G3XM.js → chunk-66WOHZZJ.js} +3 -3
- package/dist/{chunk-YMX7G3XM.js.map → chunk-66WOHZZJ.js.map} +1 -1
- package/dist/chunk-A57CRGEK.js +79 -0
- package/dist/chunk-A57CRGEK.js.map +1 -0
- package/dist/{chunk-XQZGB4FP.js → chunk-AAD3Z5E7.js} +3 -3
- package/dist/{chunk-XQZGB4FP.js.map → chunk-AAD3Z5E7.js.map} +1 -1
- package/dist/{chunk-3QJSOS7G.js → chunk-AAMQOXZC.js} +3 -3
- package/dist/{chunk-3QJSOS7G.js.map → chunk-AAMQOXZC.js.map} +1 -1
- package/dist/{chunk-EP3G4LYW.js → chunk-AROVENCE.js} +3 -3
- package/dist/{chunk-EP3G4LYW.js.map → chunk-AROVENCE.js.map} +1 -1
- package/dist/chunk-FF5F526J.js +245 -0
- package/dist/chunk-FF5F526J.js.map +1 -0
- package/dist/{chunk-57KAMBAR.js → chunk-HWVVS6HE.js} +3 -3
- package/dist/{chunk-57KAMBAR.js.map → chunk-HWVVS6HE.js.map} +1 -1
- package/dist/{chunk-FUI7KXE7.js → chunk-KMSRG5KH.js} +35 -2
- package/dist/chunk-KMSRG5KH.js.map +1 -0
- package/dist/{chunk-QDF37J3V.js → chunk-NN3ELTVO.js} +3 -3
- package/dist/{chunk-QDF37J3V.js.map → chunk-NN3ELTVO.js.map} +1 -1
- package/dist/{chunk-775LJJTJ.js → chunk-PCW2EK5G.js} +3 -3
- package/dist/{chunk-775LJJTJ.js.map → chunk-PCW2EK5G.js.map} +1 -1
- package/dist/{chunk-46H4C5AP.js → chunk-QDD4WHIV.js} +3 -3
- package/dist/{chunk-46H4C5AP.js.map → chunk-QDD4WHIV.js.map} +1 -1
- package/dist/{chunk-V5BXBX7U.js → chunk-QRDVJW6Q.js} +3 -3
- package/dist/{chunk-V5BXBX7U.js.map → chunk-QRDVJW6Q.js.map} +1 -1
- package/dist/{chunk-267JS64O.js → chunk-VFKO2VUR.js} +3 -3
- package/dist/{chunk-267JS64O.js.map → chunk-VFKO2VUR.js.map} +1 -1
- package/dist/{chunk-CLFDQ2BW.js → chunk-XMMCSQ4I.js} +3 -3
- package/dist/{chunk-CLFDQ2BW.js.map → chunk-XMMCSQ4I.js.map} +1 -1
- package/dist/{chunk-K3S6WSHZ.js → chunk-YGD2VTUM.js} +3 -3
- package/dist/{chunk-K3S6WSHZ.js.map → chunk-YGD2VTUM.js.map} +1 -1
- package/dist/{chunk-NKRSLCS7.js → chunk-ZX6UQURN.js} +3 -3
- package/dist/{chunk-NKRSLCS7.js.map → chunk-ZX6UQURN.js.map} +1 -1
- package/dist/components-shared-whiteboard.cjs +32 -0
- package/dist/components-shared-whiteboard.cjs.map +1 -1
- package/dist/components-shared-whiteboard.js +4 -4
- package/dist/index.cjs +376 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -7
- package/dist/index.d.ts +14 -7
- package/dist/index.js +54 -29
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.cts +5 -5
- package/dist/mcp/index.d.ts +5 -5
- package/dist/presence/index.d.cts +1 -1
- package/dist/presence/index.d.ts +1 -1
- package/dist/{server-BsSwfemr.d.cts → server-Dr3j48CU.d.cts} +2 -2
- package/dist/{server-Du3-IGqM.d.ts → server-FFZpYPyM.d.ts} +2 -2
- package/dist/sharing/index.d.cts +4 -3
- package/dist/sharing/index.d.ts +4 -3
- package/dist/sharing.cjs +32 -0
- package/dist/sharing.cjs.map +1 -1
- package/dist/sharing.js +2 -1
- package/dist/sheets-adapter.d.cts +3 -3
- package/dist/sheets-adapter.d.ts +3 -3
- package/dist/{tool-host-C8JMMGYq.d.ts → tool-host-C_Vh17J_.d.ts} +1 -1
- package/dist/{tool-host-BQuUygLF.d.cts → tool-host-IDecPrF1.d.cts} +1 -1
- package/dist/{types-CCSBGW9T.d.cts → types-B0rmWyoR.d.cts} +1 -1
- package/dist/{types-aOQLTW0E.d.cts → types-BDI_g5UG.d.cts} +1 -1
- package/dist/{types-aOQLTW0E.d.ts → types-BDI_g5UG.d.ts} +1 -1
- package/dist/{types-DIVNcIQO.d.ts → types-CBoQhR8L.d.ts} +1 -1
- package/dist/undo/index.d.cts +2 -2
- package/dist/undo/index.d.ts +2 -2
- package/package.json +23 -2
- package/dist/chunk-FUI7KXE7.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-
|
|
2
|
-
import { createSessionDescriptor, attachSseRelay } from './chunk-
|
|
1
|
+
import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-5KLUYF4D.js';
|
|
2
|
+
import { createSessionDescriptor, attachSseRelay } from './chunk-KMSRG5KH.js';
|
|
3
3
|
import { attachInProcess } from './chunk-AFUULW5E.js';
|
|
4
|
-
import { registerWhiteboardBridge } from './chunk-
|
|
5
|
-
import './chunk-KJ5AOOV7.js';
|
|
4
|
+
import { registerWhiteboardBridge } from './chunk-AAMQOXZC.js';
|
|
6
5
|
import './chunk-ULJL53DL.js';
|
|
6
|
+
import './chunk-KJ5AOOV7.js';
|
|
7
7
|
import './chunk-C3TYI5TJ.js';
|
|
8
8
|
import { MicroMcpServer } from './chunk-4KAIV6OD.js';
|
|
9
9
|
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var fancyAutoCommon = require('@particle-academy/fancy-auto-common');
|
|
4
4
|
var react = require('react');
|
|
5
|
+
var fancyDocCommons = require('@particle-academy/fancy-doc-commons');
|
|
5
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
7
|
var reactDom = require('react-dom');
|
|
7
8
|
|
|
@@ -2819,7 +2820,7 @@ function registerNavigationBridge(host, options) {
|
|
|
2819
2820
|
].join("\n");
|
|
2820
2821
|
return textResult(text, snap);
|
|
2821
2822
|
},
|
|
2822
|
-
|
|
2823
|
+
() => target("Inspect page")
|
|
2823
2824
|
);
|
|
2824
2825
|
reg(
|
|
2825
2826
|
"page_read",
|
|
@@ -2827,7 +2828,23 @@ function registerNavigationBridge(host, options) {
|
|
|
2827
2828
|
{},
|
|
2828
2829
|
[],
|
|
2829
2830
|
() => textResult(adapter.read ? adapter.read() : "(host did not provide page text)"),
|
|
2830
|
-
|
|
2831
|
+
() => target("Read page")
|
|
2832
|
+
);
|
|
2833
|
+
reg(
|
|
2834
|
+
"page_focus",
|
|
2835
|
+
"Move the agent's visible focus to an interactive element by stable handle without activating it.",
|
|
2836
|
+
{ handle: { type: "string" } },
|
|
2837
|
+
["handle"],
|
|
2838
|
+
(args) => {
|
|
2839
|
+
const handle = String(args.handle ?? "");
|
|
2840
|
+
const action = adapter.describe().actions.find((candidate) => candidate.handle === handle);
|
|
2841
|
+
if (!action) return errorResult(`No element for handle "${handle}"`);
|
|
2842
|
+
return textResult(`Focused ${handle}`, {
|
|
2843
|
+
handle,
|
|
2844
|
+
rect: adapter.rectFor?.(handle) ?? void 0
|
|
2845
|
+
});
|
|
2846
|
+
},
|
|
2847
|
+
(args) => target(`Focus ${String(args.handle ?? "")}`, String(args.handle ?? ""))
|
|
2831
2848
|
);
|
|
2832
2849
|
reg(
|
|
2833
2850
|
"nav_visit",
|
|
@@ -3486,6 +3503,314 @@ function registerFeaturesBridge(host, options) {
|
|
|
3486
3503
|
}
|
|
3487
3504
|
};
|
|
3488
3505
|
}
|
|
3506
|
+
var DEFAULT_AGENT14 = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
3507
|
+
function registerDocBridge(host, options) {
|
|
3508
|
+
const { adapter, surface } = options;
|
|
3509
|
+
const agent = { ...DEFAULT_AGENT14, ...options.agent ?? {} };
|
|
3510
|
+
const reducer = options.reducer ?? fancyDocCommons.treeReducer();
|
|
3511
|
+
const stage = options.stagePolicy ?? fancyDocCommons.autoApply;
|
|
3512
|
+
const makeNode = options.makeNode ?? (({ id, type, parent, order }, props) => ({ id, type, parent, order, props }));
|
|
3513
|
+
const describeNode = options.describeNode ?? ((n) => ({ id: n.id, type: n.type, parent: n.parent, props: Object.keys(n.props ?? {}) }));
|
|
3514
|
+
const disposers = [];
|
|
3515
|
+
ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
|
|
3516
|
+
let idSeq = 0;
|
|
3517
|
+
const mintId = () => adapter.newId?.() ?? `${surface}-${idSeq += 1}`;
|
|
3518
|
+
const target = (elementId) => ({ kind: surface, screenId: adapter.screenId, elementId });
|
|
3519
|
+
const pending = /* @__PURE__ */ new Map();
|
|
3520
|
+
function commit(op, label, targetId) {
|
|
3521
|
+
const prev = adapter.get();
|
|
3522
|
+
const next = reducer.reduce(prev, op);
|
|
3523
|
+
adapter.set(next);
|
|
3524
|
+
fancyAutoCommon.pushUndoEntry(agent.id, {
|
|
3525
|
+
timestamp: Date.now(),
|
|
3526
|
+
bridgeId: surface,
|
|
3527
|
+
action: label,
|
|
3528
|
+
label,
|
|
3529
|
+
undo: () => adapter.set(prev),
|
|
3530
|
+
redo: () => adapter.set(next)
|
|
3531
|
+
});
|
|
3532
|
+
return { ok: true, id: targetId };
|
|
3533
|
+
}
|
|
3534
|
+
function submit(op, label, targetId) {
|
|
3535
|
+
if (stage(op) === "confirm") {
|
|
3536
|
+
const id = `${surface}-pending-${idSeq += 1}`;
|
|
3537
|
+
pending.set(id, { op, label, targetId });
|
|
3538
|
+
options.onPending?.({ id, op, label });
|
|
3539
|
+
return { staged: true, id };
|
|
3540
|
+
}
|
|
3541
|
+
commit(op, label, targetId);
|
|
3542
|
+
return { staged: false, id: targetId };
|
|
3543
|
+
}
|
|
3544
|
+
const reg = (verb, description, properties, required, handler, isMutation, resolveTarget) => {
|
|
3545
|
+
const name = `${surface}_${verb}`;
|
|
3546
|
+
const wrapped = async (args) => {
|
|
3547
|
+
try {
|
|
3548
|
+
const { _text, ...structured } = await handler(args);
|
|
3549
|
+
return textResult(typeof _text === "string" ? _text : name, structured);
|
|
3550
|
+
} catch (e) {
|
|
3551
|
+
return errorResult(e instanceof Error ? e.message : String(e));
|
|
3552
|
+
}
|
|
3553
|
+
};
|
|
3554
|
+
const final = isMutation ? wrapToolWithActivity(wrapped, {
|
|
3555
|
+
toolName: name,
|
|
3556
|
+
agent,
|
|
3557
|
+
kind: surface,
|
|
3558
|
+
screenId: adapter.screenId,
|
|
3559
|
+
resolveTarget: ({ args, result }) => {
|
|
3560
|
+
if (result.structuredContent?.staged) return null;
|
|
3561
|
+
return resolveTarget?.(args, result.structuredContent ?? {}) ?? target();
|
|
3562
|
+
}
|
|
3563
|
+
}) : wrapped;
|
|
3564
|
+
disposers.push(
|
|
3565
|
+
host.registerTool(
|
|
3566
|
+
{ name, description, inputSchema: { type: "object", properties, required, additionalProperties: false } },
|
|
3567
|
+
final
|
|
3568
|
+
)
|
|
3569
|
+
);
|
|
3570
|
+
};
|
|
3571
|
+
reg(
|
|
3572
|
+
"describe",
|
|
3573
|
+
`Summarize the ${surface} document: node count, roots, and the active surface. Call before reading or writing.`,
|
|
3574
|
+
{},
|
|
3575
|
+
[],
|
|
3576
|
+
() => {
|
|
3577
|
+
const tree = adapter.get();
|
|
3578
|
+
const ids = Object.keys(tree.nodes);
|
|
3579
|
+
return { nodeCount: ids.length, roots: fancyDocCommons.childrenOf(tree, null).map((n) => n.id), _text: `${ids.length} nodes` };
|
|
3580
|
+
},
|
|
3581
|
+
false
|
|
3582
|
+
);
|
|
3583
|
+
reg(
|
|
3584
|
+
"get",
|
|
3585
|
+
`Get the whole ${surface} document tree as JSON.`,
|
|
3586
|
+
{},
|
|
3587
|
+
[],
|
|
3588
|
+
() => ({ tree: adapter.get(), _text: "full tree" }),
|
|
3589
|
+
false
|
|
3590
|
+
);
|
|
3591
|
+
reg(
|
|
3592
|
+
"list",
|
|
3593
|
+
"List nodes (optionally the children of `parent`), in order.",
|
|
3594
|
+
{ parent: { type: ["string", "null"], description: "Parent id, or null/omitted for roots." } },
|
|
3595
|
+
[],
|
|
3596
|
+
(args) => {
|
|
3597
|
+
const tree = adapter.get();
|
|
3598
|
+
const parent = typeof args.parent === "string" ? args.parent : null;
|
|
3599
|
+
return { nodes: fancyDocCommons.childrenOf(tree, parent).map(describeNode), _text: `children of ${parent ?? "root"}` };
|
|
3600
|
+
},
|
|
3601
|
+
false
|
|
3602
|
+
);
|
|
3603
|
+
reg(
|
|
3604
|
+
"get_node",
|
|
3605
|
+
"Get one node by id.",
|
|
3606
|
+
{ id: { type: "string" } },
|
|
3607
|
+
["id"],
|
|
3608
|
+
(args) => {
|
|
3609
|
+
const node = adapter.get().nodes[String(args.id)];
|
|
3610
|
+
if (!node) throw new Error(`No node ${args.id}`);
|
|
3611
|
+
return { node, _text: `node ${node.id}` };
|
|
3612
|
+
},
|
|
3613
|
+
false
|
|
3614
|
+
);
|
|
3615
|
+
reg(
|
|
3616
|
+
"add",
|
|
3617
|
+
"Insert a node. Returns its id. Appends under `parent` (or roots) unless `order` is given.",
|
|
3618
|
+
{
|
|
3619
|
+
type: { type: "string", description: "Node type discriminant." },
|
|
3620
|
+
parent: { type: ["string", "null"], description: "Parent id, or null for a root." },
|
|
3621
|
+
props: { type: "object", description: "JSON props bag." },
|
|
3622
|
+
order: { type: "string", description: "Fractional order key (default: append)." }
|
|
3623
|
+
},
|
|
3624
|
+
["type"],
|
|
3625
|
+
(args) => {
|
|
3626
|
+
const tree = adapter.get();
|
|
3627
|
+
const parent = typeof args.parent === "string" ? args.parent : null;
|
|
3628
|
+
const id = mintId();
|
|
3629
|
+
const order = typeof args.order === "string" ? args.order : fancyDocCommons.appendOrder(tree, parent);
|
|
3630
|
+
const props = args.props && typeof args.props === "object" ? args.props : {};
|
|
3631
|
+
const node = makeNode({ id, type: String(args.type), parent, order }, props);
|
|
3632
|
+
const res = submit({ t: "insert", node }, `add ${args.type} ${id}`, id);
|
|
3633
|
+
return { ...res, _text: res.staged ? `staged add ${id}` : `added ${id}` };
|
|
3634
|
+
},
|
|
3635
|
+
true,
|
|
3636
|
+
(_args, result) => target(result.id)
|
|
3637
|
+
);
|
|
3638
|
+
reg(
|
|
3639
|
+
"update",
|
|
3640
|
+
"Merge a props patch into a node.",
|
|
3641
|
+
{ id: { type: "string" }, patch: { type: "object" } },
|
|
3642
|
+
["id", "patch"],
|
|
3643
|
+
(args) => {
|
|
3644
|
+
const id = String(args.id);
|
|
3645
|
+
if (!adapter.get().nodes[id]) throw new Error(`No node ${id}`);
|
|
3646
|
+
const patch = args.patch && typeof args.patch === "object" ? args.patch : {};
|
|
3647
|
+
const res = submit({ t: "set_props", id, patch }, `update ${id}`, id);
|
|
3648
|
+
return { ...res, id, _text: res.staged ? `staged update ${id}` : `updated ${id}` };
|
|
3649
|
+
},
|
|
3650
|
+
true,
|
|
3651
|
+
(args) => target(String(args.id))
|
|
3652
|
+
);
|
|
3653
|
+
reg(
|
|
3654
|
+
"remove",
|
|
3655
|
+
"Remove a node and its subtree.",
|
|
3656
|
+
{ id: { type: "string" } },
|
|
3657
|
+
["id"],
|
|
3658
|
+
(args) => {
|
|
3659
|
+
const id = String(args.id);
|
|
3660
|
+
const tree = adapter.get();
|
|
3661
|
+
if (!tree.nodes[id]) throw new Error(`No node ${id}`);
|
|
3662
|
+
const count = fancyDocCommons.descendantsOf(tree, id).length + 1;
|
|
3663
|
+
const res = submit({ t: "remove", id }, `remove ${id} (${count} node${count === 1 ? "" : "s"})`, id);
|
|
3664
|
+
return { ...res, id, removed: count, _text: res.staged ? `staged remove ${id}` : `removed ${id}` };
|
|
3665
|
+
},
|
|
3666
|
+
true,
|
|
3667
|
+
(args) => target(String(args.id))
|
|
3668
|
+
);
|
|
3669
|
+
reg(
|
|
3670
|
+
"move",
|
|
3671
|
+
"Reparent + reorder a node.",
|
|
3672
|
+
{ id: { type: "string" }, parent: { type: ["string", "null"] }, order: { type: "string", description: "Fractional order key (default: append under the new parent)." } },
|
|
3673
|
+
["id"],
|
|
3674
|
+
(args) => {
|
|
3675
|
+
const id = String(args.id);
|
|
3676
|
+
const tree = adapter.get();
|
|
3677
|
+
if (!tree.nodes[id]) throw new Error(`No node ${id}`);
|
|
3678
|
+
const parent = args.parent === null ? null : typeof args.parent === "string" ? args.parent : tree.nodes[id].parent;
|
|
3679
|
+
const order = typeof args.order === "string" ? args.order : fancyDocCommons.appendOrder(tree, parent);
|
|
3680
|
+
const res = submit({ t: "move", id, parent, order }, `move ${id}`, id);
|
|
3681
|
+
return { ...res, id, _text: res.staged ? `staged move ${id}` : `moved ${id}` };
|
|
3682
|
+
},
|
|
3683
|
+
true,
|
|
3684
|
+
(args) => target(String(args.id))
|
|
3685
|
+
);
|
|
3686
|
+
for (const t of options.opTools ?? []) {
|
|
3687
|
+
reg(
|
|
3688
|
+
t.verb,
|
|
3689
|
+
t.description,
|
|
3690
|
+
t.properties,
|
|
3691
|
+
t.required,
|
|
3692
|
+
(args) => {
|
|
3693
|
+
const built = t.build(args, adapter.get());
|
|
3694
|
+
if (built && typeof built === "object" && "error" in built) throw new Error(built.error);
|
|
3695
|
+
const tid = t.targetId?.(args);
|
|
3696
|
+
const res = submit(built, `${t.verb} ${tid ?? ""}`.trim(), tid);
|
|
3697
|
+
return { ...res, id: tid, _text: res.staged ? `staged ${t.verb}` : t.verb };
|
|
3698
|
+
},
|
|
3699
|
+
true,
|
|
3700
|
+
(args) => target(t.targetId?.(args))
|
|
3701
|
+
);
|
|
3702
|
+
}
|
|
3703
|
+
reg(
|
|
3704
|
+
"confirm",
|
|
3705
|
+
"Apply a staged op by its pending id (from a staged mutation).",
|
|
3706
|
+
{ id: { type: "string" } },
|
|
3707
|
+
["id"],
|
|
3708
|
+
(args) => {
|
|
3709
|
+
const id = String(args.id);
|
|
3710
|
+
const p = pending.get(id);
|
|
3711
|
+
if (!p) throw new Error(`No pending op ${id}`);
|
|
3712
|
+
pending.delete(id);
|
|
3713
|
+
commit(p.op, p.label, p.targetId);
|
|
3714
|
+
return { ok: true, applied: p.label, id: p.targetId, _text: `applied ${p.label}` };
|
|
3715
|
+
},
|
|
3716
|
+
true,
|
|
3717
|
+
(_args, result) => target(result.id)
|
|
3718
|
+
);
|
|
3719
|
+
reg(
|
|
3720
|
+
"reject",
|
|
3721
|
+
"Discard a staged op by its pending id.",
|
|
3722
|
+
{ id: { type: "string" } },
|
|
3723
|
+
["id"],
|
|
3724
|
+
(args) => {
|
|
3725
|
+
const id = String(args.id);
|
|
3726
|
+
const p = pending.get(id);
|
|
3727
|
+
if (!p) throw new Error(`No pending op ${id}`);
|
|
3728
|
+
pending.delete(id);
|
|
3729
|
+
return { ok: true, rejected: p.label, _text: `rejected ${p.label}` };
|
|
3730
|
+
},
|
|
3731
|
+
false
|
|
3732
|
+
);
|
|
3733
|
+
return {
|
|
3734
|
+
id: surface,
|
|
3735
|
+
title: surface,
|
|
3736
|
+
dispose: () => {
|
|
3737
|
+
for (const d of disposers) d();
|
|
3738
|
+
pending.clear();
|
|
3739
|
+
}
|
|
3740
|
+
};
|
|
3741
|
+
}
|
|
3742
|
+
function cmsReducer() {
|
|
3743
|
+
const base = fancyDocCommons.treeReducer();
|
|
3744
|
+
return {
|
|
3745
|
+
reduce(doc, op) {
|
|
3746
|
+
if (op.t === "set_style") {
|
|
3747
|
+
const node = doc.nodes[op.id];
|
|
3748
|
+
if (!node) return doc;
|
|
3749
|
+
return { nodes: { ...doc.nodes, [op.id]: { ...node, style: { ...node.style, base: { ...node.style.base, ...op.patch } } } } };
|
|
3750
|
+
}
|
|
3751
|
+
if (op.t === "set_layout") {
|
|
3752
|
+
const node = doc.nodes[op.id];
|
|
3753
|
+
if (!node) return doc;
|
|
3754
|
+
return { nodes: { ...doc.nodes, [op.id]: { ...node, layout: op.layout } } };
|
|
3755
|
+
}
|
|
3756
|
+
return base.reduce(doc, op);
|
|
3757
|
+
},
|
|
3758
|
+
invert(doc, op) {
|
|
3759
|
+
if (op.t === "set_style") {
|
|
3760
|
+
const node = doc.nodes[op.id];
|
|
3761
|
+
if (!node) return [];
|
|
3762
|
+
const prev = {};
|
|
3763
|
+
for (const k in op.patch) prev[k] = node.style.base[k];
|
|
3764
|
+
return [{ t: "set_style", id: op.id, patch: prev }];
|
|
3765
|
+
}
|
|
3766
|
+
if (op.t === "set_layout") {
|
|
3767
|
+
const node = doc.nodes[op.id];
|
|
3768
|
+
if (!node) return [];
|
|
3769
|
+
return [{ t: "set_layout", id: op.id, layout: node.layout }];
|
|
3770
|
+
}
|
|
3771
|
+
return base.invert(doc, op);
|
|
3772
|
+
}
|
|
3773
|
+
};
|
|
3774
|
+
}
|
|
3775
|
+
function registerCmsBridge(host, options) {
|
|
3776
|
+
return registerDocBridge(host, {
|
|
3777
|
+
adapter: options.adapter,
|
|
3778
|
+
surface: "cms",
|
|
3779
|
+
agent: options.agent,
|
|
3780
|
+
reducer: cmsReducer(),
|
|
3781
|
+
stagePolicy: options.stagePolicy,
|
|
3782
|
+
onPending: options.onPending,
|
|
3783
|
+
// New nodes get an empty base style so they satisfy StyledNode.
|
|
3784
|
+
makeNode: ({ id, type, parent, order }, props) => ({ id, type, parent, order, props, style: { base: {} } }),
|
|
3785
|
+
describeNode: (n) => ({ id: n.id, type: n.type, parent: n.parent, layout: n.layout }),
|
|
3786
|
+
opTools: [
|
|
3787
|
+
{
|
|
3788
|
+
verb: "set_style",
|
|
3789
|
+
description: "Merge a StyleProps patch into a node's base style (color, background, padding, fontSize, gap, \u2026).",
|
|
3790
|
+
properties: { id: { type: "string" }, patch: { type: "object", description: "Partial StyleProps." } },
|
|
3791
|
+
required: ["id", "patch"],
|
|
3792
|
+
build: (args, tree) => {
|
|
3793
|
+
const id = String(args.id);
|
|
3794
|
+
if (!tree.nodes[id]) return { error: `No node ${id}` };
|
|
3795
|
+
return { t: "set_style", id, patch: args.patch && typeof args.patch === "object" ? args.patch : {} };
|
|
3796
|
+
},
|
|
3797
|
+
targetId: (args) => String(args.id)
|
|
3798
|
+
},
|
|
3799
|
+
{
|
|
3800
|
+
verb: "set_layout",
|
|
3801
|
+
description: "Set a container node's layout mode (free | stack | grid).",
|
|
3802
|
+
properties: { id: { type: "string" }, layout: { type: "string", enum: ["free", "stack", "grid"] } },
|
|
3803
|
+
required: ["id"],
|
|
3804
|
+
build: (args, tree) => {
|
|
3805
|
+
const id = String(args.id);
|
|
3806
|
+
if (!tree.nodes[id]) return { error: `No node ${id}` };
|
|
3807
|
+
return { t: "set_layout", id, layout: args.layout };
|
|
3808
|
+
},
|
|
3809
|
+
targetId: (args) => String(args.id)
|
|
3810
|
+
}
|
|
3811
|
+
]
|
|
3812
|
+
});
|
|
3813
|
+
}
|
|
3489
3814
|
|
|
3490
3815
|
// src/sharing/token.ts
|
|
3491
3816
|
var TOKEN_BYTES = 24;
|
|
@@ -3544,6 +3869,7 @@ function constantTimeEqual(a, b) {
|
|
|
3544
3869
|
}
|
|
3545
3870
|
|
|
3546
3871
|
// src/sharing/sse-relay.ts
|
|
3872
|
+
init_registry();
|
|
3547
3873
|
var SseRelayTransport = class {
|
|
3548
3874
|
constructor(options) {
|
|
3549
3875
|
this.disposed = false;
|
|
@@ -3551,6 +3877,7 @@ var SseRelayTransport = class {
|
|
|
3551
3877
|
this.connected = false;
|
|
3552
3878
|
this.listeners = /* @__PURE__ */ new Set();
|
|
3553
3879
|
this.state = "idle";
|
|
3880
|
+
this.peers = /* @__PURE__ */ new Set();
|
|
3554
3881
|
this.opts = options;
|
|
3555
3882
|
this.expectedToken = options.token;
|
|
3556
3883
|
}
|
|
@@ -3649,6 +3976,36 @@ var SseRelayTransport = class {
|
|
|
3649
3976
|
} catch {
|
|
3650
3977
|
return;
|
|
3651
3978
|
}
|
|
3979
|
+
if ("method" in message && message.method === "notifications/peer_joined") {
|
|
3980
|
+
const subscriberId = String(message.params?.subscriberId ?? "peer");
|
|
3981
|
+
this.peers.add(subscriberId);
|
|
3982
|
+
fancyAutoCommon.emitActivity({
|
|
3983
|
+
agentId: "agent",
|
|
3984
|
+
agentName: "Agent",
|
|
3985
|
+
agentColor: "#a855f7",
|
|
3986
|
+
action: "agent_connected",
|
|
3987
|
+
timestamp: Date.now(),
|
|
3988
|
+
target: { kind: "navigation", label: "Agent connected" },
|
|
3989
|
+
meta: { subscriberId }
|
|
3990
|
+
});
|
|
3991
|
+
return;
|
|
3992
|
+
}
|
|
3993
|
+
if ("method" in message && message.method === "notifications/peer_left") {
|
|
3994
|
+
const subscriberId = String(message.params?.subscriberId ?? "peer");
|
|
3995
|
+
this.peers.delete(subscriberId);
|
|
3996
|
+
if (this.peers.size === 0) {
|
|
3997
|
+
fancyAutoCommon.emitActivity({
|
|
3998
|
+
agentId: "agent",
|
|
3999
|
+
agentName: "Agent",
|
|
4000
|
+
agentColor: "#a855f7",
|
|
4001
|
+
action: "agent_disconnected",
|
|
4002
|
+
timestamp: Date.now(),
|
|
4003
|
+
target: { kind: "navigation", label: "Agent disconnected" },
|
|
4004
|
+
meta: { subscriberId }
|
|
4005
|
+
});
|
|
4006
|
+
}
|
|
4007
|
+
return;
|
|
4008
|
+
}
|
|
3652
4009
|
await this.server.receive(this, message);
|
|
3653
4010
|
}
|
|
3654
4011
|
setState(state) {
|
|
@@ -3681,11 +4038,11 @@ function attachSseRelay(server, options) {
|
|
|
3681
4038
|
|
|
3682
4039
|
// src/sharing/use-co-browse-session.ts
|
|
3683
4040
|
init_registry();
|
|
3684
|
-
var
|
|
4041
|
+
var DEFAULT_AGENT15 = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
3685
4042
|
var USER = { id: "human", name: "You" };
|
|
3686
4043
|
function useCoBrowseSession(options) {
|
|
3687
4044
|
const { adapter, extraBridges } = options;
|
|
3688
|
-
const agent = { ...
|
|
4045
|
+
const agent = { ...DEFAULT_AGENT15, ...options.agent ?? {} };
|
|
3689
4046
|
const relayBaseUrl = options.relayBaseUrl ?? "/agent-relay";
|
|
3690
4047
|
const serverRef = react.useRef(null);
|
|
3691
4048
|
const relayRef = react.useRef(null);
|
|
@@ -3717,11 +4074,14 @@ function useCoBrowseSession(options) {
|
|
|
3717
4074
|
if (!server || relayRef.current) return;
|
|
3718
4075
|
const descriptor = createSessionDescriptor();
|
|
3719
4076
|
const csrf = options.csrfToken?.() ?? "";
|
|
3720
|
-
await fetch(`${relayBaseUrl}/register`, {
|
|
4077
|
+
const response = await fetch(`${relayBaseUrl}/register`, {
|
|
3721
4078
|
method: "POST",
|
|
3722
4079
|
headers: { "content-type": "application/json", "x-csrf-token": csrf },
|
|
3723
4080
|
body: JSON.stringify({ session: descriptor.id, token: descriptor.token })
|
|
3724
4081
|
});
|
|
4082
|
+
if (!response.ok) {
|
|
4083
|
+
throw new Error(`Relay registration failed (${response.status})`);
|
|
4084
|
+
}
|
|
3725
4085
|
const relay = attachSseRelay(server, { baseUrl: relayBaseUrl, sessionId: descriptor.id, token: descriptor.token });
|
|
3726
4086
|
relay.onStateChange(setRelayState);
|
|
3727
4087
|
relayRef.current = relay;
|
|
@@ -3735,16 +4095,15 @@ function useCoBrowseSession(options) {
|
|
|
3735
4095
|
setSession(null);
|
|
3736
4096
|
if (current) {
|
|
3737
4097
|
const csrf = options.csrfToken?.() ?? "";
|
|
3738
|
-
void fetch(`${relayBaseUrl}/${current.id}/unregister`, {
|
|
4098
|
+
void fetch(`${relayBaseUrl}/${current.id}/unregister?token=${encodeURIComponent(current.token)}`, {
|
|
3739
4099
|
method: "POST",
|
|
3740
|
-
headers: { "content-type": "application/json", "x-csrf-token": csrf }
|
|
3741
|
-
body: JSON.stringify({ token: current.token })
|
|
4100
|
+
headers: { "content-type": "application/json", "x-csrf-token": csrf }
|
|
3742
4101
|
}).catch(() => {
|
|
3743
4102
|
});
|
|
3744
4103
|
}
|
|
3745
4104
|
}, [relayBaseUrl, options, session]);
|
|
3746
4105
|
const observeUser = react.useCallback((event) => {
|
|
3747
|
-
const label = event.kind === "navigation" ? `You navigated to ${event.url}` : event.kind === "scroll" ? "You scrolled" : `You edited ${event.handle}${event.masked ? " (hidden)" : ""}`;
|
|
4106
|
+
const label = event.kind === "navigation" ? `You navigated to ${event.url}` : event.kind === "scroll" ? "You scrolled" : event.kind === "click" ? `You clicked ${event.label ?? event.handle}` : `You edited ${event.handle}${event.masked ? " (hidden)" : ""}`;
|
|
3748
4107
|
fancyAutoCommon.emitActivity({
|
|
3749
4108
|
agentId: USER.id,
|
|
3750
4109
|
agentName: USER.name,
|
|
@@ -4520,6 +4879,11 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
|
4520
4879
|
const [pulse, setPulse] = react.useState(null);
|
|
4521
4880
|
react.useEffect(() => {
|
|
4522
4881
|
if (!latest || (latest.source ?? "agent") === "user") return;
|
|
4882
|
+
if (latest.action === "agent_disconnected") {
|
|
4883
|
+
setCursor(null);
|
|
4884
|
+
setPulse(null);
|
|
4885
|
+
return;
|
|
4886
|
+
}
|
|
4523
4887
|
const color = latest.agentColor ?? "#a855f7";
|
|
4524
4888
|
const name = latest.agentName ?? "Agent";
|
|
4525
4889
|
const status = latest.target?.label ?? latest.action;
|
|
@@ -4899,6 +5263,7 @@ exports.buildMcpbProxyStub = buildMcpbProxyStub;
|
|
|
4899
5263
|
exports.buildShareConfig = buildShareConfig;
|
|
4900
5264
|
exports.buildShareUrl = buildShareUrl;
|
|
4901
5265
|
exports.buildVscodeDeeplink = buildVscodeDeeplink;
|
|
5266
|
+
exports.cmsReducer = cmsReducer;
|
|
4902
5267
|
exports.connectorHref = connectorHref;
|
|
4903
5268
|
exports.createSessionDescriptor = createSessionDescriptor;
|
|
4904
5269
|
exports.describeSession = describeSession;
|
|
@@ -4909,7 +5274,9 @@ exports.mapActivityToHeuristicsEvent = mapActivityToEvent;
|
|
|
4909
5274
|
exports.readSessionFromUrl = readSessionFromUrl;
|
|
4910
5275
|
exports.registerCatalogBridge = registerCatalogBridge;
|
|
4911
5276
|
exports.registerChartsBridge = registerChartsBridge;
|
|
5277
|
+
exports.registerCmsBridge = registerCmsBridge;
|
|
4912
5278
|
exports.registerCodeBridge = registerCodeBridge;
|
|
5279
|
+
exports.registerDocBridge = registerDocBridge;
|
|
4913
5280
|
exports.registerFeaturesBridge = registerFeaturesBridge;
|
|
4914
5281
|
exports.registerFilesBridge = registerFilesBridge;
|
|
4915
5282
|
exports.registerFormBridge = registerFormBridge;
|