@particle-academy/agent-integrations 0.28.1 → 0.29.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/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 +3 -3
- package/dist/bridges/cms.d.ts +3 -3
- package/dist/bridges/code.d.cts +3 -3
- package/dist/bridges/code.d.ts +3 -3
- package/dist/bridges/doc.d.cts +3 -3
- package/dist/bridges/doc.d.ts +3 -3
- 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/tui.d.cts +45 -0
- package/dist/bridges/tui.d.ts +45 -0
- package/dist/bridges/whiteboard.d.cts +3 -3
- package/dist/bridges/whiteboard.d.ts +3 -3
- package/dist/bridges-artboard.cjs.map +1 -1
- package/dist/bridges-artboard.js +2 -2
- package/dist/bridges-catalog.cjs.map +1 -1
- package/dist/bridges-catalog.js +3 -3
- package/dist/bridges-charts.cjs.map +1 -1
- package/dist/bridges-charts.js +3 -3
- package/dist/bridges-cms.cjs.map +1 -1
- package/dist/bridges-cms.js +4 -4
- package/dist/bridges-code.cjs.map +1 -1
- package/dist/bridges-code.js +3 -3
- package/dist/bridges-doc.cjs.map +1 -1
- package/dist/bridges-doc.js +3 -3
- package/dist/bridges-features.cjs.map +1 -1
- package/dist/bridges-features.js +3 -3
- package/dist/bridges-files.cjs.map +1 -1
- package/dist/bridges-files.js +3 -3
- package/dist/bridges-flow.cjs.map +1 -1
- package/dist/bridges-flow.js +2 -2
- package/dist/bridges-forms.cjs.map +1 -1
- package/dist/bridges-forms.js +3 -3
- package/dist/bridges-map.cjs.map +1 -1
- package/dist/bridges-map.js +3 -3
- package/dist/bridges-scene.cjs.map +1 -1
- package/dist/bridges-scene.js +3 -3
- package/dist/bridges-screens.cjs.map +1 -1
- package/dist/bridges-screens.js +3 -3
- package/dist/bridges-sheets.cjs.map +1 -1
- package/dist/bridges-sheets.js +3 -3
- package/dist/bridges-slides.cjs.map +1 -1
- package/dist/bridges-slides.js +3 -3
- package/dist/bridges-terminal.cjs.map +1 -1
- package/dist/bridges-terminal.js +3 -3
- package/dist/bridges-tui.cjs +114 -0
- package/dist/bridges-tui.cjs.map +1 -0
- package/dist/bridges-tui.js +7 -0
- package/dist/bridges-tui.js.map +1 -0
- package/dist/bridges-whiteboard.cjs.map +1 -1
- package/dist/bridges-whiteboard.js +3 -3
- package/dist/{chunk-AROVENCE.js → chunk-2Y7Y5PTR.js} +4 -4
- package/dist/{chunk-AROVENCE.js.map → chunk-2Y7Y5PTR.js.map} +1 -1
- package/dist/{chunk-QDD4WHIV.js → chunk-3PKHJ4IV.js} +4 -4
- package/dist/{chunk-QDD4WHIV.js.map → chunk-3PKHJ4IV.js.map} +1 -1
- package/dist/{chunk-A57CRGEK.js → chunk-7VBB2FJB.js} +3 -3
- package/dist/{chunk-A57CRGEK.js.map → chunk-7VBB2FJB.js.map} +1 -1
- package/dist/{chunk-FF5F526J.js → chunk-AF454WRD.js} +4 -4
- package/dist/{chunk-FF5F526J.js.map → chunk-AF454WRD.js.map} +1 -1
- package/dist/{chunk-66WOHZZJ.js → chunk-BE2XS577.js} +4 -4
- package/dist/{chunk-66WOHZZJ.js.map → chunk-BE2XS577.js.map} +1 -1
- package/dist/{chunk-GHY3PBPN.js → chunk-BT7HM5I6.js} +3 -3
- package/dist/{chunk-GHY3PBPN.js.map → chunk-BT7HM5I6.js.map} +1 -1
- package/dist/{chunk-KJ5AOOV7.js → chunk-CT3LRNH7.js} +3 -3
- package/dist/{chunk-KJ5AOOV7.js.map → chunk-CT3LRNH7.js.map} +1 -1
- package/dist/{chunk-4KAIV6OD.js → chunk-DF3PLL2E.js} +10 -5
- package/dist/chunk-DF3PLL2E.js.map +1 -0
- package/dist/{chunk-AAD3Z5E7.js → chunk-HFLHLS2N.js} +4 -4
- package/dist/{chunk-AAD3Z5E7.js.map → chunk-HFLHLS2N.js.map} +1 -1
- package/dist/{chunk-HWVVS6HE.js → chunk-KKGC4ERF.js} +4 -4
- package/dist/{chunk-HWVVS6HE.js.map → chunk-KKGC4ERF.js.map} +1 -1
- package/dist/{chunk-NN3ELTVO.js → chunk-KYMEDV6E.js} +4 -4
- package/dist/{chunk-NN3ELTVO.js.map → chunk-KYMEDV6E.js.map} +1 -1
- package/dist/{chunk-YGD2VTUM.js → chunk-LZJI7EKQ.js} +4 -4
- package/dist/{chunk-YGD2VTUM.js.map → chunk-LZJI7EKQ.js.map} +1 -1
- package/dist/chunk-MFMBR6LN.js +100 -0
- package/dist/chunk-MFMBR6LN.js.map +1 -0
- package/dist/{chunk-VFKO2VUR.js → chunk-NSPL5TVF.js} +4 -4
- package/dist/{chunk-VFKO2VUR.js.map → chunk-NSPL5TVF.js.map} +1 -1
- package/dist/{chunk-AAMQOXZC.js → chunk-OFCR6JY3.js} +4 -4
- package/dist/{chunk-AAMQOXZC.js.map → chunk-OFCR6JY3.js.map} +1 -1
- package/dist/{chunk-ZX6UQURN.js → chunk-OHUDEA6R.js} +4 -4
- package/dist/{chunk-ZX6UQURN.js.map → chunk-OHUDEA6R.js.map} +1 -1
- package/dist/chunk-PMI4C5S4.js +44 -0
- package/dist/chunk-PMI4C5S4.js.map +1 -0
- package/dist/{chunk-PCW2EK5G.js → chunk-TNU6AWUO.js} +4 -4
- package/dist/{chunk-PCW2EK5G.js.map → chunk-TNU6AWUO.js.map} +1 -1
- package/dist/{chunk-QRDVJW6Q.js → chunk-UTUVN6HQ.js} +4 -4
- package/dist/{chunk-QRDVJW6Q.js.map → chunk-UTUVN6HQ.js.map} +1 -1
- package/dist/{chunk-XMMCSQ4I.js → chunk-VMCG3PJD.js} +4 -4
- package/dist/{chunk-XMMCSQ4I.js.map → chunk-VMCG3PJD.js.map} +1 -1
- package/dist/components-shared-whiteboard.cjs +8 -3
- package/dist/components-shared-whiteboard.cjs.map +1 -1
- package/dist/components-shared-whiteboard.js +3 -3
- package/dist/human-plus/file-store.d.cts +17 -0
- package/dist/human-plus/file-store.d.ts +17 -0
- package/dist/human-plus/index.d.cts +61 -0
- package/dist/human-plus/index.d.ts +61 -0
- package/dist/human-plus-node.cjs +121 -0
- package/dist/human-plus-node.cjs.map +1 -0
- package/dist/human-plus-node.js +76 -0
- package/dist/human-plus-node.js.map +1 -0
- package/dist/human-plus.cjs +46 -0
- package/dist/human-plus.cjs.map +1 -0
- package/dist/human-plus.js +3 -0
- package/dist/human-plus.js.map +1 -0
- package/dist/index.cjs +212 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -7
- package/dist/index.d.ts +9 -7
- package/dist/index.js +58 -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/mcp.cjs +8 -3
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/presence/index.d.cts +1 -1
- package/dist/presence/index.d.ts +1 -1
- package/dist/{server-FFZpYPyM.d.ts → server-CDX643Kz.d.ts} +4 -2
- package/dist/{server-Dr3j48CU.d.cts → server-DDD3IZ56.d.cts} +4 -2
- package/dist/sharing/index.d.cts +3 -3
- package/dist/sharing/index.d.ts +3 -3
- package/dist/sheets-adapter.d.cts +3 -3
- package/dist/sheets-adapter.d.ts +3 -3
- package/dist/{tool-host-C_Vh17J_.d.ts → tool-host-CWTOJEm2.d.ts} +1 -1
- package/dist/{tool-host-IDecPrF1.d.cts → tool-host-EuYHYSSH.d.cts} +1 -1
- package/dist/{types-CBoQhR8L.d.ts → types-BKD6uf86.d.ts} +1 -1
- package/dist/{types-BDI_g5UG.d.ts → types-C58ZXs4K.d.cts} +6 -2
- package/dist/{types-BDI_g5UG.d.cts → types-C58ZXs4K.d.ts} +6 -2
- package/dist/{types-B0rmWyoR.d.cts → types-NFGP769G.d.cts} +1 -1
- package/dist/undo/index.d.cts +2 -2
- package/dist/undo/index.d.ts +2 -2
- package/dist/undo.cjs.map +1 -1
- package/dist/undo.js +3 -3
- package/package.json +13 -1
- package/dist/chunk-4KAIV6OD.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -112,7 +112,7 @@ var MicroMcpServer = class extends ToolRegistry {
|
|
|
112
112
|
}
|
|
113
113
|
const request = message;
|
|
114
114
|
try {
|
|
115
|
-
const result = await this.handle(request);
|
|
115
|
+
const result = await this.handle(request, transport);
|
|
116
116
|
transport.send({ jsonrpc: "2.0", id: request.id, result });
|
|
117
117
|
} catch (err) {
|
|
118
118
|
transport.send({
|
|
@@ -122,7 +122,7 @@ var MicroMcpServer = class extends ToolRegistry {
|
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
async handle(request) {
|
|
125
|
+
async handle(request, transport) {
|
|
126
126
|
const { method, params } = request;
|
|
127
127
|
switch (method) {
|
|
128
128
|
case "initialize":
|
|
@@ -144,7 +144,7 @@ var MicroMcpServer = class extends ToolRegistry {
|
|
|
144
144
|
if (!tool) {
|
|
145
145
|
throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unknown tool: ${name}`);
|
|
146
146
|
}
|
|
147
|
-
const result = await tool.handler(args);
|
|
147
|
+
const result = await tool.handler(args, { transport });
|
|
148
148
|
return result;
|
|
149
149
|
}
|
|
150
150
|
case "ping":
|
|
@@ -161,6 +161,11 @@ var MicroMcpServer = class extends ToolRegistry {
|
|
|
161
161
|
this.broadcast({ jsonrpc: "2.0", method: "notifications/tools/list_changed" });
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
|
+
/** Send an application notification to every client, or one attached transport. */
|
|
165
|
+
notify(message, transport) {
|
|
166
|
+
if (transport) transport.send(message);
|
|
167
|
+
else this.broadcast(message);
|
|
168
|
+
}
|
|
164
169
|
broadcast(message) {
|
|
165
170
|
for (const t of this.transports) t.send(message);
|
|
166
171
|
}
|
|
@@ -252,6 +257,50 @@ function attachRelay(server, channel) {
|
|
|
252
257
|
return transport;
|
|
253
258
|
}
|
|
254
259
|
|
|
260
|
+
// src/human-plus/events.ts
|
|
261
|
+
var MemoryHumanPlusEventStore = class {
|
|
262
|
+
constructor() {
|
|
263
|
+
this.events = [];
|
|
264
|
+
this.acknowledgements = /* @__PURE__ */ new Map();
|
|
265
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
266
|
+
this.nextSequence = 1;
|
|
267
|
+
}
|
|
268
|
+
async append(input) {
|
|
269
|
+
const event = { ...input, id: input.id ?? globalThis.crypto.randomUUID(), timestamp: input.timestamp ?? Date.now(), sequence: this.nextSequence++ };
|
|
270
|
+
this.events.push(event);
|
|
271
|
+
this.listeners.forEach((listener) => listener(event));
|
|
272
|
+
return event;
|
|
273
|
+
}
|
|
274
|
+
async list(query) {
|
|
275
|
+
const acknowledged = this.acknowledgements.get(query.consumerId);
|
|
276
|
+
const events = this.events.filter((event) => event.sequence > (query.after ?? 0) && (!query.unacknowledgedOnly || !acknowledged?.has(event.id)) && (!query.types?.length || query.types.includes(event.type)) && (!query.surfaces?.length || query.surfaces.includes(event.surfaceId))).slice(0, Math.max(1, Math.min(500, query.limit ?? 50)));
|
|
277
|
+
return { events, nextCursor: events.at(-1)?.sequence ?? query.after ?? 0 };
|
|
278
|
+
}
|
|
279
|
+
async acknowledge(consumerId, eventIds, disposition) {
|
|
280
|
+
let values = this.acknowledgements.get(consumerId);
|
|
281
|
+
if (!values) {
|
|
282
|
+
values = /* @__PURE__ */ new Map();
|
|
283
|
+
this.acknowledgements.set(consumerId, values);
|
|
284
|
+
}
|
|
285
|
+
eventIds.forEach((id) => values.set(id, disposition));
|
|
286
|
+
}
|
|
287
|
+
subscribe(listener) {
|
|
288
|
+
this.listeners.add(listener);
|
|
289
|
+
return () => this.listeners.delete(listener);
|
|
290
|
+
}
|
|
291
|
+
async compact(options = {}) {
|
|
292
|
+
const cutoff = options.before ?? Number.POSITIVE_INFINITY;
|
|
293
|
+
const keep = options.keepLast ?? 1e3;
|
|
294
|
+
const removable = Math.max(0, this.events.length - keep);
|
|
295
|
+
this.events = this.events.filter((event, index) => index >= removable || event.timestamp >= cutoff);
|
|
296
|
+
const ids = new Set(this.events.map((event) => event.id));
|
|
297
|
+
for (const values of this.acknowledgements.values()) for (const id of values.keys()) if (!ids.has(id)) values.delete(id);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// src/presence/index.ts
|
|
302
|
+
init_registry();
|
|
303
|
+
|
|
255
304
|
// src/presence/wrap-tool-with-activity.ts
|
|
256
305
|
init_registry();
|
|
257
306
|
function wrapToolWithActivity(handler, options) {
|
|
@@ -286,6 +335,133 @@ function extractMeta(result) {
|
|
|
286
335
|
return void 0;
|
|
287
336
|
}
|
|
288
337
|
|
|
338
|
+
// src/presence/use-agent-activity.ts
|
|
339
|
+
init_registry();
|
|
340
|
+
function useAgentActivity(filter, options = {}) {
|
|
341
|
+
const cap = options.capacity ?? 50;
|
|
342
|
+
const [events, setEvents] = react.useState(() => fancyAutoCommon.readActivityHistory(filter).slice(-cap));
|
|
343
|
+
react.useEffect(() => {
|
|
344
|
+
setEvents(fancyAutoCommon.readActivityHistory(filter).slice(-cap));
|
|
345
|
+
return fancyAutoCommon.onActivity((event) => {
|
|
346
|
+
setEvents((prev) => {
|
|
347
|
+
const next = prev.length >= cap ? prev.slice(prev.length - cap + 1) : prev.slice();
|
|
348
|
+
next.push(event);
|
|
349
|
+
return next;
|
|
350
|
+
});
|
|
351
|
+
}, filter);
|
|
352
|
+
}, [filter?.agentId, filter?.screenId, filter?.kind, cap]);
|
|
353
|
+
return { events, latest: events.length > 0 ? events[events.length - 1] : null };
|
|
354
|
+
}
|
|
355
|
+
function useAgentActivityForScreen(screenId, options = {}) {
|
|
356
|
+
const { events, latest } = useAgentActivity({ screenId }, options);
|
|
357
|
+
const fadeAfter = latest?.ttlMs ?? 1500;
|
|
358
|
+
const [isAgentActive, setActive] = react.useState(false);
|
|
359
|
+
react.useEffect(() => {
|
|
360
|
+
if (!latest) {
|
|
361
|
+
setActive(false);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
setActive(true);
|
|
365
|
+
const timer = setTimeout(() => setActive(false), fadeAfter);
|
|
366
|
+
return () => clearTimeout(timer);
|
|
367
|
+
}, [latest, fadeAfter]);
|
|
368
|
+
return { events, latest, isAgentActive };
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/bridges/tui.ts
|
|
372
|
+
function registerTuiBridge(host, options) {
|
|
373
|
+
const disposers = [];
|
|
374
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
375
|
+
const pending = /* @__PURE__ */ new Map();
|
|
376
|
+
const defaultActor = options.actor ?? { kind: "agent", id: "agent", name: "Agent" };
|
|
377
|
+
const serverCapabilities = host.capabilities;
|
|
378
|
+
if (serverCapabilities) serverCapabilities.experimental = { ...serverCapabilities.experimental, "io.particle-academy/human-plus": { version: "1", push: true, durableCursor: true, stagedActions: true, wakesAgent: false } };
|
|
379
|
+
const register = (name, description, properties, required, handler) => {
|
|
380
|
+
disposers.push(host.registerTool({ name, description, inputSchema: { type: "object", properties, required } }, async (args, context) => {
|
|
381
|
+
try {
|
|
382
|
+
const result = await handler(args, context);
|
|
383
|
+
return textResult(typeof result === "string" ? result : JSON.stringify(result), result);
|
|
384
|
+
} catch (error) {
|
|
385
|
+
return errorResult(error instanceof Error ? error.message : String(error));
|
|
386
|
+
}
|
|
387
|
+
}));
|
|
388
|
+
};
|
|
389
|
+
const publish = async (surfaceId, type, payload, actor = defaultActor, priority = "normal") => options.eventStore.append({ appId: options.appId, sessionId: options.sessionId, surfaceId, type, payload, actor, priority });
|
|
390
|
+
register("tui_surfaces_list", "List addressable Fancy TUI surfaces and commands.", {}, [], () => options.registry.list().map((surface) => ({ id: surface.id, kind: surface.kind, label: surface.label, commands: surface.commands?.map((command) => ({ name: command.name, description: command.description, policy: command.policy ?? "execute", inputSchema: command.inputSchema })) ?? [] })));
|
|
391
|
+
register("tui_surface_read", "Read a Fancy TUI surface by stable id.", { id: { type: "string" } }, ["id"], (args) => {
|
|
392
|
+
const surface = options.registry.get(String(args.id));
|
|
393
|
+
if (!surface) throw new Error(`Unknown TUI surface: ${String(args.id)}`);
|
|
394
|
+
return { id: surface.id, kind: surface.kind, state: surface.read() };
|
|
395
|
+
});
|
|
396
|
+
register("tui_action_invoke", "Invoke or propose an action on a Fancy TUI surface.", { surfaceId: { type: "string" }, command: { type: "string" }, input: { type: "object" } }, ["surfaceId", "command"], async (args) => {
|
|
397
|
+
const surfaceId = String(args.surfaceId);
|
|
398
|
+
const commandName = String(args.command);
|
|
399
|
+
const surface = options.registry.get(surfaceId);
|
|
400
|
+
if (!surface) throw new Error(`Unknown TUI surface: ${surfaceId}`);
|
|
401
|
+
const command = surface.commands?.find((value) => value.name === commandName);
|
|
402
|
+
if (!command) throw new Error(`Unknown command '${commandName}' on ${surfaceId}`);
|
|
403
|
+
const policy = command.policy ?? "execute";
|
|
404
|
+
if (policy === "observe" || policy === "human-only") throw new Error(`Action ${surfaceId}.${commandName} is ${policy}`);
|
|
405
|
+
const input = args.input && typeof args.input === "object" && !Array.isArray(args.input) ? args.input : {};
|
|
406
|
+
if (policy === "propose" || policy === "confirm") {
|
|
407
|
+
const id = globalThis.crypto.randomUUID();
|
|
408
|
+
pending.set(id, { id, surfaceId, command: commandName, input, actor: defaultActor });
|
|
409
|
+
await publish(surfaceId, "action.proposed", { id, command: commandName, input }, defaultActor, "attention");
|
|
410
|
+
return { pending: true, id };
|
|
411
|
+
}
|
|
412
|
+
const result = await command.invoke(input);
|
|
413
|
+
await publish(surfaceId, "action.executed", { command: commandName, input, result });
|
|
414
|
+
fancyAutoCommon.emitActivity({ agentId: defaultActor.id, agentName: defaultActor.name, target: { kind: "custom", elementId: surfaceId }, action: `tui_${commandName}`, timestamp: Date.now(), meta: { surfaceId } });
|
|
415
|
+
return { executed: true, result };
|
|
416
|
+
});
|
|
417
|
+
register("tui_action_confirm", "Confirm and execute a pending TUI action.", { id: { type: "string" } }, ["id"], async (args) => {
|
|
418
|
+
const id = String(args.id);
|
|
419
|
+
const value = pending.get(id);
|
|
420
|
+
if (!value) throw new Error(`Unknown pending action: ${id}`);
|
|
421
|
+
const surface = options.registry.get(value.surfaceId);
|
|
422
|
+
const command = surface?.commands?.find((x) => x.name === value.command);
|
|
423
|
+
if (!command) throw new Error("Pending action target is no longer available");
|
|
424
|
+
pending.delete(id);
|
|
425
|
+
const result = await command.invoke(value.input);
|
|
426
|
+
await publish(value.surfaceId, "action.confirmed", { id, command: value.command, result }, { kind: "human", id: "human" });
|
|
427
|
+
return { executed: true, result };
|
|
428
|
+
});
|
|
429
|
+
register("tui_action_reject", "Reject a pending TUI action.", { id: { type: "string" } }, ["id"], async (args) => {
|
|
430
|
+
const id = String(args.id);
|
|
431
|
+
const value = pending.get(id);
|
|
432
|
+
if (!value) throw new Error(`Unknown pending action: ${id}`);
|
|
433
|
+
pending.delete(id);
|
|
434
|
+
await publish(value.surfaceId, "action.rejected", { id, command: value.command }, { kind: "human", id: "human" });
|
|
435
|
+
return { rejected: true };
|
|
436
|
+
});
|
|
437
|
+
register("human_plus_events_list", "Pull durable Human+ events for a consumer.", { consumerId: { type: "string" }, after: { type: "number" }, limit: { type: "number" }, unacknowledgedOnly: { type: "boolean" } }, ["consumerId"], (args) => options.eventStore.list({ consumerId: String(args.consumerId), after: typeof args.after === "number" ? args.after : void 0, limit: typeof args.limit === "number" ? args.limit : void 0, unacknowledgedOnly: args.unacknowledgedOnly === true }));
|
|
438
|
+
register("human_plus_events_ack", "Acknowledge durable Human+ events.", { consumerId: { type: "string" }, eventIds: { type: "array", items: { type: "string" } }, disposition: { type: "string" } }, ["consumerId", "eventIds"], async (args) => {
|
|
439
|
+
const ids = Array.isArray(args.eventIds) ? args.eventIds.map(String) : [];
|
|
440
|
+
await options.eventStore.acknowledge(String(args.consumerId), ids, ["seen", "handled", "rejected", "ignored"].includes(String(args.disposition)) ? String(args.disposition) : "handled");
|
|
441
|
+
return { acknowledged: ids.length };
|
|
442
|
+
});
|
|
443
|
+
register("human_plus_events_subscribe", "Push matching Human+ events on this MCP transport while retaining them in the inbox.", { consumerId: { type: "string" }, types: { type: "array" }, surfaces: { type: "array" } }, ["consumerId"], (args, context) => {
|
|
444
|
+
if (!context?.transport) throw new Error("Subscriptions require an attached MCP transport");
|
|
445
|
+
subscriptions.set(context.transport, { consumerId: String(args.consumerId), types: Array.isArray(args.types) ? args.types.map(String) : void 0, surfaces: Array.isArray(args.surfaces) ? args.surfaces.map(String) : void 0 });
|
|
446
|
+
return { subscribed: true, delivery: "at-least-once", wakesAgent: false };
|
|
447
|
+
});
|
|
448
|
+
const unsubscribeStore = options.eventStore.subscribe((event) => {
|
|
449
|
+
const server = host;
|
|
450
|
+
if (typeof server.notify !== "function") return;
|
|
451
|
+
for (const [transport, subscription] of subscriptions) {
|
|
452
|
+
if (subscription.types?.length && !subscription.types.includes(event.type)) continue;
|
|
453
|
+
if (subscription.surfaces?.length && !subscription.surfaces.includes(event.surfaceId)) continue;
|
|
454
|
+
server.notify({ jsonrpc: "2.0", method: "notifications/human_plus/event", params: event }, transport);
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
return { id: "tui", title: "Fancy TUI", pending: () => [...pending.values()], dispose: () => {
|
|
458
|
+
disposers.forEach((dispose) => dispose());
|
|
459
|
+
unsubscribeStore();
|
|
460
|
+
subscriptions.clear();
|
|
461
|
+
pending.clear();
|
|
462
|
+
} };
|
|
463
|
+
}
|
|
464
|
+
|
|
289
465
|
// src/undo/undo-tools.ts
|
|
290
466
|
var installedHosts = /* @__PURE__ */ new WeakSet();
|
|
291
467
|
function ensureUndoToolsRegistered(host, options = {}) {
|
|
@@ -4568,39 +4744,6 @@ function buildCurlRecipe(session) {
|
|
|
4568
4744
|
].join("\n");
|
|
4569
4745
|
}
|
|
4570
4746
|
|
|
4571
|
-
// src/presence/use-agent-activity.ts
|
|
4572
|
-
init_registry();
|
|
4573
|
-
function useAgentActivity(filter, options = {}) {
|
|
4574
|
-
const cap = options.capacity ?? 50;
|
|
4575
|
-
const [events, setEvents] = react.useState(() => fancyAutoCommon.readActivityHistory(filter).slice(-cap));
|
|
4576
|
-
react.useEffect(() => {
|
|
4577
|
-
setEvents(fancyAutoCommon.readActivityHistory(filter).slice(-cap));
|
|
4578
|
-
return fancyAutoCommon.onActivity((event) => {
|
|
4579
|
-
setEvents((prev) => {
|
|
4580
|
-
const next = prev.length >= cap ? prev.slice(prev.length - cap + 1) : prev.slice();
|
|
4581
|
-
next.push(event);
|
|
4582
|
-
return next;
|
|
4583
|
-
});
|
|
4584
|
-
}, filter);
|
|
4585
|
-
}, [filter?.agentId, filter?.screenId, filter?.kind, cap]);
|
|
4586
|
-
return { events, latest: events.length > 0 ? events[events.length - 1] : null };
|
|
4587
|
-
}
|
|
4588
|
-
function useAgentActivityForScreen(screenId, options = {}) {
|
|
4589
|
-
const { events, latest } = useAgentActivity({ screenId }, options);
|
|
4590
|
-
const fadeAfter = latest?.ttlMs ?? 1500;
|
|
4591
|
-
const [isAgentActive, setActive] = react.useState(false);
|
|
4592
|
-
react.useEffect(() => {
|
|
4593
|
-
if (!latest) {
|
|
4594
|
-
setActive(false);
|
|
4595
|
-
return;
|
|
4596
|
-
}
|
|
4597
|
-
setActive(true);
|
|
4598
|
-
const timer = setTimeout(() => setActive(false), fadeAfter);
|
|
4599
|
-
return () => clearTimeout(timer);
|
|
4600
|
-
}, [latest, fadeAfter]);
|
|
4601
|
-
return { events, latest, isAgentActive };
|
|
4602
|
-
}
|
|
4603
|
-
|
|
4604
4747
|
// src/connectors/targets.ts
|
|
4605
4748
|
var CLAUDE_CONNECTORS_URL = "https://claude.ai/settings/connectors";
|
|
4606
4749
|
function encodeBase64Json(value) {
|
|
@@ -4905,6 +5048,23 @@ function CoBrowsePresence({ session, connectUrl, shareBaseUrl, className }) {
|
|
|
4905
5048
|
] });
|
|
4906
5049
|
}
|
|
4907
5050
|
CoBrowsePresence.displayName = "CoBrowsePresence";
|
|
5051
|
+
var CURSOR_EDGE_INSET = 24;
|
|
5052
|
+
var FLUID_CURSOR_SPEED_PX_PER_SECOND = 1050;
|
|
5053
|
+
var MIN_GLIDE_MS = 240;
|
|
5054
|
+
var MAX_GLIDE_MS = 1200;
|
|
5055
|
+
function visibleCursorPoint(rect, viewport) {
|
|
5056
|
+
const x = rect.x + rect.width / 2;
|
|
5057
|
+
const y = rect.y + rect.height / 2;
|
|
5058
|
+
return {
|
|
5059
|
+
x: Math.min(Math.max(x, CURSOR_EDGE_INSET), Math.max(CURSOR_EDGE_INSET, viewport.width - CURSOR_EDGE_INSET)),
|
|
5060
|
+
y: Math.min(Math.max(y, CURSOR_EDGE_INSET), Math.max(CURSOR_EDGE_INSET, viewport.height - CURSOR_EDGE_INSET))
|
|
5061
|
+
};
|
|
5062
|
+
}
|
|
5063
|
+
function fluidGlideDuration(from, to) {
|
|
5064
|
+
if (!from) return 0;
|
|
5065
|
+
const distance = Math.hypot(to.x - from.x, to.y - from.y);
|
|
5066
|
+
return Math.round(Math.min(MAX_GLIDE_MS, Math.max(MIN_GLIDE_MS, distance / FLUID_CURSOR_SPEED_PX_PER_SECOND * 1e3)));
|
|
5067
|
+
}
|
|
4908
5068
|
function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
4909
5069
|
const { latest } = useAgentActivity(void 0, { capacity: 12 });
|
|
4910
5070
|
const [cursor, setCursor] = react.useState(
|
|
@@ -4914,7 +5074,7 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
|
4914
5074
|
react.useEffect(() => {
|
|
4915
5075
|
if (!latest || (latest.source ?? "agent") === "user") return;
|
|
4916
5076
|
if (latest.action === "agent_disconnected") {
|
|
4917
|
-
setCursor(
|
|
5077
|
+
setCursor((prev) => prev ? { ...prev, status: "Standing by", glideMs: 0 } : prev);
|
|
4918
5078
|
setPulse(null);
|
|
4919
5079
|
return;
|
|
4920
5080
|
}
|
|
@@ -4923,11 +5083,19 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
|
4923
5083
|
const status = latest.target?.label ?? latest.action;
|
|
4924
5084
|
const rect = latest.meta?.rect;
|
|
4925
5085
|
if (rect) {
|
|
4926
|
-
|
|
5086
|
+
const target = visibleCursorPoint(rect, { width: window.innerWidth, height: window.innerHeight });
|
|
5087
|
+
const reduceMotion = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
|
|
5088
|
+
setCursor((prev) => ({
|
|
5089
|
+
...target,
|
|
5090
|
+
name,
|
|
5091
|
+
color,
|
|
5092
|
+
status,
|
|
5093
|
+
glideMs: reduceMotion ? 0 : fluidGlideDuration(prev, target)
|
|
5094
|
+
}));
|
|
4927
5095
|
setPulse({ rect, color, key: latest.timestamp });
|
|
4928
5096
|
} else {
|
|
4929
5097
|
setCursor(
|
|
4930
|
-
(prev) => prev ? { ...prev, status, name, color } : { x: window.innerWidth / 2, y: window.innerHeight / 2, name, color, status }
|
|
5098
|
+
(prev) => prev ? { ...prev, status, name, color } : { x: window.innerWidth / 2, y: window.innerHeight / 2, name, color, status, glideMs: 0 }
|
|
4931
5099
|
);
|
|
4932
5100
|
}
|
|
4933
5101
|
}, [latest?.timestamp]);
|
|
@@ -4953,7 +5121,9 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
|
4953
5121
|
name: cursor.name,
|
|
4954
5122
|
color: cursor.color,
|
|
4955
5123
|
status: cursor.status,
|
|
4956
|
-
style: {
|
|
5124
|
+
style: {
|
|
5125
|
+
transition: cursor.glideMs ? `left ${cursor.glideMs}ms cubic-bezier(.22,.61,.36,1), top ${cursor.glideMs}ms cubic-bezier(.22,.61,.36,1)` : "none"
|
|
5126
|
+
}
|
|
4957
5127
|
}
|
|
4958
5128
|
)
|
|
4959
5129
|
] }),
|
|
@@ -5032,9 +5202,6 @@ function SimulateUsersButton({
|
|
|
5032
5202
|
);
|
|
5033
5203
|
}
|
|
5034
5204
|
|
|
5035
|
-
// src/presence/index.ts
|
|
5036
|
-
init_registry();
|
|
5037
|
-
|
|
5038
5205
|
// src/heuristics/sink.ts
|
|
5039
5206
|
function numericMeta(meta, key) {
|
|
5040
5207
|
const v = meta?.[key];
|
|
@@ -5275,6 +5442,7 @@ exports.InProcessTransport = InProcessTransport;
|
|
|
5275
5442
|
exports.MCPB_MANIFEST_VERSION = MCPB_MANIFEST_VERSION;
|
|
5276
5443
|
exports.MCPB_MIN_NODE = MCPB_MIN_NODE;
|
|
5277
5444
|
exports.MCP_PROTOCOL_VERSION = MCP_PROTOCOL_VERSION;
|
|
5445
|
+
exports.MemoryHumanPlusEventStore = MemoryHumanPlusEventStore;
|
|
5278
5446
|
exports.MicroMcpServer = MicroMcpServer;
|
|
5279
5447
|
exports.RelayTransport = RelayTransport;
|
|
5280
5448
|
exports.ScreensActivityBridge = ScreensActivityBridge;
|
|
@@ -5321,6 +5489,7 @@ exports.registerScreensBridge = registerScreensBridge;
|
|
|
5321
5489
|
exports.registerSheetsBridge = registerSheetsBridge;
|
|
5322
5490
|
exports.registerSlidesBridge = registerSlidesBridge;
|
|
5323
5491
|
exports.registerTerminalBridge = registerTerminalBridge;
|
|
5492
|
+
exports.registerTuiBridge = registerTuiBridge;
|
|
5324
5493
|
exports.registerUndoTools = registerUndoTools;
|
|
5325
5494
|
exports.rpcError = rpcError;
|
|
5326
5495
|
exports.slugifyServerName = slugifyServerName;
|