@particle-academy/agent-integrations 0.32.0 → 0.34.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/README.md +9 -0
- package/dist/bridges/passkeys.d.cts +185 -0
- package/dist/bridges/passkeys.d.ts +185 -0
- package/dist/bridges-passkeys.cjs +314 -0
- package/dist/bridges-passkeys.cjs.map +1 -0
- package/dist/bridges-passkeys.js +7 -0
- package/dist/bridges-passkeys.js.map +1 -0
- package/dist/chunk-7THGQUX3.js +193 -0
- package/dist/chunk-7THGQUX3.js.map +1 -0
- package/dist/{chunk-HSI5RVF4.js → chunk-SJTLTITO.js} +29 -2
- package/dist/chunk-SJTLTITO.js.map +1 -0
- package/dist/components-shared-whiteboard.cjs +27 -0
- package/dist/components-shared-whiteboard.cjs.map +1 -1
- package/dist/components-shared-whiteboard.js +1 -1
- package/dist/index.cjs +218 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/styles.css +46 -0
- package/dist/styles.css.map +1 -1
- package/package.json +17 -4
- package/dist/chunk-HSI5RVF4.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-
|
|
1
|
+
import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-SJTLTITO.js';
|
|
2
2
|
import { createSessionDescriptor, attachSseRelay } from './chunk-N6RLSLOF.js';
|
|
3
3
|
import { attachInProcess } from './chunk-AFUULW5E.js';
|
|
4
4
|
import { registerWhiteboardBridge } from './chunk-2U5JB6ZA.js';
|
package/dist/index.cjs
CHANGED
|
@@ -3896,10 +3896,196 @@ function registerFeaturesBridge(host, options) {
|
|
|
3896
3896
|
}
|
|
3897
3897
|
};
|
|
3898
3898
|
}
|
|
3899
|
+
|
|
3900
|
+
// src/bridges/passkeys.ts
|
|
3899
3901
|
var DEFAULT_AGENT14 = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
3902
|
+
var str6 = (v, fallback = "") => typeof v === "string" ? v : fallback;
|
|
3903
|
+
function toSummary(record) {
|
|
3904
|
+
return {
|
|
3905
|
+
id: str6(record?.id),
|
|
3906
|
+
name: typeof record?.name === "string" ? record.name : null,
|
|
3907
|
+
createdAt: str6(record?.createdAt),
|
|
3908
|
+
lastUsedAt: typeof record?.lastUsedAt === "string" ? record.lastUsedAt : null,
|
|
3909
|
+
transports: Array.isArray(record?.transports) ? record.transports.map((t) => String(t)) : [],
|
|
3910
|
+
backedUp: record?.backedUp === true,
|
|
3911
|
+
aaguid: str6(record?.aaguid),
|
|
3912
|
+
clonedAt: typeof record?.clonedAt === "string" ? record.clonedAt : null
|
|
3913
|
+
};
|
|
3914
|
+
}
|
|
3915
|
+
var PASSKEY_BRIDGE_TOOLS = [
|
|
3916
|
+
"passkey_list",
|
|
3917
|
+
"passkey_status",
|
|
3918
|
+
"passkey_rename",
|
|
3919
|
+
"passkey_revoke",
|
|
3920
|
+
"passkey_begin_enrollment"
|
|
3921
|
+
];
|
|
3922
|
+
function registerPasskeyBridge(host, options) {
|
|
3923
|
+
const { adapter } = options;
|
|
3924
|
+
const agent = { ...DEFAULT_AGENT14, ...options.agent ?? {} };
|
|
3925
|
+
const surfaceId = adapter.id ?? "passkeys";
|
|
3926
|
+
const disposers = [];
|
|
3927
|
+
ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
|
|
3928
|
+
const target = (elementId, label) => ({
|
|
3929
|
+
kind: "custom",
|
|
3930
|
+
screenId: adapter.screenId,
|
|
3931
|
+
elementId,
|
|
3932
|
+
label: label ?? surfaceId
|
|
3933
|
+
});
|
|
3934
|
+
const reg = (name, description, properties, required, handler, resolveTarget) => {
|
|
3935
|
+
const wrapped = async (args) => {
|
|
3936
|
+
try {
|
|
3937
|
+
return await handler(args);
|
|
3938
|
+
} catch (e) {
|
|
3939
|
+
return errorResult(e instanceof Error ? e.message : String(e));
|
|
3940
|
+
}
|
|
3941
|
+
};
|
|
3942
|
+
const final = resolveTarget ? wrapToolWithActivity(wrapped, {
|
|
3943
|
+
toolName: name,
|
|
3944
|
+
agent,
|
|
3945
|
+
kind: "custom",
|
|
3946
|
+
screenId: adapter.screenId,
|
|
3947
|
+
resolveTarget: ({ args }) => resolveTarget(args)
|
|
3948
|
+
}) : wrapped;
|
|
3949
|
+
disposers.push(
|
|
3950
|
+
host.registerTool(
|
|
3951
|
+
{
|
|
3952
|
+
name,
|
|
3953
|
+
description,
|
|
3954
|
+
inputSchema: {
|
|
3955
|
+
type: "object",
|
|
3956
|
+
properties,
|
|
3957
|
+
required,
|
|
3958
|
+
additionalProperties: false
|
|
3959
|
+
}
|
|
3960
|
+
},
|
|
3961
|
+
final
|
|
3962
|
+
)
|
|
3963
|
+
);
|
|
3964
|
+
};
|
|
3965
|
+
const findById = async (id) => (await adapter.list()).map(toSummary).find((p) => p.id === id) ?? null;
|
|
3966
|
+
reg(
|
|
3967
|
+
"passkey_list",
|
|
3968
|
+
"List the signed-in user's passkeys: credential id, label, when it was added and last used, transports, whether it is a synced passkey, and whether the server flagged it as a possible clone. Read-only. Public keys, user handles and signature counters are never returned.",
|
|
3969
|
+
{},
|
|
3970
|
+
[],
|
|
3971
|
+
async () => {
|
|
3972
|
+
const passkeys = (await adapter.list()).map(toSummary);
|
|
3973
|
+
return textResult(JSON.stringify(passkeys, null, 2), { passkeys, count: passkeys.length });
|
|
3974
|
+
},
|
|
3975
|
+
false
|
|
3976
|
+
);
|
|
3977
|
+
reg(
|
|
3978
|
+
"passkey_status",
|
|
3979
|
+
"Read what this browser can do (passkey support, a built-in authenticator, autofill sign-in) and what the management surface is currently showing (busy/error, a revoke awaiting confirmation, a rename in progress).",
|
|
3980
|
+
{},
|
|
3981
|
+
[],
|
|
3982
|
+
async () => {
|
|
3983
|
+
const support = adapter.support ? await adapter.support() : null;
|
|
3984
|
+
const state = adapter.state ? await adapter.state() : null;
|
|
3985
|
+
const out = {
|
|
3986
|
+
support,
|
|
3987
|
+
state,
|
|
3988
|
+
// Said in the payload, not only in the docs: an agent reading this to
|
|
3989
|
+
// work out "how do I sign the user in" should find the answer here.
|
|
3990
|
+
canCompleteCeremony: false,
|
|
3991
|
+
note: "A passkey ceremony needs a user gesture and a biometric or PIN. No tool on this bridge can perform one; ask the human to complete it on their device."
|
|
3992
|
+
};
|
|
3993
|
+
return textResult(JSON.stringify(out, null, 2), out);
|
|
3994
|
+
},
|
|
3995
|
+
false
|
|
3996
|
+
);
|
|
3997
|
+
reg(
|
|
3998
|
+
"passkey_rename",
|
|
3999
|
+
"Rename one passkey, by credential id (from passkey_list). Cosmetic and undoable with agent_undo.",
|
|
4000
|
+
{
|
|
4001
|
+
id: { type: "string", description: "base64url credential id." },
|
|
4002
|
+
name: { type: "string", description: "New label, e.g. 'MacBook Touch ID'. Empty string clears it." }
|
|
4003
|
+
},
|
|
4004
|
+
["id", "name"],
|
|
4005
|
+
async (args) => {
|
|
4006
|
+
const id = str6(args.id);
|
|
4007
|
+
const name = str6(args.name);
|
|
4008
|
+
if (!id) return errorResult("id is required.");
|
|
4009
|
+
const existing = await findById(id);
|
|
4010
|
+
if (!existing) return errorResult(`No passkey with id ${id}.`);
|
|
4011
|
+
if (options.confirmRename) {
|
|
4012
|
+
if (!options.confirm) {
|
|
4013
|
+
return errorResult(
|
|
4014
|
+
"passkey_rename requires confirmation (confirmRename), but the host wired no confirm hook."
|
|
4015
|
+
);
|
|
4016
|
+
}
|
|
4017
|
+
const ok = await options.confirm({ action: "passkey_rename", id, name });
|
|
4018
|
+
if (!ok) return errorResult(`Declined: rename ${id} (human did not confirm).`);
|
|
4019
|
+
}
|
|
4020
|
+
const previous = existing.name ?? "";
|
|
4021
|
+
await adapter.rename({ id, name });
|
|
4022
|
+
fancyAutoCommon.pushUndoEntry(agent.id, {
|
|
4023
|
+
timestamp: Date.now(),
|
|
4024
|
+
bridgeId: surfaceId,
|
|
4025
|
+
action: "passkey_rename",
|
|
4026
|
+
label: `Renamed passkey to ${name || "(unnamed)"}`,
|
|
4027
|
+
undo: () => void adapter.rename({ id, name: previous }),
|
|
4028
|
+
redo: () => void adapter.rename({ id, name })
|
|
4029
|
+
});
|
|
4030
|
+
return textResult(`Renamed passkey ${id} to ${name || "(unnamed)"}`, { id, name, previous });
|
|
4031
|
+
},
|
|
4032
|
+
(args) => target(str6(args.id), `rename ${str6(args.id)}`)
|
|
4033
|
+
);
|
|
4034
|
+
reg(
|
|
4035
|
+
"passkey_revoke",
|
|
4036
|
+
"PROPOSE revoking one passkey. This does NOT revoke it: the request is staged on the surface and the human confirms or cancels there. Revoking the last passkey can lock the user out, and the response says when that is the case so you can tell them before they confirm.",
|
|
4037
|
+
{ id: { type: "string", description: "base64url credential id." } },
|
|
4038
|
+
["id"],
|
|
4039
|
+
async (args) => {
|
|
4040
|
+
const id = str6(args.id);
|
|
4041
|
+
if (!id) return errorResult("id is required.");
|
|
4042
|
+
const existing = await findById(id);
|
|
4043
|
+
if (!existing) return errorResult(`No passkey with id ${id}.`);
|
|
4044
|
+
const proposal = await adapter.proposeRevoke({ id });
|
|
4045
|
+
const isLastPasskey = proposal?.isLastPasskey === true;
|
|
4046
|
+
const out = {
|
|
4047
|
+
id,
|
|
4048
|
+
name: existing.name,
|
|
4049
|
+
staged: true,
|
|
4050
|
+
awaitingHuman: true,
|
|
4051
|
+
isLastPasskey
|
|
4052
|
+
};
|
|
4053
|
+
return textResult(
|
|
4054
|
+
isLastPasskey ? `Staged a revoke of ${existing.name ?? id}. This is the account's LAST passkey \u2014 confirming it removes passkey sign-in entirely. Waiting for the human to confirm or cancel.` : `Staged a revoke of ${existing.name ?? id}. Waiting for the human to confirm or cancel on the surface.`,
|
|
4055
|
+
out
|
|
4056
|
+
);
|
|
4057
|
+
},
|
|
4058
|
+
(args) => target(str6(args.id), `propose revoke ${str6(args.id)}`)
|
|
4059
|
+
);
|
|
4060
|
+
reg(
|
|
4061
|
+
"passkey_begin_enrollment",
|
|
4062
|
+
"Ask the surface to start enrolling a new passkey. This only opens the prompt: the ceremony completes on the human's authenticator (Touch ID, Windows Hello, phone, security key) or it does not complete at all. Returns immediately.",
|
|
4063
|
+
{ name: { type: "string", description: "Optional label to pre-fill for the new passkey." } },
|
|
4064
|
+
[],
|
|
4065
|
+
async (args) => {
|
|
4066
|
+
if (!adapter.beginEnrollment) return errorResult("Host did not wire beginEnrollment().");
|
|
4067
|
+
const name = args.name === void 0 ? void 0 : str6(args.name);
|
|
4068
|
+
await adapter.beginEnrollment(name === void 0 ? {} : { name });
|
|
4069
|
+
const out = { awaitingHuman: true, ...name === void 0 ? {} : { name } };
|
|
4070
|
+
return textResult(
|
|
4071
|
+
"Enrollment prompt opened. The human has to complete it on their authenticator \u2014 there is no tool that can finish it for them.",
|
|
4072
|
+
out
|
|
4073
|
+
);
|
|
4074
|
+
},
|
|
4075
|
+
(args) => target(void 0, `begin enrollment${args.name ? ` (${str6(args.name)})` : ""}`)
|
|
4076
|
+
);
|
|
4077
|
+
return {
|
|
4078
|
+
id: `passkeys:${surfaceId}`,
|
|
4079
|
+
title: adapter.title ?? "Passkeys",
|
|
4080
|
+
dispose: () => {
|
|
4081
|
+
for (const d of disposers.splice(0)) d();
|
|
4082
|
+
}
|
|
4083
|
+
};
|
|
4084
|
+
}
|
|
4085
|
+
var DEFAULT_AGENT15 = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
3900
4086
|
function registerDocBridge(host, options) {
|
|
3901
4087
|
const { adapter, surface } = options;
|
|
3902
|
-
const agent = { ...
|
|
4088
|
+
const agent = { ...DEFAULT_AGENT15, ...options.agent ?? {} };
|
|
3903
4089
|
const reducer = options.reducer ?? fancyDocCommons.treeReducer();
|
|
3904
4090
|
const stage = options.stagePolicy ?? fancyDocCommons.autoApply;
|
|
3905
4091
|
const makeNode = options.makeNode ?? (({ id, type, parent, order }, props) => ({ id, type, parent, order, props }));
|
|
@@ -4431,11 +4617,11 @@ function attachSseRelay(server, options) {
|
|
|
4431
4617
|
|
|
4432
4618
|
// src/sharing/use-co-browse-session.ts
|
|
4433
4619
|
init_registry();
|
|
4434
|
-
var
|
|
4620
|
+
var DEFAULT_AGENT16 = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
4435
4621
|
var USER = { id: "human", name: "You" };
|
|
4436
4622
|
function useCoBrowseSession(options) {
|
|
4437
4623
|
const { adapter, extraBridges } = options;
|
|
4438
|
-
const agent = { ...
|
|
4624
|
+
const agent = { ...DEFAULT_AGENT16, ...options.agent ?? {} };
|
|
4439
4625
|
const relayBaseUrl = options.relayBaseUrl ?? "/agent-relay";
|
|
4440
4626
|
const serverRef = react.useRef(null);
|
|
4441
4627
|
const relayRef = react.useRef(null);
|
|
@@ -4772,11 +4958,21 @@ function ShareControls({
|
|
|
4772
4958
|
onStart,
|
|
4773
4959
|
onStop,
|
|
4774
4960
|
status,
|
|
4961
|
+
agentConnected = false,
|
|
4962
|
+
activity,
|
|
4775
4963
|
shareBaseUrl,
|
|
4776
4964
|
className,
|
|
4777
4965
|
style
|
|
4778
4966
|
}) {
|
|
4779
4967
|
const [tab, setTab] = react.useState("prompt");
|
|
4968
|
+
const wasConnected = react.useRef(false);
|
|
4969
|
+
react.useEffect(() => {
|
|
4970
|
+
if (agentConnected && !wasConnected.current) {
|
|
4971
|
+
wasConnected.current = true;
|
|
4972
|
+
setTab("activity");
|
|
4973
|
+
}
|
|
4974
|
+
if (!agentConnected) wasConnected.current = false;
|
|
4975
|
+
}, [agentConnected]);
|
|
4780
4976
|
if (!session) {
|
|
4781
4977
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["fai-share fai-share--idle", className ?? ""].filter(Boolean).join(" "), style, children: [
|
|
4782
4978
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "fai-share__start", onClick: onStart, children: "Start shared session" }),
|
|
@@ -4811,12 +5007,14 @@ function ShareControls({
|
|
|
4811
5007
|
] })
|
|
4812
5008
|
] }),
|
|
4813
5009
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fai-share__tabs", role: "tablist", children: [
|
|
5010
|
+
agentConnected && /* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "activity", active: tab, setTab, children: "Activity" }),
|
|
4814
5011
|
/* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "prompt", active: tab, setTab, children: "Agent prompt" }),
|
|
4815
5012
|
/* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "url", active: tab, setTab, children: "URL" }),
|
|
4816
5013
|
/* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "json", active: tab, setTab, children: "JSON" }),
|
|
4817
5014
|
/* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "curl", active: tab, setTab, children: "cURL recipe" })
|
|
4818
5015
|
] }),
|
|
4819
5016
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fai-share__panel", children: [
|
|
5017
|
+
tab === "activity" && /* @__PURE__ */ jsxRuntime.jsx(ActivityLog, { activity }),
|
|
4820
5018
|
tab === "prompt" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4821
5019
|
CopyBox,
|
|
4822
5020
|
{
|
|
@@ -4844,6 +5042,21 @@ function ShareControls({
|
|
|
4844
5042
|
] })
|
|
4845
5043
|
] });
|
|
4846
5044
|
}
|
|
5045
|
+
function ActivityLog({ activity }) {
|
|
5046
|
+
const entries = (activity ?? []).slice().reverse();
|
|
5047
|
+
if (entries.length === 0) {
|
|
5048
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "fai-share__empty", children: "Connected. Nothing yet \u2014 actions appear here as the agent takes them." });
|
|
5049
|
+
}
|
|
5050
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "fai-share__activity", "aria-live": "polite", children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "fai-share__activity-row", "data-kind": entry.kind, children: [
|
|
5051
|
+
/* @__PURE__ */ jsxRuntime.jsx("time", { className: "fai-share__activity-time", dateTime: new Date(entry.at).toISOString(), children: new Date(entry.at).toLocaleTimeString(void 0, {
|
|
5052
|
+
hour: "2-digit",
|
|
5053
|
+
minute: "2-digit",
|
|
5054
|
+
second: "2-digit"
|
|
5055
|
+
}) }),
|
|
5056
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "fai-share__activity-source", children: entry.source }),
|
|
5057
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "fai-share__activity-text", children: entry.text })
|
|
5058
|
+
] }, entry.id)) });
|
|
5059
|
+
}
|
|
4847
5060
|
function TabButton({ tab, active, setTab, children }) {
|
|
4848
5061
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4849
5062
|
"button",
|
|
@@ -5627,6 +5840,7 @@ exports.MCPB_MIN_NODE = MCPB_MIN_NODE;
|
|
|
5627
5840
|
exports.MCP_PROTOCOL_VERSION = MCP_PROTOCOL_VERSION;
|
|
5628
5841
|
exports.MemoryHumanPlusEventStore = MemoryHumanPlusEventStore;
|
|
5629
5842
|
exports.MicroMcpServer = MicroMcpServer;
|
|
5843
|
+
exports.PASSKEY_BRIDGE_TOOLS = PASSKEY_BRIDGE_TOOLS;
|
|
5630
5844
|
exports.RelayTransport = RelayTransport;
|
|
5631
5845
|
exports.ScreensActivityBridge = ScreensActivityBridge;
|
|
5632
5846
|
exports.ShareControls = ShareControls;
|
|
@@ -5668,6 +5882,7 @@ exports.registerFormBridge = registerFormBridge;
|
|
|
5668
5882
|
exports.registerGitBridge = registerGitBridge;
|
|
5669
5883
|
exports.registerMapBridge = registerMapBridge;
|
|
5670
5884
|
exports.registerNavigationBridge = registerNavigationBridge;
|
|
5885
|
+
exports.registerPasskeyBridge = registerPasskeyBridge;
|
|
5671
5886
|
exports.registerSceneBridge = registerSceneBridge;
|
|
5672
5887
|
exports.registerScreensBridge = registerScreensBridge;
|
|
5673
5888
|
exports.registerSheetsBridge = registerSheetsBridge;
|