agent-comms 1.11.0 → 1.13.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 (82) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +1 -1
  3. package/dist/bridges/pi/index.d.ts.map +1 -1
  4. package/dist/bridges/pi/index.js +29 -1
  5. package/dist/bridges/pi/index.js.map +1 -1
  6. package/dist/bridges/user/web/build.d.ts +12 -0
  7. package/dist/bridges/user/web/build.d.ts.map +1 -0
  8. package/dist/bridges/user/web/build.js +83 -0
  9. package/dist/bridges/user/web/build.js.map +1 -0
  10. package/dist/bridges/user/web/frontend/api.d.ts +29 -0
  11. package/dist/bridges/user/web/frontend/api.d.ts.map +1 -0
  12. package/dist/bridges/user/web/frontend/api.js +121 -0
  13. package/dist/bridges/user/web/frontend/api.js.map +1 -0
  14. package/dist/bridges/user/web/frontend/dom.d.ts +38 -0
  15. package/dist/bridges/user/web/frontend/dom.d.ts.map +1 -0
  16. package/dist/bridges/user/web/frontend/dom.js +71 -0
  17. package/dist/bridges/user/web/frontend/dom.js.map +1 -0
  18. package/dist/bridges/user/web/frontend/input.d.ts +22 -0
  19. package/dist/bridges/user/web/frontend/input.d.ts.map +1 -0
  20. package/dist/bridges/user/web/frontend/input.js +129 -0
  21. package/dist/bridges/user/web/frontend/input.js.map +1 -0
  22. package/dist/bridges/user/web/frontend/main.d.ts +8 -0
  23. package/dist/bridges/user/web/frontend/main.d.ts.map +1 -0
  24. package/dist/bridges/user/web/frontend/main.js +141 -0
  25. package/dist/bridges/user/web/frontend/main.js.map +1 -0
  26. package/dist/bridges/user/web/frontend/render.d.ts +30 -0
  27. package/dist/bridges/user/web/frontend/render.d.ts.map +1 -0
  28. package/dist/bridges/user/web/frontend/render.js +129 -0
  29. package/dist/bridges/user/web/frontend/render.js.map +1 -0
  30. package/dist/bridges/user/web/frontend/state.d.ts +34 -0
  31. package/dist/bridges/user/web/frontend/state.d.ts.map +1 -0
  32. package/dist/bridges/user/web/frontend/state.js +71 -0
  33. package/dist/bridges/user/web/frontend/state.js.map +1 -0
  34. package/dist/bridges/user/web/frontend/test/dom.unit.test.d.ts +5 -0
  35. package/dist/bridges/user/web/frontend/test/dom.unit.test.d.ts.map +1 -0
  36. package/dist/bridges/user/web/frontend/test/dom.unit.test.js +149 -0
  37. package/dist/bridges/user/web/frontend/test/dom.unit.test.js.map +1 -0
  38. package/dist/bridges/user/web/frontend/test/input.unit.test.d.ts +5 -0
  39. package/dist/bridges/user/web/frontend/test/input.unit.test.d.ts.map +1 -0
  40. package/dist/bridges/user/web/frontend/test/input.unit.test.js +131 -0
  41. package/dist/bridges/user/web/frontend/test/input.unit.test.js.map +1 -0
  42. package/dist/bridges/user/web/frontend/test/render.unit.test.d.ts +5 -0
  43. package/dist/bridges/user/web/frontend/test/render.unit.test.d.ts.map +1 -0
  44. package/dist/bridges/user/web/frontend/test/render.unit.test.js +436 -0
  45. package/dist/bridges/user/web/frontend/test/render.unit.test.js.map +1 -0
  46. package/dist/bridges/user/web/frontend/test/state.unit.test.d.ts +5 -0
  47. package/dist/bridges/user/web/frontend/test/state.unit.test.d.ts.map +1 -0
  48. package/dist/bridges/user/web/frontend/test/state.unit.test.js +119 -0
  49. package/dist/bridges/user/web/frontend/test/state.unit.test.js.map +1 -0
  50. package/dist/bridges/user/web/frontend/types.d.ts +157 -0
  51. package/dist/bridges/user/web/frontend/types.d.ts.map +1 -0
  52. package/dist/bridges/user/web/frontend/types.js +8 -0
  53. package/dist/bridges/user/web/frontend/types.js.map +1 -0
  54. package/dist/bridges/user/web/generated-html.d.ts +6 -0
  55. package/dist/bridges/user/web/generated-html.d.ts.map +1 -0
  56. package/dist/bridges/user/web/generated-html.js +179 -0
  57. package/dist/bridges/user/web/generated-html.js.map +1 -0
  58. package/dist/bridges/user/web/server.js +1 -1
  59. package/dist/bridges/user/web/server.js.map +1 -1
  60. package/dist/test/{coordinator-socket-error.test.d.ts → coordinator-socket-error.integration.test.d.ts} +1 -1
  61. package/dist/test/coordinator-socket-error.integration.test.d.ts.map +1 -0
  62. package/dist/test/{coordinator-socket-error.test.js → coordinator-socket-error.integration.test.js} +1 -1
  63. package/dist/test/coordinator-socket-error.integration.test.js.map +1 -0
  64. package/dist/test/{mesh-e2e.test.d.ts → mesh-e2e.integration.test.d.ts} +1 -1
  65. package/dist/test/mesh-e2e.integration.test.d.ts.map +1 -0
  66. package/dist/test/{mesh-e2e.test.js → mesh-e2e.integration.test.js} +1 -1
  67. package/dist/test/mesh-e2e.integration.test.js.map +1 -0
  68. package/dist/test/{mesh-smoke.test.d.ts → mesh-smoke.integration.test.d.ts} +1 -1
  69. package/dist/test/mesh-smoke.integration.test.d.ts.map +1 -0
  70. package/dist/test/{mesh-smoke.test.js → mesh-smoke.integration.test.js} +1 -1
  71. package/dist/test/mesh-smoke.integration.test.js.map +1 -0
  72. package/package.json +12 -2
  73. package/dist/bridges/user/web/index.html.d.ts +0 -8
  74. package/dist/bridges/user/web/index.html.d.ts.map +0 -1
  75. package/dist/bridges/user/web/index.html.js +0 -391
  76. package/dist/bridges/user/web/index.html.js.map +0 -1
  77. package/dist/test/coordinator-socket-error.test.d.ts.map +0 -1
  78. package/dist/test/coordinator-socket-error.test.js.map +0 -1
  79. package/dist/test/mesh-e2e.test.d.ts.map +0 -1
  80. package/dist/test/mesh-e2e.test.js.map +0 -1
  81. package/dist/test/mesh-smoke.test.d.ts.map +0 -1
  82. package/dist/test/mesh-smoke.test.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-comms",
3
3
  "description": "Cross-harness LLM agent communication mesh — rooms, DMs, and presence",
4
- "version": "1.11.0",
4
+ "version": "1.13.0",
5
5
  "author": {
6
6
  "name": "ExaDev"
7
7
  },
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/agent-comms)
4
4
  [![npm](https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white)](https://www.npmjs.com/package/agent-comms)
5
- [![version](https://img.shields.io/badge/version-1.11.0-blue)](https://github.com/ExaDev/agent-comms/releases/tag/v1.11.0)
5
+ [![version](https://img.shields.io/badge/version-1.13.0-blue)](https://github.com/ExaDev/agent-comms/releases/tag/v1.13.0)
6
6
  [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/agent-comms/ci.yml?branch=main)](https://github.com/ExaDev/agent-comms/actions)
7
7
 
8
8
  Cross-harness communication mesh for LLM agents: rooms, DMs, presence, and visibility over TCP with zero filesystem dependencies.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bridges/pi/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAclE,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,QAgKxC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bridges/pi/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAoBlE,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,QAwLxC"}
@@ -11,6 +11,11 @@ import { StringEnum } from "@mariozechner/pi-ai";
11
11
  import { MeshStore, CommsTool, buildAction, ensureRegistered, formatDeliveryEvent, } from "../../core/index.js";
12
12
  import { tryStartWebServer } from "../user/web/server.js";
13
13
  import { nanoid } from "../../core/nanoid.js";
14
+ /** Resolve the listening port from a running web server handle. */
15
+ function getWebPort(handle) {
16
+ const addr = handle.server.address();
17
+ return typeof addr === "object" && addr ? addr.port : undefined;
18
+ }
14
19
  export default function (pi) {
15
20
  const store = new MeshStore();
16
21
  const tool = new CommsTool(store);
@@ -62,7 +67,7 @@ export default function (pi) {
62
67
  description: [
63
68
  "Cross-harness agent communication mesh. Send messages to rooms and DM other agents.",
64
69
  "Actions: register, update, whoami, create_room, list_rooms, join_room, leave_room,",
65
- "send, dm, list_agents, read_room, invite, decline_invite, kick, destroy_room.",
70
+ "send, dm, list_agents, read_room, invite, decline_invite, kick, destroy_room, web_url.",
66
71
  "Register first, then join or create rooms to communicate.",
67
72
  ].join(" "),
68
73
  promptSnippet: "Communicate with other LLM agents via rooms and DMs",
@@ -86,6 +91,7 @@ export default function (pi) {
86
91
  "decline_invite",
87
92
  "kick",
88
93
  "destroy_room",
94
+ "web_url",
89
95
  ], { description: "Action to perform" }),
90
96
  name: Type.Optional(Type.String({
91
97
  description: "Agent display name (for register/update)",
@@ -114,6 +120,28 @@ export default function (pi) {
114
120
  })),
115
121
  }),
116
122
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
123
+ if (params.action === "web_url") {
124
+ if (!webHandle) {
125
+ return {
126
+ content: [{ type: "text", text: "Web UI is not running." }],
127
+ details: { action: "web_url" },
128
+ isError: true,
129
+ };
130
+ }
131
+ const port = getWebPort(webHandle);
132
+ if (!port) {
133
+ return {
134
+ content: [{ type: "text", text: "Web UI port not yet assigned." }],
135
+ details: { action: "web_url" },
136
+ isError: true,
137
+ };
138
+ }
139
+ return {
140
+ content: [{ type: "text", text: `http://127.0.0.1:${String(port)}` }],
141
+ details: { action: "web_url" },
142
+ isError: false,
143
+ };
144
+ }
117
145
  if (!agentId) {
118
146
  return {
119
147
  content: [{ type: "text", text: "Error: not registered" }],
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bridges/pi/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bridges/pi/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Build script — bundles the frontend into a single HTML string.
3
+ *
4
+ * Reads index.html, bundles main.ts with esbuild (inlining CSS),
5
+ * then generates a TypeScript file exporting FRONTEND_HTML.
6
+ *
7
+ * Output: src/bridges/user/web/generated-html.ts (committed, rebuilt on pnpm build)
8
+ *
9
+ * Usage: pnpm build:frontend
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../../src/bridges/user/web/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Build script — bundles the frontend into a single HTML string.
3
+ *
4
+ * Reads index.html, bundles main.ts with esbuild (inlining CSS),
5
+ * then generates a TypeScript file exporting FRONTEND_HTML.
6
+ *
7
+ * Output: src/bridges/user/web/generated-html.ts (committed, rebuilt on pnpm build)
8
+ *
9
+ * Usage: pnpm build:frontend
10
+ */
11
+ import * as esbuild from "esbuild";
12
+ import * as fs from "node:fs";
13
+ import * as path from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
+ const FRONTEND_DIR = path.join(__dirname, "frontend");
17
+ const OUT_PATH = path.join(__dirname, "generated-html.ts");
18
+ /**
19
+ * esbuild plugin to inline CSS as a side-effect import.
20
+ * Replaces `import "./styles.css"` with a <style> injection at runtime.
21
+ */
22
+ const inlineCssPlugin = {
23
+ name: "inline-css",
24
+ setup(build) {
25
+ build.onResolve({ filter: /\.css$/ }, (args) => {
26
+ return {
27
+ path: path.resolve(args.resolveDir, args.path),
28
+ namespace: "inline-css",
29
+ };
30
+ });
31
+ build.onLoad({ filter: /.*/, namespace: "inline-css" }, async (args) => {
32
+ const css = await fs.promises.readFile(args.path, "utf8");
33
+ const escaped = JSON.stringify(css);
34
+ return {
35
+ contents: `document.head.appendChild(Object.assign(document.createElement("style"), { textContent: ${escaped} }));`,
36
+ loader: "js",
37
+ };
38
+ });
39
+ },
40
+ };
41
+ async function main() {
42
+ // Bundle JS + CSS
43
+ const result = await esbuild.build({
44
+ entryPoints: [path.join(FRONTEND_DIR, "main.ts")],
45
+ bundle: true,
46
+ minify: true,
47
+ target: "es2020",
48
+ format: "iife",
49
+ write: false,
50
+ plugins: [inlineCssPlugin],
51
+ });
52
+ const files = result.outputFiles;
53
+ const first = files[0];
54
+ if (!first) {
55
+ throw new Error("esbuild produced no output");
56
+ }
57
+ const jsBundle = first.text;
58
+ // Read HTML shell
59
+ const htmlPath = path.join(FRONTEND_DIR, "index.html");
60
+ const html = fs.readFileSync(htmlPath, "utf-8");
61
+ // Inject JS into HTML
62
+ const fullHtml = html.replace("</body>", ` <script>\n${jsBundle}\n </script>\n</body>`);
63
+ // Escape for TypeScript string literal
64
+ const escaped = fullHtml
65
+ .replace(/\\/g, "\\\\")
66
+ .replace(/`/g, "\\`")
67
+ .replace(/\$/g, "\\$");
68
+ // Generate TypeScript file
69
+ const output = `/**
70
+ * GENERATED FILE — do not edit.
71
+ * Rebuild with: pnpm build:frontend
72
+ */
73
+
74
+ export const FRONTEND_HTML = \`${escaped}\`;
75
+ `;
76
+ fs.writeFileSync(OUT_PATH, output, "utf-8");
77
+ console.log(`Built frontend: ${OUT_PATH}`);
78
+ }
79
+ main().catch((err) => {
80
+ console.error(err);
81
+ process.exit(1);
82
+ });
83
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../../../src/bridges/user/web/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * API client — typed REST + WebSocket communication with the comms server.
3
+ *
4
+ * REST for initial data fetches, WebSocket for real-time delivery events.
5
+ * All methods are typed against the interfaces in types.ts.
6
+ *
7
+ * JSON boundaries use runtime validation with type predicates — no assertions.
8
+ */
9
+ import type { Action, ActionResult, AgentsResponse, MessagesResponse, RoomsResponse, WsFrame } from "./types.js";
10
+ export declare function fetchAgents(): Promise<AgentsResponse>;
11
+ export declare function fetchRooms(): Promise<RoomsResponse>;
12
+ export declare function fetchRoomMessages(roomId: string, since?: string): Promise<MessagesResponse>;
13
+ export declare function postAction(action: Action): Promise<ActionResult>;
14
+ export interface WsEventHandler {
15
+ onOpen?: () => void;
16
+ onClose?: () => void;
17
+ onFrame?: (frame: WsFrame) => void;
18
+ }
19
+ export declare class CommsWs {
20
+ private ws;
21
+ private reconnectTimer;
22
+ private readonly handler;
23
+ constructor(handler: WsEventHandler);
24
+ connect(): void;
25
+ sendAction(action: Action): void;
26
+ disconnect(): void;
27
+ private scheduleReconnect;
28
+ }
29
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/api.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,OAAO,EACR,MAAM,YAAY,CAAC;AAqCpB,wBAAsB,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC,CAK3D;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAKzD;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC,CAQ3B;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAStE;AAMD,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED,qBAAa,OAAO;IAClB,OAAO,CAAC,EAAE,CAAwB;IAClC,OAAO,CAAC,cAAc,CAA4C;IAClE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;gBAE7B,OAAO,EAAE,cAAc;IAInC,OAAO,IAAI,IAAI;IA2Bf,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOhC,UAAU,IAAI,IAAI;IAYlB,OAAO,CAAC,iBAAiB;CAK1B"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * API client — typed REST + WebSocket communication with the comms server.
3
+ *
4
+ * REST for initial data fetches, WebSocket for real-time delivery events.
5
+ * All methods are typed against the interfaces in types.ts.
6
+ *
7
+ * JSON boundaries use runtime validation with type predicates — no assertions.
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // Runtime type validators (no Zod in browser bundle)
11
+ // ---------------------------------------------------------------------------
12
+ function isObject(value) {
13
+ return typeof value === "object" && value !== null;
14
+ }
15
+ function isAgentsResponse(value) {
16
+ return Array.isArray(value);
17
+ }
18
+ function isRoomsResponse(value) {
19
+ return Array.isArray(value);
20
+ }
21
+ function isMessagesResponse(value) {
22
+ return Array.isArray(value);
23
+ }
24
+ function isActionResult(value) {
25
+ if (!isObject(value))
26
+ return false;
27
+ return (typeof value.content === "string" && typeof value.isError === "boolean");
28
+ }
29
+ function isWsFrame(value) {
30
+ return isObject(value) && typeof value.type === "string";
31
+ }
32
+ // ---------------------------------------------------------------------------
33
+ // REST client
34
+ // ---------------------------------------------------------------------------
35
+ export async function fetchAgents() {
36
+ const res = await fetch("/api/agents");
37
+ const body = await res.json();
38
+ if (!isAgentsResponse(body))
39
+ throw new Error("Invalid agents response");
40
+ return body;
41
+ }
42
+ export async function fetchRooms() {
43
+ const res = await fetch("/api/rooms");
44
+ const body = await res.json();
45
+ if (!isRoomsResponse(body))
46
+ throw new Error("Invalid rooms response");
47
+ return body;
48
+ }
49
+ export async function fetchRoomMessages(roomId, since) {
50
+ const url = since
51
+ ? `/api/rooms/${encodeURIComponent(roomId)}/messages?since=${encodeURIComponent(since)}`
52
+ : `/api/rooms/${encodeURIComponent(roomId)}/messages`;
53
+ const res = await fetch(url);
54
+ const body = await res.json();
55
+ if (!isMessagesResponse(body))
56
+ throw new Error("Invalid messages response");
57
+ return body;
58
+ }
59
+ export async function postAction(action) {
60
+ const res = await fetch("/api/action", {
61
+ method: "POST",
62
+ headers: { "Content-Type": "application/json" },
63
+ body: JSON.stringify(action),
64
+ });
65
+ const body = await res.json();
66
+ if (!isActionResult(body))
67
+ throw new Error("Invalid action result");
68
+ return body;
69
+ }
70
+ export class CommsWs {
71
+ ws;
72
+ reconnectTimer;
73
+ handler;
74
+ constructor(handler) {
75
+ this.handler = handler;
76
+ }
77
+ connect() {
78
+ const proto = location.protocol === "https:" ? "wss:" : "ws:";
79
+ const ws = new WebSocket(`${proto}//${location.host}`);
80
+ this.ws = ws;
81
+ ws.onopen = () => {
82
+ this.handler.onOpen?.();
83
+ };
84
+ ws.onclose = () => {
85
+ this.handler.onClose?.();
86
+ this.scheduleReconnect();
87
+ };
88
+ ws.onerror = () => {
89
+ // onclose will fire after this
90
+ };
91
+ ws.onmessage = (e) => {
92
+ const raw = JSON.parse(typeof e.data === "string" ? e.data : String(e.data));
93
+ if (!isWsFrame(raw))
94
+ return;
95
+ this.handler.onFrame?.(raw);
96
+ };
97
+ }
98
+ sendAction(action) {
99
+ const ws = this.ws;
100
+ if (ws?.readyState === WebSocket.OPEN) {
101
+ ws.send(JSON.stringify(action));
102
+ }
103
+ }
104
+ disconnect() {
105
+ if (this.reconnectTimer !== undefined) {
106
+ clearTimeout(this.reconnectTimer);
107
+ this.reconnectTimer = undefined;
108
+ }
109
+ const ws = this.ws;
110
+ if (ws) {
111
+ ws.close();
112
+ }
113
+ this.ws = undefined;
114
+ }
115
+ scheduleReconnect() {
116
+ this.reconnectTimer = setTimeout(() => {
117
+ this.connect();
118
+ }, 3000);
119
+ }
120
+ }
121
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Minimal DOM helpers — no framework, just typed wrappers.
3
+ *
4
+ * All functions take a Document parameter for testability (jsdom/happy-dom).
5
+ * In the browser, pass the global `document`.
6
+ */
7
+ /**
8
+ * Query selector scoped to a root element.
9
+ * Returns `undefined` if not found (not null).
10
+ */
11
+ export declare function querySelector(root: ParentNode, selector: string): HTMLElement | undefined;
12
+ /**
13
+ * Query selector that throws if the element is missing.
14
+ * Use for elements that must exist in the HTML shell.
15
+ */
16
+ export declare function requireElement(root: ParentNode, selector: string): HTMLElement;
17
+ export declare function requireElement<K extends keyof HTMLElementTagNameMap>(root: ParentNode, selector: string, tag: K): HTMLElementTagNameMap[K];
18
+ /**
19
+ * HTML-escape a string for safe insertion via textContent→innerHTML round-trip.
20
+ */
21
+ export declare function escapeHtml(doc: Document, text: string): string;
22
+ /**
23
+ * Create an HTML element with optional attributes and children.
24
+ */
25
+ export declare function createElement<K extends keyof HTMLElementTagNameMap>(doc: Document, tag: K, attrs?: Record<string, string>, ...children: (string | Node)[]): HTMLElementTagNameMap[K];
26
+ /**
27
+ * Remove all children from an element.
28
+ */
29
+ export declare function clearChildren(el: HTMLElement): void;
30
+ /**
31
+ * Append a child and return the parent for chaining.
32
+ */
33
+ export declare function appendTo(parent: HTMLElement, child: Node): HTMLElement;
34
+ /**
35
+ * Format an ISO timestamp to HH:MM:SS for display.
36
+ */
37
+ export declare function formatTime(timestamp: string): string;
38
+ //# sourceMappingURL=dom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/dom.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,GACf,WAAW,GAAG,SAAS,CAGzB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC;AAChF,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,qBAAqB,EAClE,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,CAAC,GACL,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAgB5B;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACjE,GAAG,EAAE,QAAQ,EACb,GAAG,EAAE,CAAC,EACN,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,GAAG,QAAQ,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,GAC7B,qBAAqB,CAAC,CAAC,CAAC,CAe1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,CAEnD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,GAAG,WAAW,CAGtE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Minimal DOM helpers — no framework, just typed wrappers.
3
+ *
4
+ * All functions take a Document parameter for testability (jsdom/happy-dom).
5
+ * In the browser, pass the global `document`.
6
+ */
7
+ /**
8
+ * Query selector scoped to a root element.
9
+ * Returns `undefined` if not found (not null).
10
+ */
11
+ export function querySelector(root, selector) {
12
+ const el = root.querySelector(selector);
13
+ return el ?? undefined;
14
+ }
15
+ export function requireElement(root, selector, tag) {
16
+ const el = root.querySelector(selector);
17
+ if (!el)
18
+ throw new Error(`Required element not found: ${selector}`);
19
+ if (tag && el.tagName.toLowerCase() !== tag) {
20
+ throw new Error(`Element ${selector} must be <${tag}>, got <${el.tagName.toLowerCase()}>`);
21
+ }
22
+ return el;
23
+ }
24
+ /**
25
+ * HTML-escape a string for safe insertion via textContent→innerHTML round-trip.
26
+ */
27
+ export function escapeHtml(doc, text) {
28
+ const div = doc.createElement("div");
29
+ div.textContent = text;
30
+ return div.innerHTML;
31
+ }
32
+ /**
33
+ * Create an HTML element with optional attributes and children.
34
+ */
35
+ export function createElement(doc, tag, attrs, ...children) {
36
+ const el = doc.createElement(tag);
37
+ if (attrs) {
38
+ for (const [key, value] of Object.entries(attrs)) {
39
+ el.setAttribute(key, value);
40
+ }
41
+ }
42
+ for (const child of children) {
43
+ if (typeof child === "string") {
44
+ el.appendChild(doc.createTextNode(child));
45
+ }
46
+ else {
47
+ el.appendChild(child);
48
+ }
49
+ }
50
+ return el;
51
+ }
52
+ /**
53
+ * Remove all children from an element.
54
+ */
55
+ export function clearChildren(el) {
56
+ el.innerHTML = "";
57
+ }
58
+ /**
59
+ * Append a child and return the parent for chaining.
60
+ */
61
+ export function appendTo(parent, child) {
62
+ parent.appendChild(child);
63
+ return parent;
64
+ }
65
+ /**
66
+ * Format an ISO timestamp to HH:MM:SS for display.
67
+ */
68
+ export function formatTime(timestamp) {
69
+ return timestamp.slice(11, 19);
70
+ }
71
+ //# sourceMappingURL=dom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/dom.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAgB,EAChB,QAAgB;IAEhB,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAc,QAAQ,CAAC,CAAC;IACrD,OAAO,EAAE,IAAI,SAAS,CAAC;AACzB,CAAC;AAYD,MAAM,UAAU,cAAc,CAC5B,IAAgB,EAChB,QAAgB,EAChB,GAAY;IAEZ,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAc,QAAQ,CAAC,CAAC;IACrD,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,EAAE,CAAC,CAAC;IACpE,IAAI,GAAG,IAAI,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,WAAW,QAAQ,aAAa,GAAG,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAC1E,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,GAAa,EAAE,IAAY;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACrC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC;IACvB,OAAO,GAAG,CAAC,SAAS,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAa,EACb,GAAM,EACN,KAA8B,EAC9B,GAAG,QAA2B;IAE9B,MAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,EAAe;IAC3C,EAAE,CAAC,SAAS,GAAG,EAAE,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAmB,EAAE,KAAW;IACvD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,OAAO,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,22 @@
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
+ import type { Action } from "./types.js";
8
+ export interface LocalResult {
9
+ type: "help" | "unknown" | "error";
10
+ text: string;
11
+ }
12
+ export type InputResult = {
13
+ kind: "action";
14
+ action: Action;
15
+ } | {
16
+ kind: "local";
17
+ result: LocalResult;
18
+ } | {
19
+ kind: "ignored";
20
+ };
21
+ export declare function parseInput(text: string, currentRoom: string | undefined, dmTarget?: string): InputResult;
22
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/input.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAMzC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAMxB,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,QAAQ,CAAC,EAAE,MAAM,GAChB,WAAW,CA6Bb"}
@@ -0,0 +1,129 @@
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
+ // Parser
9
+ // ---------------------------------------------------------------------------
10
+ export function parseInput(text, currentRoom, dmTarget) {
11
+ const trimmed = text.trim();
12
+ if (trimmed.length === 0)
13
+ return { kind: "ignored" };
14
+ if (trimmed.startsWith("/")) {
15
+ return parseCommand(trimmed, currentRoom);
16
+ }
17
+ if (currentRoom) {
18
+ return {
19
+ kind: "action",
20
+ action: { action: "send", target: currentRoom, content: trimmed },
21
+ };
22
+ }
23
+ if (dmTarget) {
24
+ return {
25
+ kind: "action",
26
+ action: { action: "dm", target: dmTarget, content: trimmed },
27
+ };
28
+ }
29
+ return {
30
+ kind: "local",
31
+ result: {
32
+ type: "error",
33
+ text: "Join a room or select an agent first",
34
+ },
35
+ };
36
+ }
37
+ function parseCommand(text, currentRoom) {
38
+ const parts = text.slice(1).split(/\s+/);
39
+ const cmd = (parts[0] ?? "").toLowerCase();
40
+ switch (cmd) {
41
+ case "join":
42
+ if (!parts[1]) {
43
+ return {
44
+ kind: "local",
45
+ result: { type: "error", text: "Usage: /join <room>" },
46
+ };
47
+ }
48
+ return {
49
+ kind: "action",
50
+ action: { action: "join_room", room: parts[1] },
51
+ };
52
+ case "leave":
53
+ return {
54
+ kind: "action",
55
+ action: {
56
+ action: "leave_room",
57
+ room: parts[1] ?? currentRoom ?? "",
58
+ },
59
+ };
60
+ case "rooms":
61
+ return {
62
+ kind: "action",
63
+ action: { action: "list_rooms" },
64
+ };
65
+ case "agents":
66
+ return {
67
+ kind: "action",
68
+ action: { action: "list_agents" },
69
+ };
70
+ case "dm":
71
+ if (!parts[1] || !parts[2]) {
72
+ return {
73
+ kind: "local",
74
+ result: {
75
+ type: "error",
76
+ text: "Usage: /dm <agent> <message>",
77
+ },
78
+ };
79
+ }
80
+ return {
81
+ kind: "action",
82
+ action: {
83
+ action: "dm",
84
+ target: parts[1],
85
+ content: parts.slice(2).join(" "),
86
+ },
87
+ };
88
+ case "create":
89
+ if (!parts[1]) {
90
+ return {
91
+ kind: "local",
92
+ result: { type: "error", text: "Usage: /create <name>" },
93
+ };
94
+ }
95
+ return {
96
+ kind: "action",
97
+ action: {
98
+ action: "create_room",
99
+ name: parts[1],
100
+ type: "public",
101
+ },
102
+ };
103
+ case "destroy":
104
+ if (!parts[1]) {
105
+ return {
106
+ kind: "local",
107
+ result: { type: "error", text: "Usage: /destroy <room>" },
108
+ };
109
+ }
110
+ return {
111
+ kind: "action",
112
+ action: { action: "destroy_room", room: parts[1] },
113
+ };
114
+ case "help":
115
+ return {
116
+ kind: "local",
117
+ result: {
118
+ type: "help",
119
+ text: "Commands: /join, /leave, /rooms, /agents, /dm, /create, /destroy, /help",
120
+ },
121
+ };
122
+ default:
123
+ return {
124
+ kind: "local",
125
+ result: { type: "unknown", text: `Unknown command: /${cmd}` },
126
+ };
127
+ }
128
+ }
129
+ //# sourceMappingURL=input.js.map