@hasna/conversations 0.1.28 → 0.1.29
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 +4 -0
- package/bin/index.js +48 -39
- package/bin/mcp.js +48 -39
- package/dist/index.js +41 -33
- package/dist/lib/presence.d.ts +1 -1
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/bin/hook.js
CHANGED
|
@@ -118,6 +118,7 @@ function getDb() {
|
|
|
118
118
|
agent TEXT PRIMARY KEY,
|
|
119
119
|
session_id TEXT,
|
|
120
120
|
role TEXT NOT NULL DEFAULT 'agent',
|
|
121
|
+
project_id TEXT,
|
|
121
122
|
status TEXT NOT NULL DEFAULT 'online',
|
|
122
123
|
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
123
124
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
@@ -219,6 +220,9 @@ function getDb() {
|
|
|
219
220
|
db.exec("ALTER TABLE agent_presence ADD COLUMN created_at TEXT NOT NULL DEFAULT ''");
|
|
220
221
|
db.exec("UPDATE agent_presence SET created_at = last_seen_at WHERE created_at = ''");
|
|
221
222
|
}
|
|
223
|
+
if (!presenceColNames.includes("project_id")) {
|
|
224
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN project_id TEXT");
|
|
225
|
+
}
|
|
222
226
|
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
|
|
223
227
|
if (!ftsExists) {
|
|
224
228
|
db.exec(`
|
package/bin/index.js
CHANGED
|
@@ -1972,6 +1972,7 @@ function getDb() {
|
|
|
1972
1972
|
agent TEXT PRIMARY KEY,
|
|
1973
1973
|
session_id TEXT,
|
|
1974
1974
|
role TEXT NOT NULL DEFAULT 'agent',
|
|
1975
|
+
project_id TEXT,
|
|
1975
1976
|
status TEXT NOT NULL DEFAULT 'online',
|
|
1976
1977
|
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
1977
1978
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
@@ -2073,6 +2074,9 @@ function getDb() {
|
|
|
2073
2074
|
db.exec("ALTER TABLE agent_presence ADD COLUMN created_at TEXT NOT NULL DEFAULT ''");
|
|
2074
2075
|
db.exec("UPDATE agent_presence SET created_at = last_seen_at WHERE created_at = ''");
|
|
2075
2076
|
}
|
|
2077
|
+
if (!presenceColNames.includes("project_id")) {
|
|
2078
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN project_id TEXT");
|
|
2079
|
+
}
|
|
2076
2080
|
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
|
|
2077
2081
|
if (!ftsExists) {
|
|
2078
2082
|
db.exec(`
|
|
@@ -3339,6 +3343,7 @@ function parsePresence(row) {
|
|
|
3339
3343
|
agent: row.agent,
|
|
3340
3344
|
session_id: row.session_id ?? null,
|
|
3341
3345
|
role: row.role || "agent",
|
|
3346
|
+
project_id: row.project_id ?? null,
|
|
3342
3347
|
status: row.status,
|
|
3343
3348
|
last_seen_at: lastSeenAt,
|
|
3344
3349
|
created_at: row.created_at || lastSeenAt,
|
|
@@ -3351,43 +3356,46 @@ function isActiveSession(lastSeenAt) {
|
|
|
3351
3356
|
const nowMs = Date.now();
|
|
3352
3357
|
return nowMs - lastSeenMs < CONFLICT_THRESHOLD_SECONDS * 1000;
|
|
3353
3358
|
}
|
|
3354
|
-
function registerAgent(name, sessionId, role) {
|
|
3359
|
+
function registerAgent(name, sessionId, role, projectId) {
|
|
3355
3360
|
const db2 = getDb();
|
|
3356
3361
|
const normalizedName = name.trim().toLowerCase();
|
|
3357
|
-
const
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3362
|
+
const result = db2.transaction(() => {
|
|
3363
|
+
const existing = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
3364
|
+
if (existing) {
|
|
3365
|
+
const lastSeenAt = existing.last_seen_at;
|
|
3366
|
+
const existingSessionId = existing.session_id;
|
|
3367
|
+
if (isActiveSession(lastSeenAt) && existingSessionId && existingSessionId !== sessionId) {
|
|
3368
|
+
return {
|
|
3369
|
+
conflict: true,
|
|
3370
|
+
error: "agent_conflict",
|
|
3371
|
+
message: `Agent "${normalizedName}" is already active (last seen: ${lastSeenAt}). Wait 30 minutes or use force takeover.`,
|
|
3372
|
+
existing_id: existing.id,
|
|
3373
|
+
existing_name: normalizedName,
|
|
3374
|
+
existing_session_id: existingSessionId,
|
|
3375
|
+
last_seen_at: lastSeenAt,
|
|
3376
|
+
session_hint: existingSessionId ? existingSessionId.slice(0, 8) : null,
|
|
3377
|
+
working_dir: null
|
|
3378
|
+
};
|
|
3379
|
+
}
|
|
3380
|
+
const tookOver = existingSessionId !== sessionId;
|
|
3381
|
+
db2.prepare(`
|
|
3382
|
+
UPDATE agent_presence
|
|
3383
|
+
SET session_id = ?, role = ?, project_id = ?, last_seen_at = strftime('%Y-%m-%dT%H:%M:%f', 'now')
|
|
3384
|
+
WHERE agent = ?
|
|
3385
|
+
`).run(sessionId, role || existing.role || "agent", projectId ?? existing.project_id ?? null, normalizedName);
|
|
3386
|
+
const updated = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
3387
|
+
return { agent: parsePresence(updated), created: false, took_over: tookOver };
|
|
3388
|
+
}
|
|
3389
|
+
const id = crypto.randomUUID().slice(0, 8);
|
|
3390
|
+
const resolvedRole = role || "agent";
|
|
3375
3391
|
db2.prepare(`
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
const id = crypto.randomUUID().slice(0, 8);
|
|
3384
|
-
const resolvedRole = role || "agent";
|
|
3385
|
-
db2.prepare(`
|
|
3386
|
-
INSERT INTO agent_presence (id, agent, session_id, role, status, last_seen_at, created_at)
|
|
3387
|
-
VALUES (?, ?, ?, ?, 'online', strftime('%Y-%m-%dT%H:%M:%f', 'now'), strftime('%Y-%m-%dT%H:%M:%f', 'now'))
|
|
3388
|
-
`).run(id, normalizedName, sessionId, resolvedRole);
|
|
3389
|
-
const created = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
3390
|
-
return { agent: parsePresence(created), created: true, took_over: false };
|
|
3392
|
+
INSERT INTO agent_presence (id, agent, session_id, role, project_id, status, last_seen_at, created_at)
|
|
3393
|
+
VALUES (?, ?, ?, ?, ?, 'online', strftime('%Y-%m-%dT%H:%M:%f', 'now'), strftime('%Y-%m-%dT%H:%M:%f', 'now'))
|
|
3394
|
+
`).run(id, normalizedName, sessionId, resolvedRole, projectId ?? null);
|
|
3395
|
+
const created = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
3396
|
+
return { agent: parsePresence(created), created: true, took_over: false };
|
|
3397
|
+
}).immediate();
|
|
3398
|
+
return result;
|
|
3391
3399
|
}
|
|
3392
3400
|
function heartbeat(agent, status, metadata, sessionId) {
|
|
3393
3401
|
const db2 = getDb();
|
|
@@ -3591,7 +3599,7 @@ var init_poll = __esm(() => {
|
|
|
3591
3599
|
var require_package = __commonJS((exports, module) => {
|
|
3592
3600
|
module.exports = {
|
|
3593
3601
|
name: "@hasna/conversations",
|
|
3594
|
-
version: "0.1.
|
|
3602
|
+
version: "0.1.29",
|
|
3595
3603
|
description: "Real-time CLI messaging for AI agents",
|
|
3596
3604
|
type: "module",
|
|
3597
3605
|
bin: {
|
|
@@ -33189,15 +33197,16 @@ var init_mcp2 = __esm(() => {
|
|
|
33189
33197
|
};
|
|
33190
33198
|
});
|
|
33191
33199
|
server.registerTool("register_agent", {
|
|
33192
|
-
description: "Register an agent with conflict detection. Returns AgentConflictError if another active session exists (active = heartbeat within last 30 min).",
|
|
33200
|
+
description: "Register an agent with conflict detection. Returns AgentConflictError if another active session exists (active = heartbeat within last 30 min). Optional project_id locks agent to a project for the session.",
|
|
33193
33201
|
inputSchema: {
|
|
33194
33202
|
name: exports_external.string(),
|
|
33195
33203
|
session_id: exports_external.string(),
|
|
33196
|
-
role: exports_external.string().optional()
|
|
33204
|
+
role: exports_external.string().optional(),
|
|
33205
|
+
project_id: exports_external.string().optional()
|
|
33197
33206
|
}
|
|
33198
33207
|
}, async (args) => {
|
|
33199
|
-
const { name, session_id, role } = args;
|
|
33200
|
-
const result = registerAgent(name, session_id, role);
|
|
33208
|
+
const { name, session_id, role, project_id } = args;
|
|
33209
|
+
const result = registerAgent(name, session_id, role, project_id);
|
|
33201
33210
|
return {
|
|
33202
33211
|
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
33203
33212
|
};
|
package/bin/mcp.js
CHANGED
|
@@ -6604,6 +6604,7 @@ function getDb() {
|
|
|
6604
6604
|
agent TEXT PRIMARY KEY,
|
|
6605
6605
|
session_id TEXT,
|
|
6606
6606
|
role TEXT NOT NULL DEFAULT 'agent',
|
|
6607
|
+
project_id TEXT,
|
|
6607
6608
|
status TEXT NOT NULL DEFAULT 'online',
|
|
6608
6609
|
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
6609
6610
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
@@ -6705,6 +6706,9 @@ function getDb() {
|
|
|
6705
6706
|
db.exec("ALTER TABLE agent_presence ADD COLUMN created_at TEXT NOT NULL DEFAULT ''");
|
|
6706
6707
|
db.exec("UPDATE agent_presence SET created_at = last_seen_at WHERE created_at = ''");
|
|
6707
6708
|
}
|
|
6709
|
+
if (!presenceColNames.includes("project_id")) {
|
|
6710
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN project_id TEXT");
|
|
6711
|
+
}
|
|
6708
6712
|
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
|
|
6709
6713
|
if (!ftsExists) {
|
|
6710
6714
|
db.exec(`
|
|
@@ -29765,6 +29769,7 @@ function parsePresence(row) {
|
|
|
29765
29769
|
agent: row.agent,
|
|
29766
29770
|
session_id: row.session_id ?? null,
|
|
29767
29771
|
role: row.role || "agent",
|
|
29772
|
+
project_id: row.project_id ?? null,
|
|
29768
29773
|
status: row.status,
|
|
29769
29774
|
last_seen_at: lastSeenAt,
|
|
29770
29775
|
created_at: row.created_at || lastSeenAt,
|
|
@@ -29777,43 +29782,46 @@ function isActiveSession(lastSeenAt) {
|
|
|
29777
29782
|
const nowMs = Date.now();
|
|
29778
29783
|
return nowMs - lastSeenMs < CONFLICT_THRESHOLD_SECONDS * 1000;
|
|
29779
29784
|
}
|
|
29780
|
-
function registerAgent(name, sessionId, role) {
|
|
29785
|
+
function registerAgent(name, sessionId, role, projectId) {
|
|
29781
29786
|
const db2 = getDb();
|
|
29782
29787
|
const normalizedName = name.trim().toLowerCase();
|
|
29783
|
-
const
|
|
29784
|
-
|
|
29785
|
-
|
|
29786
|
-
|
|
29787
|
-
|
|
29788
|
-
|
|
29789
|
-
|
|
29790
|
-
|
|
29791
|
-
|
|
29792
|
-
|
|
29793
|
-
|
|
29794
|
-
|
|
29795
|
-
|
|
29796
|
-
|
|
29797
|
-
|
|
29798
|
-
|
|
29799
|
-
|
|
29800
|
-
|
|
29788
|
+
const result = db2.transaction(() => {
|
|
29789
|
+
const existing = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
29790
|
+
if (existing) {
|
|
29791
|
+
const lastSeenAt = existing.last_seen_at;
|
|
29792
|
+
const existingSessionId = existing.session_id;
|
|
29793
|
+
if (isActiveSession(lastSeenAt) && existingSessionId && existingSessionId !== sessionId) {
|
|
29794
|
+
return {
|
|
29795
|
+
conflict: true,
|
|
29796
|
+
error: "agent_conflict",
|
|
29797
|
+
message: `Agent "${normalizedName}" is already active (last seen: ${lastSeenAt}). Wait 30 minutes or use force takeover.`,
|
|
29798
|
+
existing_id: existing.id,
|
|
29799
|
+
existing_name: normalizedName,
|
|
29800
|
+
existing_session_id: existingSessionId,
|
|
29801
|
+
last_seen_at: lastSeenAt,
|
|
29802
|
+
session_hint: existingSessionId ? existingSessionId.slice(0, 8) : null,
|
|
29803
|
+
working_dir: null
|
|
29804
|
+
};
|
|
29805
|
+
}
|
|
29806
|
+
const tookOver = existingSessionId !== sessionId;
|
|
29807
|
+
db2.prepare(`
|
|
29808
|
+
UPDATE agent_presence
|
|
29809
|
+
SET session_id = ?, role = ?, project_id = ?, last_seen_at = strftime('%Y-%m-%dT%H:%M:%f', 'now')
|
|
29810
|
+
WHERE agent = ?
|
|
29811
|
+
`).run(sessionId, role || existing.role || "agent", projectId ?? existing.project_id ?? null, normalizedName);
|
|
29812
|
+
const updated = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
29813
|
+
return { agent: parsePresence(updated), created: false, took_over: tookOver };
|
|
29814
|
+
}
|
|
29815
|
+
const id = crypto.randomUUID().slice(0, 8);
|
|
29816
|
+
const resolvedRole = role || "agent";
|
|
29801
29817
|
db2.prepare(`
|
|
29802
|
-
|
|
29803
|
-
|
|
29804
|
-
|
|
29805
|
-
|
|
29806
|
-
|
|
29807
|
-
|
|
29808
|
-
|
|
29809
|
-
const id = crypto.randomUUID().slice(0, 8);
|
|
29810
|
-
const resolvedRole = role || "agent";
|
|
29811
|
-
db2.prepare(`
|
|
29812
|
-
INSERT INTO agent_presence (id, agent, session_id, role, status, last_seen_at, created_at)
|
|
29813
|
-
VALUES (?, ?, ?, ?, 'online', strftime('%Y-%m-%dT%H:%M:%f', 'now'), strftime('%Y-%m-%dT%H:%M:%f', 'now'))
|
|
29814
|
-
`).run(id, normalizedName, sessionId, resolvedRole);
|
|
29815
|
-
const created = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
29816
|
-
return { agent: parsePresence(created), created: true, took_over: false };
|
|
29818
|
+
INSERT INTO agent_presence (id, agent, session_id, role, project_id, status, last_seen_at, created_at)
|
|
29819
|
+
VALUES (?, ?, ?, ?, ?, 'online', strftime('%Y-%m-%dT%H:%M:%f', 'now'), strftime('%Y-%m-%dT%H:%M:%f', 'now'))
|
|
29820
|
+
`).run(id, normalizedName, sessionId, resolvedRole, projectId ?? null);
|
|
29821
|
+
const created = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
29822
|
+
return { agent: parsePresence(created), created: true, took_over: false };
|
|
29823
|
+
}).immediate();
|
|
29824
|
+
return result;
|
|
29817
29825
|
}
|
|
29818
29826
|
function heartbeat(agent, status, metadata, sessionId) {
|
|
29819
29827
|
const db2 = getDb();
|
|
@@ -29864,7 +29872,7 @@ function renameAgent(oldName, newName) {
|
|
|
29864
29872
|
// package.json
|
|
29865
29873
|
var package_default = {
|
|
29866
29874
|
name: "@hasna/conversations",
|
|
29867
|
-
version: "0.1.
|
|
29875
|
+
version: "0.1.29",
|
|
29868
29876
|
description: "Real-time CLI messaging for AI agents",
|
|
29869
29877
|
type: "module",
|
|
29870
29878
|
bin: {
|
|
@@ -30574,15 +30582,16 @@ server.registerTool("get_pinned_messages", {
|
|
|
30574
30582
|
};
|
|
30575
30583
|
});
|
|
30576
30584
|
server.registerTool("register_agent", {
|
|
30577
|
-
description: "Register an agent with conflict detection. Returns AgentConflictError if another active session exists (active = heartbeat within last 30 min).",
|
|
30585
|
+
description: "Register an agent with conflict detection. Returns AgentConflictError if another active session exists (active = heartbeat within last 30 min). Optional project_id locks agent to a project for the session.",
|
|
30578
30586
|
inputSchema: {
|
|
30579
30587
|
name: exports_external.string(),
|
|
30580
30588
|
session_id: exports_external.string(),
|
|
30581
|
-
role: exports_external.string().optional()
|
|
30589
|
+
role: exports_external.string().optional(),
|
|
30590
|
+
project_id: exports_external.string().optional()
|
|
30582
30591
|
}
|
|
30583
30592
|
}, async (args) => {
|
|
30584
|
-
const { name, session_id, role } = args;
|
|
30585
|
-
const result = registerAgent(name, session_id, role);
|
|
30593
|
+
const { name, session_id, role, project_id } = args;
|
|
30594
|
+
const result = registerAgent(name, session_id, role, project_id);
|
|
30586
30595
|
return {
|
|
30587
30596
|
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
30588
30597
|
};
|
package/dist/index.js
CHANGED
|
@@ -131,6 +131,7 @@ function getDb() {
|
|
|
131
131
|
agent TEXT PRIMARY KEY,
|
|
132
132
|
session_id TEXT,
|
|
133
133
|
role TEXT NOT NULL DEFAULT 'agent',
|
|
134
|
+
project_id TEXT,
|
|
134
135
|
status TEXT NOT NULL DEFAULT 'online',
|
|
135
136
|
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
136
137
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f', 'now')),
|
|
@@ -232,6 +233,9 @@ function getDb() {
|
|
|
232
233
|
db.exec("ALTER TABLE agent_presence ADD COLUMN created_at TEXT NOT NULL DEFAULT ''");
|
|
233
234
|
db.exec("UPDATE agent_presence SET created_at = last_seen_at WHERE created_at = ''");
|
|
234
235
|
}
|
|
236
|
+
if (!presenceColNames.includes("project_id")) {
|
|
237
|
+
db.exec("ALTER TABLE agent_presence ADD COLUMN project_id TEXT");
|
|
238
|
+
}
|
|
235
239
|
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
|
|
236
240
|
if (!ftsExists) {
|
|
237
241
|
db.exec(`
|
|
@@ -3444,6 +3448,7 @@ function parsePresence(row) {
|
|
|
3444
3448
|
agent: row.agent,
|
|
3445
3449
|
session_id: row.session_id ?? null,
|
|
3446
3450
|
role: row.role || "agent",
|
|
3451
|
+
project_id: row.project_id ?? null,
|
|
3447
3452
|
status: row.status,
|
|
3448
3453
|
last_seen_at: lastSeenAt,
|
|
3449
3454
|
created_at: row.created_at || lastSeenAt,
|
|
@@ -3459,43 +3464,46 @@ function isActiveSession(lastSeenAt) {
|
|
|
3459
3464
|
function isAgentConflict(result) {
|
|
3460
3465
|
return result.conflict === true;
|
|
3461
3466
|
}
|
|
3462
|
-
function registerAgent(name, sessionId, role) {
|
|
3467
|
+
function registerAgent(name, sessionId, role, projectId) {
|
|
3463
3468
|
const db2 = getDb();
|
|
3464
3469
|
const normalizedName = name.trim().toLowerCase();
|
|
3465
|
-
const
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3470
|
+
const result = db2.transaction(() => {
|
|
3471
|
+
const existing = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
3472
|
+
if (existing) {
|
|
3473
|
+
const lastSeenAt = existing.last_seen_at;
|
|
3474
|
+
const existingSessionId = existing.session_id;
|
|
3475
|
+
if (isActiveSession(lastSeenAt) && existingSessionId && existingSessionId !== sessionId) {
|
|
3476
|
+
return {
|
|
3477
|
+
conflict: true,
|
|
3478
|
+
error: "agent_conflict",
|
|
3479
|
+
message: `Agent "${normalizedName}" is already active (last seen: ${lastSeenAt}). Wait 30 minutes or use force takeover.`,
|
|
3480
|
+
existing_id: existing.id,
|
|
3481
|
+
existing_name: normalizedName,
|
|
3482
|
+
existing_session_id: existingSessionId,
|
|
3483
|
+
last_seen_at: lastSeenAt,
|
|
3484
|
+
session_hint: existingSessionId ? existingSessionId.slice(0, 8) : null,
|
|
3485
|
+
working_dir: null
|
|
3486
|
+
};
|
|
3487
|
+
}
|
|
3488
|
+
const tookOver = existingSessionId !== sessionId;
|
|
3489
|
+
db2.prepare(`
|
|
3490
|
+
UPDATE agent_presence
|
|
3491
|
+
SET session_id = ?, role = ?, project_id = ?, last_seen_at = strftime('%Y-%m-%dT%H:%M:%f', 'now')
|
|
3492
|
+
WHERE agent = ?
|
|
3493
|
+
`).run(sessionId, role || existing.role || "agent", projectId ?? existing.project_id ?? null, normalizedName);
|
|
3494
|
+
const updated = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
3495
|
+
return { agent: parsePresence(updated), created: false, took_over: tookOver };
|
|
3481
3496
|
}
|
|
3482
|
-
const
|
|
3497
|
+
const id = crypto.randomUUID().slice(0, 8);
|
|
3498
|
+
const resolvedRole = role || "agent";
|
|
3483
3499
|
db2.prepare(`
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
const id = crypto.randomUUID().slice(0, 8);
|
|
3492
|
-
const resolvedRole = role || "agent";
|
|
3493
|
-
db2.prepare(`
|
|
3494
|
-
INSERT INTO agent_presence (id, agent, session_id, role, status, last_seen_at, created_at)
|
|
3495
|
-
VALUES (?, ?, ?, ?, 'online', strftime('%Y-%m-%dT%H:%M:%f', 'now'), strftime('%Y-%m-%dT%H:%M:%f', 'now'))
|
|
3496
|
-
`).run(id, normalizedName, sessionId, resolvedRole);
|
|
3497
|
-
const created = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
3498
|
-
return { agent: parsePresence(created), created: true, took_over: false };
|
|
3500
|
+
INSERT INTO agent_presence (id, agent, session_id, role, project_id, status, last_seen_at, created_at)
|
|
3501
|
+
VALUES (?, ?, ?, ?, ?, 'online', strftime('%Y-%m-%dT%H:%M:%f', 'now'), strftime('%Y-%m-%dT%H:%M:%f', 'now'))
|
|
3502
|
+
`).run(id, normalizedName, sessionId, resolvedRole, projectId ?? null);
|
|
3503
|
+
const created = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(normalizedName);
|
|
3504
|
+
return { agent: parsePresence(created), created: true, took_over: false };
|
|
3505
|
+
}).immediate();
|
|
3506
|
+
return result;
|
|
3499
3507
|
}
|
|
3500
3508
|
function heartbeat(agent, status, metadata, sessionId) {
|
|
3501
3509
|
const db2 = getDb();
|
package/dist/lib/presence.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentPresence, AgentConflictError, RegisterAgentResult } from "../types.js";
|
|
2
2
|
export declare function isAgentConflict(result: RegisterAgentResult | AgentConflictError): result is AgentConflictError;
|
|
3
|
-
export declare function registerAgent(name: string, sessionId: string, role?: string): RegisterAgentResult | AgentConflictError;
|
|
3
|
+
export declare function registerAgent(name: string, sessionId: string, role?: string, projectId?: string): RegisterAgentResult | AgentConflictError;
|
|
4
4
|
export declare function heartbeat(agent: string, status?: string, metadata?: Record<string, unknown>, sessionId?: string): void;
|
|
5
5
|
export declare function getPresence(agent: string): AgentPresence | null;
|
|
6
6
|
export declare function listAgents(opts?: {
|
package/dist/types.d.ts
CHANGED