@dalmasonto/taskflow-mcp 1.0.27 → 1.0.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/dist/agent-registry.js +22 -22
- package/package.json +1 -1
package/dist/agent-registry.js
CHANGED
|
@@ -27,25 +27,20 @@ function detectTmuxPane(pid) {
|
|
|
27
27
|
return null;
|
|
28
28
|
}
|
|
29
29
|
/** Generate a unique agent name from the project folder, auto-suffixing on collision.
|
|
30
|
-
*
|
|
30
|
+
* A name is available if no row exists or the existing row's process is dead. */
|
|
31
31
|
function generateName(folderName) {
|
|
32
32
|
const db = getDb();
|
|
33
|
-
const
|
|
33
|
+
const isAvailable = (name) => {
|
|
34
34
|
const row = db.prepare('SELECT * FROM agent_registry WHERE name = ?').get(name);
|
|
35
35
|
if (!row)
|
|
36
|
-
return true; // name is free
|
|
37
|
-
if (!isAlive(row.pid)) {
|
|
38
|
-
// Dead entry — remove it so the name can be reused via INSERT
|
|
39
|
-
db.prepare('DELETE FROM agent_registry WHERE id = ?').run(row.id);
|
|
40
36
|
return true;
|
|
41
|
-
|
|
42
|
-
return false; // name is taken by a live agent
|
|
37
|
+
return !isAlive(row.pid);
|
|
43
38
|
};
|
|
44
|
-
if (
|
|
39
|
+
if (isAvailable(folderName))
|
|
45
40
|
return folderName;
|
|
46
41
|
for (let i = 2; i < 100; i++) {
|
|
47
42
|
const candidate = `${folderName}:${i}`;
|
|
48
|
-
if (
|
|
43
|
+
if (isAvailable(candidate))
|
|
49
44
|
return candidate;
|
|
50
45
|
}
|
|
51
46
|
return `${folderName}:${Date.now()}`;
|
|
@@ -72,9 +67,12 @@ export function registerAgent(options) {
|
|
|
72
67
|
if (samePid && options?.customName && options.customName !== samePid.name) {
|
|
73
68
|
const oldName = samePid.name;
|
|
74
69
|
const newName = options.customName;
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
db.prepare('
|
|
70
|
+
// If the target name already exists as another row (disconnected from a previous session),
|
|
71
|
+
// delete it to free the UNIQUE name. Messages stay — they're linked by name string, not FK.
|
|
72
|
+
const existing = db.prepare('SELECT * FROM agent_registry WHERE name = ?').get(newName);
|
|
73
|
+
if (existing && existing.id !== samePid.id) {
|
|
74
|
+
db.prepare('DELETE FROM agent_registry WHERE id = ?').run(existing.id);
|
|
75
|
+
}
|
|
78
76
|
db.prepare('UPDATE agent_registry SET name = ?, tmux_pane = ?, connected_at = ? WHERE id = ?').run(newName, tmuxPane, ts, samePid.id);
|
|
79
77
|
const row = db.prepare('SELECT * FROM agent_registry WHERE id = ?').get(samePid.id);
|
|
80
78
|
broadcast('agent_renamed', { entity: 'agent', action: 'agent_renamed', payload: { ...row, oldName } });
|
|
@@ -98,23 +96,25 @@ export function registerAgent(options) {
|
|
|
98
96
|
|| (allDisconnected.length === 1 ? allDisconnected[0] : undefined);
|
|
99
97
|
if (disconnected) {
|
|
100
98
|
const newName = options?.customName || disconnected.name;
|
|
101
|
-
const renamed = newName !== disconnected.name;
|
|
102
|
-
// Update agent_messages if renaming to preserve history
|
|
103
|
-
if (renamed) {
|
|
104
|
-
db.prepare('UPDATE agent_messages SET sender_name = ? WHERE sender_name = ?').run(newName, disconnected.name);
|
|
105
|
-
db.prepare('UPDATE agent_messages SET recipient_name = ? WHERE recipient_name = ?').run(newName, disconnected.name);
|
|
106
|
-
}
|
|
107
99
|
db.prepare('UPDATE agent_registry SET name = ?, pid = ?, tmux_pane = ?, status = ?, connected_at = ?, disconnected_at = NULL WHERE id = ?').run(newName, agentPid, tmuxPane, 'connected', ts, disconnected.id);
|
|
108
100
|
const row = db.prepare('SELECT * FROM agent_registry WHERE id = ?').get(disconnected.id);
|
|
109
101
|
broadcast('agent_connected', { entity: 'agent', action: 'agent_connected', payload: row });
|
|
110
102
|
logActivity('agent_connected', `Agent "${newName}" reconnected`, { entityType: 'agent' });
|
|
111
103
|
return newName;
|
|
112
104
|
}
|
|
113
|
-
// Priority 3:
|
|
114
|
-
// Generate a suffixed name to avoid collision
|
|
105
|
+
// Priority 3: No reusable disconnected entry — this is a new or concurrent agent
|
|
106
|
+
// Generate a suffixed name to avoid collision with live agents
|
|
115
107
|
const baseName = options?.customName || folderName;
|
|
116
108
|
const name = entries.length === 0 ? baseName : generateName(baseName);
|
|
117
|
-
|
|
109
|
+
// Upsert: if a dead entry with this name exists (from another project path),
|
|
110
|
+
// reuse it in-place to preserve its message history. Otherwise insert fresh.
|
|
111
|
+
const stale = db.prepare('SELECT * FROM agent_registry WHERE name = ?').get(name);
|
|
112
|
+
if (stale) {
|
|
113
|
+
db.prepare('UPDATE agent_registry SET project_path = ?, pid = ?, tmux_pane = ?, status = ?, connected_at = ?, disconnected_at = NULL WHERE id = ?').run(projectPath, agentPid, tmuxPane, 'connected', ts, stale.id);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
db.prepare('INSERT INTO agent_registry (name, project_path, pid, tmux_pane, status, connected_at) VALUES (?, ?, ?, ?, ?, ?)').run(name, projectPath, agentPid, tmuxPane, 'connected', ts);
|
|
117
|
+
}
|
|
118
118
|
const row = db.prepare('SELECT * FROM agent_registry WHERE name = ?').get(name);
|
|
119
119
|
broadcast('agent_connected', { entity: 'agent', action: 'agent_connected', payload: row });
|
|
120
120
|
logActivity('agent_connected', `Agent "${name}" connected`, { entityType: 'agent' });
|