agentchannel 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/web.js CHANGED
@@ -1,160 +1,168 @@
1
1
  import { createServer } from "node:http";
2
+ import mqtt from "mqtt";
3
+ import { deriveKey, hashRoom, decrypt } from "./crypto.js";
4
+ const MAX_HISTORY = 200;
5
+ const CSS = `*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
6
+ :root{--bg-primary:#1a1a2e;--bg-secondary:#16213e;--bg-hover:#1f2b47;--text-primary:#e0e0e0;--text-secondary:#8892a4;--text-muted:#565f73;--mention-bg:rgba(88,133,240,0.15);--mention-text:#7cacf8;--mention-border:rgba(88,133,240,0.3);--system-text:#565f73;--channel-bg:rgba(77,186,135,0.12);--channel-text:#4dba87;--channel-border:rgba(77,186,135,0.25);--divider:rgba(255,255,255,0.06);--font-sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;--radius-sm:4px;--radius-lg:12px}
7
+ html{font-size:15px;-webkit-font-smoothing:antialiased}
8
+ body{font-family:var(--font-sans);background:var(--bg-primary);color:var(--text-primary);line-height:1.6;min-height:100vh}
9
+ .chat-container{max-width:820px;margin:0 auto;display:flex;flex-direction:column;min-height:100vh}
10
+ .chat-header{padding:20px 20px 16px;border-bottom:1px solid var(--divider);display:flex;align-items:baseline;gap:12px;position:sticky;top:0;background:var(--bg-primary);z-index:10}
11
+ .chat-title{font-size:1.15rem;font-weight:700;letter-spacing:-0.01em}
12
+ .chat-status{font-size:0.8rem;color:var(--text-muted)}
13
+ .chat-status.connected{color:#4ade80}
14
+ .message-list{padding:8px 0;flex:1}
15
+ .message{display:flex;padding:2px 20px;transition:background-color 0.1s ease}
16
+ .message:hover{background:var(--bg-hover)}
17
+ .message__gutter{width:40px;flex-shrink:0;margin-right:12px;display:flex;align-items:flex-start;justify-content:center;padding-top:4px}
18
+ .message__avatar{width:36px;height:36px;border-radius:var(--radius-lg);background:var(--avatar-color,#7c6bf0);color:#fff;font-weight:700;font-size:0.85rem;display:flex;align-items:center;justify-content:center;user-select:none}
19
+ .message__body{flex:1;min-width:0}
20
+ .message--first{padding-top:10px;margin-top:4px}
21
+ .message--first+.message--first{border-top:1px solid var(--divider)}
22
+ .message--system+.message--first,.message--first:first-child{border-top:none}
23
+ .message__header{display:flex;align-items:baseline;gap:8px;margin-bottom:2px;flex-wrap:wrap}
24
+ .message__sender{font-weight:700;font-size:0.935rem;color:var(--sender-color,#7c6bf0)}
25
+ .message__channel{display:inline-block;font-size:0.72rem;font-weight:600;padding:1px 7px;border-radius:9999px;background:var(--channel-bg);color:var(--channel-text);border:1px solid var(--channel-border);white-space:nowrap}
26
+ .message__time{font-size:0.72rem;color:var(--text-muted);font-variant-numeric:tabular-nums;white-space:nowrap}
27
+ .message__time--hover{opacity:0;font-size:0.68rem;transition:opacity 0.15s ease;padding-top:4px}
28
+ .message--grouped:hover .message__time--hover{opacity:1}
29
+ .message__content{font-size:0.935rem;line-height:1.65;word-wrap:break-word}
30
+ .message--grouped{padding-top:1px;padding-bottom:1px}
31
+ .mention{display:inline;background:var(--mention-bg);color:var(--mention-text);padding:1px 5px;border-radius:var(--radius-sm);font-weight:600;font-size:0.9rem;border:1px solid var(--mention-border);white-space:nowrap}
32
+ .message--system{padding-top:6px;padding-bottom:6px}
33
+ .message--system .message__body{display:flex;align-items:center;gap:10px;padding-left:52px}
34
+ .message__system-text{font-size:0.82rem;color:var(--system-text);font-style:italic}
35
+ .message--system:hover{background:transparent}
36
+ ::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.1);border-radius:3px}
37
+ @media(max-width:600px){html{font-size:14px}.message{padding-left:12px;padding-right:12px}.message__gutter{width:32px;margin-right:10px}.message__avatar{width:30px;height:30px;font-size:0.75rem}.message--system .message__body{padding-left:42px}}`;
2
38
  const HTML = `<!DOCTYPE html>
3
- <html>
39
+ <html lang="en">
4
40
  <head>
5
41
  <meta charset="utf-8">
42
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
43
  <title>AgentChannel</title>
7
- <style>
8
- * { margin: 0; padding: 0; box-sizing: border-box; }
9
- body { font-family: -apple-system, system-ui, sans-serif; background: #1a1a2e; color: #e0e0e0; height: 100vh; display: flex; flex-direction: column; }
10
- header { padding: 12px 20px; background: #16213e; border-bottom: 1px solid #0f3460; display: flex; align-items: center; gap: 12px; }
11
- header h1 { font-size: 16px; color: #e94560; }
12
- header .status { font-size: 12px; color: #4ade80; }
13
- #messages { flex: 1; overflow-y: auto; padding: 16px 20px; }
14
- .msg { margin-bottom: 8px; line-height: 1.5; }
15
- .msg .time { color: #666; font-size: 12px; }
16
- .msg .channel { color: #e94560; }
17
- .msg .sender { color: #4ade80; font-weight: bold; }
18
- .msg .content { color: #e0e0e0; }
19
- .msg.system { color: #666; font-style: italic; }
20
- .msg.mention { background: #2a2a4a; border-left: 3px solid #e94560; padding: 4px 8px; }
21
- #input-area { padding: 12px 20px; background: #16213e; border-top: 1px solid #0f3460; display: flex; gap: 8px; }
22
- #channel-select { background: #1a1a2e; color: #e94560; border: 1px solid #0f3460; padding: 8px; border-radius: 4px; }
23
- #msg-input { flex: 1; background: #1a1a2e; color: #e0e0e0; border: 1px solid #0f3460; padding: 8px 12px; border-radius: 4px; font-size: 14px; }
24
- #msg-input:focus { outline: none; border-color: #e94560; }
25
- #send-btn { background: #e94560; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; }
26
- </style>
44
+ <style>${CSS}</style>
27
45
  </head>
28
46
  <body>
29
- <header>
30
- <h1>AgentChannel</h1>
31
- <span class="status" id="status">connecting...</span>
32
- </header>
33
- <div id="messages"></div>
34
- <div id="input-area">
35
- <select id="channel-select"></select>
36
- <input id="msg-input" placeholder="Type a message..." autocomplete="off">
37
- <button id="send-btn">Send</button>
47
+ <div class="chat-container">
48
+ <header class="chat-header">
49
+ <h1 class="chat-title">AgentChannel</h1>
50
+ <span class="chat-status" id="status">connecting...</span>
51
+ </header>
52
+ <div class="message-list" id="messages"></div>
38
53
  </div>
39
54
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
40
55
  <script>
41
56
  const CONFIG = __CONFIG__;
57
+ const COLORS = ["#7c6bf0","#e06c58","#4dba87","#e0a84d","#58b4e0","#e05898","#58e0b4","#b458e0"];
58
+ const senderColors = {};
59
+ let lastSender = null;
42
60
 
43
61
  const encoder = new TextEncoder();
44
62
  const decoder = new TextDecoder();
45
63
 
46
- async function deriveKey(secret) {
47
- const keyMaterial = await crypto.subtle.importKey("raw", encoder.encode(secret), "PBKDF2", false, ["deriveKey"]);
48
- return crypto.subtle.deriveKey(
49
- { name: "PBKDF2", salt: encoder.encode("agentchannel-v1"), iterations: 100000, hash: "SHA-256" },
50
- keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]
51
- );
64
+ function getSenderColor(name) {
65
+ if (!senderColors[name]) {
66
+ const idx = Object.keys(senderColors).length % COLORS.length;
67
+ senderColors[name] = COLORS[idx];
68
+ }
69
+ return senderColors[name];
52
70
  }
53
71
 
54
- async function hashRoom(code) {
55
- const hash = await crypto.subtle.digest("SHA-256", encoder.encode(code));
56
- return Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2,"0")).join("").slice(0,16);
72
+ async function deriveKey(secret) {
73
+ const km = await crypto.subtle.importKey("raw", encoder.encode(secret), "PBKDF2", false, ["deriveKey"]);
74
+ return crypto.subtle.deriveKey({name:"PBKDF2",salt:encoder.encode("agentchannel-v1"),iterations:100000,hash:"SHA-256"},km,{name:"AES-GCM",length:256},false,["encrypt","decrypt"]);
57
75
  }
58
76
 
59
- async function encrypt(text, key) {
60
- const iv = crypto.getRandomValues(new Uint8Array(12));
61
- const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, encoder.encode(text));
62
- const buf = new Uint8Array(ct);
63
- const tag = buf.slice(-16);
64
- const data = buf.slice(0, -16);
65
- return JSON.stringify({
66
- iv: btoa(String.fromCharCode(...iv)),
67
- data: btoa(String.fromCharCode(...data)),
68
- tag: btoa(String.fromCharCode(...tag))
69
- });
77
+ async function hashRoom(code) {
78
+ const h = await crypto.subtle.digest("SHA-256", encoder.encode(code));
79
+ return Array.from(new Uint8Array(h)).map(b=>b.toString(16).padStart(2,"0")).join("").slice(0,16);
70
80
  }
71
81
 
72
82
  async function decrypt(payload, key) {
73
83
  const p = JSON.parse(payload);
74
- const iv = Uint8Array.from(atob(p.iv), c => c.charCodeAt(0));
75
- const data = Uint8Array.from(atob(p.data), c => c.charCodeAt(0));
76
- const tag = Uint8Array.from(atob(p.tag), c => c.charCodeAt(0));
77
- const combined = new Uint8Array(data.length + tag.length);
84
+ const iv = Uint8Array.from(atob(p.iv),c=>c.charCodeAt(0));
85
+ const data = Uint8Array.from(atob(p.data),c=>c.charCodeAt(0));
86
+ const tag = Uint8Array.from(atob(p.tag),c=>c.charCodeAt(0));
87
+ const combined = new Uint8Array(data.length+tag.length);
78
88
  combined.set(data); combined.set(tag, data.length);
79
- const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, combined);
89
+ const pt = await crypto.subtle.decrypt({name:"AES-GCM",iv},key,combined);
80
90
  return decoder.decode(pt);
81
91
  }
82
92
 
93
+ const msgsEl = document.getElementById("messages");
94
+ const statusEl = document.getElementById("status");
95
+
96
+ function escapeHtml(s) { return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"); }
97
+
98
+ function highlightMentions(text) {
99
+ return escapeHtml(text).replace(/@(\\w+)/g, '<span class="mention">@$1</span>');
100
+ }
101
+
102
+ function addMessage(channel, msg) {
103
+ if (msg.type === "system") {
104
+ const div = document.createElement("div");
105
+ div.className = "message message--system";
106
+ const time = new Date(msg.timestamp).toLocaleTimeString([], {hour:"2-digit",minute:"2-digit"});
107
+ div.innerHTML = '<div class="message__body"><time class="message__time">'+time+'</time><span class="message__system-text">'+escapeHtml(msg.content)+'</span></div>';
108
+ msgsEl.appendChild(div);
109
+ lastSender = null;
110
+ } else {
111
+ const isGrouped = lastSender === msg.sender;
112
+ const color = getSenderColor(msg.sender);
113
+ const time = new Date(msg.timestamp).toLocaleTimeString([], {hour:"2-digit",minute:"2-digit"});
114
+ const div = document.createElement("div");
115
+
116
+ if (isGrouped) {
117
+ div.className = "message message--grouped";
118
+ div.innerHTML = '<div class="message__gutter"><time class="message__time message__time--hover">'+time+'</time></div><div class="message__body"><div class="message__content">'+highlightMentions(msg.content)+'</div></div>';
119
+ } else {
120
+ div.className = "message message--first";
121
+ div.innerHTML = '<div class="message__gutter"><div class="message__avatar" style="--avatar-color:'+color+'">'+msg.sender[0].toUpperCase()+'</div></div><div class="message__body"><div class="message__header"><span class="message__sender" style="--sender-color:'+color+'">@'+escapeHtml(msg.sender)+'</span><span class="message__channel">#'+escapeHtml(channel)+'</span><time class="message__time">'+time+'</time></div><div class="message__content">'+highlightMentions(msg.content)+'</div></div>';
122
+ }
123
+ msgsEl.appendChild(div);
124
+ lastSender = msg.sender;
125
+ }
126
+ msgsEl.scrollTop = msgsEl.scrollHeight;
127
+ }
128
+
83
129
  async function init() {
130
+ // Load history
131
+ try {
132
+ const res = await fetch("/api/history");
133
+ const history = await res.json();
134
+ for (const msg of history) addMessage(msg.channel, msg);
135
+ } catch(e) {}
136
+
84
137
  const channels = {};
85
138
  for (const ch of CONFIG.channels) {
86
- channels[ch.channel] = { key: await deriveKey(ch.key), hash: await hashRoom(ch.key), name: ch.channel };
87
- }
88
-
89
- // Populate channel selector
90
- const sel = document.getElementById("channel-select");
91
- for (const name of Object.keys(channels)) {
92
- const opt = document.createElement("option");
93
- opt.value = name; opt.textContent = "#" + name;
94
- sel.appendChild(opt);
139
+ channels[ch.channel] = {key: await deriveKey(ch.key), hash: await hashRoom(ch.key), name: ch.channel};
95
140
  }
96
141
 
97
142
  const client = mqtt.connect("wss://broker.emqx.io:8084/mqtt");
98
- const statusEl = document.getElementById("status");
99
- const msgsEl = document.getElementById("messages");
100
-
101
143
  client.on("connect", () => {
102
144
  statusEl.textContent = "connected";
103
- for (const ch of Object.values(channels)) {
104
- client.subscribe("agentchannel/" + ch.hash + "/messages");
105
- }
145
+ statusEl.className = "chat-status connected";
146
+ for (const ch of Object.values(channels)) client.subscribe("agentchannel/"+ch.hash+"/messages");
106
147
  });
107
-
108
- client.on("close", () => { statusEl.textContent = "disconnected"; });
148
+ client.on("close", () => { statusEl.textContent = "disconnected"; statusEl.className = "chat-status"; });
109
149
 
110
150
  if (Notification.permission === "default") Notification.requestPermission();
111
151
 
112
152
  client.on("message", async (topic, payload) => {
113
153
  for (const ch of Object.values(channels)) {
114
- if (topic === "agentchannel/" + ch.hash + "/messages") {
154
+ if (topic === "agentchannel/"+ch.hash+"/messages") {
115
155
  try {
116
156
  const decrypted = await decrypt(payload.toString(), ch.key);
117
157
  const msg = JSON.parse(decrypted);
118
158
  addMessage(ch.name, msg);
119
159
  if (msg.sender !== CONFIG.name && Notification.permission === "granted") {
120
- new Notification("AgentChannel #" + ch.name, { body: "@" + msg.sender + ": " + msg.content });
160
+ new Notification("AgentChannel #"+ch.name, {body:"@"+msg.sender+": "+msg.content});
121
161
  }
122
162
  } catch(e) {}
123
163
  }
124
164
  }
125
165
  });
126
-
127
- // Send
128
- async function sendMsg() {
129
- const input = document.getElementById("msg-input");
130
- const text = input.value.trim();
131
- if (!text) return;
132
- const chName = sel.value;
133
- const ch = channels[chName];
134
- const msg = { id: Math.random().toString(16).slice(2), channel: chName, sender: CONFIG.name, content: text, timestamp: Date.now(), type: "chat" };
135
- const encrypted = await encrypt(JSON.stringify(msg), ch.key);
136
- client.publish("agentchannel/" + ch.hash + "/messages", encrypted);
137
- input.value = "";
138
- }
139
-
140
- document.getElementById("send-btn").onclick = sendMsg;
141
- document.getElementById("msg-input").onkeydown = (e) => { if (e.key === "Enter") sendMsg(); };
142
-
143
- function addMessage(channel, msg) {
144
- const div = document.createElement("div");
145
- const time = new Date(msg.timestamp).toLocaleTimeString();
146
- const isMention = msg.content.includes("@" + CONFIG.name);
147
- div.className = "msg" + (msg.type === "system" ? " system" : "") + (isMention ? " mention" : "");
148
- if (msg.type === "system") {
149
- div.innerHTML = '<span class="time">' + time + '</span> ' + msg.content;
150
- } else {
151
- div.innerHTML = '<span class="time">' + time + '</span> <span class="channel">#' + channel + '</span> <span class="sender">@' + msg.sender + '</span> <span class="content">' + escapeHtml(msg.content) + '</span>';
152
- }
153
- msgsEl.appendChild(div);
154
- msgsEl.scrollTop = msgsEl.scrollHeight;
155
- }
156
-
157
- function escapeHtml(s) { return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"); }
158
166
  }
159
167
 
160
168
  init();
@@ -162,10 +170,47 @@ init();
162
170
  </body>
163
171
  </html>`;
164
172
  export function startWebUI(config, port = 3456) {
173
+ const history = [];
174
+ const channelStates = config.channels.map((ch) => ({
175
+ channel: ch.channel,
176
+ key: deriveKey(ch.key),
177
+ hash: hashRoom(ch.key),
178
+ }));
179
+ // Server-side MQTT to collect history
180
+ const mqttClient = mqtt.connect("mqtt://broker.emqx.io:1883");
181
+ mqttClient.on("connect", () => {
182
+ for (const cs of channelStates) {
183
+ mqttClient.subscribe(`agentchannel/${cs.hash}/messages`);
184
+ }
185
+ });
186
+ mqttClient.on("message", (_topic, payload) => {
187
+ for (const cs of channelStates) {
188
+ if (_topic === `agentchannel/${cs.hash}/messages`) {
189
+ try {
190
+ const encrypted = JSON.parse(payload.toString());
191
+ const decrypted = decrypt(encrypted, cs.key);
192
+ const msg = JSON.parse(decrypted);
193
+ msg.channel = cs.channel;
194
+ history.push(msg);
195
+ if (history.length > MAX_HISTORY)
196
+ history.shift();
197
+ }
198
+ catch {
199
+ // ignore
200
+ }
201
+ }
202
+ }
203
+ });
165
204
  const html = HTML.replace("__CONFIG__", JSON.stringify(config));
166
205
  const server = createServer((req, res) => {
167
- res.writeHead(200, { "Content-Type": "text/html" });
168
- res.end(html);
206
+ if (req.url === "/api/history") {
207
+ res.writeHead(200, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" });
208
+ res.end(JSON.stringify(history));
209
+ }
210
+ else {
211
+ res.writeHead(200, { "Content-Type": "text/html" });
212
+ res.end(html);
213
+ }
169
214
  });
170
215
  server.listen(port, () => {
171
216
  console.log(`AgentChannel Web UI: http://localhost:${port}`);
package/dist/web.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAiKL,CAAC;AAET,MAAM,UAAU,UAAU,CAAC,MAAsE,EAAE,OAAe,IAAI;IACpH,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;QACpD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACvB,OAAO,CAAC,GAAG,CAAC,yCAAyC,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentchannel",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Encrypted cross-network messaging for AI coding agents via MCP",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",