@particle-academy/agent-integrations 0.2.4
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 +131 -0
- package/dist/bridges/flow.d.cts +72 -0
- package/dist/bridges/flow.d.ts +72 -0
- package/dist/bridges/whiteboard.d.cts +40 -0
- package/dist/bridges/whiteboard.d.ts +40 -0
- package/dist/bridges-flow.cjs +330 -0
- package/dist/bridges-flow.cjs.map +1 -0
- package/dist/bridges-flow.js +4 -0
- package/dist/bridges-flow.js.map +1 -0
- package/dist/bridges-whiteboard.cjs +409 -0
- package/dist/bridges-whiteboard.cjs.map +1 -0
- package/dist/bridges-whiteboard.js +4 -0
- package/dist/bridges-whiteboard.js.map +1 -0
- package/dist/chunk-2VOQJKSU.js +320 -0
- package/dist/chunk-2VOQJKSU.js.map +1 -0
- package/dist/chunk-5ZUHNNLR.js +398 -0
- package/dist/chunk-5ZUHNNLR.js.map +1 -0
- package/dist/chunk-6LTKCNLF.js +68 -0
- package/dist/chunk-6LTKCNLF.js.map +1 -0
- package/dist/chunk-FLEOQUKF.js +157 -0
- package/dist/chunk-FLEOQUKF.js.map +1 -0
- package/dist/chunk-QGCF7YKW.js +130 -0
- package/dist/chunk-QGCF7YKW.js.map +1 -0
- package/dist/index.cjs +1632 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +155 -0
- package/dist/index.d.ts +155 -0
- package/dist/index.js +567 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.cts +73 -0
- package/dist/mcp/index.d.ts +73 -0
- package/dist/mcp.cjs +210 -0
- package/dist/mcp.cjs.map +1 -0
- package/dist/mcp.js +4 -0
- package/dist/mcp.js.map +1 -0
- package/dist/server-Bv985us3.d.cts +173 -0
- package/dist/server-Bv985us3.d.ts +173 -0
- package/dist/sharing/index.d.cts +89 -0
- package/dist/sharing/index.d.ts +89 -0
- package/dist/sharing.cjs +166 -0
- package/dist/sharing.cjs.map +1 -0
- package/dist/sharing.js +3 -0
- package/dist/sharing.js.map +1 -0
- package/dist/styles.css +331 -0
- package/dist/styles.css.map +1 -0
- package/dist/types-CRPA_D0z.d.ts +18 -0
- package/dist/types-DR5AS6Rd.d.cts +18 -0
- package/docs/relay-protocol.md +57 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sharing/token.ts","../src/sharing/sse-relay.ts"],"names":[],"mappings":"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","file":"sharing.cjs","sourcesContent":["/**\n * Session-token utilities. The token is a high-entropy secret; possession\n * grants read/write on the session. We don't HMAC frames — frames carry\n * the token directly (which is fine for in-process / same-origin / TLS\n * transports). For lower-trust transports, host apps can layer signing\n * on top of the BroadcastChannelTransport.\n */\n\nconst TOKEN_BYTES = 24; // 192 bits, base64url-encoded → 32 chars\n\nexport type SessionDescriptor = {\n /** Stable session identifier. Channel name = `fai:share:${id}`. */\n id: string;\n /** Secret token. Treat as a password — anyone with it can read/write. */\n token: string;\n /** Pretty hash for display (first 8 chars of token). */\n display: string;\n};\n\nexport function createSessionDescriptor(): SessionDescriptor {\n const id = randomId(8);\n const token = randomToken();\n return { id, token, display: token.slice(0, 8) };\n}\n\nexport function describeSession(id: string, token: string): SessionDescriptor {\n return { id, token, display: token.slice(0, 8) };\n}\n\n/** Build the shareable URL for the current page (preserves path, adds session+token). */\nexport function buildShareUrl(\n descriptor: SessionDescriptor,\n baseUrl: string = typeof window !== \"undefined\" ? window.location.href.split(\"?\")[0] : \"\",\n): string {\n const u = new URL(baseUrl);\n u.searchParams.set(\"session\", descriptor.id);\n u.searchParams.set(\"token\", descriptor.token);\n return u.toString();\n}\n\n/** Build the JSON config form (suitable for Claude Desktop / Cline / etc.). */\nexport function buildShareConfig(descriptor: SessionDescriptor, transport = \"broadcast-channel\") {\n return {\n name: `whiteboard-${descriptor.id}`,\n transport,\n session: descriptor.id,\n token: descriptor.token,\n channel: `fai:share:${descriptor.id}`,\n protocol_version: \"2025-06-18\",\n };\n}\n\n/** Read session descriptor from current URL, or null if not a shared link. */\nexport function readSessionFromUrl(): SessionDescriptor | null {\n if (typeof window === \"undefined\") return null;\n const params = new URL(window.location.href).searchParams;\n const id = params.get(\"session\");\n const token = params.get(\"token\");\n if (!id || !token) return null;\n return describeSession(id, token);\n}\n\nfunction randomToken(): string {\n const bytes = new Uint8Array(TOKEN_BYTES);\n crypto.getRandomValues(bytes);\n return base64Url(bytes);\n}\n\nfunction randomId(len: number): string {\n const bytes = new Uint8Array(Math.ceil((len * 3) / 4));\n crypto.getRandomValues(bytes);\n return base64Url(bytes).slice(0, len);\n}\n\nfunction base64Url(bytes: Uint8Array): string {\n let s = \"\";\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** Constant-time string compare so a mismatched token leaks no timing info. */\nexport function constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n","import type { JsonRpcMessage } from \"../mcp/types\";\nimport type { Transport } from \"../mcp/server\";\nimport type { MicroMcpServer } from \"../mcp/server\";\nimport { constantTimeEqual } from \"./token\";\n\n/**\n * SseRelayTransport — bridges the in-page MicroMcpServer to a host-app\n * relay broker over Server-Sent Events (inbound) + POST (outbound).\n *\n * Wire model:\n * - Browser opens an EventSource at `${baseUrl}/${sessionId}/events?token=…`.\n * Each `event: mcp` carries one JSON-RPC frame from a remote client.\n * - Browser POSTs JSON-RPC frames to `${baseUrl}/${sessionId}/outbox?token=…`\n * when the local server has a response/notification to send.\n *\n * The host provides the relay endpoint (any HTTP server). See the demo\n * `WhiteboardShareController` for the reference implementation.\n *\n * Token authentication is the host's job — this transport just carries the\n * token in the query string. For lower-trust deployments, layer signing on\n * top by wrapping `send` / `deliverFromRemote`.\n */\nexport type SseRelayOptions = {\n baseUrl: string;\n sessionId: string;\n token: string;\n /** Override fetch (testing / non-browser). Defaults to global fetch. */\n fetch?: typeof fetch;\n};\n\nexport class SseRelayTransport implements Transport {\n private server?: MicroMcpServer;\n private es?: EventSource;\n private opts: SseRelayOptions;\n private sendQueue: JsonRpcMessage[] = [];\n private connected = false;\n private listeners = new Set<(state: RelayState) => void>();\n private state: RelayState = \"idle\";\n private expectedToken: string;\n\n constructor(options: SseRelayOptions) {\n this.opts = options;\n this.expectedToken = options.token;\n }\n\n bindServer(server: MicroMcpServer): void {\n this.server = server;\n }\n\n /** Open the SSE channel. Idempotent. */\n start(): void {\n if (this.connected || typeof window === \"undefined\") return;\n const url = `${this.opts.baseUrl}/${encodeURIComponent(this.opts.sessionId)}/events?token=${encodeURIComponent(this.opts.token)}`;\n this.setState(\"connecting\");\n const es = new EventSource(url, { withCredentials: false });\n this.es = es;\n\n es.addEventListener(\"open\", () => {\n this.connected = true;\n this.setState(\"open\");\n // Flush queued outbound frames (tool list_changed notifications, etc.)\n const queued = this.sendQueue.splice(0);\n for (const msg of queued) this.postOut(msg);\n });\n\n es.addEventListener(\"mcp\", (ev: MessageEvent) => {\n const raw = ev.data;\n this.handleInbound(raw);\n });\n\n es.addEventListener(\"error\", () => {\n this.setState(\"error\");\n // EventSource auto-reconnects; no need to dispose.\n });\n }\n\n send(message: JsonRpcMessage): void {\n if (!this.connected) {\n this.sendQueue.push(message);\n return;\n }\n this.postOut(message);\n }\n\n close(): void {\n this.es?.close();\n this.es = undefined;\n this.connected = false;\n this.setState(\"closed\");\n }\n\n onStateChange(listener: (state: RelayState) => void): () => void {\n this.listeners.add(listener);\n listener(this.state);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * For relays that wrap each frame with auth metadata: hosts can call this\n * directly when a frame arrives via a non-SSE path. The transport will\n * dispatch it to the bound server.\n */\n async deliverFromRemote(payload: JsonRpcMessage | string, token?: string): Promise<void> {\n if (token !== undefined && !constantTimeEqual(token, this.expectedToken)) return;\n if (!this.server) throw new Error(\"SseRelayTransport has no bound server\");\n const message: JsonRpcMessage = typeof payload === \"string\" ? JSON.parse(payload) : payload;\n await this.server.receive(this, message);\n }\n\n private async postOut(message: JsonRpcMessage): Promise<void> {\n const url = `${this.opts.baseUrl}/${encodeURIComponent(this.opts.sessionId)}/outbox?token=${encodeURIComponent(this.opts.token)}`;\n const f = this.opts.fetch ?? fetch;\n try {\n await f(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"accept\": \"application/json\" },\n body: JSON.stringify(message),\n });\n } catch {\n // Drop — relay errors are surfaced via state change separately.\n }\n }\n\n private async handleInbound(raw: string): Promise<void> {\n if (!this.server) return;\n let message: JsonRpcMessage;\n try {\n message = JSON.parse(raw);\n } catch {\n return;\n }\n await this.server.receive(this, message);\n }\n\n private setState(state: RelayState): void {\n this.state = state;\n for (const l of this.listeners) l(state);\n }\n}\n\nexport type RelayState = \"idle\" | \"connecting\" | \"open\" | \"closed\" | \"error\";\n\nexport function attachSseRelay(server: MicroMcpServer, options: SseRelayOptions): SseRelayTransport {\n const transport = new SseRelayTransport(options);\n transport.bindServer(server);\n server.attach(transport);\n transport.start();\n return transport;\n}\n"]}
|
package/dist/sharing.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"sharing.js"}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/* src/styles.css */
|
|
2
|
+
.fai-panel {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
height: 100%;
|
|
6
|
+
background: white;
|
|
7
|
+
color: #18181b;
|
|
8
|
+
border-radius: 12px;
|
|
9
|
+
border: 1px solid #e4e4e7;
|
|
10
|
+
font-family:
|
|
11
|
+
ui-sans-serif,
|
|
12
|
+
system-ui,
|
|
13
|
+
-apple-system,
|
|
14
|
+
"Segoe UI",
|
|
15
|
+
Roboto,
|
|
16
|
+
sans-serif;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
}
|
|
19
|
+
@media (prefers-color-scheme: dark) {
|
|
20
|
+
.fai-panel {
|
|
21
|
+
background: #18181b;
|
|
22
|
+
color: #fafafa;
|
|
23
|
+
border-color: #3f3f46;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
.fai-panel__header {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
gap: 10px;
|
|
30
|
+
padding: 10px 12px;
|
|
31
|
+
border-bottom: 1px solid #e4e4e7;
|
|
32
|
+
}
|
|
33
|
+
@media (prefers-color-scheme: dark) {
|
|
34
|
+
.fai-panel__header {
|
|
35
|
+
border-color: #3f3f46;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
.fai-panel__avatar {
|
|
39
|
+
width: 32px;
|
|
40
|
+
height: 32px;
|
|
41
|
+
border-radius: 50%;
|
|
42
|
+
display: inline-flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
color: white;
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
font-size: 14px;
|
|
48
|
+
}
|
|
49
|
+
.fai-panel__title {
|
|
50
|
+
display: flex;
|
|
51
|
+
flex-direction: column;
|
|
52
|
+
line-height: 1.1;
|
|
53
|
+
flex: 1;
|
|
54
|
+
}
|
|
55
|
+
.fai-panel__subtitle {
|
|
56
|
+
font-size: 11px;
|
|
57
|
+
opacity: 0.6;
|
|
58
|
+
}
|
|
59
|
+
.fai-panel__actions {
|
|
60
|
+
display: flex;
|
|
61
|
+
gap: 6px;
|
|
62
|
+
}
|
|
63
|
+
.fai-panel__stream {
|
|
64
|
+
flex: 1;
|
|
65
|
+
overflow: auto;
|
|
66
|
+
padding: 8px 12px;
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: 6px;
|
|
70
|
+
}
|
|
71
|
+
.fai-panel__empty {
|
|
72
|
+
font-size: 12px;
|
|
73
|
+
opacity: 0.5;
|
|
74
|
+
margin: auto;
|
|
75
|
+
}
|
|
76
|
+
.fai-row {
|
|
77
|
+
font-size: 12px;
|
|
78
|
+
border-radius: 6px;
|
|
79
|
+
padding: 6px 8px;
|
|
80
|
+
background: rgba(244, 244, 245, 0.6);
|
|
81
|
+
}
|
|
82
|
+
@media (prefers-color-scheme: dark) {
|
|
83
|
+
.fai-row {
|
|
84
|
+
background: rgba(63, 63, 70, 0.4);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
.fai-row--tool {
|
|
88
|
+
border-left: 3px solid #a855f7;
|
|
89
|
+
}
|
|
90
|
+
.fai-row--message {
|
|
91
|
+
border-left: 3px solid #3b82f6;
|
|
92
|
+
}
|
|
93
|
+
.fai-row--info {
|
|
94
|
+
border-left: 3px solid #71717a;
|
|
95
|
+
}
|
|
96
|
+
.fai-row--error {
|
|
97
|
+
border-left: 3px solid #ef4444;
|
|
98
|
+
background: rgba(254, 226, 226, 0.4);
|
|
99
|
+
}
|
|
100
|
+
.fai-row__meta {
|
|
101
|
+
display: flex;
|
|
102
|
+
justify-content: space-between;
|
|
103
|
+
opacity: 0.6;
|
|
104
|
+
font-size: 10px;
|
|
105
|
+
}
|
|
106
|
+
.fai-row__source {
|
|
107
|
+
font-family: ui-monospace, monospace;
|
|
108
|
+
}
|
|
109
|
+
.fai-row__text {
|
|
110
|
+
white-space: pre-wrap;
|
|
111
|
+
}
|
|
112
|
+
.fai-row__detail summary {
|
|
113
|
+
cursor: pointer;
|
|
114
|
+
opacity: 0.7;
|
|
115
|
+
font-size: 11px;
|
|
116
|
+
margin-top: 4px;
|
|
117
|
+
}
|
|
118
|
+
.fai-row__detail pre {
|
|
119
|
+
font-size: 11px;
|
|
120
|
+
margin: 4px 0 0;
|
|
121
|
+
padding: 6px;
|
|
122
|
+
background: rgba(0, 0, 0, 0.06);
|
|
123
|
+
border-radius: 4px;
|
|
124
|
+
overflow: auto;
|
|
125
|
+
max-height: 200px;
|
|
126
|
+
}
|
|
127
|
+
.fai-panel__composer {
|
|
128
|
+
display: flex;
|
|
129
|
+
gap: 6px;
|
|
130
|
+
padding: 8px;
|
|
131
|
+
border-top: 1px solid #e4e4e7;
|
|
132
|
+
}
|
|
133
|
+
@media (prefers-color-scheme: dark) {
|
|
134
|
+
.fai-panel__composer {
|
|
135
|
+
border-color: #3f3f46;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
.fai-panel__input {
|
|
139
|
+
flex: 1;
|
|
140
|
+
resize: none;
|
|
141
|
+
border-radius: 6px;
|
|
142
|
+
border: 1px solid #d4d4d8;
|
|
143
|
+
padding: 6px 8px;
|
|
144
|
+
font: inherit;
|
|
145
|
+
background: transparent;
|
|
146
|
+
color: inherit;
|
|
147
|
+
}
|
|
148
|
+
.fai-panel__input:focus {
|
|
149
|
+
outline: 2px solid #a855f7;
|
|
150
|
+
outline-offset: -1px;
|
|
151
|
+
}
|
|
152
|
+
.fai-panel__send {
|
|
153
|
+
align-self: stretch;
|
|
154
|
+
padding: 0 14px;
|
|
155
|
+
border: 0;
|
|
156
|
+
border-radius: 6px;
|
|
157
|
+
background: #a855f7;
|
|
158
|
+
color: white;
|
|
159
|
+
cursor: pointer;
|
|
160
|
+
font-weight: 500;
|
|
161
|
+
}
|
|
162
|
+
.fai-panel__send:disabled {
|
|
163
|
+
opacity: 0.5;
|
|
164
|
+
cursor: default;
|
|
165
|
+
}
|
|
166
|
+
.fai-cursor {
|
|
167
|
+
transition: left 500ms cubic-bezier(0.22, 1, 0.36, 1), top 500ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
168
|
+
}
|
|
169
|
+
@media (prefers-reduced-motion: reduce) {
|
|
170
|
+
.fai-cursor {
|
|
171
|
+
transition: none;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
.fai-cursor__tag {
|
|
175
|
+
position: absolute;
|
|
176
|
+
left: 18px;
|
|
177
|
+
top: 14px;
|
|
178
|
+
color: white;
|
|
179
|
+
padding: 2px 6px;
|
|
180
|
+
border-radius: 4px;
|
|
181
|
+
font-size: 11px;
|
|
182
|
+
font-family: system-ui, sans-serif;
|
|
183
|
+
white-space: nowrap;
|
|
184
|
+
}
|
|
185
|
+
.fai-cursor__status {
|
|
186
|
+
font-style: normal;
|
|
187
|
+
opacity: 0.85;
|
|
188
|
+
}
|
|
189
|
+
@keyframes fai-pulse {
|
|
190
|
+
0% {
|
|
191
|
+
opacity: 0;
|
|
192
|
+
transform: scale(0.96);
|
|
193
|
+
}
|
|
194
|
+
20% {
|
|
195
|
+
opacity: 1;
|
|
196
|
+
transform: scale(1.03);
|
|
197
|
+
}
|
|
198
|
+
100% {
|
|
199
|
+
opacity: 0;
|
|
200
|
+
transform: scale(1);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
.fai-share {
|
|
204
|
+
border: 1px solid #e4e4e7;
|
|
205
|
+
border-radius: 12px;
|
|
206
|
+
padding: 12px;
|
|
207
|
+
background: white;
|
|
208
|
+
color: #18181b;
|
|
209
|
+
font-family:
|
|
210
|
+
ui-sans-serif,
|
|
211
|
+
system-ui,
|
|
212
|
+
sans-serif;
|
|
213
|
+
font-size: 13px;
|
|
214
|
+
}
|
|
215
|
+
@media (prefers-color-scheme: dark) {
|
|
216
|
+
.fai-share {
|
|
217
|
+
background: #18181b;
|
|
218
|
+
color: #fafafa;
|
|
219
|
+
border-color: #3f3f46;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
.fai-share--idle {
|
|
223
|
+
display: flex;
|
|
224
|
+
flex-direction: column;
|
|
225
|
+
gap: 6px;
|
|
226
|
+
}
|
|
227
|
+
.fai-share__start {
|
|
228
|
+
align-self: flex-start;
|
|
229
|
+
padding: 8px 14px;
|
|
230
|
+
border: 0;
|
|
231
|
+
border-radius: 6px;
|
|
232
|
+
background: #a855f7;
|
|
233
|
+
color: white;
|
|
234
|
+
font-weight: 500;
|
|
235
|
+
cursor: pointer;
|
|
236
|
+
}
|
|
237
|
+
.fai-share__hint {
|
|
238
|
+
margin: 0;
|
|
239
|
+
opacity: 0.7;
|
|
240
|
+
font-size: 12px;
|
|
241
|
+
}
|
|
242
|
+
.fai-share__header {
|
|
243
|
+
display: flex;
|
|
244
|
+
justify-content: space-between;
|
|
245
|
+
align-items: center;
|
|
246
|
+
gap: 8px;
|
|
247
|
+
margin-bottom: 8px;
|
|
248
|
+
}
|
|
249
|
+
.fai-share__id {
|
|
250
|
+
display: block;
|
|
251
|
+
opacity: 0.7;
|
|
252
|
+
font-size: 11px;
|
|
253
|
+
margin-top: 2px;
|
|
254
|
+
}
|
|
255
|
+
.fai-share__id code {
|
|
256
|
+
font-family: ui-monospace, monospace;
|
|
257
|
+
}
|
|
258
|
+
.fai-share__header-actions {
|
|
259
|
+
display: flex;
|
|
260
|
+
gap: 8px;
|
|
261
|
+
align-items: center;
|
|
262
|
+
}
|
|
263
|
+
.fai-share__status {
|
|
264
|
+
font-size: 11px;
|
|
265
|
+
padding: 2px 8px;
|
|
266
|
+
border-radius: 999px;
|
|
267
|
+
background: rgba(34, 197, 94, 0.15);
|
|
268
|
+
color: #16a34a;
|
|
269
|
+
}
|
|
270
|
+
.fai-share__stop {
|
|
271
|
+
border: 1px solid #d4d4d8;
|
|
272
|
+
background: transparent;
|
|
273
|
+
border-radius: 6px;
|
|
274
|
+
padding: 4px 10px;
|
|
275
|
+
cursor: pointer;
|
|
276
|
+
font-size: 12px;
|
|
277
|
+
color: inherit;
|
|
278
|
+
}
|
|
279
|
+
.fai-share__tabs {
|
|
280
|
+
display: flex;
|
|
281
|
+
gap: 4px;
|
|
282
|
+
margin-bottom: 8px;
|
|
283
|
+
}
|
|
284
|
+
.fai-share__tab {
|
|
285
|
+
border: 0;
|
|
286
|
+
background: transparent;
|
|
287
|
+
cursor: pointer;
|
|
288
|
+
padding: 4px 10px;
|
|
289
|
+
border-radius: 4px;
|
|
290
|
+
color: inherit;
|
|
291
|
+
font-size: 12px;
|
|
292
|
+
}
|
|
293
|
+
.fai-share__tab.is-active {
|
|
294
|
+
background: rgba(168, 85, 247, 0.12);
|
|
295
|
+
color: #a855f7;
|
|
296
|
+
}
|
|
297
|
+
.fai-share__panel-label {
|
|
298
|
+
font-size: 11px;
|
|
299
|
+
opacity: 0.7;
|
|
300
|
+
margin-bottom: 4px;
|
|
301
|
+
}
|
|
302
|
+
.fai-share__copy {
|
|
303
|
+
display: flex;
|
|
304
|
+
gap: 6px;
|
|
305
|
+
align-items: stretch;
|
|
306
|
+
}
|
|
307
|
+
.fai-share__pre {
|
|
308
|
+
flex: 1;
|
|
309
|
+
margin: 0;
|
|
310
|
+
padding: 8px 10px;
|
|
311
|
+
background: rgba(0, 0, 0, 0.05);
|
|
312
|
+
border-radius: 6px;
|
|
313
|
+
font-family: ui-monospace, monospace;
|
|
314
|
+
font-size: 11px;
|
|
315
|
+
white-space: nowrap;
|
|
316
|
+
overflow: auto;
|
|
317
|
+
}
|
|
318
|
+
.fai-share__pre.is-multi {
|
|
319
|
+
white-space: pre;
|
|
320
|
+
max-height: 240px;
|
|
321
|
+
}
|
|
322
|
+
.fai-share__copy-btn {
|
|
323
|
+
border: 1px solid #d4d4d8;
|
|
324
|
+
background: transparent;
|
|
325
|
+
cursor: pointer;
|
|
326
|
+
border-radius: 6px;
|
|
327
|
+
padding: 0 12px;
|
|
328
|
+
color: inherit;
|
|
329
|
+
font-size: 12px;
|
|
330
|
+
}
|
|
331
|
+
/*# sourceMappingURL=styles.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/styles.css"],"sourcesContent":["/* @particle-academy/agent-integrations — minimal styles, host app provides tailwind/theme. */\n\n.fai-panel {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: white;\n color: #18181b;\n border-radius: 12px;\n border: 1px solid #e4e4e7;\n font-family: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n overflow: hidden;\n}\n@media (prefers-color-scheme: dark) {\n .fai-panel { background: #18181b; color: #fafafa; border-color: #3f3f46; }\n}\n.fai-panel__header {\n display: flex; align-items: center; gap: 10px;\n padding: 10px 12px; border-bottom: 1px solid #e4e4e7;\n}\n@media (prefers-color-scheme: dark) { .fai-panel__header { border-color: #3f3f46; } }\n.fai-panel__avatar {\n width: 32px; height: 32px; border-radius: 50%;\n display: inline-flex; align-items: center; justify-content: center;\n color: white; font-weight: 600; font-size: 14px;\n}\n.fai-panel__title { display: flex; flex-direction: column; line-height: 1.1; flex: 1; }\n.fai-panel__subtitle { font-size: 11px; opacity: 0.6; }\n.fai-panel__actions { display: flex; gap: 6px; }\n.fai-panel__stream {\n flex: 1; overflow: auto; padding: 8px 12px;\n display: flex; flex-direction: column; gap: 6px;\n}\n.fai-panel__empty { font-size: 12px; opacity: 0.5; margin: auto; }\n.fai-row {\n font-size: 12px;\n border-radius: 6px;\n padding: 6px 8px;\n background: rgba(244, 244, 245, 0.6);\n}\n@media (prefers-color-scheme: dark) { .fai-row { background: rgba(63, 63, 70, 0.4); } }\n.fai-row--tool { border-left: 3px solid #a855f7; }\n.fai-row--message { border-left: 3px solid #3b82f6; }\n.fai-row--info { border-left: 3px solid #71717a; }\n.fai-row--error { border-left: 3px solid #ef4444; background: rgba(254, 226, 226, 0.4); }\n.fai-row__meta { display: flex; justify-content: space-between; opacity: 0.6; font-size: 10px; }\n.fai-row__source { font-family: ui-monospace, monospace; }\n.fai-row__text { white-space: pre-wrap; }\n.fai-row__detail summary { cursor: pointer; opacity: 0.7; font-size: 11px; margin-top: 4px; }\n.fai-row__detail pre {\n font-size: 11px; margin: 4px 0 0; padding: 6px;\n background: rgba(0,0,0,0.06); border-radius: 4px; overflow: auto;\n max-height: 200px;\n}\n.fai-panel__composer {\n display: flex; gap: 6px; padding: 8px;\n border-top: 1px solid #e4e4e7;\n}\n@media (prefers-color-scheme: dark) { .fai-panel__composer { border-color: #3f3f46; } }\n.fai-panel__input {\n flex: 1;\n resize: none;\n border-radius: 6px;\n border: 1px solid #d4d4d8;\n padding: 6px 8px;\n font: inherit;\n background: transparent;\n color: inherit;\n}\n.fai-panel__input:focus { outline: 2px solid #a855f7; outline-offset: -1px; }\n.fai-panel__send {\n align-self: stretch;\n padding: 0 14px;\n border: 0; border-radius: 6px;\n background: #a855f7; color: white;\n cursor: pointer; font-weight: 500;\n}\n.fai-panel__send:disabled { opacity: 0.5; cursor: default; }\n\n/* Cursor */\n.fai-cursor {\n transition: left 500ms cubic-bezier(0.22, 1, 0.36, 1),\n top 500ms cubic-bezier(0.22, 1, 0.36, 1);\n}\n@media (prefers-reduced-motion: reduce) { .fai-cursor { transition: none; } }\n.fai-cursor__tag {\n position: absolute; left: 18px; top: 14px;\n color: white;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 11px; font-family: system-ui, sans-serif;\n white-space: nowrap;\n}\n.fai-cursor__status { font-style: normal; opacity: 0.85; }\n\n/* Highlight pulse */\n@keyframes fai-pulse {\n 0% { opacity: 0; transform: scale(0.96); }\n 20% { opacity: 1; transform: scale(1.03); }\n 100% { opacity: 0; transform: scale(1); }\n}\n\n/* ShareControls */\n.fai-share {\n border: 1px solid #e4e4e7; border-radius: 12px; padding: 12px;\n background: white; color: #18181b;\n font-family: ui-sans-serif, system-ui, sans-serif; font-size: 13px;\n}\n@media (prefers-color-scheme: dark) { .fai-share { background: #18181b; color: #fafafa; border-color: #3f3f46; } }\n.fai-share--idle { display: flex; flex-direction: column; gap: 6px; }\n.fai-share__start { align-self: flex-start; padding: 8px 14px; border: 0; border-radius: 6px; background: #a855f7; color: white; font-weight: 500; cursor: pointer; }\n.fai-share__hint { margin: 0; opacity: 0.7; font-size: 12px; }\n.fai-share__header { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 8px; }\n.fai-share__id { display: block; opacity: 0.7; font-size: 11px; margin-top: 2px; }\n.fai-share__id code { font-family: ui-monospace, monospace; }\n.fai-share__header-actions { display: flex; gap: 8px; align-items: center; }\n.fai-share__status { font-size: 11px; padding: 2px 8px; border-radius: 999px; background: rgba(34, 197, 94, 0.15); color: #16a34a; }\n.fai-share__stop { border: 1px solid #d4d4d8; background: transparent; border-radius: 6px; padding: 4px 10px; cursor: pointer; font-size: 12px; color: inherit; }\n.fai-share__tabs { display: flex; gap: 4px; margin-bottom: 8px; }\n.fai-share__tab { border: 0; background: transparent; cursor: pointer; padding: 4px 10px; border-radius: 4px; color: inherit; font-size: 12px; }\n.fai-share__tab.is-active { background: rgba(168, 85, 247, 0.12); color: #a855f7; }\n.fai-share__panel-label { font-size: 11px; opacity: 0.7; margin-bottom: 4px; }\n.fai-share__copy { display: flex; gap: 6px; align-items: stretch; }\n.fai-share__pre { flex: 1; margin: 0; padding: 8px 10px; background: rgba(0,0,0,0.05); border-radius: 6px; font-family: ui-monospace, monospace; font-size: 11px; white-space: nowrap; overflow: auto; }\n.fai-share__pre.is-multi { white-space: pre; max-height: 240px; }\n.fai-share__copy-btn { border: 1px solid #d4d4d8; background: transparent; cursor: pointer; border-radius: 6px; padding: 0 12px; color: inherit; font-size: 12px; }\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { M as MicroMcpServer } from './server-Bv985us3.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bridge — registers a cohesive set of MCP tools/resources for a single
|
|
5
|
+
* fancy-* package or app concern. Each bridge owns its lifecycle: install
|
|
6
|
+
* to register handlers on a server, dispose to remove them.
|
|
7
|
+
*/
|
|
8
|
+
type Bridge = {
|
|
9
|
+
/** Stable identifier — surfaces in agent activity logs. */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Human-readable label for UI. */
|
|
12
|
+
title?: string;
|
|
13
|
+
/** Disposes the bridge. Must remove every tool it registered. */
|
|
14
|
+
dispose: () => void;
|
|
15
|
+
};
|
|
16
|
+
type BridgeFactory<TOptions> = (server: MicroMcpServer, options: TOptions) => Bridge;
|
|
17
|
+
|
|
18
|
+
export type { Bridge as B, BridgeFactory as a };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { M as MicroMcpServer } from './server-Bv985us3.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bridge — registers a cohesive set of MCP tools/resources for a single
|
|
5
|
+
* fancy-* package or app concern. Each bridge owns its lifecycle: install
|
|
6
|
+
* to register handlers on a server, dispose to remove them.
|
|
7
|
+
*/
|
|
8
|
+
type Bridge = {
|
|
9
|
+
/** Stable identifier — surfaces in agent activity logs. */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Human-readable label for UI. */
|
|
12
|
+
title?: string;
|
|
13
|
+
/** Disposes the bridge. Must remove every tool it registered. */
|
|
14
|
+
dispose: () => void;
|
|
15
|
+
};
|
|
16
|
+
type BridgeFactory<TOptions> = (server: MicroMcpServer, options: TOptions) => Bridge;
|
|
17
|
+
|
|
18
|
+
export type { Bridge as B, BridgeFactory as a };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Relay protocol
|
|
2
|
+
|
|
3
|
+
A relay lets external MCP clients (Claude Desktop, Cline, a custom agent) reach a `MicroMcpServer` running inside a browser session. The relay carries opaque JSON-RPC frames between the two endpoints.
|
|
4
|
+
|
|
5
|
+
## Wire format
|
|
6
|
+
|
|
7
|
+
The relay is just a duplex JSON-frame channel. Each frame is a complete MCP / JSON-RPC 2.0 message:
|
|
8
|
+
|
|
9
|
+
```jsonc
|
|
10
|
+
// client → server
|
|
11
|
+
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }
|
|
12
|
+
|
|
13
|
+
// server → client
|
|
14
|
+
{ "jsonrpc": "2.0", "id": 1, "result": { "tools": [...] } }
|
|
15
|
+
|
|
16
|
+
// server → client (notification)
|
|
17
|
+
{ "jsonrpc": "2.0", "method": "notifications/tools/list_changed" }
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The relay is responsible for **delivery**, not framing or authorization — the underlying transport (websocket, SSE+POST, WebRTC data channel) handles those concerns.
|
|
21
|
+
|
|
22
|
+
## Recommended transports
|
|
23
|
+
|
|
24
|
+
### Laravel Reverb (private channel)
|
|
25
|
+
|
|
26
|
+
A single private channel per session. The browser tab and the agent both connect via the host app's auth bridge. Whispers carry MCP frames.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// Browser side
|
|
30
|
+
import { attachRelay } from "@particle-academy/agent-integrations";
|
|
31
|
+
|
|
32
|
+
const channel = Echo.private(`agent.session.${sessionId}`);
|
|
33
|
+
const transport = attachRelay(server, {
|
|
34
|
+
sendToRemote: (frame) => channel.whisper("mcp", frame),
|
|
35
|
+
});
|
|
36
|
+
channel.listenForWhisper("mcp", (frame) => transport.deliverFromRemote(frame));
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The agent side connects to the same Reverb channel via your auth bridge and reads/writes whispers identically.
|
|
40
|
+
|
|
41
|
+
### WebRTC data channel
|
|
42
|
+
|
|
43
|
+
For direct peer connections (no server hop), open a data channel and pipe frames through it.
|
|
44
|
+
|
|
45
|
+
### SSE + POST tunnel
|
|
46
|
+
|
|
47
|
+
The browser opens a long-lived `EventSource` to a relay service (e.g. a Cloudflare Worker) that also accepts `POST /mcp/{session}` from external agents. The relay forwards each request as an SSE event and accepts responses via a paired POST endpoint.
|
|
48
|
+
|
|
49
|
+
## Multiple clients
|
|
50
|
+
|
|
51
|
+
A single `MicroMcpServer` can have multiple transports attached at once (e.g. an in-page agent **and** an external relay). Each receives all server-pushed notifications; tool-call replies go back on the transport that originated the call.
|
|
52
|
+
|
|
53
|
+
## Security
|
|
54
|
+
|
|
55
|
+
- **Per-session scope.** A relay channel maps 1:1 to a collab session. Tools mutate that session's state; an agent connected to session A cannot reach session B unless the host app routes it there.
|
|
56
|
+
- **Authorization is the host's job.** The relay carries opaque frames — gate channel access with the same auth your collab session already uses.
|
|
57
|
+
- **Tool surface is intentional.** Bridges register only the tools you want exposed. To restrict an agent (e.g. read-only mode), register a subset of the bridge's tools or unregister mutators after install.
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@particle-academy/agent-integrations",
|
|
3
|
+
"version": "0.2.4",
|
|
4
|
+
"description": "MCP-driven agent presence in collab sessions: per-session micro-MCP server, pluggable bridges to fancy-* packages, and agent UX components (panel + on-canvas cursor).",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/Particle-Academy/agent-integrations.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/Particle-Academy/agent-integrations#readme",
|
|
10
|
+
"bugs": "https://github.com/Particle-Academy/agent-integrations/issues",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.cjs",
|
|
13
|
+
"module": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
|
|
18
|
+
"require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" }
|
|
19
|
+
},
|
|
20
|
+
"./mcp": {
|
|
21
|
+
"import": { "types": "./dist/mcp.d.ts", "default": "./dist/mcp.js" },
|
|
22
|
+
"require": { "types": "./dist/mcp.d.cts", "default": "./dist/mcp.cjs" }
|
|
23
|
+
},
|
|
24
|
+
"./bridges/whiteboard": {
|
|
25
|
+
"import": { "types": "./dist/bridges-whiteboard.d.ts", "default": "./dist/bridges-whiteboard.js" },
|
|
26
|
+
"require": { "types": "./dist/bridges-whiteboard.d.cts", "default": "./dist/bridges-whiteboard.cjs" }
|
|
27
|
+
},
|
|
28
|
+
"./styles.css": "./dist/styles.css"
|
|
29
|
+
},
|
|
30
|
+
"files": ["dist", "docs", "README.md"],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup",
|
|
33
|
+
"dev": "tsup --watch",
|
|
34
|
+
"lint": "tsc --noEmit",
|
|
35
|
+
"clean": "rm -rf dist",
|
|
36
|
+
"prepublishOnly": "tsup"
|
|
37
|
+
},
|
|
38
|
+
"keywords": ["react", "mcp", "model-context-protocol", "agents", "whiteboard", "collaboration", "fancy"],
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
41
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
42
|
+
"@particle-academy/fancy-whiteboard": "^0.1.0",
|
|
43
|
+
"@particle-academy/fancy-flow": "^0.2.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependenciesMeta": {
|
|
46
|
+
"@particle-academy/fancy-whiteboard": { "optional": true },
|
|
47
|
+
"@particle-academy/fancy-flow": { "optional": true }
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@particle-academy/fancy-whiteboard": "^0.1.5",
|
|
51
|
+
"@types/react": "^19.0.0",
|
|
52
|
+
"@types/react-dom": "^19.0.0",
|
|
53
|
+
"react": "^19.0.0",
|
|
54
|
+
"react-dom": "^19.0.0",
|
|
55
|
+
"tsup": "^8.0.0",
|
|
56
|
+
"typescript": "^5.7.0"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": { "access": "public" },
|
|
59
|
+
"license": "MIT",
|
|
60
|
+
"sideEffects": ["**/*.css"]
|
|
61
|
+
}
|