@hasna/conversations 0.0.4 → 0.0.6
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/bin/index.js +300 -127
- package/bin/mcp.js +1 -1
- package/dashboard/dist/assets/index-C5hQqoWV.js +163 -0
- package/dashboard/dist/assets/index-Dr54QXlJ.css +1 -0
- package/dashboard/dist/index.html +13 -0
- package/dist/cli/components/ChatView.d.ts +4 -3
- package/dist/cli/components/SessionList.d.ts +2 -1
- package/dist/server/serve.d.ts +9 -0
- package/package.json +3 -1
package/bin/index.js
CHANGED
|
@@ -31003,7 +31003,7 @@ var init_mcp2 = __esm(() => {
|
|
|
31003
31003
|
init_channels();
|
|
31004
31004
|
server = new McpServer({
|
|
31005
31005
|
name: "conversations",
|
|
31006
|
-
version: "0.0.
|
|
31006
|
+
version: "0.0.6"
|
|
31007
31007
|
});
|
|
31008
31008
|
server.registerTool("send_message", {
|
|
31009
31009
|
title: "Send Message",
|
|
@@ -31224,6 +31224,115 @@ var init_mcp2 = __esm(() => {
|
|
|
31224
31224
|
}
|
|
31225
31225
|
});
|
|
31226
31226
|
|
|
31227
|
+
// src/server/serve.ts
|
|
31228
|
+
var exports_serve = {};
|
|
31229
|
+
__export(exports_serve, {
|
|
31230
|
+
startDashboardServer: () => startDashboardServer
|
|
31231
|
+
});
|
|
31232
|
+
import { join as join2 } from "path";
|
|
31233
|
+
import { existsSync } from "fs";
|
|
31234
|
+
function jsonResponse(data, status = 200) {
|
|
31235
|
+
return new Response(JSON.stringify(data), {
|
|
31236
|
+
status,
|
|
31237
|
+
headers: { "Content-Type": "application/json" }
|
|
31238
|
+
});
|
|
31239
|
+
}
|
|
31240
|
+
function getStatus() {
|
|
31241
|
+
const db2 = getDb();
|
|
31242
|
+
const dbPath = getDbPath();
|
|
31243
|
+
const totalMessages = db2.prepare("SELECT COUNT(*) as count FROM messages").get().count;
|
|
31244
|
+
const totalSessions = db2.prepare("SELECT COUNT(DISTINCT session_id) as count FROM messages").get().count;
|
|
31245
|
+
const totalUnread = db2.prepare("SELECT COUNT(*) as count FROM messages WHERE read_at IS NULL").get().count;
|
|
31246
|
+
const totalChannels = db2.prepare("SELECT COUNT(*) as count FROM channels").get().count;
|
|
31247
|
+
return {
|
|
31248
|
+
db_path: dbPath,
|
|
31249
|
+
total_messages: totalMessages,
|
|
31250
|
+
total_sessions: totalSessions,
|
|
31251
|
+
total_channels: totalChannels,
|
|
31252
|
+
unread_messages: totalUnread
|
|
31253
|
+
};
|
|
31254
|
+
}
|
|
31255
|
+
function startDashboardServer(port = 3456) {
|
|
31256
|
+
const dashboardDist = join2(import.meta.dir, "../../dashboard/dist");
|
|
31257
|
+
const hasDist = existsSync(dashboardDist);
|
|
31258
|
+
const server2 = Bun.serve({
|
|
31259
|
+
port,
|
|
31260
|
+
async fetch(req) {
|
|
31261
|
+
const url2 = new URL(req.url);
|
|
31262
|
+
const path = url2.pathname;
|
|
31263
|
+
if (path === "/api/status") {
|
|
31264
|
+
return jsonResponse(getStatus());
|
|
31265
|
+
}
|
|
31266
|
+
if (path === "/api/messages" && req.method === "GET") {
|
|
31267
|
+
const limit = parseInt(url2.searchParams.get("limit") || "50");
|
|
31268
|
+
const session = url2.searchParams.get("session") || undefined;
|
|
31269
|
+
const channel = url2.searchParams.get("channel") || undefined;
|
|
31270
|
+
const from = url2.searchParams.get("from") || undefined;
|
|
31271
|
+
const to = url2.searchParams.get("to") || undefined;
|
|
31272
|
+
const messages = readMessages({ session_id: session, channel, from, to, limit });
|
|
31273
|
+
return jsonResponse(messages.reverse());
|
|
31274
|
+
}
|
|
31275
|
+
if (path === "/api/messages" && req.method === "POST") {
|
|
31276
|
+
try {
|
|
31277
|
+
const text = await req.text();
|
|
31278
|
+
const body = JSON.parse(text);
|
|
31279
|
+
const msg = sendMessage({
|
|
31280
|
+
from: body.from,
|
|
31281
|
+
to: body.to,
|
|
31282
|
+
content: body.content,
|
|
31283
|
+
channel: body.channel,
|
|
31284
|
+
priority: body.priority
|
|
31285
|
+
});
|
|
31286
|
+
return jsonResponse(msg);
|
|
31287
|
+
} catch (e) {
|
|
31288
|
+
return jsonResponse({ error: e.message }, 400);
|
|
31289
|
+
}
|
|
31290
|
+
}
|
|
31291
|
+
if (path === "/api/sessions") {
|
|
31292
|
+
const agent = url2.searchParams.get("agent") || undefined;
|
|
31293
|
+
return jsonResponse(listSessions(agent));
|
|
31294
|
+
}
|
|
31295
|
+
if (path === "/api/channels" && req.method === "GET") {
|
|
31296
|
+
return jsonResponse(listChannels());
|
|
31297
|
+
}
|
|
31298
|
+
if (path === "/api/channels" && req.method === "POST") {
|
|
31299
|
+
try {
|
|
31300
|
+
const text = await req.text();
|
|
31301
|
+
const body = JSON.parse(text);
|
|
31302
|
+
const ch = createChannel(body.name, body.created_by, body.description);
|
|
31303
|
+
return jsonResponse(ch);
|
|
31304
|
+
} catch (e) {
|
|
31305
|
+
return jsonResponse({ error: e.message }, 400);
|
|
31306
|
+
}
|
|
31307
|
+
}
|
|
31308
|
+
if (hasDist) {
|
|
31309
|
+
let filePath = join2(dashboardDist, path === "/" ? "index.html" : path);
|
|
31310
|
+
let file2 = Bun.file(filePath);
|
|
31311
|
+
if (await file2.exists())
|
|
31312
|
+
return new Response(file2);
|
|
31313
|
+
file2 = Bun.file(join2(dashboardDist, "index.html"));
|
|
31314
|
+
if (await file2.exists())
|
|
31315
|
+
return new Response(file2);
|
|
31316
|
+
}
|
|
31317
|
+
return new Response("Not Found", { status: 404 });
|
|
31318
|
+
}
|
|
31319
|
+
});
|
|
31320
|
+
console.log(`Dashboard running at http://localhost:${server2.port}`);
|
|
31321
|
+
return server2;
|
|
31322
|
+
}
|
|
31323
|
+
var isDirectRun2;
|
|
31324
|
+
var init_serve = __esm(() => {
|
|
31325
|
+
init_messages();
|
|
31326
|
+
init_sessions();
|
|
31327
|
+
init_channels();
|
|
31328
|
+
init_db();
|
|
31329
|
+
isDirectRun2 = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("serve.ts") || process.argv[1]?.endsWith("serve.js");
|
|
31330
|
+
if (isDirectRun2) {
|
|
31331
|
+
const port = parseInt(process.env.PORT || "3456");
|
|
31332
|
+
startDashboardServer(port);
|
|
31333
|
+
}
|
|
31334
|
+
});
|
|
31335
|
+
|
|
31227
31336
|
// node_modules/commander/esm.mjs
|
|
31228
31337
|
var import__ = __toESM(require_commander(), 1);
|
|
31229
31338
|
var {
|
|
@@ -31247,10 +31356,10 @@ init_channels();
|
|
|
31247
31356
|
init_db();
|
|
31248
31357
|
import chalk2 from "chalk";
|
|
31249
31358
|
import { render } from "ink";
|
|
31250
|
-
import
|
|
31359
|
+
import React8 from "react";
|
|
31251
31360
|
|
|
31252
31361
|
// src/cli/components/App.tsx
|
|
31253
|
-
import { useState as
|
|
31362
|
+
import { useState as useState6 } from "react";
|
|
31254
31363
|
import { Box as Box6, Text as Text7, useApp, useInput as useInput5 } from "ink";
|
|
31255
31364
|
|
|
31256
31365
|
// node_modules/ink-text-input/build/index.js
|
|
@@ -31346,6 +31455,7 @@ function TextInput({ value: originalValue, placeholder = "", focus = true, mask,
|
|
|
31346
31455
|
var build_default = TextInput;
|
|
31347
31456
|
|
|
31348
31457
|
// src/cli/components/SessionList.tsx
|
|
31458
|
+
import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
31349
31459
|
import { Box as Box3, Text as Text4, useInput as useInput3 } from "ink";
|
|
31350
31460
|
|
|
31351
31461
|
// node_modules/ink-select-input/build/Indicator.js
|
|
@@ -31753,23 +31863,37 @@ function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicator
|
|
|
31753
31863
|
var SelectInput_default = SelectInput;
|
|
31754
31864
|
// src/cli/components/SessionList.tsx
|
|
31755
31865
|
init_sessions();
|
|
31866
|
+
init_channels();
|
|
31756
31867
|
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
31757
|
-
function SessionList({ agent, onSelect, onNew }) {
|
|
31758
|
-
const sessions = listSessions(agent);
|
|
31868
|
+
function SessionList({ agent, onSelect, onSelectChannel, onNew }) {
|
|
31869
|
+
const [sessions, setSessions] = useState3(() => listSessions(agent));
|
|
31870
|
+
const [channels, setChannels] = useState3(() => listChannels());
|
|
31871
|
+
useEffect3(() => {
|
|
31872
|
+
const timer = setInterval(() => {
|
|
31873
|
+
setSessions(listSessions(agent));
|
|
31874
|
+
setChannels(listChannels());
|
|
31875
|
+
}, 1000);
|
|
31876
|
+
return () => clearInterval(timer);
|
|
31877
|
+
}, [agent]);
|
|
31759
31878
|
useInput3((input) => {
|
|
31760
31879
|
if (input === "n")
|
|
31761
31880
|
onNew();
|
|
31762
31881
|
});
|
|
31763
|
-
const
|
|
31882
|
+
const channelItems = channels.map((ch) => ({
|
|
31883
|
+
label: `#${ch.name}${ch.description ? ` \u2014 ${ch.description}` : ""} (${ch.message_count} msgs, ${ch.member_count} members)`,
|
|
31884
|
+
value: `channel:${ch.name}`
|
|
31885
|
+
}));
|
|
31886
|
+
const dmSessions = sessions.filter((s) => !s.session_id.startsWith("channel:"));
|
|
31887
|
+
const sessionItems = dmSessions.map((s) => {
|
|
31764
31888
|
const others = s.participants.filter((p) => p !== agent).join(", ") || agent;
|
|
31765
31889
|
const unread = s.unread_count > 0 ? ` (${s.unread_count} unread)` : "";
|
|
31766
31890
|
return {
|
|
31767
31891
|
label: `${others} \u2014 ${s.message_count} msgs${unread}`,
|
|
31768
|
-
value: s.session_id
|
|
31769
|
-
session: s
|
|
31892
|
+
value: s.session_id
|
|
31770
31893
|
};
|
|
31771
31894
|
});
|
|
31772
|
-
|
|
31895
|
+
const allItems = [...channelItems, ...sessionItems];
|
|
31896
|
+
if (allItems.length === 0) {
|
|
31773
31897
|
return /* @__PURE__ */ jsxDEV(Box3, {
|
|
31774
31898
|
flexDirection: "column",
|
|
31775
31899
|
padding: 1,
|
|
@@ -31781,17 +31905,37 @@ function SessionList({ agent, onSelect, onNew }) {
|
|
|
31781
31905
|
}, undefined, false, undefined, this),
|
|
31782
31906
|
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31783
31907
|
dimColor: true,
|
|
31784
|
-
children: "No conversations yet."
|
|
31785
|
-
}, undefined, false, undefined, this),
|
|
31786
|
-
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31787
|
-
dimColor: true,
|
|
31788
31908
|
children: [
|
|
31789
|
-
"
|
|
31909
|
+
" as ",
|
|
31910
|
+
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31911
|
+
color: "yellow",
|
|
31912
|
+
children: agent
|
|
31913
|
+
}, undefined, false, undefined, this)
|
|
31914
|
+
]
|
|
31915
|
+
}, undefined, true, undefined, this),
|
|
31916
|
+
/* @__PURE__ */ jsxDEV(Box3, {
|
|
31917
|
+
marginTop: 1,
|
|
31918
|
+
children: [
|
|
31919
|
+
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31920
|
+
dimColor: true,
|
|
31921
|
+
children: "No conversations yet. Press "
|
|
31922
|
+
}, undefined, false, undefined, this),
|
|
31790
31923
|
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31791
31924
|
bold: true,
|
|
31792
31925
|
children: "n"
|
|
31793
31926
|
}, undefined, false, undefined, this),
|
|
31794
|
-
|
|
31927
|
+
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31928
|
+
dimColor: true,
|
|
31929
|
+
children: " to start one, or "
|
|
31930
|
+
}, undefined, false, undefined, this),
|
|
31931
|
+
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31932
|
+
bold: true,
|
|
31933
|
+
children: "q"
|
|
31934
|
+
}, undefined, false, undefined, this),
|
|
31935
|
+
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31936
|
+
dimColor: true,
|
|
31937
|
+
children: " to quit."
|
|
31938
|
+
}, undefined, false, undefined, this)
|
|
31795
31939
|
]
|
|
31796
31940
|
}, undefined, true, undefined, this)
|
|
31797
31941
|
]
|
|
@@ -31803,6 +31947,7 @@ function SessionList({ agent, onSelect, onNew }) {
|
|
|
31803
31947
|
children: [
|
|
31804
31948
|
/* @__PURE__ */ jsxDEV(Box3, {
|
|
31805
31949
|
marginBottom: 1,
|
|
31950
|
+
flexDirection: "column",
|
|
31806
31951
|
children: [
|
|
31807
31952
|
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31808
31953
|
bold: true,
|
|
@@ -31811,16 +31956,27 @@ function SessionList({ agent, onSelect, onNew }) {
|
|
|
31811
31956
|
}, undefined, false, undefined, this),
|
|
31812
31957
|
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31813
31958
|
dimColor: true,
|
|
31814
|
-
children:
|
|
31815
|
-
|
|
31959
|
+
children: [
|
|
31960
|
+
" as ",
|
|
31961
|
+
/* @__PURE__ */ jsxDEV(Text4, {
|
|
31962
|
+
color: "yellow",
|
|
31963
|
+
children: agent
|
|
31964
|
+
}, undefined, false, undefined, this),
|
|
31965
|
+
" (n: new, q: quit)"
|
|
31966
|
+
]
|
|
31967
|
+
}, undefined, true, undefined, this)
|
|
31816
31968
|
]
|
|
31817
31969
|
}, undefined, true, undefined, this),
|
|
31818
31970
|
/* @__PURE__ */ jsxDEV(SelectInput_default, {
|
|
31819
|
-
items,
|
|
31971
|
+
items: allItems,
|
|
31820
31972
|
onSelect: (item) => {
|
|
31821
|
-
|
|
31822
|
-
|
|
31823
|
-
|
|
31973
|
+
if (item.value.startsWith("channel:")) {
|
|
31974
|
+
onSelectChannel(item.value.slice(8));
|
|
31975
|
+
} else {
|
|
31976
|
+
const session = dmSessions.find((s) => s.session_id === item.value);
|
|
31977
|
+
if (session)
|
|
31978
|
+
onSelect(session);
|
|
31979
|
+
}
|
|
31824
31980
|
}
|
|
31825
31981
|
}, undefined, false, undefined, this)
|
|
31826
31982
|
]
|
|
@@ -31828,12 +31984,13 @@ function SessionList({ agent, onSelect, onNew }) {
|
|
|
31828
31984
|
}
|
|
31829
31985
|
|
|
31830
31986
|
// src/cli/components/ChatView.tsx
|
|
31831
|
-
import
|
|
31987
|
+
import { useState as useState5, useEffect as useEffect5 } from "react";
|
|
31832
31988
|
import { Box as Box5, Text as Text6, useInput as useInput4 } from "ink";
|
|
31989
|
+
init_messages();
|
|
31833
31990
|
|
|
31834
31991
|
// src/lib/poll.ts
|
|
31835
31992
|
init_messages();
|
|
31836
|
-
import { useState as
|
|
31993
|
+
import { useState as useState4, useEffect as useEffect4, useRef as useRef2 } from "react";
|
|
31837
31994
|
function startPolling(opts) {
|
|
31838
31995
|
const interval = opts.interval_ms ?? 200;
|
|
31839
31996
|
let lastSeen = new Date().toISOString();
|
|
@@ -31860,95 +32017,78 @@ function startPolling(opts) {
|
|
|
31860
32017
|
}
|
|
31861
32018
|
};
|
|
31862
32019
|
}
|
|
31863
|
-
function useMessages(sessionId, agent) {
|
|
31864
|
-
const [messages, setMessages] = useState3([]);
|
|
31865
|
-
const initialLoad = useRef2(false);
|
|
31866
|
-
useEffect3(() => {
|
|
31867
|
-
if (!initialLoad.current) {
|
|
31868
|
-
const existing = readMessages({ session_id: sessionId });
|
|
31869
|
-
setMessages(existing);
|
|
31870
|
-
initialLoad.current = true;
|
|
31871
|
-
}
|
|
31872
|
-
const { stop } = startPolling({
|
|
31873
|
-
session_id: sessionId,
|
|
31874
|
-
interval_ms: 200,
|
|
31875
|
-
on_messages: (newMessages) => {
|
|
31876
|
-
setMessages((prev) => [...prev, ...newMessages]);
|
|
31877
|
-
}
|
|
31878
|
-
});
|
|
31879
|
-
return stop;
|
|
31880
|
-
}, [sessionId, agent]);
|
|
31881
|
-
return messages;
|
|
31882
|
-
}
|
|
31883
|
-
|
|
31884
|
-
// src/cli/components/ChatView.tsx
|
|
31885
|
-
init_messages();
|
|
31886
32020
|
|
|
31887
32021
|
// src/cli/components/MessageBubble.tsx
|
|
31888
32022
|
import { Box as Box4, Text as Text5 } from "ink";
|
|
31889
32023
|
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
31890
|
-
var priorityColors = {
|
|
31891
|
-
urgent: "red",
|
|
31892
|
-
high: "yellow",
|
|
31893
|
-
normal: "",
|
|
31894
|
-
low: "dim"
|
|
31895
|
-
};
|
|
31896
32024
|
function MessageBubble({ message, isOwn }) {
|
|
31897
32025
|
const time = message.created_at.slice(11, 19);
|
|
31898
|
-
const color = priorityColors[message.priority] || "";
|
|
31899
32026
|
return /* @__PURE__ */ jsxDEV2(Box4, {
|
|
31900
|
-
flexDirection: "column",
|
|
31901
|
-
alignItems: isOwn ? "flex-end" : "flex-start",
|
|
31902
|
-
marginBottom: 0,
|
|
31903
32027
|
children: [
|
|
31904
|
-
/* @__PURE__ */ jsxDEV2(
|
|
31905
|
-
|
|
32028
|
+
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
32029
|
+
dimColor: true,
|
|
31906
32030
|
children: [
|
|
31907
|
-
|
|
31908
|
-
|
|
31909
|
-
children: time
|
|
31910
|
-
}, undefined, false, undefined, this),
|
|
31911
|
-
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
31912
|
-
bold: true,
|
|
31913
|
-
color: isOwn ? "cyan" : "green",
|
|
31914
|
-
children: message.from_agent
|
|
31915
|
-
}, undefined, false, undefined, this),
|
|
31916
|
-
message.priority !== "normal" && /* @__PURE__ */ jsxDEV2(Text5, {
|
|
31917
|
-
color,
|
|
31918
|
-
children: [
|
|
31919
|
-
"[",
|
|
31920
|
-
message.priority,
|
|
31921
|
-
"]"
|
|
31922
|
-
]
|
|
31923
|
-
}, undefined, true, undefined, this),
|
|
31924
|
-
!message.read_at && !isOwn && /* @__PURE__ */ jsxDEV2(Text5, {
|
|
31925
|
-
color: "green",
|
|
31926
|
-
children: "*"
|
|
31927
|
-
}, undefined, false, undefined, this)
|
|
32031
|
+
time,
|
|
32032
|
+
" "
|
|
31928
32033
|
]
|
|
31929
32034
|
}, undefined, true, undefined, this),
|
|
31930
|
-
/* @__PURE__ */ jsxDEV2(
|
|
31931
|
-
|
|
31932
|
-
|
|
31933
|
-
children:
|
|
31934
|
-
|
|
31935
|
-
|
|
31936
|
-
|
|
31937
|
-
|
|
32035
|
+
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
32036
|
+
bold: true,
|
|
32037
|
+
color: isOwn ? "cyan" : "green",
|
|
32038
|
+
children: message.from_agent
|
|
32039
|
+
}, undefined, false, undefined, this),
|
|
32040
|
+
message.priority !== "normal" && /* @__PURE__ */ jsxDEV2(Text5, {
|
|
32041
|
+
color: message.priority === "urgent" ? "red" : "yellow",
|
|
32042
|
+
children: [
|
|
32043
|
+
" [",
|
|
32044
|
+
message.priority,
|
|
32045
|
+
"]"
|
|
32046
|
+
]
|
|
32047
|
+
}, undefined, true, undefined, this),
|
|
32048
|
+
/* @__PURE__ */ jsxDEV2(Text5, {
|
|
32049
|
+
children: [
|
|
32050
|
+
": ",
|
|
32051
|
+
message.content
|
|
32052
|
+
]
|
|
32053
|
+
}, undefined, true, undefined, this)
|
|
31938
32054
|
]
|
|
31939
32055
|
}, undefined, true, undefined, this);
|
|
31940
32056
|
}
|
|
31941
32057
|
|
|
31942
32058
|
// src/cli/components/ChatView.tsx
|
|
31943
32059
|
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
31944
|
-
function ChatView({
|
|
31945
|
-
const messages =
|
|
31946
|
-
const [input, setInput] =
|
|
31947
|
-
const
|
|
31948
|
-
const
|
|
31949
|
-
|
|
31950
|
-
|
|
31951
|
-
|
|
32060
|
+
function ChatView({ agent, onBack, sessionId: initialSessionId, recipient, channelName }) {
|
|
32061
|
+
const [messages, setMessages] = useState5([]);
|
|
32062
|
+
const [input, setInput] = useState5("");
|
|
32063
|
+
const [sessionId, setSessionId] = useState5(initialSessionId);
|
|
32064
|
+
const isChannel = !!channelName;
|
|
32065
|
+
useEffect5(() => {
|
|
32066
|
+
const opts = isChannel ? { channel: channelName } : sessionId ? { session_id: sessionId } : {};
|
|
32067
|
+
if (isChannel || sessionId) {
|
|
32068
|
+
const existing = readMessages(opts);
|
|
32069
|
+
setMessages(existing);
|
|
32070
|
+
}
|
|
32071
|
+
const pollOpts = isChannel ? { channel: channelName } : sessionId ? { session_id: sessionId } : null;
|
|
32072
|
+
if (!pollOpts)
|
|
32073
|
+
return;
|
|
32074
|
+
const { stop } = startPolling({
|
|
32075
|
+
...pollOpts,
|
|
32076
|
+
interval_ms: 200,
|
|
32077
|
+
on_messages: (newMsgs) => {
|
|
32078
|
+
setMessages((prev) => [...prev, ...newMsgs]);
|
|
32079
|
+
}
|
|
32080
|
+
});
|
|
32081
|
+
return stop;
|
|
32082
|
+
}, [sessionId, channelName]);
|
|
32083
|
+
useEffect5(() => {
|
|
32084
|
+
if (messages.length === 0)
|
|
32085
|
+
return;
|
|
32086
|
+
if (isChannel && channelName) {
|
|
32087
|
+
markChannelRead(channelName, agent);
|
|
32088
|
+
} else if (sessionId) {
|
|
32089
|
+
markSessionRead(sessionId, agent);
|
|
32090
|
+
}
|
|
32091
|
+
}, [messages.length]);
|
|
31952
32092
|
useInput4((_, key) => {
|
|
31953
32093
|
if (key.escape)
|
|
31954
32094
|
onBack();
|
|
@@ -31956,33 +32096,46 @@ function ChatView({ sessionId, agent, participants, onBack }) {
|
|
|
31956
32096
|
const handleSubmit = (value) => {
|
|
31957
32097
|
if (!value.trim())
|
|
31958
32098
|
return;
|
|
31959
|
-
|
|
31960
|
-
|
|
31961
|
-
|
|
31962
|
-
|
|
31963
|
-
|
|
31964
|
-
|
|
32099
|
+
if (isChannel && channelName) {
|
|
32100
|
+
const msg = sendMessage({
|
|
32101
|
+
from: agent,
|
|
32102
|
+
to: channelName,
|
|
32103
|
+
content: value.trim(),
|
|
32104
|
+
channel: channelName,
|
|
32105
|
+
session_id: `channel:${channelName}`
|
|
32106
|
+
});
|
|
32107
|
+
setMessages((prev) => [...prev, msg]);
|
|
32108
|
+
} else {
|
|
32109
|
+
const to = recipient || agent;
|
|
32110
|
+
const msg = sendMessage({
|
|
32111
|
+
from: agent,
|
|
32112
|
+
to,
|
|
32113
|
+
content: value.trim(),
|
|
32114
|
+
session_id: sessionId
|
|
32115
|
+
});
|
|
32116
|
+
if (!sessionId) {
|
|
32117
|
+
setSessionId(msg.session_id);
|
|
32118
|
+
}
|
|
32119
|
+
}
|
|
31965
32120
|
setInput("");
|
|
31966
32121
|
};
|
|
32122
|
+
const title = isChannel ? `#${channelName}` : recipient || "self";
|
|
32123
|
+
const prompt = isChannel ? `${agent} \u2192 #${channelName}` : `${agent} \u2192 ${recipient || "self"}`;
|
|
31967
32124
|
return /* @__PURE__ */ jsxDEV3(Box5, {
|
|
31968
32125
|
flexDirection: "column",
|
|
31969
32126
|
padding: 1,
|
|
31970
32127
|
children: [
|
|
31971
32128
|
/* @__PURE__ */ jsxDEV3(Box5, {
|
|
31972
32129
|
marginBottom: 1,
|
|
31973
|
-
gap: 1,
|
|
31974
32130
|
children: [
|
|
31975
32131
|
/* @__PURE__ */ jsxDEV3(Text6, {
|
|
31976
32132
|
bold: true,
|
|
31977
|
-
color: "cyan",
|
|
31978
|
-
children:
|
|
31979
|
-
|
|
31980
|
-
others.join(", ") || "self"
|
|
31981
|
-
]
|
|
31982
|
-
}, undefined, true, undefined, this),
|
|
32133
|
+
color: isChannel ? "magenta" : "cyan",
|
|
32134
|
+
children: title
|
|
32135
|
+
}, undefined, false, undefined, this),
|
|
31983
32136
|
/* @__PURE__ */ jsxDEV3(Text6, {
|
|
31984
32137
|
dimColor: true,
|
|
31985
|
-
children: "(Esc: back)"
|
|
32138
|
+
children: " (Esc: back)"
|
|
31986
32139
|
}, undefined, false, undefined, this)
|
|
31987
32140
|
]
|
|
31988
32141
|
}, undefined, true, undefined, this),
|
|
@@ -31991,7 +32144,7 @@ function ChatView({ sessionId, agent, participants, onBack }) {
|
|
|
31991
32144
|
flexGrow: 1,
|
|
31992
32145
|
children: messages.length === 0 ? /* @__PURE__ */ jsxDEV3(Text6, {
|
|
31993
32146
|
dimColor: true,
|
|
31994
|
-
children: "No messages yet.
|
|
32147
|
+
children: "No messages yet. Type below and press Enter."
|
|
31995
32148
|
}, undefined, false, undefined, this) : messages.map((msg) => /* @__PURE__ */ jsxDEV3(MessageBubble, {
|
|
31996
32149
|
message: msg,
|
|
31997
32150
|
isOwn: msg.from_agent === agent
|
|
@@ -32001,11 +32154,9 @@ function ChatView({ sessionId, agent, participants, onBack }) {
|
|
|
32001
32154
|
marginTop: 1,
|
|
32002
32155
|
children: [
|
|
32003
32156
|
/* @__PURE__ */ jsxDEV3(Text6, {
|
|
32004
|
-
color: "cyan",
|
|
32157
|
+
color: isChannel ? "magenta" : "cyan",
|
|
32005
32158
|
children: [
|
|
32006
|
-
|
|
32007
|
-
" \u2192 ",
|
|
32008
|
-
recipient,
|
|
32159
|
+
prompt,
|
|
32009
32160
|
": "
|
|
32010
32161
|
]
|
|
32011
32162
|
}, undefined, true, undefined, this),
|
|
@@ -32025,37 +32176,46 @@ function ChatView({ sessionId, agent, participants, onBack }) {
|
|
|
32025
32176
|
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
32026
32177
|
function App({ agent }) {
|
|
32027
32178
|
const { exit } = useApp();
|
|
32028
|
-
const [view, setView] =
|
|
32029
|
-
const [currentSession, setCurrentSession] =
|
|
32030
|
-
const [
|
|
32179
|
+
const [view, setView] = useState6("sessions");
|
|
32180
|
+
const [currentSession, setCurrentSession] = useState6(null);
|
|
32181
|
+
const [currentChannel, setCurrentChannel] = useState6(null);
|
|
32182
|
+
const [newTo, setNewTo] = useState6("");
|
|
32031
32183
|
useInput5((input, key) => {
|
|
32032
32184
|
if (input === "q" && view === "sessions") {
|
|
32033
32185
|
exit();
|
|
32034
32186
|
}
|
|
32187
|
+
if (key.escape && view === "new") {
|
|
32188
|
+
setNewTo("");
|
|
32189
|
+
setView("sessions");
|
|
32190
|
+
}
|
|
32035
32191
|
});
|
|
32036
32192
|
const handleSelectSession = (session) => {
|
|
32037
32193
|
setCurrentSession(session);
|
|
32038
32194
|
setView("chat");
|
|
32039
32195
|
};
|
|
32196
|
+
const handleSelectChannel = (channelName) => {
|
|
32197
|
+
setCurrentChannel(channelName);
|
|
32198
|
+
setView("channel");
|
|
32199
|
+
};
|
|
32040
32200
|
const handleNewConversation = () => {
|
|
32041
32201
|
setView("new");
|
|
32042
32202
|
};
|
|
32043
32203
|
const handleStartNew = (to) => {
|
|
32044
32204
|
if (!to.trim())
|
|
32045
32205
|
return;
|
|
32046
|
-
|
|
32047
|
-
session_id:
|
|
32206
|
+
setCurrentSession({
|
|
32207
|
+
session_id: "",
|
|
32048
32208
|
participants: [agent, to.trim()],
|
|
32049
|
-
last_message_at:
|
|
32209
|
+
last_message_at: "",
|
|
32050
32210
|
message_count: 0,
|
|
32051
32211
|
unread_count: 0
|
|
32052
|
-
};
|
|
32053
|
-
setCurrentSession(tempSession);
|
|
32212
|
+
});
|
|
32054
32213
|
setNewTo("");
|
|
32055
32214
|
setView("chat");
|
|
32056
32215
|
};
|
|
32057
32216
|
const handleBack = () => {
|
|
32058
32217
|
setCurrentSession(null);
|
|
32218
|
+
setCurrentChannel(null);
|
|
32059
32219
|
setView("sessions");
|
|
32060
32220
|
};
|
|
32061
32221
|
if (view === "new") {
|
|
@@ -32084,29 +32244,38 @@ function App({ agent }) {
|
|
|
32084
32244
|
}, undefined, true, undefined, this),
|
|
32085
32245
|
/* @__PURE__ */ jsxDEV4(Text7, {
|
|
32086
32246
|
dimColor: true,
|
|
32087
|
-
children: "
|
|
32247
|
+
children: "Enter to start, Esc to cancel"
|
|
32088
32248
|
}, undefined, false, undefined, this)
|
|
32089
32249
|
]
|
|
32090
32250
|
}, undefined, true, undefined, this);
|
|
32091
32251
|
}
|
|
32252
|
+
if (view === "channel" && currentChannel) {
|
|
32253
|
+
return /* @__PURE__ */ jsxDEV4(ChatView, {
|
|
32254
|
+
agent,
|
|
32255
|
+
channelName: currentChannel,
|
|
32256
|
+
onBack: handleBack
|
|
32257
|
+
}, undefined, false, undefined, this);
|
|
32258
|
+
}
|
|
32092
32259
|
if (view === "chat" && currentSession) {
|
|
32260
|
+
const others = currentSession.participants.filter((p) => p !== agent);
|
|
32093
32261
|
return /* @__PURE__ */ jsxDEV4(ChatView, {
|
|
32094
|
-
sessionId: currentSession.session_id,
|
|
32095
32262
|
agent,
|
|
32096
|
-
|
|
32263
|
+
sessionId: currentSession.session_id || undefined,
|
|
32264
|
+
recipient: others[0] || agent,
|
|
32097
32265
|
onBack: handleBack
|
|
32098
32266
|
}, undefined, false, undefined, this);
|
|
32099
32267
|
}
|
|
32100
32268
|
return /* @__PURE__ */ jsxDEV4(SessionList, {
|
|
32101
32269
|
agent,
|
|
32102
32270
|
onSelect: handleSelectSession,
|
|
32271
|
+
onSelectChannel: handleSelectChannel,
|
|
32103
32272
|
onNew: handleNewConversation
|
|
32104
32273
|
}, undefined, false, undefined, this);
|
|
32105
32274
|
}
|
|
32106
32275
|
|
|
32107
32276
|
// src/cli/index.tsx
|
|
32108
32277
|
var program2 = new Command;
|
|
32109
|
-
program2.name("conversations").description("Real-time CLI messaging for AI agents").version("0.0.
|
|
32278
|
+
program2.name("conversations").description("Real-time CLI messaging for AI agents").version("0.0.6");
|
|
32110
32279
|
program2.command("send").description("Send a message to an agent").argument("<message>", "Message content").requiredOption("--to <agent>", "Recipient agent ID").option("--from <agent>", "Sender agent ID").option("--session <id>", "Session ID (auto-generated if omitted)").option("--priority <level>", "Priority: low, normal, high, urgent", "normal").option("--working-dir <path>", "Working directory context").option("--repository <repo>", "Repository context").option("--branch <branch>", "Branch context").option("--metadata <json>", "JSON metadata string").option("--json", "Output as JSON").action((message, opts) => {
|
|
32111
32280
|
const from = resolveIdentity(opts.from);
|
|
32112
32281
|
const metadata = opts.metadata ? JSON.parse(opts.metadata) : undefined;
|
|
@@ -32372,8 +32541,12 @@ program2.command("mcp").description("Start MCP server").action(async () => {
|
|
|
32372
32541
|
const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_mcp2(), exports_mcp));
|
|
32373
32542
|
await startMcpServer2();
|
|
32374
32543
|
});
|
|
32544
|
+
program2.command("dashboard").description("Start web dashboard").option("--port <port>", "Port to listen on", parseInt).action(async (opts) => {
|
|
32545
|
+
const { startDashboardServer: startDashboardServer2 } = await Promise.resolve().then(() => (init_serve(), exports_serve));
|
|
32546
|
+
startDashboardServer2(opts.port || 3456);
|
|
32547
|
+
});
|
|
32375
32548
|
program2.action(() => {
|
|
32376
32549
|
const agent = resolveIdentity();
|
|
32377
|
-
render(
|
|
32550
|
+
render(React8.createElement(App, { agent }));
|
|
32378
32551
|
});
|
|
32379
32552
|
program2.parse();
|
package/bin/mcp.js
CHANGED
|
@@ -28537,7 +28537,7 @@ function resolveIdentity(explicit) {
|
|
|
28537
28537
|
// src/mcp/index.ts
|
|
28538
28538
|
var server = new McpServer({
|
|
28539
28539
|
name: "conversations",
|
|
28540
|
-
version: "0.0.
|
|
28540
|
+
version: "0.0.6"
|
|
28541
28541
|
});
|
|
28542
28542
|
server.registerTool("send_message", {
|
|
28543
28543
|
title: "Send Message",
|