@hasna/conversations 0.1.25 → 0.1.26
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 +23 -0
- package/bin/index.js +116 -109
- package/bin/mcp.js +112 -100
- package/dashboard/dist/assets/index-Bw0wMcXE.js +186 -0
- package/dashboard/dist/assets/index-CF_GDtNp.css +1 -0
- package/dashboard/dist/index.html +13 -0
- package/dashboard/dist/logo.jpg +0 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +80 -17
- package/dist/lib/identity.d.ts +0 -4
- package/dist/lib/presence.d.ts +3 -2
- package/dist/types.d.ts +15 -0
- package/package.json +1 -1
package/bin/hook.js
CHANGED
|
@@ -114,9 +114,13 @@ function getDb() {
|
|
|
114
114
|
`);
|
|
115
115
|
db.exec(`
|
|
116
116
|
CREATE TABLE IF NOT EXISTS agent_presence (
|
|
117
|
+
id TEXT NOT NULL,
|
|
117
118
|
agent TEXT PRIMARY KEY,
|
|
119
|
+
session_id TEXT,
|
|
120
|
+
role TEXT NOT NULL DEFAULT 'agent',
|
|
118
121
|
status TEXT NOT NULL DEFAULT 'online',
|
|
119
122
|
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
123
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
120
124
|
metadata TEXT
|
|
121
125
|
)
|
|
122
126
|
`);
|
|
@@ -195,6 +199,25 @@ function getDb() {
|
|
|
195
199
|
db.exec("ALTER TABLE messages ADD COLUMN reply_to INTEGER REFERENCES messages(id)");
|
|
196
200
|
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_reply_to ON messages(reply_to)");
|
|
197
201
|
}
|
|
202
|
+
const presenceCols = db.prepare("PRAGMA table_info(agent_presence)").all();
|
|
203
|
+
const presenceColNames = presenceCols.map((c) => c.name);
|
|
204
|
+
if (!presenceColNames.includes("id")) {
|
|
205
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN id TEXT NOT NULL DEFAULT ''");
|
|
206
|
+
const rows = db.prepare("SELECT agent FROM agent_presence").all();
|
|
207
|
+
for (const row of rows) {
|
|
208
|
+
const id = crypto.randomUUID().slice(0, 8);
|
|
209
|
+
db.prepare("UPDATE agent_presence SET id = ? WHERE agent = ?").run(id, row.agent);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (!presenceColNames.includes("session_id")) {
|
|
213
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN session_id TEXT");
|
|
214
|
+
}
|
|
215
|
+
if (!presenceColNames.includes("role")) {
|
|
216
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN role TEXT NOT NULL DEFAULT 'agent'");
|
|
217
|
+
}
|
|
218
|
+
if (!presenceColNames.includes("created_at")) {
|
|
219
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now'))");
|
|
220
|
+
}
|
|
198
221
|
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
|
|
199
222
|
if (!ftsExists) {
|
|
200
223
|
db.exec(`
|
package/bin/index.js
CHANGED
|
@@ -1968,9 +1968,13 @@ function getDb() {
|
|
|
1968
1968
|
`);
|
|
1969
1969
|
db.exec(`
|
|
1970
1970
|
CREATE TABLE IF NOT EXISTS agent_presence (
|
|
1971
|
+
id TEXT NOT NULL,
|
|
1971
1972
|
agent TEXT PRIMARY KEY,
|
|
1973
|
+
session_id TEXT,
|
|
1974
|
+
role TEXT NOT NULL DEFAULT 'agent',
|
|
1972
1975
|
status TEXT NOT NULL DEFAULT 'online',
|
|
1973
1976
|
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
1977
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
1974
1978
|
metadata TEXT
|
|
1975
1979
|
)
|
|
1976
1980
|
`);
|
|
@@ -2049,6 +2053,25 @@ function getDb() {
|
|
|
2049
2053
|
db.exec("ALTER TABLE messages ADD COLUMN reply_to INTEGER REFERENCES messages(id)");
|
|
2050
2054
|
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_reply_to ON messages(reply_to)");
|
|
2051
2055
|
}
|
|
2056
|
+
const presenceCols = db.prepare("PRAGMA table_info(agent_presence)").all();
|
|
2057
|
+
const presenceColNames = presenceCols.map((c) => c.name);
|
|
2058
|
+
if (!presenceColNames.includes("id")) {
|
|
2059
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN id TEXT NOT NULL DEFAULT ''");
|
|
2060
|
+
const rows = db.prepare("SELECT agent FROM agent_presence").all();
|
|
2061
|
+
for (const row of rows) {
|
|
2062
|
+
const id = crypto.randomUUID().slice(0, 8);
|
|
2063
|
+
db.prepare("UPDATE agent_presence SET id = ? WHERE agent = ?").run(id, row.agent);
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
if (!presenceColNames.includes("session_id")) {
|
|
2067
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN session_id TEXT");
|
|
2068
|
+
}
|
|
2069
|
+
if (!presenceColNames.includes("role")) {
|
|
2070
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN role TEXT NOT NULL DEFAULT 'agent'");
|
|
2071
|
+
}
|
|
2072
|
+
if (!presenceColNames.includes("created_at")) {
|
|
2073
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now'))");
|
|
2074
|
+
}
|
|
2052
2075
|
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
|
|
2053
2076
|
if (!ftsExists) {
|
|
2054
2077
|
db.exec(`
|
|
@@ -3282,14 +3305,6 @@ function resolveIdentity(explicit) {
|
|
|
3282
3305
|
return envValue;
|
|
3283
3306
|
return getAutoName();
|
|
3284
3307
|
}
|
|
3285
|
-
function updateCachedAutoName(newName) {
|
|
3286
|
-
cachedAutoName = newName;
|
|
3287
|
-
try {
|
|
3288
|
-
mkdirSync3(dirname2(AGENT_ID_FILE), { recursive: true });
|
|
3289
|
-
writeFileSync(AGENT_ID_FILE, newName + `
|
|
3290
|
-
`, "utf-8");
|
|
3291
|
-
} catch {}
|
|
3292
|
-
}
|
|
3293
3308
|
var AGENT_ID_FILE, cachedAutoName = null;
|
|
3294
3309
|
var init_identity = __esm(() => {
|
|
3295
3310
|
init_names();
|
|
@@ -3311,66 +3326,105 @@ function parsePresence(row) {
|
|
|
3311
3326
|
const nowMs = Date.now();
|
|
3312
3327
|
const online = nowMs - lastSeenMs < ONLINE_THRESHOLD_SECONDS * 1000;
|
|
3313
3328
|
return {
|
|
3329
|
+
id: row.id || "",
|
|
3314
3330
|
agent: row.agent,
|
|
3331
|
+
session_id: row.session_id ?? null,
|
|
3332
|
+
role: row.role || "agent",
|
|
3315
3333
|
status: row.status,
|
|
3316
3334
|
last_seen_at: lastSeenAt,
|
|
3335
|
+
created_at: row.created_at || lastSeenAt,
|
|
3317
3336
|
online,
|
|
3318
3337
|
metadata
|
|
3319
3338
|
};
|
|
3320
3339
|
}
|
|
3321
|
-
function
|
|
3340
|
+
function isActiveSession(lastSeenAt) {
|
|
3341
|
+
const lastSeenMs = new Date(lastSeenAt + "Z").getTime();
|
|
3342
|
+
const nowMs = Date.now();
|
|
3343
|
+
return nowMs - lastSeenMs < CONFLICT_THRESHOLD_SECONDS * 1000;
|
|
3344
|
+
}
|
|
3345
|
+
function registerAgent(name, sessionId, role) {
|
|
3346
|
+
const db2 = getDb();
|
|
3347
|
+
const existing = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(name);
|
|
3348
|
+
if (existing) {
|
|
3349
|
+
const lastSeenAt = existing.last_seen_at;
|
|
3350
|
+
const existingSessionId = existing.session_id;
|
|
3351
|
+
if (isActiveSession(lastSeenAt) && existingSessionId && existingSessionId !== sessionId) {
|
|
3352
|
+
return {
|
|
3353
|
+
error: "agent_conflict",
|
|
3354
|
+
message: `Agent "${name}" is already active (last seen: ${lastSeenAt}). Wait 30 minutes or use force takeover.`,
|
|
3355
|
+
existing_session_id: existingSessionId,
|
|
3356
|
+
last_seen_at: lastSeenAt
|
|
3357
|
+
};
|
|
3358
|
+
}
|
|
3359
|
+
const tookOver = existingSessionId !== sessionId;
|
|
3360
|
+
db2.prepare(`
|
|
3361
|
+
UPDATE agent_presence
|
|
3362
|
+
SET session_id = ?, role = ?, last_seen_at = strftime('%Y-%m-%dT%H:%M:%f', 'now')
|
|
3363
|
+
WHERE agent = ?
|
|
3364
|
+
`).run(sessionId, role || existing.role || "agent", name);
|
|
3365
|
+
const updated = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(name);
|
|
3366
|
+
return { agent: parsePresence(updated), created: false, took_over: tookOver };
|
|
3367
|
+
}
|
|
3368
|
+
const id = crypto.randomUUID().slice(0, 8);
|
|
3369
|
+
const resolvedRole = role || "agent";
|
|
3370
|
+
db2.prepare(`
|
|
3371
|
+
INSERT INTO agent_presence (id, agent, session_id, role, status, last_seen_at, created_at)
|
|
3372
|
+
VALUES (?, ?, ?, ?, 'online', strftime('%Y-%m-%dT%H:%M:%f', 'now'), strftime('%Y-%m-%dT%H:%M:%f', 'now'))
|
|
3373
|
+
`).run(id, name, sessionId, resolvedRole);
|
|
3374
|
+
const created = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(name);
|
|
3375
|
+
return { agent: parsePresence(created), created: true, took_over: false };
|
|
3376
|
+
}
|
|
3377
|
+
function heartbeat(agent, status, metadata, sessionId) {
|
|
3322
3378
|
const db2 = getDb();
|
|
3323
3379
|
const metadataJson = metadata ? JSON.stringify(metadata) : null;
|
|
3324
3380
|
const resolvedStatus = status || "online";
|
|
3325
|
-
const
|
|
3381
|
+
const existing = db2.prepare("SELECT id FROM agent_presence WHERE agent = ?").get(agent);
|
|
3382
|
+
const id = existing?.id || crypto.randomUUID().slice(0, 8);
|
|
3326
3383
|
db2.prepare(`
|
|
3327
|
-
INSERT INTO agent_presence (agent, status, last_seen_at, metadata)
|
|
3328
|
-
VALUES (?, ?, strftime('%Y-%m-%dT%H:%M:%f', 'now'), ?)
|
|
3384
|
+
INSERT INTO agent_presence (id, agent, session_id, role, status, last_seen_at, created_at, metadata)
|
|
3385
|
+
VALUES (?, ?, ?, 'agent', ?, strftime('%Y-%m-%dT%H:%M:%f', 'now'), strftime('%Y-%m-%dT%H:%M:%f', 'now'), ?)
|
|
3329
3386
|
ON CONFLICT(agent) DO UPDATE SET
|
|
3330
3387
|
status = excluded.status,
|
|
3331
3388
|
last_seen_at = excluded.last_seen_at,
|
|
3389
|
+
session_id = COALESCE(excluded.session_id, agent_presence.session_id),
|
|
3332
3390
|
metadata = excluded.metadata
|
|
3333
|
-
`).run(
|
|
3391
|
+
`).run(id, agent, sessionId ?? null, resolvedStatus, metadataJson);
|
|
3334
3392
|
}
|
|
3335
3393
|
function getPresence(agent) {
|
|
3336
3394
|
const db2 = getDb();
|
|
3337
|
-
const
|
|
3338
|
-
const row = db2.prepare("SELECT * FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedAgent);
|
|
3395
|
+
const row = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(agent);
|
|
3339
3396
|
return row ? parsePresence(row) : null;
|
|
3340
3397
|
}
|
|
3341
3398
|
function listAgents(opts) {
|
|
3342
3399
|
const db2 = getDb();
|
|
3343
3400
|
let query = "SELECT * FROM agent_presence";
|
|
3344
|
-
const params = [];
|
|
3345
3401
|
if (opts?.online_only) {
|
|
3346
3402
|
query += " WHERE last_seen_at > strftime('%Y-%m-%dT%H:%M:%f', 'now', '-60 seconds')";
|
|
3347
3403
|
}
|
|
3348
3404
|
query += " ORDER BY last_seen_at DESC";
|
|
3349
|
-
const rows = db2.prepare(query).all(
|
|
3405
|
+
const rows = db2.prepare(query).all();
|
|
3350
3406
|
return rows.map(parsePresence);
|
|
3351
3407
|
}
|
|
3352
3408
|
function removePresence(agent) {
|
|
3353
3409
|
const db2 = getDb();
|
|
3354
|
-
const
|
|
3355
|
-
const result = db2.prepare("DELETE FROM agent_presence WHERE LOWER(agent) = ?").run(normalizedAgent);
|
|
3410
|
+
const result = db2.prepare("DELETE FROM agent_presence WHERE agent = ?").run(agent);
|
|
3356
3411
|
return result.changes > 0;
|
|
3357
3412
|
}
|
|
3358
3413
|
function renameAgent(oldName, newName) {
|
|
3359
3414
|
const db2 = getDb();
|
|
3360
|
-
const
|
|
3361
|
-
const normalizedNew = newName.trim().toLowerCase();
|
|
3362
|
-
const existing = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedOld);
|
|
3415
|
+
const existing = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(oldName);
|
|
3363
3416
|
if (!existing)
|
|
3364
3417
|
return false;
|
|
3365
|
-
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE
|
|
3418
|
+
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(newName);
|
|
3366
3419
|
if (conflict)
|
|
3367
|
-
throw new Error(`Agent "${
|
|
3368
|
-
db2.prepare("UPDATE agent_presence SET agent = ? WHERE
|
|
3420
|
+
throw new Error(`Agent "${newName}" already exists`);
|
|
3421
|
+
db2.prepare("UPDATE agent_presence SET agent = ? WHERE agent = ?").run(newName, oldName);
|
|
3369
3422
|
return true;
|
|
3370
3423
|
}
|
|
3371
|
-
var ONLINE_THRESHOLD_SECONDS = 60;
|
|
3424
|
+
var ONLINE_THRESHOLD_SECONDS = 60, CONFLICT_THRESHOLD_SECONDS;
|
|
3372
3425
|
var init_presence = __esm(() => {
|
|
3373
3426
|
init_db();
|
|
3427
|
+
CONFLICT_THRESHOLD_SECONDS = 30 * 60;
|
|
3374
3428
|
});
|
|
3375
3429
|
|
|
3376
3430
|
// src/lib/terminal-markdown.ts
|
|
@@ -3517,7 +3571,7 @@ var init_poll = __esm(() => {
|
|
|
3517
3571
|
var require_package = __commonJS((exports, module) => {
|
|
3518
3572
|
module.exports = {
|
|
3519
3573
|
name: "@hasna/conversations",
|
|
3520
|
-
version: "0.1.
|
|
3574
|
+
version: "0.1.26",
|
|
3521
3575
|
description: "Real-time CLI messaging for AI agents",
|
|
3522
3576
|
type: "module",
|
|
3523
3577
|
bin: {
|
|
@@ -30885,7 +30939,7 @@ var require_formats = __commonJS((exports) => {
|
|
|
30885
30939
|
}
|
|
30886
30940
|
var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
|
|
30887
30941
|
function getTime(strictTimeZone) {
|
|
30888
|
-
return function
|
|
30942
|
+
return function time(str) {
|
|
30889
30943
|
const matches = TIME.exec(str);
|
|
30890
30944
|
if (!matches)
|
|
30891
30945
|
return false;
|
|
@@ -31149,62 +31203,6 @@ class ExperimentalServerTasks {
|
|
|
31149
31203
|
requestStream(request, resultSchema, options) {
|
|
31150
31204
|
return this._server.requestStream(request, resultSchema, options);
|
|
31151
31205
|
}
|
|
31152
|
-
createMessageStream(params, options) {
|
|
31153
|
-
const clientCapabilities = this._server.getClientCapabilities();
|
|
31154
|
-
if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
|
|
31155
|
-
throw new Error("Client does not support sampling tools capability.");
|
|
31156
|
-
}
|
|
31157
|
-
if (params.messages.length > 0) {
|
|
31158
|
-
const lastMessage = params.messages[params.messages.length - 1];
|
|
31159
|
-
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
|
|
31160
|
-
const hasToolResults = lastContent.some((c) => c.type === "tool_result");
|
|
31161
|
-
const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : undefined;
|
|
31162
|
-
const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
|
|
31163
|
-
const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
|
|
31164
|
-
if (hasToolResults) {
|
|
31165
|
-
if (lastContent.some((c) => c.type !== "tool_result")) {
|
|
31166
|
-
throw new Error("The last message must contain only tool_result content if any is present");
|
|
31167
|
-
}
|
|
31168
|
-
if (!hasPreviousToolUse) {
|
|
31169
|
-
throw new Error("tool_result blocks are not matching any tool_use from the previous message");
|
|
31170
|
-
}
|
|
31171
|
-
}
|
|
31172
|
-
if (hasPreviousToolUse) {
|
|
31173
|
-
const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
|
|
31174
|
-
const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
|
|
31175
|
-
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
|
|
31176
|
-
throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
|
|
31177
|
-
}
|
|
31178
|
-
}
|
|
31179
|
-
}
|
|
31180
|
-
return this.requestStream({
|
|
31181
|
-
method: "sampling/createMessage",
|
|
31182
|
-
params
|
|
31183
|
-
}, CreateMessageResultSchema, options);
|
|
31184
|
-
}
|
|
31185
|
-
elicitInputStream(params, options) {
|
|
31186
|
-
const clientCapabilities = this._server.getClientCapabilities();
|
|
31187
|
-
const mode = params.mode ?? "form";
|
|
31188
|
-
switch (mode) {
|
|
31189
|
-
case "url": {
|
|
31190
|
-
if (!clientCapabilities?.elicitation?.url) {
|
|
31191
|
-
throw new Error("Client does not support url elicitation.");
|
|
31192
|
-
}
|
|
31193
|
-
break;
|
|
31194
|
-
}
|
|
31195
|
-
case "form": {
|
|
31196
|
-
if (!clientCapabilities?.elicitation?.form) {
|
|
31197
|
-
throw new Error("Client does not support form elicitation.");
|
|
31198
|
-
}
|
|
31199
|
-
break;
|
|
31200
|
-
}
|
|
31201
|
-
}
|
|
31202
|
-
const normalizedParams = mode === "form" && params.mode === undefined ? { ...params, mode: "form" } : params;
|
|
31203
|
-
return this.requestStream({
|
|
31204
|
-
method: "elicitation/create",
|
|
31205
|
-
params: normalizedParams
|
|
31206
|
-
}, ElicitResultSchema, options);
|
|
31207
|
-
}
|
|
31208
31206
|
async getTask(taskId, options) {
|
|
31209
31207
|
return this._server.getTask({ taskId }, options);
|
|
31210
31208
|
}
|
|
@@ -31218,9 +31216,6 @@ class ExperimentalServerTasks {
|
|
|
31218
31216
|
return this._server.cancelTask({ taskId }, options);
|
|
31219
31217
|
}
|
|
31220
31218
|
}
|
|
31221
|
-
var init_server = __esm(() => {
|
|
31222
|
-
init_types2();
|
|
31223
|
-
});
|
|
31224
31219
|
|
|
31225
31220
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
31226
31221
|
function assertToolsCallTaskCapability(requests, method, entityName) {
|
|
@@ -31259,12 +31254,11 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
|
|
|
31259
31254
|
|
|
31260
31255
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
31261
31256
|
var Server;
|
|
31262
|
-
var
|
|
31257
|
+
var init_server = __esm(() => {
|
|
31263
31258
|
init_protocol();
|
|
31264
31259
|
init_types2();
|
|
31265
31260
|
init_ajv_provider();
|
|
31266
31261
|
init_zod_compat();
|
|
31267
|
-
init_server();
|
|
31268
31262
|
Server = class Server extends Protocol {
|
|
31269
31263
|
constructor(_serverInfo, options) {
|
|
31270
31264
|
super(options);
|
|
@@ -32406,7 +32400,7 @@ function createCompletionResult(suggestions) {
|
|
|
32406
32400
|
}
|
|
32407
32401
|
var EMPTY_OBJECT_JSON_SCHEMA, EMPTY_COMPLETION_RESULT;
|
|
32408
32402
|
var init_mcp = __esm(() => {
|
|
32409
|
-
|
|
32403
|
+
init_server();
|
|
32410
32404
|
init_zod_compat();
|
|
32411
32405
|
init_zod_json_schema_compat();
|
|
32412
32406
|
init_types2();
|
|
@@ -32554,7 +32548,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32554
32548
|
content: exports_external.string(),
|
|
32555
32549
|
from: exports_external.string().optional(),
|
|
32556
32550
|
priority: exports_external.string().optional(),
|
|
32557
|
-
blocking: exports_external.
|
|
32551
|
+
blocking: exports_external.boolean().optional()
|
|
32558
32552
|
}
|
|
32559
32553
|
}, async (args) => {
|
|
32560
32554
|
const { from: fromParam, to, content, priority, blocking } = args;
|
|
@@ -32578,8 +32572,8 @@ var init_mcp2 = __esm(() => {
|
|
|
32578
32572
|
to: exports_external.string().optional(),
|
|
32579
32573
|
space: exports_external.string().optional(),
|
|
32580
32574
|
since: exports_external.string().optional(),
|
|
32581
|
-
limit: exports_external.
|
|
32582
|
-
unread_only: exports_external.
|
|
32575
|
+
limit: exports_external.number().optional(),
|
|
32576
|
+
unread_only: exports_external.boolean().optional()
|
|
32583
32577
|
}
|
|
32584
32578
|
}, async (args) => {
|
|
32585
32579
|
const messages = readMessages(args);
|
|
@@ -32602,7 +32596,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32602
32596
|
server.registerTool("reply", {
|
|
32603
32597
|
description: "Reply to a message by ID.",
|
|
32604
32598
|
inputSchema: {
|
|
32605
|
-
message_id: exports_external.
|
|
32599
|
+
message_id: exports_external.number(),
|
|
32606
32600
|
content: exports_external.string(),
|
|
32607
32601
|
from: exports_external.string().optional()
|
|
32608
32602
|
}
|
|
@@ -32633,8 +32627,8 @@ var init_mcp2 = __esm(() => {
|
|
|
32633
32627
|
description: "Mark messages read by IDs or all.",
|
|
32634
32628
|
inputSchema: {
|
|
32635
32629
|
from: exports_external.string().optional(),
|
|
32636
|
-
ids: exports_external.array(exports_external.
|
|
32637
|
-
all: exports_external.
|
|
32630
|
+
ids: exports_external.array(exports_external.number()).optional(),
|
|
32631
|
+
all: exports_external.boolean().optional()
|
|
32638
32632
|
}
|
|
32639
32633
|
}, async (args) => {
|
|
32640
32634
|
const { from: fromParam, ids, all } = args;
|
|
@@ -32661,7 +32655,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32661
32655
|
space: exports_external.string().optional(),
|
|
32662
32656
|
from: exports_external.string().optional(),
|
|
32663
32657
|
to: exports_external.string().optional(),
|
|
32664
|
-
limit: exports_external.
|
|
32658
|
+
limit: exports_external.number().optional()
|
|
32665
32659
|
}
|
|
32666
32660
|
}, async (args) => {
|
|
32667
32661
|
const { query, space, from, to, limit } = args;
|
|
@@ -32722,7 +32716,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32722
32716
|
inputSchema: {
|
|
32723
32717
|
project_id: exports_external.string().optional(),
|
|
32724
32718
|
parent_id: exports_external.string().optional(),
|
|
32725
|
-
include_archived: exports_external.
|
|
32719
|
+
include_archived: exports_external.boolean().optional()
|
|
32726
32720
|
}
|
|
32727
32721
|
}, async (args) => {
|
|
32728
32722
|
const { project_id, parent_id, include_archived } = args;
|
|
@@ -32748,7 +32742,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32748
32742
|
content: exports_external.string(),
|
|
32749
32743
|
from: exports_external.string().optional(),
|
|
32750
32744
|
priority: exports_external.string().optional(),
|
|
32751
|
-
blocking: exports_external.
|
|
32745
|
+
blocking: exports_external.boolean().optional()
|
|
32752
32746
|
}
|
|
32753
32747
|
}, async (args) => {
|
|
32754
32748
|
const { from: fromParam, space, content, priority, blocking } = args;
|
|
@@ -32778,7 +32772,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32778
32772
|
inputSchema: {
|
|
32779
32773
|
space: exports_external.string(),
|
|
32780
32774
|
since: exports_external.string().optional(),
|
|
32781
|
-
limit: exports_external.
|
|
32775
|
+
limit: exports_external.number().optional()
|
|
32782
32776
|
}
|
|
32783
32777
|
}, async (args) => {
|
|
32784
32778
|
const { space, since, limit } = args;
|
|
@@ -33088,7 +33082,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33088
33082
|
server.registerTool("delete_message", {
|
|
33089
33083
|
description: "Delete a message (sender only).",
|
|
33090
33084
|
inputSchema: {
|
|
33091
|
-
id: exports_external.
|
|
33085
|
+
id: exports_external.number(),
|
|
33092
33086
|
from: exports_external.string().optional()
|
|
33093
33087
|
}
|
|
33094
33088
|
}, async (args) => {
|
|
@@ -33108,7 +33102,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33108
33102
|
server.registerTool("edit_message", {
|
|
33109
33103
|
description: "Edit message content (sender only).",
|
|
33110
33104
|
inputSchema: {
|
|
33111
|
-
id: exports_external.
|
|
33105
|
+
id: exports_external.number(),
|
|
33112
33106
|
content: exports_external.string(),
|
|
33113
33107
|
from: exports_external.string().optional()
|
|
33114
33108
|
}
|
|
@@ -33129,7 +33123,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33129
33123
|
server.registerTool("pin_message", {
|
|
33130
33124
|
description: "Pin a message.",
|
|
33131
33125
|
inputSchema: {
|
|
33132
|
-
id: exports_external.
|
|
33126
|
+
id: exports_external.number()
|
|
33133
33127
|
}
|
|
33134
33128
|
}, async ({ id }) => {
|
|
33135
33129
|
const msg = pinMessage(id);
|
|
@@ -33146,7 +33140,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33146
33140
|
server.registerTool("unpin_message", {
|
|
33147
33141
|
description: "Unpin a message.",
|
|
33148
33142
|
inputSchema: {
|
|
33149
|
-
id: exports_external.
|
|
33143
|
+
id: exports_external.number()
|
|
33150
33144
|
}
|
|
33151
33145
|
}, async ({ id }) => {
|
|
33152
33146
|
const msg = unpinMessage(id);
|
|
@@ -33165,7 +33159,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33165
33159
|
inputSchema: {
|
|
33166
33160
|
space: exports_external.string().optional(),
|
|
33167
33161
|
session_id: exports_external.string().optional(),
|
|
33168
|
-
limit: exports_external.
|
|
33162
|
+
limit: exports_external.number().optional()
|
|
33169
33163
|
}
|
|
33170
33164
|
}, async (args) => {
|
|
33171
33165
|
const { space, session_id, limit } = args;
|
|
@@ -33174,6 +33168,20 @@ var init_mcp2 = __esm(() => {
|
|
|
33174
33168
|
content: [{ type: "text", text: JSON.stringify(messages) }]
|
|
33175
33169
|
};
|
|
33176
33170
|
});
|
|
33171
|
+
server.registerTool("register_agent", {
|
|
33172
|
+
description: "Register an agent with conflict detection. Returns AgentConflictError if another active session exists (active = heartbeat within last 30 min).",
|
|
33173
|
+
inputSchema: {
|
|
33174
|
+
name: exports_external.string(),
|
|
33175
|
+
session_id: exports_external.string(),
|
|
33176
|
+
role: exports_external.string().optional()
|
|
33177
|
+
}
|
|
33178
|
+
}, async (args) => {
|
|
33179
|
+
const { name, session_id, role } = args;
|
|
33180
|
+
const result = registerAgent(name, session_id, role);
|
|
33181
|
+
return {
|
|
33182
|
+
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
33183
|
+
};
|
|
33184
|
+
});
|
|
33177
33185
|
server.registerTool("heartbeat", {
|
|
33178
33186
|
description: "Send presence heartbeat.",
|
|
33179
33187
|
inputSchema: {
|
|
@@ -33191,7 +33199,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33191
33199
|
server.registerTool("list_agents", {
|
|
33192
33200
|
description: "List agents with presence status.",
|
|
33193
33201
|
inputSchema: {
|
|
33194
|
-
online_only: exports_external.
|
|
33202
|
+
online_only: exports_external.boolean().optional()
|
|
33195
33203
|
}
|
|
33196
33204
|
}, async (args) => {
|
|
33197
33205
|
const { online_only } = args;
|
|
@@ -33258,9 +33266,6 @@ var init_mcp2 = __esm(() => {
|
|
|
33258
33266
|
isError: true
|
|
33259
33267
|
};
|
|
33260
33268
|
}
|
|
33261
|
-
if (!fromParam) {
|
|
33262
|
-
updateCachedAutoName(newName);
|
|
33263
|
-
}
|
|
33264
33269
|
return {
|
|
33265
33270
|
content: [{ type: "text", text: JSON.stringify({ old_name: oldName, new_name: newName, renamed: true }) }]
|
|
33266
33271
|
};
|
|
@@ -33305,6 +33310,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33305
33310
|
"pin_message",
|
|
33306
33311
|
"unpin_message",
|
|
33307
33312
|
"get_pinned_messages",
|
|
33313
|
+
"register_agent",
|
|
33308
33314
|
"heartbeat",
|
|
33309
33315
|
"list_agents",
|
|
33310
33316
|
"get_blockers",
|
|
@@ -33350,6 +33356,7 @@ var init_mcp2 = __esm(() => {
|
|
|
33350
33356
|
pin_message: "Pin a message. Required: id",
|
|
33351
33357
|
unpin_message: "Unpin a message. Required: id",
|
|
33352
33358
|
get_pinned_messages: "Get pinned messages. Optional: space?, session_id?, limit?",
|
|
33359
|
+
register_agent: "Register agent with conflict detection (30min active window). Required: name, session_id. Optional: role?. Returns AgentConflictError if another session is active.",
|
|
33353
33360
|
heartbeat: "Register/refresh agent presence. Optional: from?, status?(online|busy|idle, default: online)",
|
|
33354
33361
|
list_agents: "List agents with presence timestamps. Optional: online_only?(only agents seen in last 60s)",
|
|
33355
33362
|
get_blockers: "Get unread blocking messages for agent. Optional: from?",
|