@particle-academy/agent-integrations 0.2.4 → 0.4.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.
Files changed (132) hide show
  1. package/README.md +20 -0
  2. package/dist/bridges/charts.d.cts +39 -0
  3. package/dist/bridges/charts.d.ts +39 -0
  4. package/dist/bridges/code.d.cts +47 -0
  5. package/dist/bridges/code.d.ts +47 -0
  6. package/dist/bridges/flow.d.cts +4 -3
  7. package/dist/bridges/flow.d.ts +4 -3
  8. package/dist/bridges/forms.d.cts +76 -0
  9. package/dist/bridges/forms.d.ts +76 -0
  10. package/dist/bridges/scene.d.cts +54 -0
  11. package/dist/bridges/scene.d.ts +54 -0
  12. package/dist/bridges/screens.d.cts +78 -0
  13. package/dist/bridges/screens.d.ts +78 -0
  14. package/dist/bridges/sheets.d.cts +62 -0
  15. package/dist/bridges/sheets.d.ts +62 -0
  16. package/dist/bridges/whiteboard.d.cts +4 -3
  17. package/dist/bridges/whiteboard.d.ts +4 -3
  18. package/dist/bridges-charts.cjs +167 -0
  19. package/dist/bridges-charts.cjs.map +1 -0
  20. package/dist/bridges-charts.js +6 -0
  21. package/dist/bridges-charts.js.map +1 -0
  22. package/dist/bridges-code.cjs +219 -0
  23. package/dist/bridges-code.cjs.map +1 -0
  24. package/dist/bridges-code.js +6 -0
  25. package/dist/bridges-code.js.map +1 -0
  26. package/dist/bridges-flow.cjs +78 -19
  27. package/dist/bridges-flow.cjs.map +1 -1
  28. package/dist/bridges-flow.js +4 -2
  29. package/dist/bridges-forms.cjs +205 -0
  30. package/dist/bridges-forms.cjs.map +1 -0
  31. package/dist/bridges-forms.js +6 -0
  32. package/dist/bridges-forms.js.map +1 -0
  33. package/dist/bridges-scene.cjs +250 -0
  34. package/dist/bridges-scene.cjs.map +1 -0
  35. package/dist/bridges-scene.js +6 -0
  36. package/dist/bridges-scene.js.map +1 -0
  37. package/dist/bridges-screens.cjs +227 -0
  38. package/dist/bridges-screens.cjs.map +1 -0
  39. package/dist/bridges-screens.js +6 -0
  40. package/dist/bridges-screens.js.map +1 -0
  41. package/dist/bridges-sheets.cjs +327 -0
  42. package/dist/bridges-sheets.cjs.map +1 -0
  43. package/dist/bridges-sheets.js +6 -0
  44. package/dist/bridges-sheets.js.map +1 -0
  45. package/dist/bridges-whiteboard.cjs +226 -40
  46. package/dist/bridges-whiteboard.cjs.map +1 -1
  47. package/dist/bridges-whiteboard.js +5 -2
  48. package/dist/{chunk-5ZUHNNLR.js → chunk-3KSZNGNW.js} +81 -43
  49. package/dist/chunk-3KSZNGNW.js.map +1 -0
  50. package/dist/chunk-4BL5M3U3.js +158 -0
  51. package/dist/chunk-4BL5M3U3.js.map +1 -0
  52. package/dist/{chunk-QGCF7YKW.js → chunk-4KAIV6OD.js} +40 -12
  53. package/dist/chunk-4KAIV6OD.js.map +1 -0
  54. package/dist/chunk-52S7XYZK.js +38 -0
  55. package/dist/chunk-52S7XYZK.js.map +1 -0
  56. package/dist/chunk-57ZDHD53.js +180 -0
  57. package/dist/chunk-57ZDHD53.js.map +1 -0
  58. package/dist/chunk-E4AICMFZ.js +83 -0
  59. package/dist/chunk-E4AICMFZ.js.map +1 -0
  60. package/dist/chunk-GQ7XXK7G.js +124 -0
  61. package/dist/chunk-GQ7XXK7G.js.map +1 -0
  62. package/dist/chunk-HSTW7ZNO.js +172 -0
  63. package/dist/chunk-HSTW7ZNO.js.map +1 -0
  64. package/dist/chunk-IANI25IT.js +280 -0
  65. package/dist/chunk-IANI25IT.js.map +1 -0
  66. package/dist/{chunk-FLEOQUKF.js → chunk-JMYPUAFH.js} +17 -2
  67. package/dist/chunk-JMYPUAFH.js.map +1 -0
  68. package/dist/chunk-JU2N4KK6.js +34 -0
  69. package/dist/chunk-JU2N4KK6.js.map +1 -0
  70. package/dist/{chunk-2VOQJKSU.js → chunk-N3H4DXY5.js} +44 -22
  71. package/dist/chunk-N3H4DXY5.js.map +1 -0
  72. package/dist/chunk-NTDZWGYB.js +120 -0
  73. package/dist/chunk-NTDZWGYB.js.map +1 -0
  74. package/dist/chunk-RGO42EQ6.js +25 -0
  75. package/dist/chunk-RGO42EQ6.js.map +1 -0
  76. package/dist/chunk-X66JWQBB.js +37 -0
  77. package/dist/chunk-X66JWQBB.js.map +1 -0
  78. package/dist/chunk-XRAJSOPS.js +203 -0
  79. package/dist/chunk-XRAJSOPS.js.map +1 -0
  80. package/dist/index.cjs +1766 -127
  81. package/dist/index.cjs.map +1 -1
  82. package/dist/index.d.cts +99 -3
  83. package/dist/index.d.ts +99 -3
  84. package/dist/index.js +115 -9
  85. package/dist/index.js.map +1 -1
  86. package/dist/mcp/index.d.cts +5 -2
  87. package/dist/mcp/index.d.ts +5 -2
  88. package/dist/mcp.cjs +37 -9
  89. package/dist/mcp.cjs.map +1 -1
  90. package/dist/mcp.js +1 -1
  91. package/dist/presence/index.d.cts +136 -0
  92. package/dist/presence/index.d.ts +136 -0
  93. package/dist/presence.cjs +107 -0
  94. package/dist/presence.cjs.map +1 -0
  95. package/dist/presence.js +5 -0
  96. package/dist/presence.js.map +1 -0
  97. package/dist/registry-2DRURS6U.js +3 -0
  98. package/dist/registry-2DRURS6U.js.map +1 -0
  99. package/dist/server-BsSwfemr.d.cts +63 -0
  100. package/dist/server-Du3-IGqM.d.ts +63 -0
  101. package/dist/sharing/index.d.cts +3 -1
  102. package/dist/sharing/index.d.ts +3 -1
  103. package/dist/sharing.cjs +68 -0
  104. package/dist/sharing.cjs.map +1 -1
  105. package/dist/sharing.js +1 -1
  106. package/dist/sheets-adapter.cjs +96 -0
  107. package/dist/sheets-adapter.cjs.map +1 -0
  108. package/dist/sheets-adapter.d.cts +115 -0
  109. package/dist/sheets-adapter.d.ts +115 -0
  110. package/dist/sheets-adapter.js +4 -0
  111. package/dist/sheets-adapter.js.map +1 -0
  112. package/dist/styles.css +57 -0
  113. package/dist/styles.css.map +1 -1
  114. package/dist/tool-host-BQuUygLF.d.cts +60 -0
  115. package/dist/tool-host-C8JMMGYq.d.ts +60 -0
  116. package/dist/{types-CRPA_D0z.d.ts → types-CCSBGW9T.d.cts} +2 -2
  117. package/dist/{types-DR5AS6Rd.d.cts → types-DIVNcIQO.d.ts} +2 -2
  118. package/dist/types-aOQLTW0E.d.cts +112 -0
  119. package/dist/types-aOQLTW0E.d.ts +112 -0
  120. package/dist/undo/index.d.cts +69 -0
  121. package/dist/undo/index.d.ts +69 -0
  122. package/dist/undo.cjs +163 -0
  123. package/dist/undo.cjs.map +1 -0
  124. package/dist/undo.js +5 -0
  125. package/dist/undo.js.map +1 -0
  126. package/package.json +1 -1
  127. package/dist/chunk-2VOQJKSU.js.map +0 -1
  128. package/dist/chunk-5ZUHNNLR.js.map +0 -1
  129. package/dist/chunk-FLEOQUKF.js.map +0 -1
  130. package/dist/chunk-QGCF7YKW.js.map +0 -1
  131. package/dist/server-Bv985us3.d.cts +0 -173
  132. package/dist/server-Bv985us3.d.ts +0 -173
@@ -0,0 +1,136 @@
1
+ import { C as CallToolResult } from '../types-aOQLTW0E.cjs';
2
+
3
+ /**
4
+ * Presence layer types — describe what the agent is doing right now and
5
+ * where. Every bridge tool emits one of these when it runs; the registry
6
+ * fans them out to in-process subscribers + the SSE relay so external
7
+ * clients can render presence indicators across the whole app.
8
+ */
9
+ type AgentTargetKind = "whiteboard" | "flow" | "form" | "sheet" | "code" | "chart" | "scene" | "custom";
10
+ type AgentTarget = {
11
+ /** Which package surface the action affects. */
12
+ kind: AgentTargetKind | string;
13
+ /** Optional fancy-screens screen id, for screen-scoped UIs. */
14
+ screenId?: string;
15
+ /** Optional element id within the surface (sticky id, node id, field name, …). */
16
+ elementId?: string;
17
+ /** Free-form label the host can render (e.g. "the 'email' field"). */
18
+ label?: string;
19
+ };
20
+ type AgentActivityEvent = {
21
+ /** Stable identifier for the acting agent. */
22
+ agentId: string;
23
+ /** Human-friendly name (used by indicators / activity log). */
24
+ agentName?: string;
25
+ /** Color for cursor / highlight CSS. */
26
+ agentColor?: string;
27
+ /** What the agent is touching. */
28
+ target: AgentTarget;
29
+ /** Snake-case action verb mirroring the tool name (e.g. "whiteboard_add_sticky"). */
30
+ action: string;
31
+ /** Wall-clock ms — when the action ran. */
32
+ timestamp: number;
33
+ /** Optional small structured payload describing the action's effect. */
34
+ meta?: Record<string, unknown>;
35
+ /** Optional duration in ms — how long the activity should "stick" on the
36
+ * UI before fading. Default 1500. */
37
+ ttlMs?: number;
38
+ };
39
+ type AgentActivityListener = (event: AgentActivityEvent) => void;
40
+ type ActivityFilter = {
41
+ agentId?: string;
42
+ screenId?: string;
43
+ kind?: string;
44
+ };
45
+
46
+ /** Emit an activity event. All current listeners receive it synchronously. */
47
+ declare function emitActivity(event: AgentActivityEvent): void;
48
+ /**
49
+ * Subscribe to all events (or a filtered subset). Returns an unsubscribe
50
+ * function. Filter checks all provided keys with strict equality; omit a
51
+ * key to ignore it.
52
+ */
53
+ declare function onActivity(listener: AgentActivityListener, filter?: ActivityFilter): () => void;
54
+ /** Read the recent history (newest last). Optional filter. */
55
+ declare function readActivityHistory(filter?: ActivityFilter): AgentActivityEvent[];
56
+ /** Wipe history + clear listeners. Test/teardown helper. */
57
+ declare function resetActivityRegistry(): void;
58
+
59
+ type ActivityAgent = {
60
+ id: string;
61
+ name?: string;
62
+ color?: string;
63
+ };
64
+ type ActivityResolverContext<TArgs = Record<string, unknown>> = {
65
+ /** Tool name as registered. */
66
+ toolName: string;
67
+ /** Arguments the tool was called with. */
68
+ args: TArgs;
69
+ /** The CallToolResult the underlying handler produced. */
70
+ result: CallToolResult;
71
+ };
72
+ /**
73
+ * Resolves an `AgentTarget` for an executed tool. Bridges declare one of
74
+ * these per registration so the wrapper knows which surface / element /
75
+ * screen the activity belongs to.
76
+ *
77
+ * The resolver runs AFTER the tool handler so it can inspect the result
78
+ * (e.g. read a newly-created item id from `structuredContent`).
79
+ */
80
+ type ActivityTargetResolver<TArgs = Record<string, unknown>> = (ctx: ActivityResolverContext<TArgs>) => AgentTarget | null;
81
+ type ToolHandler<TArgs = Record<string, unknown>> = (args: TArgs) => Promise<CallToolResult> | CallToolResult;
82
+ /**
83
+ * wrapToolWithActivity — decorate a bridge tool handler so every successful
84
+ * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.
85
+ *
86
+ * Usage in a bridge:
87
+ *
88
+ * server.registerTool(
89
+ * definition,
90
+ * wrapToolWithActivity(
91
+ * handler,
92
+ * { agent, kind: "whiteboard", resolveTarget: ({ args }) => ({
93
+ * kind: "whiteboard", elementId: args.id as string,
94
+ * }) },
95
+ * ),
96
+ * );
97
+ */
98
+ declare function wrapToolWithActivity<TArgs = Record<string, unknown>>(handler: ToolHandler<TArgs>, options: {
99
+ toolName: string;
100
+ agent: ActivityAgent;
101
+ /** Optional fancy-screens screen id this bridge is scoped to. */
102
+ screenId?: string;
103
+ /** Default target kind if the resolver returns one without `kind`. */
104
+ kind: AgentTarget["kind"];
105
+ /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */
106
+ resolveTarget?: ActivityTargetResolver<TArgs>;
107
+ /** Optional ttl override. */
108
+ ttlMs?: number;
109
+ }): ToolHandler<TArgs>;
110
+
111
+ /**
112
+ * useAgentActivity — React subscription to the in-process activity stream.
113
+ *
114
+ * Returns:
115
+ * - `events`: capped scrollback of recent events matching the filter
116
+ * - `latest`: the most recent event (handy for transient highlights)
117
+ */
118
+ declare function useAgentActivity(filter?: ActivityFilter, options?: {
119
+ capacity?: number;
120
+ }): {
121
+ events: AgentActivityEvent[];
122
+ latest: AgentActivityEvent | null;
123
+ };
124
+ /**
125
+ * useAgentActivityForScreen — convenience wrapper that filters by screen id.
126
+ * Drives "agent is here" badges in fancy-screens-based shells.
127
+ */
128
+ declare function useAgentActivityForScreen(screenId: string, options?: {
129
+ capacity?: number;
130
+ }): {
131
+ events: AgentActivityEvent[];
132
+ latest: AgentActivityEvent | null;
133
+ isAgentActive: boolean;
134
+ };
135
+
136
+ export { type ActivityAgent, type ActivityFilter, type ActivityResolverContext, type ActivityTargetResolver, type AgentActivityEvent, type AgentActivityListener, type AgentTarget, type AgentTargetKind, type ToolHandler, emitActivity, onActivity, readActivityHistory, resetActivityRegistry, useAgentActivity, useAgentActivityForScreen, wrapToolWithActivity };
@@ -0,0 +1,136 @@
1
+ import { C as CallToolResult } from '../types-aOQLTW0E.js';
2
+
3
+ /**
4
+ * Presence layer types — describe what the agent is doing right now and
5
+ * where. Every bridge tool emits one of these when it runs; the registry
6
+ * fans them out to in-process subscribers + the SSE relay so external
7
+ * clients can render presence indicators across the whole app.
8
+ */
9
+ type AgentTargetKind = "whiteboard" | "flow" | "form" | "sheet" | "code" | "chart" | "scene" | "custom";
10
+ type AgentTarget = {
11
+ /** Which package surface the action affects. */
12
+ kind: AgentTargetKind | string;
13
+ /** Optional fancy-screens screen id, for screen-scoped UIs. */
14
+ screenId?: string;
15
+ /** Optional element id within the surface (sticky id, node id, field name, …). */
16
+ elementId?: string;
17
+ /** Free-form label the host can render (e.g. "the 'email' field"). */
18
+ label?: string;
19
+ };
20
+ type AgentActivityEvent = {
21
+ /** Stable identifier for the acting agent. */
22
+ agentId: string;
23
+ /** Human-friendly name (used by indicators / activity log). */
24
+ agentName?: string;
25
+ /** Color for cursor / highlight CSS. */
26
+ agentColor?: string;
27
+ /** What the agent is touching. */
28
+ target: AgentTarget;
29
+ /** Snake-case action verb mirroring the tool name (e.g. "whiteboard_add_sticky"). */
30
+ action: string;
31
+ /** Wall-clock ms — when the action ran. */
32
+ timestamp: number;
33
+ /** Optional small structured payload describing the action's effect. */
34
+ meta?: Record<string, unknown>;
35
+ /** Optional duration in ms — how long the activity should "stick" on the
36
+ * UI before fading. Default 1500. */
37
+ ttlMs?: number;
38
+ };
39
+ type AgentActivityListener = (event: AgentActivityEvent) => void;
40
+ type ActivityFilter = {
41
+ agentId?: string;
42
+ screenId?: string;
43
+ kind?: string;
44
+ };
45
+
46
+ /** Emit an activity event. All current listeners receive it synchronously. */
47
+ declare function emitActivity(event: AgentActivityEvent): void;
48
+ /**
49
+ * Subscribe to all events (or a filtered subset). Returns an unsubscribe
50
+ * function. Filter checks all provided keys with strict equality; omit a
51
+ * key to ignore it.
52
+ */
53
+ declare function onActivity(listener: AgentActivityListener, filter?: ActivityFilter): () => void;
54
+ /** Read the recent history (newest last). Optional filter. */
55
+ declare function readActivityHistory(filter?: ActivityFilter): AgentActivityEvent[];
56
+ /** Wipe history + clear listeners. Test/teardown helper. */
57
+ declare function resetActivityRegistry(): void;
58
+
59
+ type ActivityAgent = {
60
+ id: string;
61
+ name?: string;
62
+ color?: string;
63
+ };
64
+ type ActivityResolverContext<TArgs = Record<string, unknown>> = {
65
+ /** Tool name as registered. */
66
+ toolName: string;
67
+ /** Arguments the tool was called with. */
68
+ args: TArgs;
69
+ /** The CallToolResult the underlying handler produced. */
70
+ result: CallToolResult;
71
+ };
72
+ /**
73
+ * Resolves an `AgentTarget` for an executed tool. Bridges declare one of
74
+ * these per registration so the wrapper knows which surface / element /
75
+ * screen the activity belongs to.
76
+ *
77
+ * The resolver runs AFTER the tool handler so it can inspect the result
78
+ * (e.g. read a newly-created item id from `structuredContent`).
79
+ */
80
+ type ActivityTargetResolver<TArgs = Record<string, unknown>> = (ctx: ActivityResolverContext<TArgs>) => AgentTarget | null;
81
+ type ToolHandler<TArgs = Record<string, unknown>> = (args: TArgs) => Promise<CallToolResult> | CallToolResult;
82
+ /**
83
+ * wrapToolWithActivity — decorate a bridge tool handler so every successful
84
+ * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.
85
+ *
86
+ * Usage in a bridge:
87
+ *
88
+ * server.registerTool(
89
+ * definition,
90
+ * wrapToolWithActivity(
91
+ * handler,
92
+ * { agent, kind: "whiteboard", resolveTarget: ({ args }) => ({
93
+ * kind: "whiteboard", elementId: args.id as string,
94
+ * }) },
95
+ * ),
96
+ * );
97
+ */
98
+ declare function wrapToolWithActivity<TArgs = Record<string, unknown>>(handler: ToolHandler<TArgs>, options: {
99
+ toolName: string;
100
+ agent: ActivityAgent;
101
+ /** Optional fancy-screens screen id this bridge is scoped to. */
102
+ screenId?: string;
103
+ /** Default target kind if the resolver returns one without `kind`. */
104
+ kind: AgentTarget["kind"];
105
+ /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */
106
+ resolveTarget?: ActivityTargetResolver<TArgs>;
107
+ /** Optional ttl override. */
108
+ ttlMs?: number;
109
+ }): ToolHandler<TArgs>;
110
+
111
+ /**
112
+ * useAgentActivity — React subscription to the in-process activity stream.
113
+ *
114
+ * Returns:
115
+ * - `events`: capped scrollback of recent events matching the filter
116
+ * - `latest`: the most recent event (handy for transient highlights)
117
+ */
118
+ declare function useAgentActivity(filter?: ActivityFilter, options?: {
119
+ capacity?: number;
120
+ }): {
121
+ events: AgentActivityEvent[];
122
+ latest: AgentActivityEvent | null;
123
+ };
124
+ /**
125
+ * useAgentActivityForScreen — convenience wrapper that filters by screen id.
126
+ * Drives "agent is here" badges in fancy-screens-based shells.
127
+ */
128
+ declare function useAgentActivityForScreen(screenId: string, options?: {
129
+ capacity?: number;
130
+ }): {
131
+ events: AgentActivityEvent[];
132
+ latest: AgentActivityEvent | null;
133
+ isAgentActive: boolean;
134
+ };
135
+
136
+ export { type ActivityAgent, type ActivityFilter, type ActivityResolverContext, type ActivityTargetResolver, type AgentActivityEvent, type AgentActivityListener, type AgentTarget, type AgentTargetKind, type ToolHandler, emitActivity, onActivity, readActivityHistory, resetActivityRegistry, useAgentActivity, useAgentActivityForScreen, wrapToolWithActivity };
@@ -0,0 +1,107 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ // src/presence/registry.ts
6
+ var HISTORY_CAP = 200;
7
+ var listeners = /* @__PURE__ */ new Set();
8
+ var history = [];
9
+ function emitActivity(event) {
10
+ history.push(event);
11
+ if (history.length > HISTORY_CAP) history.splice(0, history.length - HISTORY_CAP);
12
+ for (const l of listeners) l(event);
13
+ }
14
+ function onActivity(listener, filter) {
15
+ const wrapped = filter ? (e) => {
16
+ if (matches(e, filter)) listener(e);
17
+ } : listener;
18
+ listeners.add(wrapped);
19
+ return () => listeners.delete(wrapped);
20
+ }
21
+ function readActivityHistory(filter) {
22
+ if (!filter) return history.slice();
23
+ return history.filter((e) => matches(e, filter));
24
+ }
25
+ function resetActivityRegistry() {
26
+ listeners.clear();
27
+ history.length = 0;
28
+ }
29
+ function matches(e, f) {
30
+ if (f.agentId !== void 0 && e.agentId !== f.agentId) return false;
31
+ if (f.screenId !== void 0 && e.target.screenId !== f.screenId) return false;
32
+ if (f.kind !== void 0 && e.target.kind !== f.kind) return false;
33
+ return true;
34
+ }
35
+
36
+ // src/presence/wrap-tool-with-activity.ts
37
+ function wrapToolWithActivity(handler, options) {
38
+ return async (args) => {
39
+ const result = await handler(args);
40
+ if (result.isError) return result;
41
+ let target;
42
+ if (options.resolveTarget) {
43
+ target = options.resolveTarget({ toolName: options.toolName, args, result });
44
+ } else {
45
+ target = { kind: options.kind, screenId: options.screenId };
46
+ }
47
+ if (!target) return result;
48
+ emitActivity({
49
+ agentId: options.agent.id,
50
+ agentName: options.agent.name,
51
+ agentColor: options.agent.color,
52
+ target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },
53
+ action: options.toolName,
54
+ timestamp: Date.now(),
55
+ meta: extractMeta(result),
56
+ ttlMs: options.ttlMs
57
+ });
58
+ return result;
59
+ };
60
+ }
61
+ function extractMeta(result) {
62
+ const sc = result.structuredContent;
63
+ if (sc && typeof sc === "object" && !Array.isArray(sc)) {
64
+ return sc;
65
+ }
66
+ return void 0;
67
+ }
68
+ function useAgentActivity(filter, options = {}) {
69
+ const cap = options.capacity ?? 50;
70
+ const [events, setEvents] = react.useState(() => readActivityHistory(filter).slice(-cap));
71
+ react.useEffect(() => {
72
+ setEvents(readActivityHistory(filter).slice(-cap));
73
+ return onActivity((event) => {
74
+ setEvents((prev) => {
75
+ const next = prev.length >= cap ? prev.slice(prev.length - cap + 1) : prev.slice();
76
+ next.push(event);
77
+ return next;
78
+ });
79
+ }, filter);
80
+ }, [filter?.agentId, filter?.screenId, filter?.kind, cap]);
81
+ return { events, latest: events.length > 0 ? events[events.length - 1] : null };
82
+ }
83
+ function useAgentActivityForScreen(screenId, options = {}) {
84
+ const { events, latest } = useAgentActivity({ screenId }, options);
85
+ const fadeAfter = latest?.ttlMs ?? 1500;
86
+ const [isAgentActive, setActive] = react.useState(false);
87
+ react.useEffect(() => {
88
+ if (!latest) {
89
+ setActive(false);
90
+ return;
91
+ }
92
+ setActive(true);
93
+ const timer = setTimeout(() => setActive(false), fadeAfter);
94
+ return () => clearTimeout(timer);
95
+ }, [latest, fadeAfter]);
96
+ return { events, latest, isAgentActive };
97
+ }
98
+
99
+ exports.emitActivity = emitActivity;
100
+ exports.onActivity = onActivity;
101
+ exports.readActivityHistory = readActivityHistory;
102
+ exports.resetActivityRegistry = resetActivityRegistry;
103
+ exports.useAgentActivity = useAgentActivity;
104
+ exports.useAgentActivityForScreen = useAgentActivityForScreen;
105
+ exports.wrapToolWithActivity = wrapToolWithActivity;
106
+ //# sourceMappingURL=presence.cjs.map
107
+ //# sourceMappingURL=presence.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/presence/registry.ts","../src/presence/wrap-tool-with-activity.ts","../src/presence/use-agent-activity.ts"],"names":["useState","useEffect"],"mappings":"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","file":"presence.cjs","sourcesContent":["import type { ActivityFilter, AgentActivityEvent, AgentActivityListener } from \"./types\";\n\n/**\n * In-process registry of agent activity events. Bridges call `emitActivity`\n * after a tool runs; React hooks + the SSE relay subscribe via\n * `onActivity()`.\n *\n * Holds a short scrollback of recent events (default 200) so newly-mounted\n * subscribers can render the recent past — useful for activity-log UIs\n * that rejoin a session mid-stream.\n */\n\nconst HISTORY_CAP = 200;\n\nconst listeners = new Set<AgentActivityListener>();\nconst history: AgentActivityEvent[] = [];\n\n/** Emit an activity event. All current listeners receive it synchronously. */\nexport function emitActivity(event: AgentActivityEvent): void {\n history.push(event);\n if (history.length > HISTORY_CAP) history.splice(0, history.length - HISTORY_CAP);\n for (const l of listeners) l(event);\n}\n\n/**\n * Subscribe to all events (or a filtered subset). Returns an unsubscribe\n * function. Filter checks all provided keys with strict equality; omit a\n * key to ignore it.\n */\nexport function onActivity(listener: AgentActivityListener, filter?: ActivityFilter): () => void {\n const wrapped: AgentActivityListener = filter\n ? (e) => { if (matches(e, filter)) listener(e); }\n : listener;\n listeners.add(wrapped);\n return () => listeners.delete(wrapped);\n}\n\n/** Read the recent history (newest last). Optional filter. */\nexport function readActivityHistory(filter?: ActivityFilter): AgentActivityEvent[] {\n if (!filter) return history.slice();\n return history.filter((e) => matches(e, filter));\n}\n\n/** Wipe history + clear listeners. Test/teardown helper. */\nexport function resetActivityRegistry(): void {\n listeners.clear();\n history.length = 0;\n}\n\nfunction matches(e: AgentActivityEvent, f: ActivityFilter): boolean {\n if (f.agentId !== undefined && e.agentId !== f.agentId) return false;\n if (f.screenId !== undefined && e.target.screenId !== f.screenId) return false;\n if (f.kind !== undefined && e.target.kind !== f.kind) return false;\n return true;\n}\n","import type { CallToolResult } from \"../mcp/types\";\nimport { emitActivity } from \"./registry\";\nimport type { AgentTarget } from \"./types\";\n\nexport type ActivityAgent = { id: string; name?: string; color?: string };\n\nexport type ActivityResolverContext<TArgs = Record<string, unknown>> = {\n /** Tool name as registered. */\n toolName: string;\n /** Arguments the tool was called with. */\n args: TArgs;\n /** The CallToolResult the underlying handler produced. */\n result: CallToolResult;\n};\n\n/**\n * Resolves an `AgentTarget` for an executed tool. Bridges declare one of\n * these per registration so the wrapper knows which surface / element /\n * screen the activity belongs to.\n *\n * The resolver runs AFTER the tool handler so it can inspect the result\n * (e.g. read a newly-created item id from `structuredContent`).\n */\nexport type ActivityTargetResolver<TArgs = Record<string, unknown>> = (\n ctx: ActivityResolverContext<TArgs>,\n) => AgentTarget | null;\n\nexport type ToolHandler<TArgs = Record<string, unknown>> = (\n args: TArgs,\n) => Promise<CallToolResult> | CallToolResult;\n\n/**\n * wrapToolWithActivity — decorate a bridge tool handler so every successful\n * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.\n *\n * Usage in a bridge:\n *\n * server.registerTool(\n * definition,\n * wrapToolWithActivity(\n * handler,\n * { agent, kind: \"whiteboard\", resolveTarget: ({ args }) => ({\n * kind: \"whiteboard\", elementId: args.id as string,\n * }) },\n * ),\n * );\n */\nexport function wrapToolWithActivity<TArgs = Record<string, unknown>>(\n handler: ToolHandler<TArgs>,\n options: {\n toolName: string;\n agent: ActivityAgent;\n /** Optional fancy-screens screen id this bridge is scoped to. */\n screenId?: string;\n /** Default target kind if the resolver returns one without `kind`. */\n kind: AgentTarget[\"kind\"];\n /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */\n resolveTarget?: ActivityTargetResolver<TArgs>;\n /** Optional ttl override. */\n ttlMs?: number;\n },\n): ToolHandler<TArgs> {\n return async (args) => {\n const result = await handler(args);\n if (result.isError) return result;\n\n let target: AgentTarget | null;\n if (options.resolveTarget) {\n target = options.resolveTarget({ toolName: options.toolName, args, result });\n } else {\n target = { kind: options.kind, screenId: options.screenId };\n }\n if (!target) return result;\n\n emitActivity({\n agentId: options.agent.id,\n agentName: options.agent.name,\n agentColor: options.agent.color,\n target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },\n action: options.toolName,\n timestamp: Date.now(),\n meta: extractMeta(result),\n ttlMs: options.ttlMs,\n });\n return result;\n };\n}\n\nfunction extractMeta(result: CallToolResult): Record<string, unknown> | undefined {\n const sc = result.structuredContent;\n if (sc && typeof sc === \"object\" && !Array.isArray(sc)) {\n return sc as Record<string, unknown>;\n }\n return undefined;\n}\n","import { useEffect, useState } from \"react\";\nimport { onActivity, readActivityHistory } from \"./registry\";\nimport type { ActivityFilter, AgentActivityEvent } from \"./types\";\n\n/**\n * useAgentActivity — React subscription to the in-process activity stream.\n *\n * Returns:\n * - `events`: capped scrollback of recent events matching the filter\n * - `latest`: the most recent event (handy for transient highlights)\n */\nexport function useAgentActivity(\n filter?: ActivityFilter,\n options: { capacity?: number } = {},\n): { events: AgentActivityEvent[]; latest: AgentActivityEvent | null } {\n const cap = options.capacity ?? 50;\n const [events, setEvents] = useState<AgentActivityEvent[]>(() => readActivityHistory(filter).slice(-cap));\n\n useEffect(() => {\n setEvents(readActivityHistory(filter).slice(-cap));\n return onActivity((event) => {\n setEvents((prev) => {\n const next = prev.length >= cap ? prev.slice(prev.length - cap + 1) : prev.slice();\n next.push(event);\n return next;\n });\n }, filter);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filter?.agentId, filter?.screenId, filter?.kind, cap]);\n\n return { events, latest: events.length > 0 ? events[events.length - 1] : null };\n}\n\n/**\n * useAgentActivityForScreen — convenience wrapper that filters by screen id.\n * Drives \"agent is here\" badges in fancy-screens-based shells.\n */\nexport function useAgentActivityForScreen(\n screenId: string,\n options: { capacity?: number } = {},\n): { events: AgentActivityEvent[]; latest: AgentActivityEvent | null; isAgentActive: boolean } {\n const { events, latest } = useAgentActivity({ screenId }, options);\n const fadeAfter = latest?.ttlMs ?? 1500;\n const [isAgentActive, setActive] = useState(false);\n\n useEffect(() => {\n if (!latest) {\n setActive(false);\n return;\n }\n setActive(true);\n const timer = setTimeout(() => setActive(false), fadeAfter);\n return () => clearTimeout(timer);\n }, [latest, fadeAfter]);\n\n return { events, latest, isAgentActive };\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export { useAgentActivity, useAgentActivityForScreen } from './chunk-X66JWQBB.js';
2
+ export { wrapToolWithActivity } from './chunk-52S7XYZK.js';
3
+ export { emitActivity, onActivity, readActivityHistory, resetActivityRegistry } from './chunk-JU2N4KK6.js';
4
+ //# sourceMappingURL=presence.js.map
5
+ //# sourceMappingURL=presence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"presence.js"}
@@ -0,0 +1,3 @@
1
+ export { emitActivity, onActivity, readActivityHistory, resetActivityRegistry } from './chunk-JU2N4KK6.js';
2
+ //# sourceMappingURL=registry-2DRURS6U.js.map
3
+ //# sourceMappingURL=registry-2DRURS6U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"registry-2DRURS6U.js"}
@@ -0,0 +1,63 @@
1
+ import { S as ServerInfo, a as ServerCapabilities, J as JsonRpcMessage, C as CallToolResult } from './types-aOQLTW0E.cjs';
2
+ import { a as ToolRegistry } from './tool-host-BQuUygLF.cjs';
3
+
4
+ type McpServerOptions = {
5
+ info: ServerInfo;
6
+ /** Defaults to { tools: { listChanged: true } } */
7
+ capabilities?: ServerCapabilities;
8
+ /** Free-text instructions surfaced to clients during initialize. */
9
+ instructions?: string;
10
+ };
11
+ type Transport = {
12
+ /** Called by the server when it has a message to deliver to the client. */
13
+ send: (message: JsonRpcMessage) => void;
14
+ /** Called by the server when it's torn down so the transport can clean up. */
15
+ close?: () => void;
16
+ };
17
+ /**
18
+ * MicroMcpServer — protocol-level MCP server, transport-agnostic.
19
+ *
20
+ * Use it like:
21
+ *
22
+ * const server = new MicroMcpServer({ info: { name: "session", version: "0.1" } });
23
+ * server.registerTool({ name: "...", inputSchema: { type: "object" } }, async (args) => ({...}));
24
+ * const transport = new InProcessTransport();
25
+ * server.attach(transport);
26
+ * transport.deliver({ ... }); // client → server frames
27
+ *
28
+ * The same server can serve multiple transports (e.g. an in-process agent
29
+ * AND a relayed external client) by attaching each one.
30
+ */
31
+ declare class MicroMcpServer extends ToolRegistry {
32
+ private transports;
33
+ private notifyListChangedScheduled;
34
+ readonly info: ServerInfo;
35
+ readonly capabilities: ServerCapabilities;
36
+ readonly instructions?: string;
37
+ constructor(options: McpServerOptions);
38
+ attach(transport: Transport): () => void;
39
+ detach(transport: Transport): void;
40
+ unregisterTool(name: string): void;
41
+ protected onToolsChanged(): void;
42
+ /**
43
+ * Receive a JSON-RPC frame from a client (called by the transport).
44
+ * The transport is responsible for sending the response back.
45
+ */
46
+ receive(transport: Transport, message: JsonRpcMessage): Promise<void>;
47
+ private handle;
48
+ private scheduleListChangedNotification;
49
+ private broadcast;
50
+ private toRpcError;
51
+ }
52
+ declare function rpcError(code: number, message: string, data?: any): {
53
+ data?: any;
54
+ code: number;
55
+ message: string;
56
+ };
57
+ /**
58
+ * Helper to build a CallToolResult from a string or structured value.
59
+ */
60
+ declare function textResult(text: string, structured?: any): CallToolResult;
61
+ declare function errorResult(text: string): CallToolResult;
62
+
63
+ export { MicroMcpServer as M, type Transport as T, type McpServerOptions as a, errorResult as e, rpcError as r, textResult as t };
@@ -0,0 +1,63 @@
1
+ import { S as ServerInfo, a as ServerCapabilities, J as JsonRpcMessage, C as CallToolResult } from './types-aOQLTW0E.js';
2
+ import { a as ToolRegistry } from './tool-host-C8JMMGYq.js';
3
+
4
+ type McpServerOptions = {
5
+ info: ServerInfo;
6
+ /** Defaults to { tools: { listChanged: true } } */
7
+ capabilities?: ServerCapabilities;
8
+ /** Free-text instructions surfaced to clients during initialize. */
9
+ instructions?: string;
10
+ };
11
+ type Transport = {
12
+ /** Called by the server when it has a message to deliver to the client. */
13
+ send: (message: JsonRpcMessage) => void;
14
+ /** Called by the server when it's torn down so the transport can clean up. */
15
+ close?: () => void;
16
+ };
17
+ /**
18
+ * MicroMcpServer — protocol-level MCP server, transport-agnostic.
19
+ *
20
+ * Use it like:
21
+ *
22
+ * const server = new MicroMcpServer({ info: { name: "session", version: "0.1" } });
23
+ * server.registerTool({ name: "...", inputSchema: { type: "object" } }, async (args) => ({...}));
24
+ * const transport = new InProcessTransport();
25
+ * server.attach(transport);
26
+ * transport.deliver({ ... }); // client → server frames
27
+ *
28
+ * The same server can serve multiple transports (e.g. an in-process agent
29
+ * AND a relayed external client) by attaching each one.
30
+ */
31
+ declare class MicroMcpServer extends ToolRegistry {
32
+ private transports;
33
+ private notifyListChangedScheduled;
34
+ readonly info: ServerInfo;
35
+ readonly capabilities: ServerCapabilities;
36
+ readonly instructions?: string;
37
+ constructor(options: McpServerOptions);
38
+ attach(transport: Transport): () => void;
39
+ detach(transport: Transport): void;
40
+ unregisterTool(name: string): void;
41
+ protected onToolsChanged(): void;
42
+ /**
43
+ * Receive a JSON-RPC frame from a client (called by the transport).
44
+ * The transport is responsible for sending the response back.
45
+ */
46
+ receive(transport: Transport, message: JsonRpcMessage): Promise<void>;
47
+ private handle;
48
+ private scheduleListChangedNotification;
49
+ private broadcast;
50
+ private toRpcError;
51
+ }
52
+ declare function rpcError(code: number, message: string, data?: any): {
53
+ data?: any;
54
+ code: number;
55
+ message: string;
56
+ };
57
+ /**
58
+ * Helper to build a CallToolResult from a string or structured value.
59
+ */
60
+ declare function textResult(text: string, structured?: any): CallToolResult;
61
+ declare function errorResult(text: string): CallToolResult;
62
+
63
+ export { MicroMcpServer as M, type Transport as T, type McpServerOptions as a, errorResult as e, rpcError as r, textResult as t };
@@ -1,4 +1,6 @@
1
- import { j as Transport, M as MicroMcpServer, b as JsonRpcMessage } from '../server-Bv985us3.cjs';
1
+ import { J as JsonRpcMessage } from '../types-aOQLTW0E.cjs';
2
+ import { T as Transport, M as MicroMcpServer } from '../server-BsSwfemr.cjs';
3
+ import '../tool-host-BQuUygLF.cjs';
2
4
 
3
5
  /**
4
6
  * Session-token utilities. The token is a high-entropy secret; possession
@@ -1,4 +1,6 @@
1
- import { j as Transport, M as MicroMcpServer, b as JsonRpcMessage } from '../server-Bv985us3.js';
1
+ import { J as JsonRpcMessage } from '../types-aOQLTW0E.js';
2
+ import { T as Transport, M as MicroMcpServer } from '../server-Du3-IGqM.js';
3
+ import '../tool-host-C8JMMGYq.js';
2
4
 
3
5
  /**
4
6
  * Session-token utilities. The token is a high-entropy secret; possession
package/dist/sharing.cjs CHANGED
@@ -1,5 +1,58 @@
1
1
  'use strict';
2
2
 
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __esm = (fn, res) => function __init() {
6
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
+ };
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+
13
+ // src/presence/registry.ts
14
+ var registry_exports = {};
15
+ __export(registry_exports, {
16
+ emitActivity: () => emitActivity,
17
+ onActivity: () => onActivity,
18
+ readActivityHistory: () => readActivityHistory,
19
+ resetActivityRegistry: () => resetActivityRegistry
20
+ });
21
+ function emitActivity(event) {
22
+ history.push(event);
23
+ if (history.length > HISTORY_CAP) history.splice(0, history.length - HISTORY_CAP);
24
+ for (const l of listeners) l(event);
25
+ }
26
+ function onActivity(listener, filter) {
27
+ const wrapped = filter ? (e) => {
28
+ if (matches(e, filter)) listener(e);
29
+ } : listener;
30
+ listeners.add(wrapped);
31
+ return () => listeners.delete(wrapped);
32
+ }
33
+ function readActivityHistory(filter) {
34
+ if (!filter) return history.slice();
35
+ return history.filter((e) => matches(e, filter));
36
+ }
37
+ function resetActivityRegistry() {
38
+ listeners.clear();
39
+ history.length = 0;
40
+ }
41
+ function matches(e, f) {
42
+ if (f.agentId !== void 0 && e.agentId !== f.agentId) return false;
43
+ if (f.screenId !== void 0 && e.target.screenId !== f.screenId) return false;
44
+ if (f.kind !== void 0 && e.target.kind !== f.kind) return false;
45
+ return true;
46
+ }
47
+ var HISTORY_CAP, listeners, history;
48
+ var init_registry = __esm({
49
+ "src/presence/registry.ts"() {
50
+ HISTORY_CAP = 200;
51
+ listeners = /* @__PURE__ */ new Set();
52
+ history = [];
53
+ }
54
+ });
55
+
3
56
  // src/sharing/token.ts
4
57
  var TOKEN_BYTES = 24;
5
58
  function createSessionDescriptor() {
@@ -151,6 +204,21 @@ function attachSseRelay(server, options) {
151
204
  transport.bindServer(server);
152
205
  server.attach(transport);
153
206
  transport.start();
207
+ Promise.resolve().then(() => (init_registry(), registry_exports)).then(({ onActivity: onActivity2 }) => {
208
+ const off = onActivity2((event) => {
209
+ transport.send({
210
+ jsonrpc: "2.0",
211
+ method: "notifications/agent_activity",
212
+ params: event
213
+ });
214
+ });
215
+ const origClose = transport.close.bind(transport);
216
+ transport.close = () => {
217
+ off();
218
+ origClose();
219
+ };
220
+ }).catch(() => {
221
+ });
154
222
  return transport;
155
223
  }
156
224