agent-comms 1.12.0 → 1.14.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 (134) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +1 -1
  3. package/dist/bridges/pi/index.d.ts +5 -2
  4. package/dist/bridges/pi/index.d.ts.map +1 -1
  5. package/dist/bridges/pi/index.js +118 -7
  6. package/dist/bridges/pi/index.js.map +1 -1
  7. package/dist/bridges/user/controller.d.ts +1 -0
  8. package/dist/bridges/user/controller.d.ts.map +1 -1
  9. package/dist/bridges/user/controller.js +12 -0
  10. package/dist/bridges/user/controller.js.map +1 -1
  11. package/dist/bridges/user/tui.js +2 -0
  12. package/dist/bridges/user/tui.js.map +1 -1
  13. package/dist/bridges/user/web/build.d.ts +10 -0
  14. package/dist/bridges/user/web/build.d.ts.map +1 -0
  15. package/dist/bridges/user/web/build.js +58 -0
  16. package/dist/bridges/user/web/build.js.map +1 -0
  17. package/dist/bridges/user/web/frontend/api.d.ts +29 -0
  18. package/dist/bridges/user/web/frontend/api.d.ts.map +1 -0
  19. package/dist/bridges/user/web/frontend/api.js +121 -0
  20. package/dist/bridges/user/web/frontend/api.js.map +1 -0
  21. package/dist/bridges/user/web/frontend/components/App.d.ts +23 -0
  22. package/dist/bridges/user/web/frontend/components/App.d.ts.map +1 -0
  23. package/dist/bridges/user/web/frontend/components/App.js +7 -0
  24. package/dist/bridges/user/web/frontend/components/App.js.map +1 -0
  25. package/dist/bridges/user/web/frontend/components/ChatArea.d.ts +14 -0
  26. package/dist/bridges/user/web/frontend/components/ChatArea.d.ts.map +1 -0
  27. package/dist/bridges/user/web/frontend/components/ChatArea.js +38 -0
  28. package/dist/bridges/user/web/frontend/components/ChatArea.js.map +1 -0
  29. package/dist/bridges/user/web/frontend/components/CreateRoomForm.d.ts +11 -0
  30. package/dist/bridges/user/web/frontend/components/CreateRoomForm.d.ts.map +1 -0
  31. package/dist/bridges/user/web/frontend/components/CreateRoomForm.js +33 -0
  32. package/dist/bridges/user/web/frontend/components/CreateRoomForm.js.map +1 -0
  33. package/dist/bridges/user/web/frontend/components/JoinForm.d.ts +11 -0
  34. package/dist/bridges/user/web/frontend/components/JoinForm.d.ts.map +1 -0
  35. package/dist/bridges/user/web/frontend/components/JoinForm.js +28 -0
  36. package/dist/bridges/user/web/frontend/components/JoinForm.js.map +1 -0
  37. package/dist/bridges/user/web/frontend/components/Message.d.ts +8 -0
  38. package/dist/bridges/user/web/frontend/components/Message.d.ts.map +1 -0
  39. package/dist/bridges/user/web/frontend/components/Message.js +15 -0
  40. package/dist/bridges/user/web/frontend/components/Message.js.map +1 -0
  41. package/dist/bridges/user/web/frontend/components/MessageList.d.ts +8 -0
  42. package/dist/bridges/user/web/frontend/components/MessageList.d.ts.map +1 -0
  43. package/dist/bridges/user/web/frontend/components/MessageList.js +16 -0
  44. package/dist/bridges/user/web/frontend/components/MessageList.js.map +1 -0
  45. package/dist/bridges/user/web/frontend/components/ProjectTree.d.ts +17 -0
  46. package/dist/bridges/user/web/frontend/components/ProjectTree.d.ts.map +1 -0
  47. package/dist/bridges/user/web/frontend/components/ProjectTree.js +59 -0
  48. package/dist/bridges/user/web/frontend/components/ProjectTree.js.map +1 -0
  49. package/dist/bridges/user/web/frontend/components/Sidebar.d.ts +16 -0
  50. package/dist/bridges/user/web/frontend/components/Sidebar.d.ts.map +1 -0
  51. package/dist/bridges/user/web/frontend/components/Sidebar.js +31 -0
  52. package/dist/bridges/user/web/frontend/components/Sidebar.js.map +1 -0
  53. package/dist/bridges/user/web/frontend/dom.d.ts +28 -0
  54. package/dist/bridges/user/web/frontend/dom.d.ts.map +1 -0
  55. package/dist/bridges/user/web/frontend/dom.js +46 -0
  56. package/dist/bridges/user/web/frontend/dom.js.map +1 -0
  57. package/dist/bridges/user/web/frontend/input.d.ts +37 -0
  58. package/dist/bridges/user/web/frontend/input.d.ts.map +1 -0
  59. package/dist/bridges/user/web/frontend/input.js +167 -0
  60. package/dist/bridges/user/web/frontend/input.js.map +1 -0
  61. package/dist/bridges/user/web/frontend/main.d.ts +8 -0
  62. package/dist/bridges/user/web/frontend/main.d.ts.map +1 -0
  63. package/dist/bridges/user/web/frontend/main.js +156 -0
  64. package/dist/bridges/user/web/frontend/main.js.map +1 -0
  65. package/dist/bridges/user/web/frontend/messages.d.ts +17 -0
  66. package/dist/bridges/user/web/frontend/messages.d.ts.map +1 -0
  67. package/dist/bridges/user/web/frontend/messages.js +82 -0
  68. package/dist/bridges/user/web/frontend/messages.js.map +1 -0
  69. package/dist/bridges/user/web/frontend/project-tree.d.ts +9 -0
  70. package/dist/bridges/user/web/frontend/project-tree.d.ts.map +1 -0
  71. package/dist/bridges/user/web/frontend/project-tree.js +173 -0
  72. package/dist/bridges/user/web/frontend/project-tree.js.map +1 -0
  73. package/dist/bridges/user/web/frontend/state.d.ts +41 -0
  74. package/dist/bridges/user/web/frontend/state.d.ts.map +1 -0
  75. package/dist/bridges/user/web/frontend/state.js +87 -0
  76. package/dist/bridges/user/web/frontend/state.js.map +1 -0
  77. package/dist/bridges/user/web/frontend/types.d.ts +209 -0
  78. package/dist/bridges/user/web/frontend/types.d.ts.map +1 -0
  79. package/dist/bridges/user/web/frontend/types.js +8 -0
  80. package/dist/bridges/user/web/frontend/types.js.map +1 -0
  81. package/dist/bridges/user/web/generated-html.d.ts +6 -0
  82. package/dist/bridges/user/web/generated-html.d.ts.map +1 -0
  83. package/dist/bridges/user/web/generated-html.js +179 -0
  84. package/dist/bridges/user/web/generated-html.js.map +1 -0
  85. package/dist/bridges/user/web/server.d.ts.map +1 -1
  86. package/dist/bridges/user/web/server.js +26 -3
  87. package/dist/bridges/user/web/server.js.map +1 -1
  88. package/dist/bridges/user/web/test/web-server.integration.test.d.ts +7 -0
  89. package/dist/bridges/user/web/test/web-server.integration.test.d.ts.map +1 -0
  90. package/dist/bridges/user/web/test/web-server.integration.test.js +187 -0
  91. package/dist/bridges/user/web/test/web-server.integration.test.js.map +1 -0
  92. package/dist/core/bridge.d.ts +15 -0
  93. package/dist/core/bridge.d.ts.map +1 -1
  94. package/dist/core/bridge.js +60 -0
  95. package/dist/core/bridge.js.map +1 -1
  96. package/dist/core/index.d.ts +1 -1
  97. package/dist/core/index.d.ts.map +1 -1
  98. package/dist/core/index.js +1 -1
  99. package/dist/core/index.js.map +1 -1
  100. package/dist/core/mesh-store.d.ts +3 -0
  101. package/dist/core/mesh-store.d.ts.map +1 -1
  102. package/dist/core/mesh-store.js +107 -7
  103. package/dist/core/mesh-store.js.map +1 -1
  104. package/dist/core/test/bridge.unit.test.d.ts +5 -0
  105. package/dist/core/test/bridge.unit.test.d.ts.map +1 -0
  106. package/dist/core/test/bridge.unit.test.js +120 -0
  107. package/dist/core/test/bridge.unit.test.js.map +1 -0
  108. package/dist/core/types.d.ts +10 -0
  109. package/dist/core/types.d.ts.map +1 -1
  110. package/dist/core/types.js +6 -0
  111. package/dist/core/types.js.map +1 -1
  112. package/dist/test/{coordinator-socket-error.test.d.ts → coordinator-socket-error.integration.test.d.ts} +1 -1
  113. package/dist/test/coordinator-socket-error.integration.test.d.ts.map +1 -0
  114. package/dist/test/{coordinator-socket-error.test.js → coordinator-socket-error.integration.test.js} +1 -1
  115. package/dist/test/coordinator-socket-error.integration.test.js.map +1 -0
  116. package/dist/test/{mesh-e2e.test.d.ts → mesh-e2e.integration.test.d.ts} +1 -1
  117. package/dist/test/mesh-e2e.integration.test.d.ts.map +1 -0
  118. package/dist/test/{mesh-e2e.test.js → mesh-e2e.integration.test.js} +1 -1
  119. package/dist/test/mesh-e2e.integration.test.js.map +1 -0
  120. package/dist/test/{mesh-smoke.test.d.ts → mesh-smoke.integration.test.d.ts} +1 -1
  121. package/dist/test/mesh-smoke.integration.test.d.ts.map +1 -0
  122. package/dist/test/{mesh-smoke.test.js → mesh-smoke.integration.test.js} +1 -1
  123. package/dist/test/mesh-smoke.integration.test.js.map +1 -0
  124. package/package.json +11 -4
  125. package/dist/bridges/user/web/index.html.d.ts +0 -8
  126. package/dist/bridges/user/web/index.html.d.ts.map +0 -1
  127. package/dist/bridges/user/web/index.html.js +0 -391
  128. package/dist/bridges/user/web/index.html.js.map +0 -1
  129. package/dist/test/coordinator-socket-error.test.d.ts.map +0 -1
  130. package/dist/test/coordinator-socket-error.test.js.map +0 -1
  131. package/dist/test/mesh-e2e.test.d.ts.map +0 -1
  132. package/dist/test/mesh-e2e.test.js.map +0 -1
  133. package/dist/test/mesh-smoke.test.d.ts.map +0 -1
  134. package/dist/test/mesh-smoke.test.js.map +0 -1
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Input handler — parse slash commands and plain messages.
3
+ *
4
+ * Pure logic, no DOM dependency. Returns an Action or a local command result.
5
+ * Testable in isolation.
6
+ */
7
+ /**
8
+ * Classify an InputResult to determine if it should be handled locally
9
+ * (e.g. join_room needs to set client state and fetch history) or sent
10
+ * directly to the server via sendAction.
11
+ *
12
+ * Returns null for actions that should go through sendAction directly,
13
+ * and for non-action results (local, ignored).
14
+ */
15
+ export function routeAction(result) {
16
+ if (result.kind !== "action")
17
+ return null;
18
+ const action = result.action;
19
+ if (action.action === "join_room") {
20
+ return { kind: "join_room", room: action.room };
21
+ }
22
+ if (action.action === "leave_room") {
23
+ return { kind: "leave_room" };
24
+ }
25
+ return null;
26
+ }
27
+ // ---------------------------------------------------------------------------
28
+ // Parser
29
+ // ---------------------------------------------------------------------------
30
+ export function parseInput(text, currentRoom, dmTarget) {
31
+ const trimmed = text.trim();
32
+ if (trimmed.length === 0)
33
+ return { kind: "ignored" };
34
+ if (trimmed.startsWith("/")) {
35
+ return parseCommand(trimmed, currentRoom);
36
+ }
37
+ if (currentRoom) {
38
+ return {
39
+ kind: "action",
40
+ action: { action: "send", target: currentRoom, content: trimmed },
41
+ };
42
+ }
43
+ if (dmTarget) {
44
+ return {
45
+ kind: "action",
46
+ action: { action: "dm", target: dmTarget, content: trimmed },
47
+ };
48
+ }
49
+ return {
50
+ kind: "local",
51
+ result: {
52
+ type: "error",
53
+ text: "Join a room or select an agent first",
54
+ },
55
+ };
56
+ }
57
+ function parseCommand(text, currentRoom) {
58
+ const parts = text.slice(1).split(/\s+/);
59
+ const cmd = (parts[0] ?? "").toLowerCase();
60
+ switch (cmd) {
61
+ case "join":
62
+ if (!parts[1]) {
63
+ return {
64
+ kind: "local",
65
+ result: { type: "error", text: "Usage: /join <room>" },
66
+ };
67
+ }
68
+ return {
69
+ kind: "action",
70
+ action: { action: "join_room", room: parts[1] },
71
+ };
72
+ case "leave":
73
+ return {
74
+ kind: "action",
75
+ action: {
76
+ action: "leave_room",
77
+ room: parts[1] ?? currentRoom ?? "",
78
+ },
79
+ };
80
+ case "rooms":
81
+ return {
82
+ kind: "action",
83
+ action: { action: "list_rooms" },
84
+ };
85
+ case "agents":
86
+ return {
87
+ kind: "action",
88
+ action: { action: "list_agents" },
89
+ };
90
+ case "dm":
91
+ if (!parts[1] || !parts[2]) {
92
+ return {
93
+ kind: "local",
94
+ result: {
95
+ type: "error",
96
+ text: "Usage: /dm <agent> <message>",
97
+ },
98
+ };
99
+ }
100
+ return {
101
+ kind: "action",
102
+ action: {
103
+ action: "dm",
104
+ target: parts[1],
105
+ content: parts.slice(2).join(" "),
106
+ },
107
+ };
108
+ case "create":
109
+ if (!parts[1]) {
110
+ return {
111
+ kind: "local",
112
+ result: { type: "error", text: "Usage: /create <name>" },
113
+ };
114
+ }
115
+ return {
116
+ kind: "action",
117
+ action: {
118
+ action: "create_room",
119
+ name: parts[1],
120
+ type: "public",
121
+ },
122
+ };
123
+ case "destroy":
124
+ if (!parts[1]) {
125
+ return {
126
+ kind: "local",
127
+ result: { type: "error", text: "Usage: /destroy <room>" },
128
+ };
129
+ }
130
+ return {
131
+ kind: "action",
132
+ action: { action: "destroy_room", room: parts[1] },
133
+ };
134
+ case "rename":
135
+ if (!parts[1] || !parts[2]) {
136
+ return {
137
+ kind: "local",
138
+ result: {
139
+ type: "error",
140
+ text: "Usage: /rename <agent> <new-name>",
141
+ },
142
+ };
143
+ }
144
+ return {
145
+ kind: "action",
146
+ action: {
147
+ action: "rename_agent",
148
+ agent: parts[1],
149
+ name: parts.slice(2).join(" "),
150
+ },
151
+ };
152
+ case "help":
153
+ return {
154
+ kind: "local",
155
+ result: {
156
+ type: "help",
157
+ text: "Commands: /join, /leave, /rooms, /agents, /dm, /create, /destroy, /help",
158
+ },
159
+ };
160
+ default:
161
+ return {
162
+ kind: "local",
163
+ result: { type: "unknown", text: `Unknown command: /${cmd}` },
164
+ };
165
+ }
166
+ }
167
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Entry point — bootstraps the web UI with Preact.
3
+ *
4
+ * Owns the state store, WebSocket connection, and action handlers.
5
+ * Renders the App component on every state change.
6
+ */
7
+ import "./styles.css";
8
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/main.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,cAAc,CAAC"}
@@ -0,0 +1,156 @@
1
+ import { jsx as _jsx } from "preact/jsx-runtime";
2
+ /**
3
+ * Entry point — bootstraps the web UI with Preact.
4
+ *
5
+ * Owns the state store, WebSocket connection, and action handlers.
6
+ * Renders the App component on every state change.
7
+ */
8
+ import { render } from "preact";
9
+ import "./styles.css";
10
+ import { App } from "./components/App.js";
11
+ import { CommsWs, fetchAgents, fetchRoomMessages, fetchRooms } from "./api.js";
12
+ import { requireElement } from "./dom.js";
13
+ import { parseInput } from "./input.js";
14
+ import { State } from "./state.js";
15
+ import { deliveryEventToMessage, roomMessageToDisplay } from "./messages.js";
16
+ // ---------------------------------------------------------------------------
17
+ // Mount point
18
+ // ---------------------------------------------------------------------------
19
+ const rootEl = requireElement(document, "#root");
20
+ // ---------------------------------------------------------------------------
21
+ // State
22
+ // ---------------------------------------------------------------------------
23
+ const state = new State();
24
+ // ---------------------------------------------------------------------------
25
+ // Helpers
26
+ // ---------------------------------------------------------------------------
27
+ function addMessage(msg) {
28
+ state.addMessage(msg);
29
+ }
30
+ // ---------------------------------------------------------------------------
31
+ // WebSocket
32
+ // ---------------------------------------------------------------------------
33
+ let pendingAction;
34
+ const ws = new CommsWs({
35
+ onOpen: () => {
36
+ state.setConnected(true);
37
+ addMessage({ type: "system", text: "Connected to mesh" });
38
+ },
39
+ onClose: () => {
40
+ state.setConnected(false);
41
+ addMessage({ type: "system", text: "Disconnected — reconnecting..." });
42
+ },
43
+ onFrame: handleFrame,
44
+ });
45
+ function handleFrame(frame) {
46
+ const s = state.get();
47
+ switch (frame.type) {
48
+ case "delivery": {
49
+ const msg = deliveryEventToMessage(frame.event, s.currentRoom);
50
+ if (msg)
51
+ addMessage(msg);
52
+ if (frame.event.type === "member_joined" ||
53
+ frame.event.type === "member_left" ||
54
+ frame.event.type === "member_status") {
55
+ void refreshState();
56
+ }
57
+ break;
58
+ }
59
+ case "result":
60
+ addMessage({ type: "system", text: frame.result.content });
61
+ if (!frame.result.isError) {
62
+ if (pendingAction?.action === "join_room" && !state.get().currentRoom) {
63
+ const roomId = pendingAction.room;
64
+ state.setDmTarget(undefined);
65
+ state.setCurrentRoom(roomId);
66
+ }
67
+ void refreshState();
68
+ }
69
+ pendingAction = undefined;
70
+ break;
71
+ case "error":
72
+ addMessage({ type: "status", text: `Error: ${frame.message}` });
73
+ break;
74
+ case "state":
75
+ state.applyState(frame.agents, frame.rooms);
76
+ break;
77
+ }
78
+ }
79
+ // ---------------------------------------------------------------------------
80
+ // Actions
81
+ // ---------------------------------------------------------------------------
82
+ function sendAction(action) {
83
+ pendingAction = action;
84
+ ws.sendAction(action);
85
+ }
86
+ async function refreshState() {
87
+ const [agents, rooms] = await Promise.all([fetchAgents(), fetchRooms()]);
88
+ state.setAgents(agents);
89
+ state.setRooms(rooms);
90
+ }
91
+ async function onJoinRoom(roomId) {
92
+ state.setDmTarget(undefined);
93
+ state.setCurrentRoom(roomId);
94
+ state.clearMessages();
95
+ sendAction({ action: "join_room", room: roomId });
96
+ // Load history
97
+ const messages = await fetchRoomMessages(roomId);
98
+ state.setMessages(messages.map(roomMessageToDisplay));
99
+ addMessage({ type: "system", text: `Joined ${roomId}` });
100
+ }
101
+ function onSelectAgent(agentId) {
102
+ state.setCurrentRoom(undefined);
103
+ state.setDmTarget(agentId);
104
+ state.clearMessages();
105
+ }
106
+ function onLeaveRoom() {
107
+ const currentRoom = state.get().currentRoom;
108
+ if (currentRoom) {
109
+ sendAction({ action: "leave_room", room: currentRoom });
110
+ state.setCurrentRoom(undefined);
111
+ state.clearMessages();
112
+ addMessage({ type: "system", text: `Left room "${currentRoom}"` });
113
+ }
114
+ }
115
+ function handleSendAction(text) {
116
+ const s = state.get();
117
+ const result = parseInput(text, s.currentRoom, s.dmTarget);
118
+ switch (result.kind) {
119
+ case "action":
120
+ sendAction(result.action);
121
+ break;
122
+ case "local":
123
+ addMessage({ type: "system", text: result.result.text });
124
+ break;
125
+ case "ignored":
126
+ break;
127
+ }
128
+ }
129
+ function onCreateRoom(name, type, description) {
130
+ const action = {
131
+ action: "create_room",
132
+ name,
133
+ type,
134
+ ...(description ? { description } : {}),
135
+ };
136
+ sendAction(action);
137
+ }
138
+ function onJoinRoomInput(roomName) {
139
+ void onJoinRoom(roomName);
140
+ }
141
+ // ---------------------------------------------------------------------------
142
+ // Render loop
143
+ // ---------------------------------------------------------------------------
144
+ function rerender() {
145
+ const s = state.get();
146
+ render(_jsx(App, { rooms: s.rooms, agents: s.agents, currentRoom: s.currentRoom, dmTarget: s.dmTarget, messages: s.messages, connected: s.connected, onJoinRoom: (roomId) => {
147
+ void onJoinRoom(roomId);
148
+ }, onSelectAgent: onSelectAgent, onLeaveRoom: onLeaveRoom, onSendAction: handleSendAction, onCreateRoom: onCreateRoom, onJoinRoomInput: onJoinRoomInput }), rootEl);
149
+ }
150
+ state.subscribe(rerender);
151
+ // ---------------------------------------------------------------------------
152
+ // Boot
153
+ // ---------------------------------------------------------------------------
154
+ ws.connect();
155
+ void refreshState();
156
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/main.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Message conversion — transforms wire-format events into display messages.
3
+ *
4
+ * Pure functions, no DOM or state dependency. Testable in isolation.
5
+ */
6
+ import type { DeliveryEvent, DisplayMessage, RoomMessage } from "./types.js";
7
+ /**
8
+ * Convert a delivery event to a display message for the UI.
9
+ * Returns undefined if the event should not be displayed
10
+ * (e.g. room_message for a room that isn't currently active).
11
+ */
12
+ export declare function deliveryEventToMessage(event: DeliveryEvent, currentRoom: string | undefined): DisplayMessage | undefined;
13
+ /**
14
+ * Convert a room message (from REST API history) to a display message.
15
+ */
16
+ export declare function roomMessageToDisplay(m: RoomMessage): DisplayMessage;
17
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/messages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,cAAc,GAAG,SAAS,CAoE5B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,WAAW,GAAG,cAAc,CAOnE"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Message conversion — transforms wire-format events into display messages.
3
+ *
4
+ * Pure functions, no DOM or state dependency. Testable in isolation.
5
+ */
6
+ /**
7
+ * Convert a delivery event to a display message for the UI.
8
+ * Returns undefined if the event should not be displayed
9
+ * (e.g. room_message for a room that isn't currently active).
10
+ */
11
+ export function deliveryEventToMessage(event, currentRoom) {
12
+ switch (event.type) {
13
+ case "room_message":
14
+ if (currentRoom === event.message.room) {
15
+ return {
16
+ type: "chat",
17
+ sender: event.message.from,
18
+ content: event.message.content,
19
+ timestamp: event.message.timestamp,
20
+ };
21
+ }
22
+ return undefined;
23
+ case "dm":
24
+ return {
25
+ type: "dm",
26
+ sender: event.message.from,
27
+ content: event.message.content,
28
+ timestamp: event.message.timestamp,
29
+ };
30
+ case "member_joined":
31
+ return { type: "system", text: `${event.agent} joined ${event.room}` };
32
+ case "member_left":
33
+ return { type: "system", text: `${event.agent} left ${event.room}` };
34
+ case "member_status":
35
+ return {
36
+ type: "status",
37
+ text: `${event.agent} is now ${event.status} in ${event.room}`,
38
+ };
39
+ case "delivery_status":
40
+ return {
41
+ type: "status",
42
+ text: `Message ${event.messageId} ${event.status} by ${event.agent}`,
43
+ };
44
+ case "room_members":
45
+ if (currentRoom === event.room) {
46
+ const memberList = event.members
47
+ .map((m) => `${m.name} (${m.status})`)
48
+ .join(", ");
49
+ return { type: "system", text: `Members: ${memberList}` };
50
+ }
51
+ return undefined;
52
+ case "room_invite": {
53
+ const desc = event.roomDescription ? ` — ${event.roomDescription}` : "";
54
+ return {
55
+ type: "system",
56
+ text: `${event.fromName} invited you to "${event.room}"${desc}`,
57
+ };
58
+ }
59
+ case "invite_declined":
60
+ return {
61
+ type: "system",
62
+ text: `${event.agentName} declined invite to ${event.room}: "${event.reason}"`,
63
+ };
64
+ case "name_changed":
65
+ return {
66
+ type: "system",
67
+ text: `${event.oldName} is now known as ${event.newName}`,
68
+ };
69
+ }
70
+ }
71
+ /**
72
+ * Convert a room message (from REST API history) to a display message.
73
+ */
74
+ export function roomMessageToDisplay(m) {
75
+ return {
76
+ type: "chat",
77
+ sender: m.from,
78
+ content: m.content,
79
+ timestamp: m.timestamp,
80
+ };
81
+ }
82
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Project tree — builds a nested directory tree from agent working directories.
3
+ *
4
+ * Pure function: agents + rooms → ProjectTree. No side effects.
5
+ * Project rooms (auto-created per cwd) are embedded in their directory nodes.
6
+ */
7
+ import type { Agent, ProjectTree, Room } from "./types.js";
8
+ export declare function buildProjectTree(agents: Agent[], rooms: Room[]): ProjectTree;
9
+ //# sourceMappingURL=project-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-tree.d.ts","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/project-tree.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAY,MAAM,YAAY,CAAC;AA0DrE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,WAAW,CA8C5E"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Project tree — builds a nested directory tree from agent working directories.
3
+ *
4
+ * Pure function: agents + rooms → ProjectTree. No side effects.
5
+ * Project rooms (auto-created per cwd) are embedded in their directory nodes.
6
+ */
7
+ function insertIntoTrie(node, segments, agent) {
8
+ const [seg, ...rest] = segments;
9
+ if (seg === undefined) {
10
+ node.agents.push(agent);
11
+ return;
12
+ }
13
+ let target = node.children.get(seg);
14
+ if (!target) {
15
+ target = { children: new Map(), agents: [] };
16
+ node.children.set(seg, target);
17
+ }
18
+ insertIntoTrie(target, rest, agent);
19
+ }
20
+ /** Ensure a branch path exists in the trie (creates intermediate nodes). */
21
+ function ensureBranch(node, segments) {
22
+ const [seg, ...rest] = segments;
23
+ if (seg === undefined)
24
+ return;
25
+ let child = node.children.get(seg);
26
+ if (!child) {
27
+ child = { children: new Map(), agents: [] };
28
+ node.children.set(seg, child);
29
+ }
30
+ ensureBranch(child, rest);
31
+ }
32
+ /**
33
+ * Build a nested project tree from agent cwd paths.
34
+ *
35
+ * - Trims the longest common prefix shared by ALL agent paths.
36
+ * - Agents in parent directories appear alongside child directories.
37
+ * - Empty branches are pruned.
38
+ * - Manual rooms (not auto-created per cwd) are separated out.
39
+ * - Children sorted: directories first (alphabetical), then agents (alphabetical).
40
+ */
41
+ const PROJECT_ROOM_PREFIX = "Project room for ";
42
+ /** Check if a room is an auto-created project room. */
43
+ function isProjectRoom(room) {
44
+ return room.description.startsWith(PROJECT_ROOM_PREFIX);
45
+ }
46
+ /** Extract the cwd path from a project room's description. */
47
+ function projectRoomCwd(room) {
48
+ return room.description.slice(PROJECT_ROOM_PREFIX.length);
49
+ }
50
+ export function buildProjectTree(agents, rooms) {
51
+ const manualRooms = rooms.filter((r) => !isProjectRoom(r));
52
+ // Index project rooms by their cwd path
53
+ const projectRoomsByPath = new Map();
54
+ for (const room of rooms) {
55
+ if (isProjectRoom(room)) {
56
+ projectRoomsByPath.set(projectRoomCwd(room), room);
57
+ }
58
+ }
59
+ // Use all project rooms as tree nodes even if no agents are in that directory
60
+ const allPaths = new Set();
61
+ for (const agent of agents) {
62
+ allPaths.add(agent.cwd);
63
+ }
64
+ for (const cwd of projectRoomsByPath.keys()) {
65
+ allPaths.add(cwd);
66
+ }
67
+ if (allPaths.size === 0) {
68
+ return { roots: [], manualRooms };
69
+ }
70
+ const paths = Array.from(allPaths);
71
+ const prefix = commonPathPrefix(paths);
72
+ const prefixSegments = prefix === "/" ? [] : splitPath(prefix);
73
+ // Group agents by their trimmed path
74
+ const root = { children: new Map(), agents: [] };
75
+ for (const agent of agents) {
76
+ const segments = splitPath(agent.cwd).slice(prefixSegments.length);
77
+ insertIntoTrie(root, segments, agent);
78
+ }
79
+ // Ensure directory branches exist for project room paths that have no agents
80
+ for (const cwd of projectRoomsByPath.keys()) {
81
+ const segments = splitPath(cwd).slice(prefixSegments.length);
82
+ ensureBranch(root, segments);
83
+ }
84
+ // Convert branch tree to TreeNode tree, embedding project rooms
85
+ const roots = branchToNodesWithRooms(root, prefix, "", projectRoomsByPath);
86
+ return { roots: sortChildren(roots), manualRooms };
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // Internal helpers
90
+ // ---------------------------------------------------------------------------
91
+ function splitPath(p) {
92
+ // "/Users/joe/Developer" → ["Users", "joe", "Developer"]
93
+ return p.split("/").filter((s) => s.length > 0);
94
+ }
95
+ function joinPath(...segments) {
96
+ return "/" + segments.join("/");
97
+ }
98
+ /**
99
+ * Find the longest common parent directory among all paths.
100
+ * Returns "/" if there's no common prefix beyond root.
101
+ */
102
+ function commonPathPrefix(paths) {
103
+ if (paths.length === 0)
104
+ return "/";
105
+ const split = paths.map(splitPath);
106
+ const minLength = Math.min(...split.map((s) => s.length));
107
+ let commonLen = 0;
108
+ for (let i = 0; i < minLength; i++) {
109
+ const segment = split[0]?.[i];
110
+ if (segment === undefined)
111
+ break;
112
+ if (split.every((s) => s[i] === segment)) {
113
+ commonLen++;
114
+ }
115
+ else {
116
+ break;
117
+ }
118
+ }
119
+ // Use parent of the common prefix so the last shared segment
120
+ // appears as a directory in the tree
121
+ if (commonLen > 0)
122
+ commonLen--;
123
+ if (commonLen === 0)
124
+ return "/";
125
+ return joinPath(...(split[0]?.slice(0, commonLen) ?? []));
126
+ }
127
+ /**
128
+ * Convert the internal branch tree into TreeNode[], embedding project rooms.
129
+ */
130
+ function branchToNodesWithRooms(branch, prefix, currentPath, projectRoomsByPath) {
131
+ const nodes = [];
132
+ // Subdirectories
133
+ for (const [name, child] of branch.children) {
134
+ const childPath = currentPath === "" && prefix === "/"
135
+ ? "/" + name
136
+ : currentPath === ""
137
+ ? prefix + "/" + name
138
+ : currentPath + "/" + name;
139
+ const childNodes = branchToNodesWithRooms(child, prefix, childPath, projectRoomsByPath);
140
+ if (childNodes.length > 0) {
141
+ // Check if this directory has a project room
142
+ const room = projectRoomsByPath.get(childPath);
143
+ nodes.push({
144
+ type: "directory",
145
+ name,
146
+ path: childPath,
147
+ ...(room ? { roomId: room.id } : {}),
148
+ children: sortChildren(childNodes),
149
+ });
150
+ }
151
+ }
152
+ // Agents in this directory
153
+ for (const agent of branch.agents) {
154
+ nodes.push({
155
+ type: "agent",
156
+ name: agent.name,
157
+ agentId: agent.id,
158
+ status: agent.status,
159
+ cwd: agent.cwd,
160
+ });
161
+ }
162
+ return nodes;
163
+ }
164
+ function sortChildren(nodes) {
165
+ return [...nodes].sort((a, b) => {
166
+ // Directories first, then agents
167
+ if (a.type !== b.type) {
168
+ return a.type === "directory" ? -1 : 1;
169
+ }
170
+ return a.name.localeCompare(b.name);
171
+ });
172
+ }
173
+ //# sourceMappingURL=project-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-tree.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/project-tree.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,SAAS,cAAc,CAAC,IAAY,EAAE,QAAkB,EAAE,KAAY;IACpE,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC;IAChC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO;IACT,CAAC;IACD,IAAI,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;IACD,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,4EAA4E;AAC5E,SAAS,YAAY,CAAC,IAAY,EAAE,QAAkB;IACpD,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC;IAChC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO;IAC9B,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IACD,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEhD,uDAAuD;AACvD,SAAS,aAAa,CAAC,IAAU;IAC/B,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AAC1D,CAAC;AAED,8DAA8D;AAC9D,SAAS,cAAc,CAAC,IAAU;IAChC,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAe,EAAE,KAAa;IAC7D,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3D,wCAAwC;IACxC,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAgB,CAAC;IACnD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,kBAAkB,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5C,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,cAAc,GAAG,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE/D,qCAAqC;IACrC,MAAM,IAAI,GAAW,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAEzD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACnE,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,6EAA6E;IAC7E,KAAK,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC7D,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,gEAAgE;IAChE,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAE3E,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;AACrD,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,SAAS,CAAC,CAAS;IAC1B,yDAAyD;IACzD,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,QAAQ,CAAC,GAAG,QAAkB;IACrC,OAAO,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,KAAe;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEnC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM;QACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,EAAE,CAAC;YACzC,SAAS,EAAE,CAAC;QACd,CAAC;aAAM,CAAC;YACN,MAAM;QACR,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,qCAAqC;IACrC,IAAI,SAAS,GAAG,CAAC;QAAE,SAAS,EAAE,CAAC;IAE/B,IAAI,SAAS,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAChC,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAC7B,MAAc,EACd,MAAc,EACd,WAAmB,EACnB,kBAAqC;IAErC,MAAM,KAAK,GAAe,EAAE,CAAC;IAE7B,iBAAiB;IACjB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC5C,MAAM,SAAS,GACb,WAAW,KAAK,EAAE,IAAI,MAAM,KAAK,GAAG;YAClC,CAAC,CAAC,GAAG,GAAG,IAAI;YACZ,CAAC,CAAC,WAAW,KAAK,EAAE;gBAClB,CAAC,CAAC,MAAM,GAAG,GAAG,GAAG,IAAI;gBACrB,CAAC,CAAC,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC;QAEjC,MAAM,UAAU,GAAG,sBAAsB,CACvC,KAAK,EACL,MAAM,EACN,SAAS,EACT,kBAAkB,CACnB,CAAC;QACF,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,6CAA6C;YAC7C,MAAM,IAAI,GAAG,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,WAAW;gBACjB,IAAI;gBACJ,IAAI,EAAE,SAAS;gBACf,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpC,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC;aACnC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,EAAE;YACjB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,KAAiB;IACrC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC9B,iCAAiC;QACjC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC"}