@hasna/conversations 0.1.18 → 0.1.19
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/hook.js +37 -0
- package/bin/index.js +455 -292
- package/bin/mcp.js +234 -89
- package/dashboard/dist/assets/index-Bw0wMcXE.js +186 -0
- package/dashboard/dist/assets/index-CF_GDtNp.css +1 -0
- package/dashboard/dist/index.html +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +168 -16
- package/dist/lib/messages.d.ts +3 -0
- package/dist/lib/terminal-markdown.d.ts +11 -0
- package/dist/lib/webhooks.d.ts +11 -0
- package/dist/lib/webhooks.test.d.ts +1 -0
- package/dist/types.d.ts +3 -0
- package/package.json +1 -1
- package/dashboard/dist/assets/index-CCdh63JU.js +0 -186
- package/dashboard/dist/assets/index-VFT0_0LI.css +0 -1
package/bin/index.js
CHANGED
|
@@ -2045,6 +2045,43 @@ function getDb() {
|
|
|
2045
2045
|
if (!colNames2.includes("attachments")) {
|
|
2046
2046
|
db.exec("ALTER TABLE messages ADD COLUMN attachments TEXT");
|
|
2047
2047
|
}
|
|
2048
|
+
if (!colNames2.includes("reply_to")) {
|
|
2049
|
+
db.exec("ALTER TABLE messages ADD COLUMN reply_to INTEGER REFERENCES messages(id)");
|
|
2050
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_reply_to ON messages(reply_to)");
|
|
2051
|
+
}
|
|
2052
|
+
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
|
|
2053
|
+
if (!ftsExists) {
|
|
2054
|
+
db.exec(`
|
|
2055
|
+
CREATE VIRTUAL TABLE messages_fts USING fts5(
|
|
2056
|
+
content, from_agent, to_agent, space,
|
|
2057
|
+
content_rowid='id', content='messages'
|
|
2058
|
+
)
|
|
2059
|
+
`);
|
|
2060
|
+
db.exec(`
|
|
2061
|
+
INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
|
|
2062
|
+
SELECT id, content, from_agent, to_agent, space FROM messages
|
|
2063
|
+
`);
|
|
2064
|
+
db.exec(`
|
|
2065
|
+
CREATE TRIGGER IF NOT EXISTS messages_fts_insert AFTER INSERT ON messages BEGIN
|
|
2066
|
+
INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
|
|
2067
|
+
VALUES (new.id, new.content, new.from_agent, new.to_agent, new.space);
|
|
2068
|
+
END
|
|
2069
|
+
`);
|
|
2070
|
+
db.exec(`
|
|
2071
|
+
CREATE TRIGGER IF NOT EXISTS messages_fts_delete AFTER DELETE ON messages BEGIN
|
|
2072
|
+
INSERT INTO messages_fts(messages_fts, rowid, content, from_agent, to_agent, space)
|
|
2073
|
+
VALUES ('delete', old.id, old.content, old.from_agent, old.to_agent, old.space);
|
|
2074
|
+
END
|
|
2075
|
+
`);
|
|
2076
|
+
db.exec(`
|
|
2077
|
+
CREATE TRIGGER IF NOT EXISTS messages_fts_update AFTER UPDATE OF content ON messages BEGIN
|
|
2078
|
+
INSERT INTO messages_fts(messages_fts, rowid, content, from_agent, to_agent, space)
|
|
2079
|
+
VALUES ('delete', old.id, old.content, old.from_agent, old.to_agent, old.space);
|
|
2080
|
+
INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
|
|
2081
|
+
VALUES (new.id, new.content, new.from_agent, new.to_agent, new.space);
|
|
2082
|
+
END
|
|
2083
|
+
`);
|
|
2084
|
+
}
|
|
2048
2085
|
return db;
|
|
2049
2086
|
}
|
|
2050
2087
|
function closeDb() {
|
|
@@ -2056,11 +2093,84 @@ function closeDb() {
|
|
|
2056
2093
|
var db = null;
|
|
2057
2094
|
var init_db = () => {};
|
|
2058
2095
|
|
|
2096
|
+
// src/lib/webhooks.ts
|
|
2097
|
+
import { readFileSync } from "fs";
|
|
2098
|
+
import { join as join2 } from "path";
|
|
2099
|
+
import { homedir as homedir2 } from "os";
|
|
2100
|
+
function getConfigPath() {
|
|
2101
|
+
return process.env.CONVERSATIONS_CONFIG_PATH || join2(homedir2(), ".conversations", "config.json");
|
|
2102
|
+
}
|
|
2103
|
+
function loadConfig() {
|
|
2104
|
+
const now = Date.now();
|
|
2105
|
+
if (cachedConfig && now - configLoadedAt < CONFIG_CACHE_MS)
|
|
2106
|
+
return cachedConfig;
|
|
2107
|
+
try {
|
|
2108
|
+
const raw = readFileSync(getConfigPath(), "utf-8");
|
|
2109
|
+
cachedConfig = JSON.parse(raw);
|
|
2110
|
+
configLoadedAt = now;
|
|
2111
|
+
return cachedConfig;
|
|
2112
|
+
} catch {
|
|
2113
|
+
cachedConfig = {};
|
|
2114
|
+
configLoadedAt = now;
|
|
2115
|
+
return cachedConfig;
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
function matchesEvent(webhook, msg) {
|
|
2119
|
+
for (const event of webhook.events) {
|
|
2120
|
+
if (event === "dm" && !msg.space)
|
|
2121
|
+
return true;
|
|
2122
|
+
if (event === "blocker" && msg.blocking)
|
|
2123
|
+
return true;
|
|
2124
|
+
if (event === "space" && msg.space)
|
|
2125
|
+
return true;
|
|
2126
|
+
if (event === "mention" && webhook.agent && msg.content.includes(`@${webhook.agent}`))
|
|
2127
|
+
return true;
|
|
2128
|
+
}
|
|
2129
|
+
return false;
|
|
2130
|
+
}
|
|
2131
|
+
function fireWebhooks(msg) {
|
|
2132
|
+
const config = loadConfig();
|
|
2133
|
+
if (!config.webhooks || config.webhooks.length === 0)
|
|
2134
|
+
return;
|
|
2135
|
+
for (const webhook of config.webhooks) {
|
|
2136
|
+
if (webhook.agent && msg.to_agent !== webhook.agent && !msg.space)
|
|
2137
|
+
continue;
|
|
2138
|
+
if (!matchesEvent(webhook, msg))
|
|
2139
|
+
continue;
|
|
2140
|
+
fetch(webhook.url, {
|
|
2141
|
+
method: "POST",
|
|
2142
|
+
headers: { "Content-Type": "application/json" },
|
|
2143
|
+
body: JSON.stringify({
|
|
2144
|
+
id: msg.id,
|
|
2145
|
+
from: msg.from_agent,
|
|
2146
|
+
to: msg.to_agent,
|
|
2147
|
+
space: msg.space,
|
|
2148
|
+
content: msg.content,
|
|
2149
|
+
priority: msg.priority,
|
|
2150
|
+
blocking: msg.blocking,
|
|
2151
|
+
created_at: msg.created_at
|
|
2152
|
+
})
|
|
2153
|
+
}).catch(() => {});
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
var cachedConfig = null, configLoadedAt = 0, CONFIG_CACHE_MS = 1e4;
|
|
2157
|
+
var init_webhooks = () => {};
|
|
2158
|
+
|
|
2059
2159
|
// src/lib/messages.ts
|
|
2060
2160
|
import { randomUUID } from "crypto";
|
|
2061
2161
|
import { mkdirSync as mkdirSync2, copyFileSync, statSync } from "fs";
|
|
2062
|
-
import { join as
|
|
2063
|
-
import { homedir as
|
|
2162
|
+
import { join as join3 } from "path";
|
|
2163
|
+
import { homedir as homedir3 } from "os";
|
|
2164
|
+
function compactMessage(msg) {
|
|
2165
|
+
const result = {};
|
|
2166
|
+
for (const key of Object.keys(msg)) {
|
|
2167
|
+
const val = msg[key];
|
|
2168
|
+
if (val !== null && val !== undefined) {
|
|
2169
|
+
result[key] = val;
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
return result;
|
|
2173
|
+
}
|
|
2064
2174
|
function parseMessage(row) {
|
|
2065
2175
|
let metadata = null;
|
|
2066
2176
|
if (row.metadata) {
|
|
@@ -2082,13 +2192,14 @@ function parseMessage(row) {
|
|
|
2082
2192
|
...row,
|
|
2083
2193
|
metadata,
|
|
2084
2194
|
attachments,
|
|
2085
|
-
blocking: !!row.blocking
|
|
2195
|
+
blocking: !!row.blocking,
|
|
2196
|
+
reply_to: row.reply_to || null
|
|
2086
2197
|
};
|
|
2087
2198
|
}
|
|
2088
2199
|
function getAttachmentsDir() {
|
|
2089
2200
|
if (process.env.CONVERSATIONS_ATTACHMENTS_DIR)
|
|
2090
2201
|
return process.env.CONVERSATIONS_ATTACHMENTS_DIR;
|
|
2091
|
-
return
|
|
2202
|
+
return join3(homedir3(), ".conversations", "attachments");
|
|
2092
2203
|
}
|
|
2093
2204
|
function guessMimeType(name) {
|
|
2094
2205
|
const ext = name.split(".").pop()?.toLowerCase();
|
|
@@ -2124,19 +2235,20 @@ function sendMessage(opts) {
|
|
|
2124
2235
|
const metadata = opts.metadata ? JSON.stringify(opts.metadata) : null;
|
|
2125
2236
|
const normalizedPriority = opts.priority === "low" || opts.priority === "normal" || opts.priority === "high" || opts.priority === "urgent" ? opts.priority : "normal";
|
|
2126
2237
|
const blocking = opts.blocking ? 1 : 0;
|
|
2238
|
+
const replyTo = opts.reply_to || null;
|
|
2127
2239
|
const stmt = db2.prepare(`
|
|
2128
|
-
INSERT INTO messages (session_id, from_agent, to_agent, space, content, priority, working_dir, repository, branch, metadata, blocking)
|
|
2129
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2240
|
+
INSERT INTO messages (session_id, from_agent, to_agent, space, content, priority, working_dir, repository, branch, metadata, blocking, reply_to)
|
|
2241
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2130
2242
|
RETURNING *
|
|
2131
2243
|
`);
|
|
2132
|
-
const row = stmt.get(sessionId, opts.from, opts.to, opts.space || null, opts.content, normalizedPriority, opts.working_dir || null, opts.repository || null, opts.branch || null, metadata, blocking);
|
|
2244
|
+
const row = stmt.get(sessionId, opts.from, opts.to, opts.space || null, opts.content, normalizedPriority, opts.working_dir || null, opts.repository || null, opts.branch || null, metadata, blocking, replyTo);
|
|
2133
2245
|
const message = parseMessage(row);
|
|
2134
2246
|
if (opts.attachments && opts.attachments.length > 0) {
|
|
2135
|
-
const attachmentsDir =
|
|
2247
|
+
const attachmentsDir = join3(getAttachmentsDir(), String(message.id));
|
|
2136
2248
|
mkdirSync2(attachmentsDir, { recursive: true });
|
|
2137
2249
|
const attachmentInfos = [];
|
|
2138
2250
|
for (const att of opts.attachments) {
|
|
2139
|
-
const destPath =
|
|
2251
|
+
const destPath = join3(attachmentsDir, att.name);
|
|
2140
2252
|
copyFileSync(att.source_path, destPath);
|
|
2141
2253
|
const stat = statSync(destPath);
|
|
2142
2254
|
attachmentInfos.push({
|
|
@@ -2150,6 +2262,7 @@ function sendMessage(opts) {
|
|
|
2150
2262
|
db2.prepare("UPDATE messages SET attachments = ? WHERE id = ?").run(attachmentsJson, message.id);
|
|
2151
2263
|
message.attachments = attachmentInfos;
|
|
2152
2264
|
}
|
|
2265
|
+
fireWebhooks(message);
|
|
2153
2266
|
return message;
|
|
2154
2267
|
}
|
|
2155
2268
|
function readMessages(opts = {}) {
|
|
@@ -2184,10 +2297,13 @@ function readMessages(opts = {}) {
|
|
|
2184
2297
|
conditions.push("read_at IS NULL");
|
|
2185
2298
|
}
|
|
2186
2299
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2187
|
-
const
|
|
2300
|
+
const resolvedLimit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
2188
2301
|
const order = opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
|
|
2189
|
-
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} ${
|
|
2190
|
-
|
|
2302
|
+
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
|
|
2303
|
+
const messages = rows.map(parseMessage);
|
|
2304
|
+
if (opts.compact)
|
|
2305
|
+
return messages.map(compactMessage);
|
|
2306
|
+
return messages;
|
|
2191
2307
|
}
|
|
2192
2308
|
function markRead(ids, reader) {
|
|
2193
2309
|
const db2 = getDb();
|
|
@@ -2333,6 +2449,33 @@ function getUnreadBlockers(agent) {
|
|
|
2333
2449
|
}
|
|
2334
2450
|
function searchMessages(opts) {
|
|
2335
2451
|
const db2 = getDb();
|
|
2452
|
+
const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
2453
|
+
try {
|
|
2454
|
+
const ftsConditions = [];
|
|
2455
|
+
const ftsParams = [];
|
|
2456
|
+
const words = opts.query.trim().split(/\s+/).filter(Boolean);
|
|
2457
|
+
const ftsQuery = words.map((w) => `"${w.replace(/"/g, '""')}"`).join(" ");
|
|
2458
|
+
ftsConditions.push("messages_fts MATCH ?");
|
|
2459
|
+
ftsParams.push(ftsQuery);
|
|
2460
|
+
let extraWhere = "";
|
|
2461
|
+
if (opts.space) {
|
|
2462
|
+
extraWhere += " AND m.space = ?";
|
|
2463
|
+
ftsParams.push(opts.space);
|
|
2464
|
+
}
|
|
2465
|
+
if (opts.from) {
|
|
2466
|
+
extraWhere += " AND m.from_agent = ?";
|
|
2467
|
+
ftsParams.push(opts.from);
|
|
2468
|
+
}
|
|
2469
|
+
if (opts.to) {
|
|
2470
|
+
extraWhere += " AND m.to_agent = ?";
|
|
2471
|
+
ftsParams.push(opts.to);
|
|
2472
|
+
}
|
|
2473
|
+
const rows2 = db2.prepare(`SELECT m.* FROM messages m
|
|
2474
|
+
JOIN messages_fts ON messages_fts.rowid = m.id
|
|
2475
|
+
WHERE ${ftsConditions.join(" AND ")}${extraWhere}
|
|
2476
|
+
ORDER BY m.created_at DESC, m.id DESC LIMIT ${limit}`).all(...ftsParams);
|
|
2477
|
+
return rows2.map(parseMessage);
|
|
2478
|
+
} catch {}
|
|
2336
2479
|
const conditions = ["content LIKE ?"];
|
|
2337
2480
|
const params = [`%${opts.query}%`];
|
|
2338
2481
|
if (opts.space) {
|
|
@@ -2347,13 +2490,13 @@ function searchMessages(opts) {
|
|
|
2347
2490
|
conditions.push("to_agent = ?");
|
|
2348
2491
|
params.push(opts.to);
|
|
2349
2492
|
}
|
|
2350
|
-
const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 50;
|
|
2351
2493
|
const where = `WHERE ${conditions.join(" AND ")}`;
|
|
2352
2494
|
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at DESC, id DESC LIMIT ${limit}`).all(...params);
|
|
2353
2495
|
return rows.map(parseMessage);
|
|
2354
2496
|
}
|
|
2355
2497
|
var init_messages = __esm(() => {
|
|
2356
2498
|
init_db();
|
|
2499
|
+
init_webhooks();
|
|
2357
2500
|
});
|
|
2358
2501
|
|
|
2359
2502
|
// src/lib/sessions.ts
|
|
@@ -3090,9 +3233,9 @@ var init_names = __esm(() => {
|
|
|
3090
3233
|
});
|
|
3091
3234
|
|
|
3092
3235
|
// src/lib/identity.ts
|
|
3093
|
-
import { readFileSync, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
3094
|
-
import { join as
|
|
3095
|
-
import { homedir as
|
|
3236
|
+
import { readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
3237
|
+
import { join as join4, dirname as dirname2 } from "path";
|
|
3238
|
+
import { homedir as homedir4 } from "os";
|
|
3096
3239
|
function isNameTaken(name) {
|
|
3097
3240
|
try {
|
|
3098
3241
|
const { getDb: getDb2 } = (init_db(), __toCommonJS(exports_db));
|
|
@@ -3107,7 +3250,7 @@ function getAutoName() {
|
|
|
3107
3250
|
if (cachedAutoName)
|
|
3108
3251
|
return cachedAutoName;
|
|
3109
3252
|
try {
|
|
3110
|
-
const name2 =
|
|
3253
|
+
const name2 = readFileSync2(AGENT_ID_FILE, "utf-8").trim();
|
|
3111
3254
|
if (name2) {
|
|
3112
3255
|
cachedAutoName = name2;
|
|
3113
3256
|
return name2;
|
|
@@ -3141,7 +3284,7 @@ function resolveIdentity(explicit) {
|
|
|
3141
3284
|
var AGENT_ID_FILE, cachedAutoName = null;
|
|
3142
3285
|
var init_identity = __esm(() => {
|
|
3143
3286
|
init_names();
|
|
3144
|
-
AGENT_ID_FILE =
|
|
3287
|
+
AGENT_ID_FILE = join4(homedir4(), ".conversations", "agent-id");
|
|
3145
3288
|
});
|
|
3146
3289
|
|
|
3147
3290
|
// src/lib/presence.ts
|
|
@@ -3216,6 +3359,52 @@ var init_presence = __esm(() => {
|
|
|
3216
3359
|
init_db();
|
|
3217
3360
|
});
|
|
3218
3361
|
|
|
3362
|
+
// src/lib/terminal-markdown.ts
|
|
3363
|
+
var exports_terminal_markdown = {};
|
|
3364
|
+
__export(exports_terminal_markdown, {
|
|
3365
|
+
renderInline: () => renderInline,
|
|
3366
|
+
renderContent: () => renderContent
|
|
3367
|
+
});
|
|
3368
|
+
import chalk from "chalk";
|
|
3369
|
+
var renderInline = (text) => {
|
|
3370
|
+
return text.replace(/`([^`]+)`/g, (_, code) => chalk.bgGray.white(` ${code} `)).replace(/\*\*\*(.+?)\*\*\*/g, (_, t) => chalk.bold.italic(t)).replace(/\*\*(.+?)\*\*/g, (_, t) => chalk.bold(t)).replace(/\*(.+?)\*/g, (_, t) => chalk.italic(t)).replace(/~~(.+?)~~/g, (_, t) => chalk.strikethrough(t));
|
|
3371
|
+
}, renderContent = (content) => {
|
|
3372
|
+
const lines = content.split(`
|
|
3373
|
+
`);
|
|
3374
|
+
const rendered = [];
|
|
3375
|
+
for (const line of lines) {
|
|
3376
|
+
let l = line;
|
|
3377
|
+
const h = l.match(/^(#{1,3})\s+(.+)/);
|
|
3378
|
+
if (h) {
|
|
3379
|
+
rendered.push(chalk.bold(h[2]));
|
|
3380
|
+
continue;
|
|
3381
|
+
}
|
|
3382
|
+
if (/^\s*[-*+]\s/.test(l)) {
|
|
3383
|
+
rendered.push(" " + chalk.dim("\u2022") + " " + renderInline(l.replace(/^\s*[-*+]\s/, "")));
|
|
3384
|
+
continue;
|
|
3385
|
+
}
|
|
3386
|
+
const ol = l.match(/^\s*(\d+)[.)]\s(.*)/);
|
|
3387
|
+
if (ol) {
|
|
3388
|
+
rendered.push(" " + chalk.dim(ol[1] + ".") + " " + renderInline(ol[2]));
|
|
3389
|
+
continue;
|
|
3390
|
+
}
|
|
3391
|
+
if (l.startsWith(">")) {
|
|
3392
|
+
rendered.push(chalk.dim(" \u2502 ") + chalk.italic(renderInline(l.replace(/^>\s?/, ""))));
|
|
3393
|
+
continue;
|
|
3394
|
+
}
|
|
3395
|
+
if (l.trimStart().startsWith("```"))
|
|
3396
|
+
continue;
|
|
3397
|
+
if (l.trim() === "") {
|
|
3398
|
+
rendered.push("");
|
|
3399
|
+
continue;
|
|
3400
|
+
}
|
|
3401
|
+
rendered.push(renderInline(l));
|
|
3402
|
+
}
|
|
3403
|
+
return rendered.join(`
|
|
3404
|
+
`);
|
|
3405
|
+
};
|
|
3406
|
+
var init_terminal_markdown = () => {};
|
|
3407
|
+
|
|
3219
3408
|
// src/lib/poll.ts
|
|
3220
3409
|
var exports_poll = {};
|
|
3221
3410
|
__export(exports_poll, {
|
|
@@ -3314,7 +3503,7 @@ var init_poll = __esm(() => {
|
|
|
3314
3503
|
var require_package = __commonJS((exports, module) => {
|
|
3315
3504
|
module.exports = {
|
|
3316
3505
|
name: "@hasna/conversations",
|
|
3317
|
-
version: "0.1.
|
|
3506
|
+
version: "0.1.19",
|
|
3318
3507
|
description: "Real-time CLI messaging for AI agents",
|
|
3319
3508
|
type: "module",
|
|
3320
3509
|
bin: {
|
|
@@ -32286,9 +32475,9 @@ var init_mcp2 = __esm(() => {
|
|
|
32286
32475
|
});
|
|
32287
32476
|
server.registerTool("send_message", {
|
|
32288
32477
|
title: "Send Message",
|
|
32289
|
-
description: "Send a direct message to another agent.
|
|
32478
|
+
description: "Send a direct message to another agent.",
|
|
32290
32479
|
inputSchema: {
|
|
32291
|
-
from: exports_external.string().optional().describe("Your agent ID
|
|
32480
|
+
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
32292
32481
|
to: exports_external.string().describe("Recipient agent ID"),
|
|
32293
32482
|
content: exports_external.string().describe("Message content"),
|
|
32294
32483
|
session_id: exports_external.string().optional().describe("Session ID (auto-generated if omitted)"),
|
|
@@ -32297,7 +32486,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32297
32486
|
repository: exports_external.string().optional().describe("Repository context"),
|
|
32298
32487
|
branch: exports_external.string().optional().describe("Branch context"),
|
|
32299
32488
|
metadata: exports_external.string().optional().describe("JSON metadata string"),
|
|
32300
|
-
blocking: exports_external.boolean().optional().describe("
|
|
32489
|
+
blocking: exports_external.boolean().optional().describe("Blocking message \u2014 recipients must acknowledge before continuing")
|
|
32301
32490
|
}
|
|
32302
32491
|
}, async ({ from: fromParam, to, content, session_id, priority, working_dir, repository, branch, metadata, blocking }) => {
|
|
32303
32492
|
const from = resolveIdentity(fromParam);
|
|
@@ -32307,7 +32496,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32307
32496
|
parsedMetadata = JSON.parse(metadata);
|
|
32308
32497
|
} catch {
|
|
32309
32498
|
return {
|
|
32310
|
-
content: [{ type: "text", text: "
|
|
32499
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
32311
32500
|
isError: true
|
|
32312
32501
|
};
|
|
32313
32502
|
}
|
|
@@ -32333,12 +32522,12 @@ var init_mcp2 = __esm(() => {
|
|
|
32333
32522
|
description: "Read messages with optional filters. Returns messages sorted by time.",
|
|
32334
32523
|
inputSchema: {
|
|
32335
32524
|
session_id: exports_external.string().optional().describe("Filter by session ID"),
|
|
32336
|
-
from: exports_external.string().optional().describe("Filter by sender
|
|
32337
|
-
to: exports_external.string().optional().describe("Filter by recipient
|
|
32525
|
+
from: exports_external.string().optional().describe("Filter by sender"),
|
|
32526
|
+
to: exports_external.string().optional().describe("Filter by recipient"),
|
|
32338
32527
|
space: exports_external.string().optional().describe("Filter by space name"),
|
|
32339
|
-
since: exports_external.string().optional().describe("
|
|
32340
|
-
limit: exports_external.number().optional().describe("Max messages to return"),
|
|
32341
|
-
unread_only: exports_external.boolean().optional().describe("Only
|
|
32528
|
+
since: exports_external.string().optional().describe("ISO timestamp lower bound"),
|
|
32529
|
+
limit: exports_external.number().optional().describe("Max messages to return (default 20)"),
|
|
32530
|
+
unread_only: exports_external.boolean().optional().describe("Only unread messages")
|
|
32342
32531
|
}
|
|
32343
32532
|
}, async (opts) => {
|
|
32344
32533
|
const messages = readMessages(opts);
|
|
@@ -32360,7 +32549,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32360
32549
|
});
|
|
32361
32550
|
server.registerTool("reply", {
|
|
32362
32551
|
title: "Reply to Message",
|
|
32363
|
-
description: "Reply to a message by
|
|
32552
|
+
description: "Reply to a message by ID. Uses the same session and sends to the original sender.",
|
|
32364
32553
|
inputSchema: {
|
|
32365
32554
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
32366
32555
|
message_id: exports_external.number().describe("ID of the message to reply to"),
|
|
@@ -32392,7 +32581,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32392
32581
|
});
|
|
32393
32582
|
server.registerTool("mark_read", {
|
|
32394
32583
|
title: "Mark Read",
|
|
32395
|
-
description: "Mark
|
|
32584
|
+
description: "Mark messages as read. Provide IDs or set 'all' to true.",
|
|
32396
32585
|
inputSchema: {
|
|
32397
32586
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
32398
32587
|
ids: exports_external.array(exports_external.number()).optional().describe("Message IDs to mark as read"),
|
|
@@ -32407,7 +32596,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32407
32596
|
count = markRead(ids, agent);
|
|
32408
32597
|
} else {
|
|
32409
32598
|
return {
|
|
32410
|
-
content: [{ type: "text", text: "
|
|
32599
|
+
content: [{ type: "text", text: "provide ids or set all=true" }],
|
|
32411
32600
|
isError: true
|
|
32412
32601
|
};
|
|
32413
32602
|
}
|
|
@@ -32417,13 +32606,13 @@ var init_mcp2 = __esm(() => {
|
|
|
32417
32606
|
});
|
|
32418
32607
|
server.registerTool("search_messages", {
|
|
32419
32608
|
title: "Search Messages",
|
|
32420
|
-
description: "Full-text search across message content
|
|
32609
|
+
description: "Full-text search across message content, newest first.",
|
|
32421
32610
|
inputSchema: {
|
|
32422
|
-
query: exports_external.string().describe("Search query
|
|
32423
|
-
space: exports_external.string().optional().describe("Filter by space
|
|
32424
|
-
from: exports_external.string().optional().describe("Filter by sender
|
|
32425
|
-
to: exports_external.string().optional().describe("Filter by recipient
|
|
32426
|
-
limit: exports_external.number().optional().describe("Max results
|
|
32611
|
+
query: exports_external.string().describe("Search query"),
|
|
32612
|
+
space: exports_external.string().optional().describe("Filter by space"),
|
|
32613
|
+
from: exports_external.string().optional().describe("Filter by sender"),
|
|
32614
|
+
to: exports_external.string().optional().describe("Filter by recipient"),
|
|
32615
|
+
limit: exports_external.number().optional().describe("Max results (default 20)")
|
|
32427
32616
|
}
|
|
32428
32617
|
}, async ({ query, space, from, to, limit }) => {
|
|
32429
32618
|
const messages = searchMessages({ query, space, from, to, limit });
|
|
@@ -32435,11 +32624,11 @@ var init_mcp2 = __esm(() => {
|
|
|
32435
32624
|
title: "Export Messages",
|
|
32436
32625
|
description: "Export messages as JSON or CSV with optional filters.",
|
|
32437
32626
|
inputSchema: {
|
|
32438
|
-
space: exports_external.string().optional().describe("Filter by space
|
|
32627
|
+
space: exports_external.string().optional().describe("Filter by space"),
|
|
32439
32628
|
session_id: exports_external.string().optional().describe("Filter by session ID"),
|
|
32440
|
-
from: exports_external.string().optional().describe("Filter by sender
|
|
32441
|
-
since: exports_external.string().optional().describe("
|
|
32442
|
-
until: exports_external.string().optional().describe("
|
|
32629
|
+
from: exports_external.string().optional().describe("Filter by sender"),
|
|
32630
|
+
since: exports_external.string().optional().describe("ISO date lower bound"),
|
|
32631
|
+
until: exports_external.string().optional().describe("ISO date upper bound"),
|
|
32443
32632
|
format: exports_external.enum(["json", "csv"]).optional().describe("Output format (default: json)")
|
|
32444
32633
|
}
|
|
32445
32634
|
}, async ({ space, session_id, from, since, until, format }) => {
|
|
@@ -32450,13 +32639,13 @@ var init_mcp2 = __esm(() => {
|
|
|
32450
32639
|
});
|
|
32451
32640
|
server.registerTool("create_space", {
|
|
32452
32641
|
title: "Create Space",
|
|
32453
|
-
description: "Create a new space.
|
|
32642
|
+
description: "Create a new space. Creator is auto-joined. Supports nesting (max 3 levels) and project association.",
|
|
32454
32643
|
inputSchema: {
|
|
32455
32644
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
32456
|
-
name: exports_external.string().describe("Space name
|
|
32645
|
+
name: exports_external.string().describe("Space name"),
|
|
32457
32646
|
description: exports_external.string().optional().describe("Space description"),
|
|
32458
|
-
parent_id: exports_external.string().optional().describe("Parent space name
|
|
32459
|
-
project_id: exports_external.string().optional().describe("Project ID to associate
|
|
32647
|
+
parent_id: exports_external.string().optional().describe("Parent space name (max 3 levels deep)"),
|
|
32648
|
+
project_id: exports_external.string().optional().describe("Project ID to associate with")
|
|
32460
32649
|
}
|
|
32461
32650
|
}, async ({ from: fromParam, name, description, parent_id, project_id }) => {
|
|
32462
32651
|
const agent = resolveIdentity(fromParam);
|
|
@@ -32468,7 +32657,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32468
32657
|
} catch (e) {
|
|
32469
32658
|
if (e.message?.includes("UNIQUE constraint")) {
|
|
32470
32659
|
return {
|
|
32471
|
-
content: [{ type: "text", text: `
|
|
32660
|
+
content: [{ type: "text", text: `space "${name}" already exists` }],
|
|
32472
32661
|
isError: true
|
|
32473
32662
|
};
|
|
32474
32663
|
}
|
|
@@ -32480,11 +32669,11 @@ var init_mcp2 = __esm(() => {
|
|
|
32480
32669
|
});
|
|
32481
32670
|
server.registerTool("list_spaces", {
|
|
32482
32671
|
title: "List Spaces",
|
|
32483
|
-
description: "List
|
|
32672
|
+
description: "List spaces with member/message counts. Archived spaces excluded by default.",
|
|
32484
32673
|
inputSchema: {
|
|
32485
32674
|
project_id: exports_external.string().optional().describe("Filter by project ID"),
|
|
32486
|
-
parent_id: exports_external.string().optional().describe("Filter by parent space
|
|
32487
|
-
include_archived: exports_external.boolean().optional().describe("Include archived spaces
|
|
32675
|
+
parent_id: exports_external.string().optional().describe("Filter by parent space. Use 'null' for top-level only."),
|
|
32676
|
+
include_archived: exports_external.boolean().optional().describe("Include archived spaces")
|
|
32488
32677
|
}
|
|
32489
32678
|
}, async ({ project_id, parent_id, include_archived }) => {
|
|
32490
32679
|
const opts = {};
|
|
@@ -32510,14 +32699,14 @@ var init_mcp2 = __esm(() => {
|
|
|
32510
32699
|
space: exports_external.string().describe("Space name"),
|
|
32511
32700
|
content: exports_external.string().describe("Message content"),
|
|
32512
32701
|
priority: exports_external.enum(["low", "normal", "high", "urgent"]).optional().describe("Message priority"),
|
|
32513
|
-
blocking: exports_external.boolean().optional().describe("
|
|
32702
|
+
blocking: exports_external.boolean().optional().describe("Blocking message \u2014 all space members must acknowledge")
|
|
32514
32703
|
}
|
|
32515
32704
|
}, async ({ from: fromParam, space, content, priority, blocking }) => {
|
|
32516
32705
|
const from = resolveIdentity(fromParam);
|
|
32517
32706
|
const sp = getSpace(space);
|
|
32518
32707
|
if (!sp) {
|
|
32519
32708
|
return {
|
|
32520
|
-
content: [{ type: "text", text: `
|
|
32709
|
+
content: [{ type: "text", text: `space "${space}" not found` }],
|
|
32521
32710
|
isError: true
|
|
32522
32711
|
};
|
|
32523
32712
|
}
|
|
@@ -32539,7 +32728,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32539
32728
|
description: "Read messages from a space.",
|
|
32540
32729
|
inputSchema: {
|
|
32541
32730
|
space: exports_external.string().describe("Space name"),
|
|
32542
|
-
since: exports_external.string().optional().describe("
|
|
32731
|
+
since: exports_external.string().optional().describe("ISO timestamp lower bound"),
|
|
32543
32732
|
limit: exports_external.number().optional().describe("Max messages to return")
|
|
32544
32733
|
}
|
|
32545
32734
|
}, async ({ space, since, limit }) => {
|
|
@@ -32560,7 +32749,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32560
32749
|
const ok = joinSpace(space, agent);
|
|
32561
32750
|
if (!ok) {
|
|
32562
32751
|
return {
|
|
32563
|
-
content: [{ type: "text", text: `
|
|
32752
|
+
content: [{ type: "text", text: `space "${space}" not found` }],
|
|
32564
32753
|
isError: true
|
|
32565
32754
|
};
|
|
32566
32755
|
}
|
|
@@ -32584,12 +32773,12 @@ var init_mcp2 = __esm(() => {
|
|
|
32584
32773
|
});
|
|
32585
32774
|
server.registerTool("update_space", {
|
|
32586
32775
|
title: "Update Space",
|
|
32587
|
-
description: "Update a space's description, parent, or project
|
|
32776
|
+
description: "Update a space's description, parent, or project.",
|
|
32588
32777
|
inputSchema: {
|
|
32589
|
-
name: exports_external.string().describe("Space name
|
|
32778
|
+
name: exports_external.string().describe("Space name"),
|
|
32590
32779
|
description: exports_external.string().optional().describe("New description"),
|
|
32591
|
-
parent_id: exports_external.string().optional().describe("New parent space
|
|
32592
|
-
project_id: exports_external.string().optional().describe("New project ID (use 'null' to remove
|
|
32780
|
+
parent_id: exports_external.string().optional().describe("New parent space (use 'null' to remove)"),
|
|
32781
|
+
project_id: exports_external.string().optional().describe("New project ID (use 'null' to remove)")
|
|
32593
32782
|
}
|
|
32594
32783
|
}, async ({ name, description, parent_id, project_id }) => {
|
|
32595
32784
|
const updates = {};
|
|
@@ -32613,7 +32802,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32613
32802
|
});
|
|
32614
32803
|
server.registerTool("archive_space", {
|
|
32615
32804
|
title: "Archive Space",
|
|
32616
|
-
description: "Archive a space.
|
|
32805
|
+
description: "Archive a space. Hidden from list by default.",
|
|
32617
32806
|
inputSchema: {
|
|
32618
32807
|
name: exports_external.string().describe("Space name to archive")
|
|
32619
32808
|
}
|
|
@@ -32651,16 +32840,16 @@ var init_mcp2 = __esm(() => {
|
|
|
32651
32840
|
});
|
|
32652
32841
|
server.registerTool("create_project", {
|
|
32653
32842
|
title: "Create Project",
|
|
32654
|
-
description: "Create a new project
|
|
32843
|
+
description: "Create a new project to organize spaces and agent collaboration.",
|
|
32655
32844
|
inputSchema: {
|
|
32656
32845
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
32657
32846
|
name: exports_external.string().describe("Project name (unique)"),
|
|
32658
32847
|
description: exports_external.string().optional().describe("Project description"),
|
|
32659
|
-
path: exports_external.string().optional().describe("Absolute path
|
|
32848
|
+
path: exports_external.string().optional().describe("Absolute path on disk"),
|
|
32660
32849
|
repository: exports_external.string().optional().describe("Repository URL"),
|
|
32661
|
-
tags: exports_external.string().optional().describe(
|
|
32662
|
-
metadata: exports_external.string().optional().describe("JSON metadata
|
|
32663
|
-
settings: exports_external.string().optional().describe("JSON settings
|
|
32850
|
+
tags: exports_external.string().optional().describe("JSON array of tags"),
|
|
32851
|
+
metadata: exports_external.string().optional().describe("JSON metadata"),
|
|
32852
|
+
settings: exports_external.string().optional().describe("JSON settings")
|
|
32664
32853
|
}
|
|
32665
32854
|
}, async ({ from: fromParam, name, description, path, repository, tags, metadata, settings }) => {
|
|
32666
32855
|
const agent = resolveIdentity(fromParam);
|
|
@@ -32670,7 +32859,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32670
32859
|
parsedTags = JSON.parse(tags);
|
|
32671
32860
|
} catch {
|
|
32672
32861
|
return {
|
|
32673
|
-
content: [{ type: "text", text: "
|
|
32862
|
+
content: [{ type: "text", text: "invalid tags JSON (expected array)" }],
|
|
32674
32863
|
isError: true
|
|
32675
32864
|
};
|
|
32676
32865
|
}
|
|
@@ -32681,7 +32870,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32681
32870
|
parsedMetadata = JSON.parse(metadata);
|
|
32682
32871
|
} catch {
|
|
32683
32872
|
return {
|
|
32684
|
-
content: [{ type: "text", text: "
|
|
32873
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
32685
32874
|
isError: true
|
|
32686
32875
|
};
|
|
32687
32876
|
}
|
|
@@ -32692,7 +32881,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32692
32881
|
parsedSettings = JSON.parse(settings);
|
|
32693
32882
|
} catch {
|
|
32694
32883
|
return {
|
|
32695
|
-
content: [{ type: "text", text: "
|
|
32884
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
32696
32885
|
isError: true
|
|
32697
32886
|
};
|
|
32698
32887
|
}
|
|
@@ -32714,7 +32903,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32714
32903
|
} catch (e) {
|
|
32715
32904
|
if (e.message?.includes("UNIQUE constraint")) {
|
|
32716
32905
|
return {
|
|
32717
|
-
content: [{ type: "text", text: `
|
|
32906
|
+
content: [{ type: "text", text: `project "${name}" already exists` }],
|
|
32718
32907
|
isError: true
|
|
32719
32908
|
};
|
|
32720
32909
|
}
|
|
@@ -32728,7 +32917,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32728
32917
|
title: "List Projects",
|
|
32729
32918
|
description: "List all registered projects.",
|
|
32730
32919
|
inputSchema: {
|
|
32731
|
-
status: exports_external.enum(["active", "archived"]).optional().describe("Filter by
|
|
32920
|
+
status: exports_external.enum(["active", "archived"]).optional().describe("Filter by status")
|
|
32732
32921
|
}
|
|
32733
32922
|
}, async ({ status }) => {
|
|
32734
32923
|
const projects = listProjects(status ? { status } : undefined);
|
|
@@ -32749,7 +32938,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32749
32938
|
}
|
|
32750
32939
|
if (!project) {
|
|
32751
32940
|
return {
|
|
32752
|
-
content: [{ type: "text", text: `
|
|
32941
|
+
content: [{ type: "text", text: `project "${id}" not found` }],
|
|
32753
32942
|
isError: true
|
|
32754
32943
|
};
|
|
32755
32944
|
}
|
|
@@ -32762,14 +32951,14 @@ var init_mcp2 = __esm(() => {
|
|
|
32762
32951
|
description: "Update a project's fields.",
|
|
32763
32952
|
inputSchema: {
|
|
32764
32953
|
id: exports_external.string().describe("Project ID (UUID)"),
|
|
32765
|
-
name: exports_external.string().optional().describe("New
|
|
32954
|
+
name: exports_external.string().optional().describe("New name"),
|
|
32766
32955
|
description: exports_external.string().optional().describe("New description"),
|
|
32767
32956
|
path: exports_external.string().optional().describe("New path"),
|
|
32768
32957
|
status: exports_external.enum(["active", "archived"]).optional().describe("New status"),
|
|
32769
32958
|
repository: exports_external.string().optional().describe("New repository URL"),
|
|
32770
32959
|
tags: exports_external.string().optional().describe("JSON array of tags"),
|
|
32771
|
-
metadata: exports_external.string().optional().describe("JSON metadata
|
|
32772
|
-
settings: exports_external.string().optional().describe("JSON settings
|
|
32960
|
+
metadata: exports_external.string().optional().describe("JSON metadata"),
|
|
32961
|
+
settings: exports_external.string().optional().describe("JSON settings")
|
|
32773
32962
|
}
|
|
32774
32963
|
}, async ({ id, name, description, path, status, repository, tags, metadata, settings }) => {
|
|
32775
32964
|
const updates = {};
|
|
@@ -32788,7 +32977,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32788
32977
|
updates.tags = JSON.parse(tags);
|
|
32789
32978
|
} catch {
|
|
32790
32979
|
return {
|
|
32791
|
-
content: [{ type: "text", text: "
|
|
32980
|
+
content: [{ type: "text", text: "invalid tags JSON" }],
|
|
32792
32981
|
isError: true
|
|
32793
32982
|
};
|
|
32794
32983
|
}
|
|
@@ -32798,7 +32987,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32798
32987
|
updates.metadata = JSON.parse(metadata);
|
|
32799
32988
|
} catch {
|
|
32800
32989
|
return {
|
|
32801
|
-
content: [{ type: "text", text: "
|
|
32990
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
32802
32991
|
isError: true
|
|
32803
32992
|
};
|
|
32804
32993
|
}
|
|
@@ -32808,7 +32997,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32808
32997
|
updates.settings = JSON.parse(settings);
|
|
32809
32998
|
} catch {
|
|
32810
32999
|
return {
|
|
32811
|
-
content: [{ type: "text", text: "
|
|
33000
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
32812
33001
|
isError: true
|
|
32813
33002
|
};
|
|
32814
33003
|
}
|
|
@@ -32827,7 +33016,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32827
33016
|
});
|
|
32828
33017
|
server.registerTool("delete_project", {
|
|
32829
33018
|
title: "Delete Project",
|
|
32830
|
-
description: "Delete a project permanently. Fails if spaces
|
|
33019
|
+
description: "Delete a project permanently. Fails if spaces reference it.",
|
|
32831
33020
|
inputSchema: {
|
|
32832
33021
|
id: exports_external.string().describe("Project ID (UUID)")
|
|
32833
33022
|
}
|
|
@@ -32836,7 +33025,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32836
33025
|
const deleted = deleteProject(id);
|
|
32837
33026
|
if (!deleted) {
|
|
32838
33027
|
return {
|
|
32839
|
-
content: [{ type: "text", text: `
|
|
33028
|
+
content: [{ type: "text", text: `project "${id}" not found` }],
|
|
32840
33029
|
isError: true
|
|
32841
33030
|
};
|
|
32842
33031
|
}
|
|
@@ -32862,7 +33051,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32862
33051
|
const deleted = deleteMessage(id, agent);
|
|
32863
33052
|
if (!deleted) {
|
|
32864
33053
|
return {
|
|
32865
|
-
content: [{ type: "text", text: `
|
|
33054
|
+
content: [{ type: "text", text: `not found or forbidden` }],
|
|
32866
33055
|
isError: true
|
|
32867
33056
|
};
|
|
32868
33057
|
}
|
|
@@ -32883,7 +33072,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32883
33072
|
const msg = editMessage(id, agent, content);
|
|
32884
33073
|
if (!msg) {
|
|
32885
33074
|
return {
|
|
32886
|
-
content: [{ type: "text", text: `
|
|
33075
|
+
content: [{ type: "text", text: `not found or forbidden` }],
|
|
32887
33076
|
isError: true
|
|
32888
33077
|
};
|
|
32889
33078
|
}
|
|
@@ -32893,7 +33082,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32893
33082
|
});
|
|
32894
33083
|
server.registerTool("pin_message", {
|
|
32895
33084
|
title: "Pin Message",
|
|
32896
|
-
description: "Pin a message.
|
|
33085
|
+
description: "Pin a message. Retrieve pinned messages with get_pinned_messages.",
|
|
32897
33086
|
inputSchema: {
|
|
32898
33087
|
id: exports_external.number().describe("Message ID to pin")
|
|
32899
33088
|
}
|
|
@@ -32901,7 +33090,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32901
33090
|
const msg = pinMessage(id);
|
|
32902
33091
|
if (!msg) {
|
|
32903
33092
|
return {
|
|
32904
|
-
content: [{ type: "text", text: `
|
|
33093
|
+
content: [{ type: "text", text: `message #${id} not found` }],
|
|
32905
33094
|
isError: true
|
|
32906
33095
|
};
|
|
32907
33096
|
}
|
|
@@ -32919,7 +33108,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32919
33108
|
const msg = unpinMessage(id);
|
|
32920
33109
|
if (!msg) {
|
|
32921
33110
|
return {
|
|
32922
|
-
content: [{ type: "text", text: `
|
|
33111
|
+
content: [{ type: "text", text: `message #${id} not found` }],
|
|
32923
33112
|
isError: true
|
|
32924
33113
|
};
|
|
32925
33114
|
}
|
|
@@ -32931,7 +33120,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32931
33120
|
title: "Get Pinned Messages",
|
|
32932
33121
|
description: "Retrieve pinned messages, optionally filtered by space or session.",
|
|
32933
33122
|
inputSchema: {
|
|
32934
|
-
space: exports_external.string().optional().describe("Filter by space
|
|
33123
|
+
space: exports_external.string().optional().describe("Filter by space"),
|
|
32935
33124
|
session_id: exports_external.string().optional().describe("Filter by session ID"),
|
|
32936
33125
|
limit: exports_external.number().optional().describe("Max messages to return")
|
|
32937
33126
|
}
|
|
@@ -32957,9 +33146,9 @@ var init_mcp2 = __esm(() => {
|
|
|
32957
33146
|
});
|
|
32958
33147
|
server.registerTool("list_agents", {
|
|
32959
33148
|
title: "List Agents",
|
|
32960
|
-
description: "List
|
|
33149
|
+
description: "List agents with presence status (name, status, last_seen, online).",
|
|
32961
33150
|
inputSchema: {
|
|
32962
|
-
online_only: exports_external.boolean().optional().describe("Only return agents
|
|
33151
|
+
online_only: exports_external.boolean().optional().describe("Only return agents online within last 60s")
|
|
32963
33152
|
}
|
|
32964
33153
|
}, async ({ online_only }) => {
|
|
32965
33154
|
const agents = listAgents({ online_only });
|
|
@@ -32969,7 +33158,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32969
33158
|
});
|
|
32970
33159
|
server.registerTool("get_blockers", {
|
|
32971
33160
|
title: "Get Blockers",
|
|
32972
|
-
description: "Check for unread blocking messages targeting you.
|
|
33161
|
+
description: "Check for unread blocking messages targeting you. Must acknowledge before continuing.",
|
|
32973
33162
|
inputSchema: {
|
|
32974
33163
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var.")
|
|
32975
33164
|
}
|
|
@@ -32982,7 +33171,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32982
33171
|
});
|
|
32983
33172
|
server.registerTool("remove_agent", {
|
|
32984
33173
|
title: "Remove Agent",
|
|
32985
|
-
description: "Remove an agent from the presence list.
|
|
33174
|
+
description: "Remove an agent from the presence list.",
|
|
32986
33175
|
inputSchema: {
|
|
32987
33176
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
32988
33177
|
agent: exports_external.string().optional().describe("Agent to remove (defaults to yourself)")
|
|
@@ -32993,7 +33182,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32993
33182
|
const removed = removePresence(agent);
|
|
32994
33183
|
if (!removed) {
|
|
32995
33184
|
return {
|
|
32996
|
-
content: [{ type: "text", text: `
|
|
33185
|
+
content: [{ type: "text", text: `agent "${agent}" not found` }],
|
|
32997
33186
|
isError: true
|
|
32998
33187
|
};
|
|
32999
33188
|
}
|
|
@@ -33003,7 +33192,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33003
33192
|
});
|
|
33004
33193
|
server.registerTool("rename_agent", {
|
|
33005
33194
|
title: "Rename Agent",
|
|
33006
|
-
description: "Rename an agent in the presence list.
|
|
33195
|
+
description: "Rename an agent in the presence list. Defaults to renaming yourself.",
|
|
33007
33196
|
inputSchema: {
|
|
33008
33197
|
from: exports_external.string().optional().describe("Your current agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
33009
33198
|
new_name: exports_external.string().describe("The new name for the agent")
|
|
@@ -33013,7 +33202,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33013
33202
|
const newName = new_name.trim();
|
|
33014
33203
|
if (!newName) {
|
|
33015
33204
|
return {
|
|
33016
|
-
content: [{ type: "text", text: "
|
|
33205
|
+
content: [{ type: "text", text: "new name cannot be empty" }],
|
|
33017
33206
|
isError: true
|
|
33018
33207
|
};
|
|
33019
33208
|
}
|
|
@@ -33021,7 +33210,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33021
33210
|
const renamed = renameAgent(oldName, newName);
|
|
33022
33211
|
if (!renamed) {
|
|
33023
33212
|
return {
|
|
33024
|
-
content: [{ type: "text", text: `
|
|
33213
|
+
content: [{ type: "text", text: `agent "${oldName}" not found` }],
|
|
33025
33214
|
isError: true
|
|
33026
33215
|
};
|
|
33027
33216
|
}
|
|
@@ -33049,7 +33238,7 @@ var exports_serve = {};
|
|
|
33049
33238
|
__export(exports_serve, {
|
|
33050
33239
|
startDashboardServer: () => startDashboardServer
|
|
33051
33240
|
});
|
|
33052
|
-
import { join as
|
|
33241
|
+
import { join as join5, resolve, sep } from "path";
|
|
33053
33242
|
import { existsSync } from "fs";
|
|
33054
33243
|
function securityHeaders(base) {
|
|
33055
33244
|
const headers = new Headers(base);
|
|
@@ -33120,7 +33309,7 @@ function isSameOrigin(req) {
|
|
|
33120
33309
|
function startDashboardServer(port = 0, host) {
|
|
33121
33310
|
const resolvedPort = normalizePort(port, 0);
|
|
33122
33311
|
const resolvedHost = normalizeHost(host ?? process.env.CONVERSATIONS_DASHBOARD_HOST);
|
|
33123
|
-
const dashboardDist =
|
|
33312
|
+
const dashboardDist = join5(import.meta.dir, "../../dashboard/dist");
|
|
33124
33313
|
const hasDist = existsSync(dashboardDist);
|
|
33125
33314
|
const server2 = Bun.serve({
|
|
33126
33315
|
port: resolvedPort,
|
|
@@ -33504,7 +33693,7 @@ function startDashboardServer(port = 0, host) {
|
|
|
33504
33693
|
headers.set("Content-Type", file2.type);
|
|
33505
33694
|
return new Response(file2, { headers });
|
|
33506
33695
|
}
|
|
33507
|
-
file2 = Bun.file(
|
|
33696
|
+
file2 = Bun.file(join5(dashboardDist, "index.html"));
|
|
33508
33697
|
if (await file2.exists()) {
|
|
33509
33698
|
const headers = securityHeaders();
|
|
33510
33699
|
if (file2.type)
|
|
@@ -33560,7 +33749,8 @@ init_projects();
|
|
|
33560
33749
|
init_db();
|
|
33561
33750
|
init_identity();
|
|
33562
33751
|
init_presence();
|
|
33563
|
-
|
|
33752
|
+
init_terminal_markdown();
|
|
33753
|
+
import chalk3 from "chalk";
|
|
33564
33754
|
import { render } from "ink";
|
|
33565
33755
|
import React8 from "react";
|
|
33566
33756
|
|
|
@@ -33571,7 +33761,7 @@ import { Box as Box6, Text as Text7, useApp, useInput as useInput5 } from "ink";
|
|
|
33571
33761
|
// node_modules/ink-text-input/build/index.js
|
|
33572
33762
|
import React, { useState, useEffect } from "react";
|
|
33573
33763
|
import { Text, useInput } from "ink";
|
|
33574
|
-
import
|
|
33764
|
+
import chalk2 from "chalk";
|
|
33575
33765
|
function TextInput({ value: originalValue, placeholder = "", focus = true, mask, highlightPastedText = false, showCursor = true, onChange, onSubmit }) {
|
|
33576
33766
|
const [state, setState] = useState({
|
|
33577
33767
|
cursorOffset: (originalValue || "").length,
|
|
@@ -33596,17 +33786,17 @@ function TextInput({ value: originalValue, placeholder = "", focus = true, mask,
|
|
|
33596
33786
|
const cursorActualWidth = highlightPastedText ? cursorWidth : 0;
|
|
33597
33787
|
const value = mask ? mask.repeat(originalValue.length) : originalValue;
|
|
33598
33788
|
let renderedValue = value;
|
|
33599
|
-
let renderedPlaceholder = placeholder ?
|
|
33789
|
+
let renderedPlaceholder = placeholder ? chalk2.grey(placeholder) : undefined;
|
|
33600
33790
|
if (showCursor && focus) {
|
|
33601
|
-
renderedPlaceholder = placeholder.length > 0 ?
|
|
33602
|
-
renderedValue = value.length > 0 ? "" :
|
|
33791
|
+
renderedPlaceholder = placeholder.length > 0 ? chalk2.inverse(placeholder[0]) + chalk2.grey(placeholder.slice(1)) : chalk2.inverse(" ");
|
|
33792
|
+
renderedValue = value.length > 0 ? "" : chalk2.inverse(" ");
|
|
33603
33793
|
let i = 0;
|
|
33604
33794
|
for (const char of value) {
|
|
33605
|
-
renderedValue += i >= cursorOffset - cursorActualWidth && i <= cursorOffset ?
|
|
33795
|
+
renderedValue += i >= cursorOffset - cursorActualWidth && i <= cursorOffset ? chalk2.inverse(char) : char;
|
|
33606
33796
|
i++;
|
|
33607
33797
|
}
|
|
33608
33798
|
if (value.length > 0 && cursorOffset === value.length) {
|
|
33609
|
-
renderedValue +=
|
|
33799
|
+
renderedValue += chalk2.inverse(" ");
|
|
33610
33800
|
}
|
|
33611
33801
|
}
|
|
33612
33802
|
useInput((input, key) => {
|
|
@@ -34507,15 +34697,15 @@ program2.command("send").description("Send a message to an agent").argument("<me
|
|
|
34507
34697
|
const content = typeof message === "string" ? message : "";
|
|
34508
34698
|
const session = typeof opts.session === "string" && opts.session.trim() ? opts.session.trim() : undefined;
|
|
34509
34699
|
if (!from) {
|
|
34510
|
-
console.error(
|
|
34700
|
+
console.error(chalk3.red("Sender identity is required."));
|
|
34511
34701
|
process.exit(1);
|
|
34512
34702
|
}
|
|
34513
34703
|
if (!to) {
|
|
34514
|
-
console.error(
|
|
34704
|
+
console.error(chalk3.red("Recipient is required."));
|
|
34515
34705
|
process.exit(1);
|
|
34516
34706
|
}
|
|
34517
34707
|
if (!content.trim()) {
|
|
34518
|
-
console.error(
|
|
34708
|
+
console.error(chalk3.red("Message content cannot be empty."));
|
|
34519
34709
|
process.exit(1);
|
|
34520
34710
|
}
|
|
34521
34711
|
let metadata;
|
|
@@ -34523,7 +34713,7 @@ program2.command("send").description("Send a message to an agent").argument("<me
|
|
|
34523
34713
|
try {
|
|
34524
34714
|
metadata = JSON.parse(opts.metadata);
|
|
34525
34715
|
} catch {
|
|
34526
|
-
console.error(
|
|
34716
|
+
console.error(chalk3.red("Invalid --metadata JSON."));
|
|
34527
34717
|
process.exit(1);
|
|
34528
34718
|
}
|
|
34529
34719
|
}
|
|
@@ -34542,7 +34732,7 @@ program2.command("send").description("Send a message to an agent").argument("<me
|
|
|
34542
34732
|
if (opts.json) {
|
|
34543
34733
|
console.log(JSON.stringify(msg, null, 2));
|
|
34544
34734
|
} else {
|
|
34545
|
-
console.log(
|
|
34735
|
+
console.log(chalk3.green(`Message sent`) + chalk3.dim(` (id: ${msg.id}, session: ${msg.session_id})`));
|
|
34546
34736
|
}
|
|
34547
34737
|
closeDb();
|
|
34548
34738
|
});
|
|
@@ -34572,15 +34762,20 @@ program2.command("read").description("Read messages").option("--session <id>", "
|
|
|
34572
34762
|
console.log(JSON.stringify(messages, null, 2));
|
|
34573
34763
|
} else {
|
|
34574
34764
|
if (messages.length === 0) {
|
|
34575
|
-
console.log(
|
|
34765
|
+
console.log(chalk3.dim("No messages found."));
|
|
34576
34766
|
} else {
|
|
34577
34767
|
for (const msg of messages) {
|
|
34578
|
-
const time3 =
|
|
34579
|
-
const from =
|
|
34580
|
-
const to = msg.space ?
|
|
34581
|
-
const priority = msg.priority !== "normal" ?
|
|
34582
|
-
const unread = !msg.read_at ?
|
|
34583
|
-
console.log(`${time3} ${from} \u2192 ${to}${priority}${unread}
|
|
34768
|
+
const time3 = chalk3.dim(msg.created_at.slice(11, 19));
|
|
34769
|
+
const from = chalk3.cyan(msg.from_agent);
|
|
34770
|
+
const to = msg.space ? chalk3.magenta(`#${msg.space}`) : chalk3.yellow(msg.to_agent);
|
|
34771
|
+
const priority = msg.priority !== "normal" ? chalk3.red(` [${msg.priority}]`) : "";
|
|
34772
|
+
const unread = !msg.read_at ? chalk3.green(" *") : "";
|
|
34773
|
+
console.log(`${time3} ${from} \u2192 ${to}${priority}${unread}`);
|
|
34774
|
+
const rendered = renderContent(msg.content);
|
|
34775
|
+
const indented = rendered.split(`
|
|
34776
|
+
`).map((l) => " " + l).join(`
|
|
34777
|
+
`);
|
|
34778
|
+
console.log(indented);
|
|
34584
34779
|
}
|
|
34585
34780
|
}
|
|
34586
34781
|
}
|
|
@@ -34589,7 +34784,7 @@ program2.command("read").description("Read messages").option("--session <id>", "
|
|
|
34589
34784
|
program2.command("search").description("Search messages by content").argument("<query>", "Search query string").option("--space <name>", "Filter by space").option("--from <agent>", "Filter by sender").option("--to <agent>", "Filter by recipient").option("--limit <n>", "Max results to return", parseInt).option("--json", "Output as JSON").action((query, opts) => {
|
|
34590
34785
|
const q = typeof query === "string" ? query.trim() : "";
|
|
34591
34786
|
if (!q) {
|
|
34592
|
-
console.error(
|
|
34787
|
+
console.error(chalk3.red("Search query cannot be empty."));
|
|
34593
34788
|
process.exit(1);
|
|
34594
34789
|
}
|
|
34595
34790
|
const messages = searchMessages({
|
|
@@ -34603,16 +34798,16 @@ program2.command("search").description("Search messages by content").argument("<
|
|
|
34603
34798
|
console.log(JSON.stringify(messages, null, 2));
|
|
34604
34799
|
} else {
|
|
34605
34800
|
if (messages.length === 0) {
|
|
34606
|
-
console.log(
|
|
34801
|
+
console.log(chalk3.dim("No messages found."));
|
|
34607
34802
|
} else {
|
|
34608
|
-
console.log(
|
|
34803
|
+
console.log(chalk3.dim(`Found ${messages.length} result(s) for "${q}":
|
|
34609
34804
|
`));
|
|
34610
34805
|
for (const msg of messages) {
|
|
34611
|
-
const time3 =
|
|
34612
|
-
const from =
|
|
34613
|
-
const to = msg.space ?
|
|
34614
|
-
const priority = msg.priority !== "normal" ?
|
|
34615
|
-
const unread = !msg.read_at ?
|
|
34806
|
+
const time3 = chalk3.dim(msg.created_at.slice(11, 19));
|
|
34807
|
+
const from = chalk3.cyan(msg.from_agent);
|
|
34808
|
+
const to = msg.space ? chalk3.magenta(`#${msg.space}`) : chalk3.yellow(msg.to_agent);
|
|
34809
|
+
const priority = msg.priority !== "normal" ? chalk3.red(` [${msg.priority}]`) : "";
|
|
34810
|
+
const unread = !msg.read_at ? chalk3.green(" *") : "";
|
|
34616
34811
|
console.log(`${time3} ${from} \u2192 ${to}${priority}${unread}: ${msg.content}`);
|
|
34617
34812
|
}
|
|
34618
34813
|
}
|
|
@@ -34625,12 +34820,12 @@ program2.command("sessions").description("List conversation sessions").option("-
|
|
|
34625
34820
|
console.log(JSON.stringify(sessions, null, 2));
|
|
34626
34821
|
} else {
|
|
34627
34822
|
if (sessions.length === 0) {
|
|
34628
|
-
console.log(
|
|
34823
|
+
console.log(chalk3.dim("No sessions found."));
|
|
34629
34824
|
} else {
|
|
34630
34825
|
for (const s of sessions) {
|
|
34631
|
-
const unread = s.unread_count > 0 ?
|
|
34826
|
+
const unread = s.unread_count > 0 ? chalk3.green(` (${s.unread_count} unread)`) : "";
|
|
34632
34827
|
const participants = s.participants.join(", ");
|
|
34633
|
-
console.log(`${
|
|
34828
|
+
console.log(`${chalk3.bold(s.session_id)} \u2014 ${participants} \u2014 ${s.message_count} messages${unread}`);
|
|
34634
34829
|
}
|
|
34635
34830
|
}
|
|
34636
34831
|
}
|
|
@@ -34639,17 +34834,17 @@ program2.command("sessions").description("List conversation sessions").option("-
|
|
|
34639
34834
|
program2.command("reply").description("Reply to a message (uses same session)").argument("<message>", "Reply content").requiredOption("--to <message-id>", "Message ID to reply to", parseInt).option("--from <agent>", "Sender agent ID").option("--priority <level>", "Priority: low, normal, high, urgent", "normal").option("--json", "Output as JSON").action((message, opts) => {
|
|
34640
34835
|
const original = getMessageById(opts.to);
|
|
34641
34836
|
if (!original) {
|
|
34642
|
-
console.error(
|
|
34837
|
+
console.error(chalk3.red(`Message #${opts.to} not found.`));
|
|
34643
34838
|
process.exit(1);
|
|
34644
34839
|
}
|
|
34645
34840
|
const from = resolveIdentity(opts.from).trim();
|
|
34646
34841
|
const content = typeof message === "string" ? message : "";
|
|
34647
34842
|
if (!from) {
|
|
34648
|
-
console.error(
|
|
34843
|
+
console.error(chalk3.red("Sender identity is required."));
|
|
34649
34844
|
process.exit(1);
|
|
34650
34845
|
}
|
|
34651
34846
|
if (!content.trim()) {
|
|
34652
|
-
console.error(
|
|
34847
|
+
console.error(chalk3.red("Reply content cannot be empty."));
|
|
34653
34848
|
process.exit(1);
|
|
34654
34849
|
}
|
|
34655
34850
|
const space = original.space || (original.session_id?.startsWith("space:") ? original.session_id.slice(6) : undefined);
|
|
@@ -34665,7 +34860,7 @@ program2.command("reply").description("Reply to a message (uses same session)").
|
|
|
34665
34860
|
if (opts.json) {
|
|
34666
34861
|
console.log(JSON.stringify(msg, null, 2));
|
|
34667
34862
|
} else {
|
|
34668
|
-
console.log(
|
|
34863
|
+
console.log(chalk3.green(`Reply sent`) + chalk3.dim(` (id: ${msg.id}, session: ${msg.session_id})`));
|
|
34669
34864
|
}
|
|
34670
34865
|
closeDb();
|
|
34671
34866
|
});
|
|
@@ -34681,13 +34876,13 @@ program2.command("mark-read").description("Mark messages as read").argument("[id
|
|
|
34681
34876
|
} else if (ids.length > 0) {
|
|
34682
34877
|
count = markRead(ids.map(Number), agent);
|
|
34683
34878
|
} else {
|
|
34684
|
-
console.error(
|
|
34879
|
+
console.error(chalk3.red("Provide message IDs, --all, --session, or --space flag."));
|
|
34685
34880
|
process.exit(1);
|
|
34686
34881
|
}
|
|
34687
34882
|
if (opts.json) {
|
|
34688
34883
|
console.log(JSON.stringify({ marked_read: count }));
|
|
34689
34884
|
} else {
|
|
34690
|
-
console.log(
|
|
34885
|
+
console.log(chalk3.green(`Marked ${count} message(s) as read.`));
|
|
34691
34886
|
}
|
|
34692
34887
|
closeDb();
|
|
34693
34888
|
});
|
|
@@ -34723,7 +34918,7 @@ program2.command("status").description("Show database stats").option("--json", "
|
|
|
34723
34918
|
if (opts.json) {
|
|
34724
34919
|
console.log(JSON.stringify(stats, null, 2));
|
|
34725
34920
|
} else {
|
|
34726
|
-
console.log(
|
|
34921
|
+
console.log(chalk3.bold("Conversations Status"));
|
|
34727
34922
|
console.log(` DB Path: ${stats.db_path}`);
|
|
34728
34923
|
console.log(` Messages: ${stats.total_messages}`);
|
|
34729
34924
|
console.log(` Sessions: ${stats.total_sessions}`);
|
|
@@ -34745,7 +34940,7 @@ program2.command("update").description("Check for and install updates").option("
|
|
|
34745
34940
|
if (opts.json) {
|
|
34746
34941
|
console.log(JSON.stringify({ error: "Failed to check npm registry" }));
|
|
34747
34942
|
} else {
|
|
34748
|
-
console.error(
|
|
34943
|
+
console.error(chalk3.red("Failed to check npm registry for updates."));
|
|
34749
34944
|
}
|
|
34750
34945
|
process.exit(1);
|
|
34751
34946
|
}
|
|
@@ -34754,18 +34949,18 @@ program2.command("update").description("Check for and install updates").option("
|
|
|
34754
34949
|
if (opts.json) {
|
|
34755
34950
|
console.log(JSON.stringify({ current, latest, updateAvailable }));
|
|
34756
34951
|
} else if (updateAvailable) {
|
|
34757
|
-
console.log(`Current version: ${
|
|
34758
|
-
console.log(`Latest version: ${
|
|
34759
|
-
console.log(
|
|
34952
|
+
console.log(`Current version: ${chalk3.yellow(current)}`);
|
|
34953
|
+
console.log(`Latest version: ${chalk3.green(latest)}`);
|
|
34954
|
+
console.log(chalk3.cyan(`Run ${chalk3.bold("conversations update")} to install.`));
|
|
34760
34955
|
} else {
|
|
34761
|
-
console.log(
|
|
34956
|
+
console.log(chalk3.green(`Already on latest version (${current})`));
|
|
34762
34957
|
}
|
|
34763
34958
|
return;
|
|
34764
34959
|
}
|
|
34765
34960
|
if (opts.json) {
|
|
34766
34961
|
console.log(JSON.stringify({ current, latest, updateAvailable, status: "updating" }));
|
|
34767
34962
|
} else {
|
|
34768
|
-
console.log(`Updating from ${
|
|
34963
|
+
console.log(`Updating from ${chalk3.yellow(current)} to ${chalk3.green(latest)}...`);
|
|
34769
34964
|
}
|
|
34770
34965
|
const proc = Bun.spawn(["bun", "install", "-g", `@hasna/conversations@${latest}`], {
|
|
34771
34966
|
stdout: "inherit",
|
|
@@ -34774,14 +34969,14 @@ program2.command("update").description("Check for and install updates").option("
|
|
|
34774
34969
|
const exitCode = await proc.exited;
|
|
34775
34970
|
if (exitCode === 0) {
|
|
34776
34971
|
if (!opts.json) {
|
|
34777
|
-
console.log(
|
|
34972
|
+
console.log(chalk3.green(`
|
|
34778
34973
|
Successfully updated to v${latest}`));
|
|
34779
34974
|
}
|
|
34780
34975
|
} else {
|
|
34781
34976
|
if (opts.json) {
|
|
34782
34977
|
console.log(JSON.stringify({ error: "Update failed", exitCode }));
|
|
34783
34978
|
} else {
|
|
34784
|
-
console.error(
|
|
34979
|
+
console.error(chalk3.red(`
|
|
34785
34980
|
Update failed (exit code ${exitCode})`));
|
|
34786
34981
|
}
|
|
34787
34982
|
process.exit(1);
|
|
@@ -34792,11 +34987,11 @@ space.command("create").description("Create a new space").argument("<name>", "Sp
|
|
|
34792
34987
|
const agent = resolveIdentity(opts.from).trim();
|
|
34793
34988
|
const spaceName = typeof name === "string" ? name.trim() : "";
|
|
34794
34989
|
if (!agent) {
|
|
34795
|
-
console.error(
|
|
34990
|
+
console.error(chalk3.red("Creator identity is required."));
|
|
34796
34991
|
process.exit(1);
|
|
34797
34992
|
}
|
|
34798
34993
|
if (!spaceName) {
|
|
34799
|
-
console.error(
|
|
34994
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
34800
34995
|
process.exit(1);
|
|
34801
34996
|
}
|
|
34802
34997
|
try {
|
|
@@ -34809,14 +35004,14 @@ space.command("create").description("Create a new space").argument("<name>", "Sp
|
|
|
34809
35004
|
if (opts.json) {
|
|
34810
35005
|
console.log(JSON.stringify(sp, null, 2));
|
|
34811
35006
|
} else {
|
|
34812
|
-
console.log(
|
|
35007
|
+
console.log(chalk3.green(`Space #${sp.name} created`) + (sp.description ? chalk3.dim(` \u2014 ${sp.description}`) : ""));
|
|
34813
35008
|
}
|
|
34814
35009
|
} catch (e) {
|
|
34815
35010
|
if (e.message?.includes("UNIQUE constraint")) {
|
|
34816
|
-
console.error(
|
|
35011
|
+
console.error(chalk3.red(`Space #${spaceName} already exists.`));
|
|
34817
35012
|
process.exit(1);
|
|
34818
35013
|
}
|
|
34819
|
-
console.error(
|
|
35014
|
+
console.error(chalk3.red(e.message));
|
|
34820
35015
|
process.exit(1);
|
|
34821
35016
|
}
|
|
34822
35017
|
closeDb();
|
|
@@ -34837,13 +35032,13 @@ space.command("list").description("List all spaces").option("--project <id>", "F
|
|
|
34837
35032
|
console.log(JSON.stringify(spaces, null, 2));
|
|
34838
35033
|
} else {
|
|
34839
35034
|
if (spaces.length === 0) {
|
|
34840
|
-
console.log(
|
|
35035
|
+
console.log(chalk3.dim("No spaces found."));
|
|
34841
35036
|
} else {
|
|
34842
35037
|
for (const sp of spaces) {
|
|
34843
|
-
const desc = sp.description ?
|
|
34844
|
-
const parent = sp.parent_id ?
|
|
34845
|
-
const archived = sp.archived_at ?
|
|
34846
|
-
console.log(`${
|
|
35038
|
+
const desc = sp.description ? chalk3.dim(` \u2014 ${sp.description}`) : "";
|
|
35039
|
+
const parent = sp.parent_id ? chalk3.dim(` (child of ${sp.parent_id})`) : "";
|
|
35040
|
+
const archived = sp.archived_at ? chalk3.yellow(" [archived]") : "";
|
|
35041
|
+
console.log(`${chalk3.magenta(`#${sp.name}`)}${desc}${parent}${archived} ${sp.member_count} members, ${sp.message_count} messages`);
|
|
34847
35042
|
}
|
|
34848
35043
|
}
|
|
34849
35044
|
}
|
|
@@ -34852,7 +35047,7 @@ space.command("list").description("List all spaces").option("--project <id>", "F
|
|
|
34852
35047
|
space.command("update").description("Update a space").argument("<name>", "Space name").option("--description <text>", "New description").option("--parent <name>", "New parent space name").option("--project <id>", "New project ID").option("--json", "Output as JSON").action((name, opts) => {
|
|
34853
35048
|
const spaceName = typeof name === "string" ? name.trim() : "";
|
|
34854
35049
|
if (!spaceName) {
|
|
34855
|
-
console.error(
|
|
35050
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
34856
35051
|
process.exit(1);
|
|
34857
35052
|
}
|
|
34858
35053
|
const updates = {};
|
|
@@ -34867,10 +35062,10 @@ space.command("update").description("Update a space").argument("<name>", "Space
|
|
|
34867
35062
|
if (opts.json) {
|
|
34868
35063
|
console.log(JSON.stringify(sp, null, 2));
|
|
34869
35064
|
} else {
|
|
34870
|
-
console.log(
|
|
35065
|
+
console.log(chalk3.green(`Space #${sp.name} updated.`));
|
|
34871
35066
|
}
|
|
34872
35067
|
} catch (e) {
|
|
34873
|
-
console.error(
|
|
35068
|
+
console.error(chalk3.red(e.message));
|
|
34874
35069
|
process.exit(1);
|
|
34875
35070
|
}
|
|
34876
35071
|
closeDb();
|
|
@@ -34878,7 +35073,7 @@ space.command("update").description("Update a space").argument("<name>", "Space
|
|
|
34878
35073
|
space.command("archive").description("Archive a space").argument("<name>", "Space name").option("--json", "Output as JSON").action((name, opts) => {
|
|
34879
35074
|
const spaceName = typeof name === "string" ? name.trim() : "";
|
|
34880
35075
|
if (!spaceName) {
|
|
34881
|
-
console.error(
|
|
35076
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
34882
35077
|
process.exit(1);
|
|
34883
35078
|
}
|
|
34884
35079
|
try {
|
|
@@ -34886,10 +35081,10 @@ space.command("archive").description("Archive a space").argument("<name>", "Spac
|
|
|
34886
35081
|
if (opts.json) {
|
|
34887
35082
|
console.log(JSON.stringify(sp, null, 2));
|
|
34888
35083
|
} else {
|
|
34889
|
-
console.log(
|
|
35084
|
+
console.log(chalk3.green(`Space #${sp.name} archived.`));
|
|
34890
35085
|
}
|
|
34891
35086
|
} catch (e) {
|
|
34892
|
-
console.error(
|
|
35087
|
+
console.error(chalk3.red(e.message));
|
|
34893
35088
|
process.exit(1);
|
|
34894
35089
|
}
|
|
34895
35090
|
closeDb();
|
|
@@ -34897,7 +35092,7 @@ space.command("archive").description("Archive a space").argument("<name>", "Spac
|
|
|
34897
35092
|
space.command("unarchive").description("Unarchive a space").argument("<name>", "Space name").option("--json", "Output as JSON").action((name, opts) => {
|
|
34898
35093
|
const spaceName = typeof name === "string" ? name.trim() : "";
|
|
34899
35094
|
if (!spaceName) {
|
|
34900
|
-
console.error(
|
|
35095
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
34901
35096
|
process.exit(1);
|
|
34902
35097
|
}
|
|
34903
35098
|
try {
|
|
@@ -34905,10 +35100,10 @@ space.command("unarchive").description("Unarchive a space").argument("<name>", "
|
|
|
34905
35100
|
if (opts.json) {
|
|
34906
35101
|
console.log(JSON.stringify(sp, null, 2));
|
|
34907
35102
|
} else {
|
|
34908
|
-
console.log(
|
|
35103
|
+
console.log(chalk3.green(`Space #${sp.name} unarchived.`));
|
|
34909
35104
|
}
|
|
34910
35105
|
} catch (e) {
|
|
34911
|
-
console.error(
|
|
35106
|
+
console.error(chalk3.red(e.message));
|
|
34912
35107
|
process.exit(1);
|
|
34913
35108
|
}
|
|
34914
35109
|
closeDb();
|
|
@@ -34918,20 +35113,20 @@ space.command("send").description("Send a message to a space").argument("<space>
|
|
|
34918
35113
|
const spaceArg = typeof spaceName === "string" ? spaceName.trim() : "";
|
|
34919
35114
|
const content = typeof message === "string" ? message : "";
|
|
34920
35115
|
if (!from) {
|
|
34921
|
-
console.error(
|
|
35116
|
+
console.error(chalk3.red("Sender identity is required."));
|
|
34922
35117
|
process.exit(1);
|
|
34923
35118
|
}
|
|
34924
35119
|
if (!spaceArg) {
|
|
34925
|
-
console.error(
|
|
35120
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
34926
35121
|
process.exit(1);
|
|
34927
35122
|
}
|
|
34928
35123
|
if (!content.trim()) {
|
|
34929
|
-
console.error(
|
|
35124
|
+
console.error(chalk3.red("Message content cannot be empty."));
|
|
34930
35125
|
process.exit(1);
|
|
34931
35126
|
}
|
|
34932
35127
|
const sp = getSpace(spaceArg);
|
|
34933
35128
|
if (!sp) {
|
|
34934
|
-
console.error(
|
|
35129
|
+
console.error(chalk3.red(`Space #${spaceArg} not found.`));
|
|
34935
35130
|
process.exit(1);
|
|
34936
35131
|
}
|
|
34937
35132
|
const msg = sendMessage({
|
|
@@ -34945,14 +35140,14 @@ space.command("send").description("Send a message to a space").argument("<space>
|
|
|
34945
35140
|
if (opts.json) {
|
|
34946
35141
|
console.log(JSON.stringify(msg, null, 2));
|
|
34947
35142
|
} else {
|
|
34948
|
-
console.log(
|
|
35143
|
+
console.log(chalk3.green(`Message sent to #${spaceArg}`) + chalk3.dim(` (id: ${msg.id})`));
|
|
34949
35144
|
}
|
|
34950
35145
|
closeDb();
|
|
34951
35146
|
});
|
|
34952
35147
|
space.command("read").description("Read messages from a space").argument("<space>", "Space name").option("--since <timestamp>", "Messages after this ISO timestamp").option("--limit <n>", "Max messages to return", parseInt).option("--json", "Output as JSON").action((spaceName, opts) => {
|
|
34953
35148
|
const spaceArg = typeof spaceName === "string" ? spaceName.trim() : "";
|
|
34954
35149
|
if (!spaceArg) {
|
|
34955
|
-
console.error(
|
|
35150
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
34956
35151
|
process.exit(1);
|
|
34957
35152
|
}
|
|
34958
35153
|
const messages = readMessages({
|
|
@@ -34964,13 +35159,18 @@ space.command("read").description("Read messages from a space").argument("<space
|
|
|
34964
35159
|
console.log(JSON.stringify(messages, null, 2));
|
|
34965
35160
|
} else {
|
|
34966
35161
|
if (messages.length === 0) {
|
|
34967
|
-
console.log(
|
|
35162
|
+
console.log(chalk3.dim(`No messages in #${spaceArg}.`));
|
|
34968
35163
|
} else {
|
|
34969
35164
|
for (const msg of messages) {
|
|
34970
|
-
const time3 =
|
|
34971
|
-
const from =
|
|
34972
|
-
const priority = msg.priority !== "normal" ?
|
|
34973
|
-
console.log(`${time3} ${from} \u2192 ${
|
|
35165
|
+
const time3 = chalk3.dim(msg.created_at.slice(11, 19));
|
|
35166
|
+
const from = chalk3.cyan(msg.from_agent);
|
|
35167
|
+
const priority = msg.priority !== "normal" ? chalk3.red(` [${msg.priority}]`) : "";
|
|
35168
|
+
console.log(`${time3} ${from} \u2192 ${chalk3.magenta(`#${spaceArg}`)}${priority}`);
|
|
35169
|
+
const rendered = renderContent(msg.content);
|
|
35170
|
+
const indented = rendered.split(`
|
|
35171
|
+
`).map((l) => " " + l).join(`
|
|
35172
|
+
`);
|
|
35173
|
+
console.log(indented);
|
|
34974
35174
|
}
|
|
34975
35175
|
}
|
|
34976
35176
|
}
|
|
@@ -34980,22 +35180,22 @@ space.command("join").description("Join a space").argument("<space>", "Space nam
|
|
|
34980
35180
|
const agent = resolveIdentity(opts.from).trim();
|
|
34981
35181
|
const spaceArg = typeof spaceName === "string" ? spaceName.trim() : "";
|
|
34982
35182
|
if (!agent) {
|
|
34983
|
-
console.error(
|
|
35183
|
+
console.error(chalk3.red("Agent identity is required."));
|
|
34984
35184
|
process.exit(1);
|
|
34985
35185
|
}
|
|
34986
35186
|
if (!spaceArg) {
|
|
34987
|
-
console.error(
|
|
35187
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
34988
35188
|
process.exit(1);
|
|
34989
35189
|
}
|
|
34990
35190
|
const ok = joinSpace(spaceArg, agent);
|
|
34991
35191
|
if (!ok) {
|
|
34992
|
-
console.error(
|
|
35192
|
+
console.error(chalk3.red(`Space #${spaceArg} not found.`));
|
|
34993
35193
|
process.exit(1);
|
|
34994
35194
|
}
|
|
34995
35195
|
if (opts.json) {
|
|
34996
35196
|
console.log(JSON.stringify({ space: spaceArg, agent, joined: true }));
|
|
34997
35197
|
} else {
|
|
34998
|
-
console.log(
|
|
35198
|
+
console.log(chalk3.green(`${agent} joined #${spaceArg}`));
|
|
34999
35199
|
}
|
|
35000
35200
|
closeDb();
|
|
35001
35201
|
});
|
|
@@ -35003,11 +35203,11 @@ space.command("leave").description("Leave a space").argument("<space>", "Space n
|
|
|
35003
35203
|
const agent = resolveIdentity(opts.from).trim();
|
|
35004
35204
|
const spaceArg = typeof spaceName === "string" ? spaceName.trim() : "";
|
|
35005
35205
|
if (!agent) {
|
|
35006
|
-
console.error(
|
|
35206
|
+
console.error(chalk3.red("Agent identity is required."));
|
|
35007
35207
|
process.exit(1);
|
|
35008
35208
|
}
|
|
35009
35209
|
if (!spaceArg) {
|
|
35010
|
-
console.error(
|
|
35210
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
35011
35211
|
process.exit(1);
|
|
35012
35212
|
}
|
|
35013
35213
|
const ok = leaveSpace(spaceArg, agent);
|
|
@@ -35015,9 +35215,9 @@ space.command("leave").description("Leave a space").argument("<space>", "Space n
|
|
|
35015
35215
|
console.log(JSON.stringify({ space: spaceArg, agent, left: ok }));
|
|
35016
35216
|
} else {
|
|
35017
35217
|
if (ok) {
|
|
35018
|
-
console.log(
|
|
35218
|
+
console.log(chalk3.green(`${agent} left #${spaceArg}`));
|
|
35019
35219
|
} else {
|
|
35020
|
-
console.log(
|
|
35220
|
+
console.log(chalk3.dim(`${agent} was not a member of #${spaceArg}`));
|
|
35021
35221
|
}
|
|
35022
35222
|
}
|
|
35023
35223
|
closeDb();
|
|
@@ -35025,7 +35225,7 @@ space.command("leave").description("Leave a space").argument("<space>", "Space n
|
|
|
35025
35225
|
space.command("members").description("List space members").argument("<space>", "Space name").option("--json", "Output as JSON").action((spaceName, opts) => {
|
|
35026
35226
|
const spaceArg = typeof spaceName === "string" ? spaceName.trim() : "";
|
|
35027
35227
|
if (!spaceArg) {
|
|
35028
|
-
console.error(
|
|
35228
|
+
console.error(chalk3.red("Space name cannot be empty."));
|
|
35029
35229
|
process.exit(1);
|
|
35030
35230
|
}
|
|
35031
35231
|
const members = getSpaceMembers(spaceArg);
|
|
@@ -35033,11 +35233,11 @@ space.command("members").description("List space members").argument("<space>", "
|
|
|
35033
35233
|
console.log(JSON.stringify(members, null, 2));
|
|
35034
35234
|
} else {
|
|
35035
35235
|
if (members.length === 0) {
|
|
35036
|
-
console.log(
|
|
35236
|
+
console.log(chalk3.dim(`No members in #${spaceArg}.`));
|
|
35037
35237
|
} else {
|
|
35038
|
-
console.log(
|
|
35238
|
+
console.log(chalk3.magenta(`#${spaceArg}`) + chalk3.dim(` \u2014 ${members.length} member(s)`));
|
|
35039
35239
|
for (const m of members) {
|
|
35040
|
-
console.log(` ${
|
|
35240
|
+
console.log(` ${chalk3.cyan(m.agent)} ${chalk3.dim(`joined ${m.joined_at.slice(0, 10)}`)}`);
|
|
35041
35241
|
}
|
|
35042
35242
|
}
|
|
35043
35243
|
}
|
|
@@ -35048,11 +35248,11 @@ project.command("create").description("Create a new project").argument("<name>",
|
|
|
35048
35248
|
const agent = resolveIdentity(opts.from).trim();
|
|
35049
35249
|
const projectName = typeof name === "string" ? name.trim() : "";
|
|
35050
35250
|
if (!agent) {
|
|
35051
|
-
console.error(
|
|
35251
|
+
console.error(chalk3.red("Creator identity is required."));
|
|
35052
35252
|
process.exit(1);
|
|
35053
35253
|
}
|
|
35054
35254
|
if (!projectName) {
|
|
35055
|
-
console.error(
|
|
35255
|
+
console.error(chalk3.red("Project name cannot be empty."));
|
|
35056
35256
|
process.exit(1);
|
|
35057
35257
|
}
|
|
35058
35258
|
let tags;
|
|
@@ -35060,7 +35260,7 @@ project.command("create").description("Create a new project").argument("<name>",
|
|
|
35060
35260
|
try {
|
|
35061
35261
|
tags = JSON.parse(opts.tags);
|
|
35062
35262
|
} catch {
|
|
35063
|
-
console.error(
|
|
35263
|
+
console.error(chalk3.red("Invalid --tags JSON. Expected array of strings."));
|
|
35064
35264
|
process.exit(1);
|
|
35065
35265
|
}
|
|
35066
35266
|
}
|
|
@@ -35076,14 +35276,14 @@ project.command("create").description("Create a new project").argument("<name>",
|
|
|
35076
35276
|
if (opts.json) {
|
|
35077
35277
|
console.log(JSON.stringify(p, null, 2));
|
|
35078
35278
|
} else {
|
|
35079
|
-
console.log(
|
|
35279
|
+
console.log(chalk3.green(`Project "${p.name}" created`) + chalk3.dim(` (id: ${p.id})`));
|
|
35080
35280
|
}
|
|
35081
35281
|
} catch (e) {
|
|
35082
35282
|
if (e.message?.includes("UNIQUE constraint")) {
|
|
35083
|
-
console.error(
|
|
35283
|
+
console.error(chalk3.red(`Project "${projectName}" already exists.`));
|
|
35084
35284
|
process.exit(1);
|
|
35085
35285
|
}
|
|
35086
|
-
console.error(
|
|
35286
|
+
console.error(chalk3.red(e.message));
|
|
35087
35287
|
process.exit(1);
|
|
35088
35288
|
}
|
|
35089
35289
|
closeDb();
|
|
@@ -35095,12 +35295,12 @@ project.command("list").description("List all projects").option("--status <statu
|
|
|
35095
35295
|
console.log(JSON.stringify(projects, null, 2));
|
|
35096
35296
|
} else {
|
|
35097
35297
|
if (projects.length === 0) {
|
|
35098
|
-
console.log(
|
|
35298
|
+
console.log(chalk3.dim("No projects found."));
|
|
35099
35299
|
} else {
|
|
35100
35300
|
for (const p of projects) {
|
|
35101
|
-
const desc = p.description ?
|
|
35102
|
-
const statusBadge = p.status === "archived" ?
|
|
35103
|
-
console.log(`${
|
|
35301
|
+
const desc = p.description ? chalk3.dim(` \u2014 ${p.description}`) : "";
|
|
35302
|
+
const statusBadge = p.status === "archived" ? chalk3.yellow(" [archived]") : "";
|
|
35303
|
+
console.log(`${chalk3.bold(p.name)}${desc}${statusBadge} ${p.space_count} spaces`);
|
|
35104
35304
|
}
|
|
35105
35305
|
}
|
|
35106
35306
|
}
|
|
@@ -35111,13 +35311,13 @@ project.command("get").description("Get project details").argument("<id-or-name>
|
|
|
35111
35311
|
if (!p)
|
|
35112
35312
|
p = getProjectByName(idOrName);
|
|
35113
35313
|
if (!p) {
|
|
35114
|
-
console.error(
|
|
35314
|
+
console.error(chalk3.red(`Project "${idOrName}" not found.`));
|
|
35115
35315
|
process.exit(1);
|
|
35116
35316
|
}
|
|
35117
35317
|
if (opts.json) {
|
|
35118
35318
|
console.log(JSON.stringify(p, null, 2));
|
|
35119
35319
|
} else {
|
|
35120
|
-
console.log(
|
|
35320
|
+
console.log(chalk3.bold(p.name));
|
|
35121
35321
|
if (p.description)
|
|
35122
35322
|
console.log(` Description: ${p.description}`);
|
|
35123
35323
|
if (p.path)
|
|
@@ -35148,7 +35348,7 @@ project.command("update").description("Update a project").argument("<id>", "Proj
|
|
|
35148
35348
|
try {
|
|
35149
35349
|
updates.tags = JSON.parse(opts.tags);
|
|
35150
35350
|
} catch {
|
|
35151
|
-
console.error(
|
|
35351
|
+
console.error(chalk3.red("Invalid --tags JSON."));
|
|
35152
35352
|
process.exit(1);
|
|
35153
35353
|
}
|
|
35154
35354
|
}
|
|
@@ -35157,10 +35357,10 @@ project.command("update").description("Update a project").argument("<id>", "Proj
|
|
|
35157
35357
|
if (opts.json) {
|
|
35158
35358
|
console.log(JSON.stringify(p, null, 2));
|
|
35159
35359
|
} else {
|
|
35160
|
-
console.log(
|
|
35360
|
+
console.log(chalk3.green(`Project "${p.name}" updated.`));
|
|
35161
35361
|
}
|
|
35162
35362
|
} catch (e) {
|
|
35163
|
-
console.error(
|
|
35363
|
+
console.error(chalk3.red(e.message));
|
|
35164
35364
|
process.exit(1);
|
|
35165
35365
|
}
|
|
35166
35366
|
closeDb();
|
|
@@ -35169,16 +35369,16 @@ project.command("delete").description("Delete a project").argument("<id>", "Proj
|
|
|
35169
35369
|
try {
|
|
35170
35370
|
const deleted = deleteProject(id);
|
|
35171
35371
|
if (!deleted) {
|
|
35172
|
-
console.error(
|
|
35372
|
+
console.error(chalk3.red(`Project "${id}" not found.`));
|
|
35173
35373
|
process.exit(1);
|
|
35174
35374
|
}
|
|
35175
35375
|
if (opts.json) {
|
|
35176
35376
|
console.log(JSON.stringify({ id, deleted: true }));
|
|
35177
35377
|
} else {
|
|
35178
|
-
console.log(
|
|
35378
|
+
console.log(chalk3.green(`Project deleted.`));
|
|
35179
35379
|
}
|
|
35180
35380
|
} catch (e) {
|
|
35181
|
-
console.error(
|
|
35381
|
+
console.error(chalk3.red(e.message));
|
|
35182
35382
|
process.exit(1);
|
|
35183
35383
|
}
|
|
35184
35384
|
closeDb();
|
|
@@ -35186,7 +35386,7 @@ project.command("delete").description("Delete a project").argument("<id>", "Proj
|
|
|
35186
35386
|
program2.command("delete").description("Delete a message (only sender can delete)").argument("<id>", "Message ID", parseInt).option("--from <agent>", "Sender agent ID").option("--json", "Output as JSON").action((id, opts) => {
|
|
35187
35387
|
const agent = resolveIdentity(opts.from).trim();
|
|
35188
35388
|
if (!agent) {
|
|
35189
|
-
console.error(
|
|
35389
|
+
console.error(chalk3.red("Agent identity is required."));
|
|
35190
35390
|
process.exit(1);
|
|
35191
35391
|
}
|
|
35192
35392
|
const result = deleteMessage(id, agent);
|
|
@@ -35194,9 +35394,9 @@ program2.command("delete").description("Delete a message (only sender can delete
|
|
|
35194
35394
|
console.log(JSON.stringify({ id, deleted: result }));
|
|
35195
35395
|
} else {
|
|
35196
35396
|
if (result) {
|
|
35197
|
-
console.log(
|
|
35397
|
+
console.log(chalk3.green(`Message #${id} deleted.`));
|
|
35198
35398
|
} else {
|
|
35199
|
-
console.error(
|
|
35399
|
+
console.error(chalk3.red(`Message #${id} not found or not your message.`));
|
|
35200
35400
|
process.exit(1);
|
|
35201
35401
|
}
|
|
35202
35402
|
}
|
|
@@ -35206,11 +35406,11 @@ program2.command("edit").description("Edit a message (only sender can edit)").ar
|
|
|
35206
35406
|
const agent = resolveIdentity(opts.from).trim();
|
|
35207
35407
|
const content = typeof newContent === "string" ? newContent : "";
|
|
35208
35408
|
if (!agent) {
|
|
35209
|
-
console.error(
|
|
35409
|
+
console.error(chalk3.red("Agent identity is required."));
|
|
35210
35410
|
process.exit(1);
|
|
35211
35411
|
}
|
|
35212
35412
|
if (!content.trim()) {
|
|
35213
|
-
console.error(
|
|
35413
|
+
console.error(chalk3.red("New content cannot be empty."));
|
|
35214
35414
|
process.exit(1);
|
|
35215
35415
|
}
|
|
35216
35416
|
const msg = editMessage(id, agent, content);
|
|
@@ -35218,9 +35418,9 @@ program2.command("edit").description("Edit a message (only sender can edit)").ar
|
|
|
35218
35418
|
console.log(JSON.stringify(msg, null, 2));
|
|
35219
35419
|
} else {
|
|
35220
35420
|
if (msg) {
|
|
35221
|
-
console.log(
|
|
35421
|
+
console.log(chalk3.green(`Message #${id} edited.`));
|
|
35222
35422
|
} else {
|
|
35223
|
-
console.error(
|
|
35423
|
+
console.error(chalk3.red(`Message #${id} not found or not your message.`));
|
|
35224
35424
|
process.exit(1);
|
|
35225
35425
|
}
|
|
35226
35426
|
}
|
|
@@ -35232,9 +35432,9 @@ program2.command("pin").description("Pin a message").argument("<id>", "Message I
|
|
|
35232
35432
|
console.log(JSON.stringify(msg, null, 2));
|
|
35233
35433
|
} else {
|
|
35234
35434
|
if (msg) {
|
|
35235
|
-
console.log(
|
|
35435
|
+
console.log(chalk3.green(`Message #${id} pinned.`));
|
|
35236
35436
|
} else {
|
|
35237
|
-
console.error(
|
|
35437
|
+
console.error(chalk3.red(`Message #${id} not found.`));
|
|
35238
35438
|
process.exit(1);
|
|
35239
35439
|
}
|
|
35240
35440
|
}
|
|
@@ -35246,9 +35446,9 @@ program2.command("unpin").description("Unpin a message").argument("<id>", "Messa
|
|
|
35246
35446
|
console.log(JSON.stringify(msg, null, 2));
|
|
35247
35447
|
} else {
|
|
35248
35448
|
if (msg) {
|
|
35249
|
-
console.log(
|
|
35449
|
+
console.log(chalk3.green(`Message #${id} unpinned.`));
|
|
35250
35450
|
} else {
|
|
35251
|
-
console.error(
|
|
35451
|
+
console.error(chalk3.red(`Message #${id} not found.`));
|
|
35252
35452
|
process.exit(1);
|
|
35253
35453
|
}
|
|
35254
35454
|
}
|
|
@@ -35263,13 +35463,13 @@ agents.command("list").description("List all agents with their presence status")
|
|
|
35263
35463
|
console.log(JSON.stringify(agentsList, null, 2));
|
|
35264
35464
|
} else {
|
|
35265
35465
|
if (agentsList.length === 0) {
|
|
35266
|
-
console.log(
|
|
35466
|
+
console.log(chalk3.dim("No agents found."));
|
|
35267
35467
|
} else {
|
|
35268
35468
|
for (const a of agentsList) {
|
|
35269
|
-
const status = a.online ?
|
|
35270
|
-
const lastSeen =
|
|
35271
|
-
const agentName = a.agent === agent ?
|
|
35272
|
-
console.log(` ${agentName} ${status} ${
|
|
35469
|
+
const status = a.online ? chalk3.green("online") : chalk3.dim("offline");
|
|
35470
|
+
const lastSeen = chalk3.dim(a.last_seen_at.slice(0, 19));
|
|
35471
|
+
const agentName = a.agent === agent ? chalk3.cyan(`${a.agent} (you)`) : chalk3.cyan(a.agent);
|
|
35472
|
+
console.log(` ${agentName} ${status} ${chalk3.dim(a.status)} ${lastSeen}`);
|
|
35273
35473
|
}
|
|
35274
35474
|
}
|
|
35275
35475
|
}
|
|
@@ -35278,7 +35478,7 @@ agents.command("list").description("List all agents with their presence status")
|
|
|
35278
35478
|
agents.command("remove").description("Remove an agent from the presence list").argument("<name>", "Agent name to remove").option("--json", "Output as JSON").action((name, opts) => {
|
|
35279
35479
|
const agentName = typeof name === "string" ? name.trim() : "";
|
|
35280
35480
|
if (!agentName) {
|
|
35281
|
-
console.error(
|
|
35481
|
+
console.error(chalk3.red("Agent name cannot be empty."));
|
|
35282
35482
|
process.exit(1);
|
|
35283
35483
|
}
|
|
35284
35484
|
const removed = removePresence(agentName);
|
|
@@ -35286,9 +35486,9 @@ agents.command("remove").description("Remove an agent from the presence list").a
|
|
|
35286
35486
|
console.log(JSON.stringify({ agent: agentName, removed }));
|
|
35287
35487
|
} else {
|
|
35288
35488
|
if (removed) {
|
|
35289
|
-
console.log(
|
|
35489
|
+
console.log(chalk3.green(`Agent "${agentName}" removed.`));
|
|
35290
35490
|
} else {
|
|
35291
|
-
console.error(
|
|
35491
|
+
console.error(chalk3.red(`Agent "${agentName}" not found.`));
|
|
35292
35492
|
process.exit(1);
|
|
35293
35493
|
}
|
|
35294
35494
|
}
|
|
@@ -35298,22 +35498,22 @@ agents.command("rename").description("Rename an agent in the presence list").arg
|
|
|
35298
35498
|
const old = typeof oldName === "string" ? oldName.trim() : "";
|
|
35299
35499
|
const renamed = typeof newName === "string" ? newName.trim() : "";
|
|
35300
35500
|
if (!old || !renamed) {
|
|
35301
|
-
console.error(
|
|
35501
|
+
console.error(chalk3.red("Both old and new names are required."));
|
|
35302
35502
|
process.exit(1);
|
|
35303
35503
|
}
|
|
35304
35504
|
try {
|
|
35305
35505
|
const ok = renameAgent(old, renamed);
|
|
35306
35506
|
if (!ok) {
|
|
35307
|
-
console.error(
|
|
35507
|
+
console.error(chalk3.red(`Agent "${old}" not found.`));
|
|
35308
35508
|
process.exit(1);
|
|
35309
35509
|
}
|
|
35310
35510
|
if (opts.json) {
|
|
35311
35511
|
console.log(JSON.stringify({ old_name: old, new_name: renamed, renamed: true }));
|
|
35312
35512
|
} else {
|
|
35313
|
-
console.log(
|
|
35513
|
+
console.log(chalk3.green(`Agent "${old}" renamed to "${renamed}".`));
|
|
35314
35514
|
}
|
|
35315
35515
|
} catch (e) {
|
|
35316
|
-
console.error(
|
|
35516
|
+
console.error(chalk3.red(e.message));
|
|
35317
35517
|
process.exit(1);
|
|
35318
35518
|
}
|
|
35319
35519
|
closeDb();
|
|
@@ -35327,9 +35527,9 @@ program2.command("whoami").description("Show current agent identity and online s
|
|
|
35327
35527
|
} else if (envValue) {
|
|
35328
35528
|
source = "env var (CONVERSATIONS_AGENT_ID)";
|
|
35329
35529
|
} else {
|
|
35330
|
-
const { join:
|
|
35331
|
-
const { homedir:
|
|
35332
|
-
const agentIdFile =
|
|
35530
|
+
const { join: join6 } = __require("path");
|
|
35531
|
+
const { homedir: homedir5 } = __require("os");
|
|
35532
|
+
const agentIdFile = join6(homedir5(), ".conversations", "agent-id");
|
|
35333
35533
|
source = `auto-generated (${agentIdFile})`;
|
|
35334
35534
|
}
|
|
35335
35535
|
const presence = getPresence(agent);
|
|
@@ -35339,15 +35539,15 @@ program2.command("whoami").description("Show current agent identity and online s
|
|
|
35339
35539
|
const agoMs = Date.now() - lastSeenMs;
|
|
35340
35540
|
const agoSec = Math.floor(agoMs / 1000);
|
|
35341
35541
|
const agoStr = agoSec < 60 ? `${agoSec}s ago` : `${Math.floor(agoSec / 60)}m ago`;
|
|
35342
|
-
onlineStatus =
|
|
35542
|
+
onlineStatus = chalk3.green(`yes`) + chalk3.dim(` (last seen ${agoStr})`);
|
|
35343
35543
|
} else if (presence) {
|
|
35344
|
-
onlineStatus =
|
|
35544
|
+
onlineStatus = chalk3.red("no") + chalk3.dim(` (last seen ${presence.last_seen_at})`);
|
|
35345
35545
|
} else {
|
|
35346
|
-
onlineStatus =
|
|
35546
|
+
onlineStatus = chalk3.red("no") + chalk3.dim(" (no presence record)");
|
|
35347
35547
|
}
|
|
35348
|
-
console.log(` ${
|
|
35349
|
-
console.log(` ${
|
|
35350
|
-
console.log(` ${
|
|
35548
|
+
console.log(` ${chalk3.bold("Agent:")} ${chalk3.cyan(agent)}`);
|
|
35549
|
+
console.log(` ${chalk3.bold("Source:")} ${source}`);
|
|
35550
|
+
console.log(` ${chalk3.bold("Online:")} ${onlineStatus}`);
|
|
35351
35551
|
closeDb();
|
|
35352
35552
|
});
|
|
35353
35553
|
program2.command("blockers").description("Check for unread blocking messages").option("--from <agent>", "Agent to check blockers for").option("--json", "Output as JSON").action((opts) => {
|
|
@@ -35357,16 +35557,16 @@ program2.command("blockers").description("Check for unread blocking messages").o
|
|
|
35357
35557
|
console.log(JSON.stringify(blockers, null, 2));
|
|
35358
35558
|
} else {
|
|
35359
35559
|
if (blockers.length === 0) {
|
|
35360
|
-
console.log(
|
|
35560
|
+
console.log(chalk3.dim("No blocking messages."));
|
|
35361
35561
|
} else {
|
|
35362
|
-
console.log(
|
|
35562
|
+
console.log(chalk3.red.bold(`${blockers.length} blocking message(s):
|
|
35363
35563
|
`));
|
|
35364
35564
|
for (const b of blockers) {
|
|
35365
|
-
const where = b.space ?
|
|
35366
|
-
const time3 =
|
|
35367
|
-
console.log(` ${
|
|
35565
|
+
const where = b.space ? chalk3.magenta(`#${b.space}`) : chalk3.yellow("DM");
|
|
35566
|
+
const time3 = chalk3.dim(b.created_at.slice(11, 19));
|
|
35567
|
+
console.log(` ${chalk3.red(`[#${b.id}]`)} ${time3} ${chalk3.cyan(b.from_agent)} ${where}: ${b.content}`);
|
|
35368
35568
|
}
|
|
35369
|
-
console.log(
|
|
35569
|
+
console.log(chalk3.dim(`
|
|
35370
35570
|
Acknowledge with: conversations mark-read ${blockers.map((b) => b.id).join(" ")}`));
|
|
35371
35571
|
}
|
|
35372
35572
|
}
|
|
@@ -35385,49 +35585,12 @@ program2.command("watch").description("Watch for new messages with desktop notif
|
|
|
35385
35585
|
}
|
|
35386
35586
|
const modeLabel = opts.all ? `DMs + ${agentSpaces.length} space(s)` : opts.space ? `Space: #${opts.space}` : "All DMs";
|
|
35387
35587
|
console.log("");
|
|
35388
|
-
console.log(
|
|
35389
|
-
console.log(
|
|
35390
|
-
console.log(
|
|
35588
|
+
console.log(chalk3.bold(` Conversations`) + chalk3.dim(` \u2014 watching as ${chalk3.cyan(agent)}`));
|
|
35589
|
+
console.log(chalk3.dim(` ${modeLabel} \xB7 Poll: ${interval}ms \xB7 Ctrl+C to stop`));
|
|
35590
|
+
console.log(chalk3.dim(" " + "\u2500".repeat(cols - 4)));
|
|
35391
35591
|
console.log("");
|
|
35392
35592
|
const { startPolling: startPolling2 } = (init_poll(), __toCommonJS(exports_poll));
|
|
35393
|
-
const renderContent = (
|
|
35394
|
-
const lines = content.split(`
|
|
35395
|
-
`);
|
|
35396
|
-
const rendered = [];
|
|
35397
|
-
for (const line of lines) {
|
|
35398
|
-
let l = line;
|
|
35399
|
-
const h = l.match(/^(#{1,3})\s+(.+)/);
|
|
35400
|
-
if (h) {
|
|
35401
|
-
rendered.push(chalk2.bold(h[2]));
|
|
35402
|
-
continue;
|
|
35403
|
-
}
|
|
35404
|
-
if (/^\s*[-*+]\s/.test(l)) {
|
|
35405
|
-
rendered.push(" " + chalk2.dim("\u2022") + " " + renderInline(l.replace(/^\s*[-*+]\s/, "")));
|
|
35406
|
-
continue;
|
|
35407
|
-
}
|
|
35408
|
-
const ol = l.match(/^\s*(\d+)[.)]\s(.*)/);
|
|
35409
|
-
if (ol) {
|
|
35410
|
-
rendered.push(" " + chalk2.dim(ol[1] + ".") + " " + renderInline(ol[2]));
|
|
35411
|
-
continue;
|
|
35412
|
-
}
|
|
35413
|
-
if (l.startsWith(">")) {
|
|
35414
|
-
rendered.push(chalk2.dim(" \u2502 ") + chalk2.italic(renderInline(l.replace(/^>\s?/, ""))));
|
|
35415
|
-
continue;
|
|
35416
|
-
}
|
|
35417
|
-
if (l.trimStart().startsWith("```"))
|
|
35418
|
-
continue;
|
|
35419
|
-
if (l.trim() === "") {
|
|
35420
|
-
rendered.push("");
|
|
35421
|
-
continue;
|
|
35422
|
-
}
|
|
35423
|
-
rendered.push(renderInline(l));
|
|
35424
|
-
}
|
|
35425
|
-
return rendered.join(`
|
|
35426
|
-
`);
|
|
35427
|
-
};
|
|
35428
|
-
const renderInline = (text) => {
|
|
35429
|
-
return text.replace(/`([^`]+)`/g, (_, code) => chalk2.bgGray.white(` ${code} `)).replace(/\*\*\*(.+?)\*\*\*/g, (_, t) => chalk2.bold.italic(t)).replace(/\*\*(.+?)\*\*/g, (_, t) => chalk2.bold(t)).replace(/\*(.+?)\*/g, (_, t) => chalk2.italic(t)).replace(/~~(.+?)~~/g, (_, t) => chalk2.strikethrough(t));
|
|
35430
|
-
};
|
|
35593
|
+
const { renderContent: renderContent2 } = (init_terminal_markdown(), __toCommonJS(exports_terminal_markdown));
|
|
35431
35594
|
const desktopNotify = (title, body) => {
|
|
35432
35595
|
if (process.platform === "darwin") {
|
|
35433
35596
|
try {
|
|
@@ -35439,18 +35602,18 @@ program2.command("watch").description("Watch for new messages with desktop notif
|
|
|
35439
35602
|
}
|
|
35440
35603
|
};
|
|
35441
35604
|
const renderMessage = (msg) => {
|
|
35442
|
-
const time3 =
|
|
35443
|
-
const where = msg.space ?
|
|
35444
|
-
const priority = msg.priority !== "normal" ? msg.priority === "urgent" ?
|
|
35445
|
-
const blocking = msg.blocking ?
|
|
35446
|
-
const sender =
|
|
35605
|
+
const time3 = chalk3.dim(msg.created_at.slice(11, 19));
|
|
35606
|
+
const where = msg.space ? chalk3.magenta(`#${msg.space}`) : chalk3.yellow("DM");
|
|
35607
|
+
const priority = msg.priority !== "normal" ? msg.priority === "urgent" ? chalk3.red.bold(` [${msg.priority}]`) : msg.priority === "high" ? chalk3.yellow(` [${msg.priority}]`) : chalk3.dim(` [${msg.priority}]`) : "";
|
|
35608
|
+
const blocking = msg.blocking ? chalk3.red.bold(" \u26A0 BLOCKER") : "";
|
|
35609
|
+
const sender = chalk3.cyan.bold(msg.from_agent);
|
|
35447
35610
|
console.log(` ${sender} ${where} ${time3}${priority}${blocking}`);
|
|
35448
|
-
const content =
|
|
35611
|
+
const content = renderContent2(msg.content);
|
|
35449
35612
|
const indented = content.split(`
|
|
35450
35613
|
`).map((l) => " " + l).join(`
|
|
35451
35614
|
`);
|
|
35452
35615
|
console.log(indented);
|
|
35453
|
-
console.log(
|
|
35616
|
+
console.log(chalk3.dim(" " + "\xB7".repeat(Math.min(cols - 8, 60))));
|
|
35454
35617
|
console.log("");
|
|
35455
35618
|
};
|
|
35456
35619
|
if (opts.all) {
|
|
@@ -35461,12 +35624,12 @@ program2.command("watch").description("Watch for new messages with desktop notif
|
|
|
35461
35624
|
}
|
|
35462
35625
|
const recent = [...dmRecent, ...spaceRecent].sort((a, b) => a.created_at.localeCompare(b.created_at)).slice(-20);
|
|
35463
35626
|
if (recent.length > 0) {
|
|
35464
|
-
console.log(
|
|
35627
|
+
console.log(chalk3.dim(` \u2500\u2500 Recent messages (${recent.length}) \u2500\u2500
|
|
35465
35628
|
`));
|
|
35466
35629
|
for (const msg of recent) {
|
|
35467
35630
|
renderMessage(msg);
|
|
35468
35631
|
}
|
|
35469
|
-
console.log(
|
|
35632
|
+
console.log(chalk3.dim(` \u2500\u2500 Live \u2500\u2500
|
|
35470
35633
|
`));
|
|
35471
35634
|
}
|
|
35472
35635
|
} else {
|
|
@@ -35477,12 +35640,12 @@ program2.command("watch").description("Watch for new messages with desktop notif
|
|
|
35477
35640
|
order: "asc"
|
|
35478
35641
|
});
|
|
35479
35642
|
if (recent.length > 0) {
|
|
35480
|
-
console.log(
|
|
35643
|
+
console.log(chalk3.dim(` \u2500\u2500 Recent messages (${recent.length}) \u2500\u2500
|
|
35481
35644
|
`));
|
|
35482
35645
|
for (const msg of recent) {
|
|
35483
35646
|
renderMessage(msg);
|
|
35484
35647
|
}
|
|
35485
|
-
console.log(
|
|
35648
|
+
console.log(chalk3.dim(` \u2500\u2500 Live \u2500\u2500
|
|
35486
35649
|
`));
|
|
35487
35650
|
}
|
|
35488
35651
|
}
|
|
@@ -35510,7 +35673,7 @@ program2.command("watch").description("Watch for new messages with desktop notif
|
|
|
35510
35673
|
});
|
|
35511
35674
|
}
|
|
35512
35675
|
process.on("SIGINT", () => {
|
|
35513
|
-
console.log(
|
|
35676
|
+
console.log(chalk3.dim(`
|
|
35514
35677
|
Stopped watching.`));
|
|
35515
35678
|
closeDb();
|
|
35516
35679
|
process.exit(0);
|
|
@@ -35531,8 +35694,8 @@ program2.command("dashboard").description("Start web dashboard").option("--port
|
|
|
35531
35694
|
});
|
|
35532
35695
|
program2.action(() => {
|
|
35533
35696
|
if (!process.stdin.isTTY) {
|
|
35534
|
-
console.error(
|
|
35535
|
-
console.error(
|
|
35697
|
+
console.error(chalk3.red("Interactive mode requires a TTY terminal."));
|
|
35698
|
+
console.error(chalk3.dim("Use subcommands (send, read, sessions, etc.) for non-interactive use."));
|
|
35536
35699
|
process.exit(1);
|
|
35537
35700
|
}
|
|
35538
35701
|
const agent = resolveIdentity();
|