@hasna/conversations 0.1.22 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +87 -11
- package/bin/mcp.js +79 -8
- package/dist/index.js +12 -7
- package/dist/lib/identity.d.ts +4 -0
- package/package.json +1 -1
- package/dashboard/dist/assets/index-Bw0wMcXE.js +0 -186
- package/dashboard/dist/assets/index-CF_GDtNp.css +0 -1
- package/dashboard/dist/index.html +0 -13
- package/dashboard/dist/logo.jpg +0 -0
package/bin/index.js
CHANGED
|
@@ -3282,6 +3282,14 @@ function resolveIdentity(explicit) {
|
|
|
3282
3282
|
return envValue;
|
|
3283
3283
|
return getAutoName();
|
|
3284
3284
|
}
|
|
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
|
+
}
|
|
3285
3293
|
var AGENT_ID_FILE, cachedAutoName = null;
|
|
3286
3294
|
var init_identity = __esm(() => {
|
|
3287
3295
|
init_names();
|
|
@@ -3314,6 +3322,7 @@ function heartbeat(agent, status, metadata) {
|
|
|
3314
3322
|
const db2 = getDb();
|
|
3315
3323
|
const metadataJson = metadata ? JSON.stringify(metadata) : null;
|
|
3316
3324
|
const resolvedStatus = status || "online";
|
|
3325
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
3317
3326
|
db2.prepare(`
|
|
3318
3327
|
INSERT INTO agent_presence (agent, status, last_seen_at, metadata)
|
|
3319
3328
|
VALUES (?, ?, strftime('%Y-%m-%dT%H:%M:%f', 'now'), ?)
|
|
@@ -3321,11 +3330,12 @@ function heartbeat(agent, status, metadata) {
|
|
|
3321
3330
|
status = excluded.status,
|
|
3322
3331
|
last_seen_at = excluded.last_seen_at,
|
|
3323
3332
|
metadata = excluded.metadata
|
|
3324
|
-
`).run(
|
|
3333
|
+
`).run(normalizedAgent, resolvedStatus, metadataJson);
|
|
3325
3334
|
}
|
|
3326
3335
|
function getPresence(agent) {
|
|
3327
3336
|
const db2 = getDb();
|
|
3328
|
-
const
|
|
3337
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
3338
|
+
const row = db2.prepare("SELECT * FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedAgent);
|
|
3329
3339
|
return row ? parsePresence(row) : null;
|
|
3330
3340
|
}
|
|
3331
3341
|
function listAgents(opts) {
|
|
@@ -3341,18 +3351,21 @@ function listAgents(opts) {
|
|
|
3341
3351
|
}
|
|
3342
3352
|
function removePresence(agent) {
|
|
3343
3353
|
const db2 = getDb();
|
|
3344
|
-
const
|
|
3354
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
3355
|
+
const result = db2.prepare("DELETE FROM agent_presence WHERE LOWER(agent) = ?").run(normalizedAgent);
|
|
3345
3356
|
return result.changes > 0;
|
|
3346
3357
|
}
|
|
3347
3358
|
function renameAgent(oldName, newName) {
|
|
3348
3359
|
const db2 = getDb();
|
|
3349
|
-
const
|
|
3360
|
+
const normalizedOld = oldName.trim().toLowerCase();
|
|
3361
|
+
const normalizedNew = newName.trim().toLowerCase();
|
|
3362
|
+
const existing = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedOld);
|
|
3350
3363
|
if (!existing)
|
|
3351
3364
|
return false;
|
|
3352
|
-
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(
|
|
3365
|
+
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedNew);
|
|
3353
3366
|
if (conflict)
|
|
3354
|
-
throw new Error(`Agent "${
|
|
3355
|
-
db2.prepare("UPDATE agent_presence SET agent = ? WHERE agent = ?").run(
|
|
3367
|
+
throw new Error(`Agent "${normalizedNew}" already exists`);
|
|
3368
|
+
db2.prepare("UPDATE agent_presence SET agent = ? WHERE LOWER(agent) = ?").run(normalizedNew, normalizedOld);
|
|
3356
3369
|
return true;
|
|
3357
3370
|
}
|
|
3358
3371
|
var ONLINE_THRESHOLD_SECONDS = 60;
|
|
@@ -3504,7 +3517,7 @@ var init_poll = __esm(() => {
|
|
|
3504
3517
|
var require_package = __commonJS((exports, module) => {
|
|
3505
3518
|
module.exports = {
|
|
3506
3519
|
name: "@hasna/conversations",
|
|
3507
|
-
version: "0.1.
|
|
3520
|
+
version: "0.1.24",
|
|
3508
3521
|
description: "Real-time CLI messaging for AI agents",
|
|
3509
3522
|
type: "module",
|
|
3510
3523
|
bin: {
|
|
@@ -30872,7 +30885,7 @@ var require_formats = __commonJS((exports) => {
|
|
|
30872
30885
|
}
|
|
30873
30886
|
var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
|
|
30874
30887
|
function getTime(strictTimeZone) {
|
|
30875
|
-
return function
|
|
30888
|
+
return function time3(str) {
|
|
30876
30889
|
const matches = TIME.exec(str);
|
|
30877
30890
|
if (!matches)
|
|
30878
30891
|
return false;
|
|
@@ -31136,6 +31149,62 @@ class ExperimentalServerTasks {
|
|
|
31136
31149
|
requestStream(request, resultSchema, options) {
|
|
31137
31150
|
return this._server.requestStream(request, resultSchema, options);
|
|
31138
31151
|
}
|
|
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
|
+
}
|
|
31139
31208
|
async getTask(taskId, options) {
|
|
31140
31209
|
return this._server.getTask({ taskId }, options);
|
|
31141
31210
|
}
|
|
@@ -31149,6 +31218,9 @@ class ExperimentalServerTasks {
|
|
|
31149
31218
|
return this._server.cancelTask({ taskId }, options);
|
|
31150
31219
|
}
|
|
31151
31220
|
}
|
|
31221
|
+
var init_server = __esm(() => {
|
|
31222
|
+
init_types2();
|
|
31223
|
+
});
|
|
31152
31224
|
|
|
31153
31225
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
31154
31226
|
function assertToolsCallTaskCapability(requests, method, entityName) {
|
|
@@ -31187,11 +31259,12 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
|
|
|
31187
31259
|
|
|
31188
31260
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
31189
31261
|
var Server;
|
|
31190
|
-
var
|
|
31262
|
+
var init_server2 = __esm(() => {
|
|
31191
31263
|
init_protocol();
|
|
31192
31264
|
init_types2();
|
|
31193
31265
|
init_ajv_provider();
|
|
31194
31266
|
init_zod_compat();
|
|
31267
|
+
init_server();
|
|
31195
31268
|
Server = class Server extends Protocol {
|
|
31196
31269
|
constructor(_serverInfo, options) {
|
|
31197
31270
|
super(options);
|
|
@@ -32333,7 +32406,7 @@ function createCompletionResult(suggestions) {
|
|
|
32333
32406
|
}
|
|
32334
32407
|
var EMPTY_OBJECT_JSON_SCHEMA, EMPTY_COMPLETION_RESULT;
|
|
32335
32408
|
var init_mcp = __esm(() => {
|
|
32336
|
-
|
|
32409
|
+
init_server2();
|
|
32337
32410
|
init_zod_compat();
|
|
32338
32411
|
init_zod_json_schema_compat();
|
|
32339
32412
|
init_types2();
|
|
@@ -33185,6 +33258,9 @@ var init_mcp2 = __esm(() => {
|
|
|
33185
33258
|
isError: true
|
|
33186
33259
|
};
|
|
33187
33260
|
}
|
|
33261
|
+
if (!fromParam) {
|
|
33262
|
+
updateCachedAutoName(newName);
|
|
33263
|
+
}
|
|
33188
33264
|
return {
|
|
33189
33265
|
content: [{ type: "text", text: JSON.stringify({ old_name: oldName, new_name: newName, renamed: true }) }]
|
|
33190
33266
|
};
|
package/bin/mcp.js
CHANGED
|
@@ -6302,7 +6302,7 @@ var require_formats = __commonJS((exports) => {
|
|
|
6302
6302
|
}
|
|
6303
6303
|
var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
|
|
6304
6304
|
function getTime(strictTimeZone) {
|
|
6305
|
-
return function
|
|
6305
|
+
return function time3(str) {
|
|
6306
6306
|
const matches = TIME.exec(str);
|
|
6307
6307
|
if (!matches)
|
|
6308
6308
|
return false;
|
|
@@ -27263,6 +27263,62 @@ class ExperimentalServerTasks {
|
|
|
27263
27263
|
requestStream(request, resultSchema, options) {
|
|
27264
27264
|
return this._server.requestStream(request, resultSchema, options);
|
|
27265
27265
|
}
|
|
27266
|
+
createMessageStream(params, options) {
|
|
27267
|
+
const clientCapabilities = this._server.getClientCapabilities();
|
|
27268
|
+
if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
|
|
27269
|
+
throw new Error("Client does not support sampling tools capability.");
|
|
27270
|
+
}
|
|
27271
|
+
if (params.messages.length > 0) {
|
|
27272
|
+
const lastMessage = params.messages[params.messages.length - 1];
|
|
27273
|
+
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
|
|
27274
|
+
const hasToolResults = lastContent.some((c) => c.type === "tool_result");
|
|
27275
|
+
const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : undefined;
|
|
27276
|
+
const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
|
|
27277
|
+
const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
|
|
27278
|
+
if (hasToolResults) {
|
|
27279
|
+
if (lastContent.some((c) => c.type !== "tool_result")) {
|
|
27280
|
+
throw new Error("The last message must contain only tool_result content if any is present");
|
|
27281
|
+
}
|
|
27282
|
+
if (!hasPreviousToolUse) {
|
|
27283
|
+
throw new Error("tool_result blocks are not matching any tool_use from the previous message");
|
|
27284
|
+
}
|
|
27285
|
+
}
|
|
27286
|
+
if (hasPreviousToolUse) {
|
|
27287
|
+
const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
|
|
27288
|
+
const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
|
|
27289
|
+
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
|
|
27290
|
+
throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
|
|
27291
|
+
}
|
|
27292
|
+
}
|
|
27293
|
+
}
|
|
27294
|
+
return this.requestStream({
|
|
27295
|
+
method: "sampling/createMessage",
|
|
27296
|
+
params
|
|
27297
|
+
}, CreateMessageResultSchema, options);
|
|
27298
|
+
}
|
|
27299
|
+
elicitInputStream(params, options) {
|
|
27300
|
+
const clientCapabilities = this._server.getClientCapabilities();
|
|
27301
|
+
const mode = params.mode ?? "form";
|
|
27302
|
+
switch (mode) {
|
|
27303
|
+
case "url": {
|
|
27304
|
+
if (!clientCapabilities?.elicitation?.url) {
|
|
27305
|
+
throw new Error("Client does not support url elicitation.");
|
|
27306
|
+
}
|
|
27307
|
+
break;
|
|
27308
|
+
}
|
|
27309
|
+
case "form": {
|
|
27310
|
+
if (!clientCapabilities?.elicitation?.form) {
|
|
27311
|
+
throw new Error("Client does not support form elicitation.");
|
|
27312
|
+
}
|
|
27313
|
+
break;
|
|
27314
|
+
}
|
|
27315
|
+
}
|
|
27316
|
+
const normalizedParams = mode === "form" && params.mode === undefined ? { ...params, mode: "form" } : params;
|
|
27317
|
+
return this.requestStream({
|
|
27318
|
+
method: "elicitation/create",
|
|
27319
|
+
params: normalizedParams
|
|
27320
|
+
}, ElicitResultSchema, options);
|
|
27321
|
+
}
|
|
27266
27322
|
async getTask(taskId, options) {
|
|
27267
27323
|
return this._server.getTask({ taskId }, options);
|
|
27268
27324
|
}
|
|
@@ -29710,6 +29766,14 @@ function resolveIdentity(explicit) {
|
|
|
29710
29766
|
return envValue;
|
|
29711
29767
|
return getAutoName();
|
|
29712
29768
|
}
|
|
29769
|
+
function updateCachedAutoName(newName) {
|
|
29770
|
+
cachedAutoName = newName;
|
|
29771
|
+
try {
|
|
29772
|
+
mkdirSync3(dirname2(AGENT_ID_FILE), { recursive: true });
|
|
29773
|
+
writeFileSync(AGENT_ID_FILE, newName + `
|
|
29774
|
+
`, "utf-8");
|
|
29775
|
+
} catch {}
|
|
29776
|
+
}
|
|
29713
29777
|
|
|
29714
29778
|
// src/lib/presence.ts
|
|
29715
29779
|
init_db();
|
|
@@ -29739,6 +29803,7 @@ function heartbeat(agent, status, metadata) {
|
|
|
29739
29803
|
const db2 = getDb();
|
|
29740
29804
|
const metadataJson = metadata ? JSON.stringify(metadata) : null;
|
|
29741
29805
|
const resolvedStatus = status || "online";
|
|
29806
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
29742
29807
|
db2.prepare(`
|
|
29743
29808
|
INSERT INTO agent_presence (agent, status, last_seen_at, metadata)
|
|
29744
29809
|
VALUES (?, ?, strftime('%Y-%m-%dT%H:%M:%f', 'now'), ?)
|
|
@@ -29746,7 +29811,7 @@ function heartbeat(agent, status, metadata) {
|
|
|
29746
29811
|
status = excluded.status,
|
|
29747
29812
|
last_seen_at = excluded.last_seen_at,
|
|
29748
29813
|
metadata = excluded.metadata
|
|
29749
|
-
`).run(
|
|
29814
|
+
`).run(normalizedAgent, resolvedStatus, metadataJson);
|
|
29750
29815
|
}
|
|
29751
29816
|
function listAgents(opts) {
|
|
29752
29817
|
const db2 = getDb();
|
|
@@ -29761,24 +29826,27 @@ function listAgents(opts) {
|
|
|
29761
29826
|
}
|
|
29762
29827
|
function removePresence(agent) {
|
|
29763
29828
|
const db2 = getDb();
|
|
29764
|
-
const
|
|
29829
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
29830
|
+
const result = db2.prepare("DELETE FROM agent_presence WHERE LOWER(agent) = ?").run(normalizedAgent);
|
|
29765
29831
|
return result.changes > 0;
|
|
29766
29832
|
}
|
|
29767
29833
|
function renameAgent(oldName, newName) {
|
|
29768
29834
|
const db2 = getDb();
|
|
29769
|
-
const
|
|
29835
|
+
const normalizedOld = oldName.trim().toLowerCase();
|
|
29836
|
+
const normalizedNew = newName.trim().toLowerCase();
|
|
29837
|
+
const existing = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedOld);
|
|
29770
29838
|
if (!existing)
|
|
29771
29839
|
return false;
|
|
29772
|
-
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(
|
|
29840
|
+
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedNew);
|
|
29773
29841
|
if (conflict)
|
|
29774
|
-
throw new Error(`Agent "${
|
|
29775
|
-
db2.prepare("UPDATE agent_presence SET agent = ? WHERE agent = ?").run(
|
|
29842
|
+
throw new Error(`Agent "${normalizedNew}" already exists`);
|
|
29843
|
+
db2.prepare("UPDATE agent_presence SET agent = ? WHERE LOWER(agent) = ?").run(normalizedNew, normalizedOld);
|
|
29776
29844
|
return true;
|
|
29777
29845
|
}
|
|
29778
29846
|
// package.json
|
|
29779
29847
|
var package_default = {
|
|
29780
29848
|
name: "@hasna/conversations",
|
|
29781
|
-
version: "0.1.
|
|
29849
|
+
version: "0.1.24",
|
|
29782
29850
|
description: "Real-time CLI messaging for AI agents",
|
|
29783
29851
|
type: "module",
|
|
29784
29852
|
bin: {
|
|
@@ -30571,6 +30639,9 @@ server.registerTool("rename_agent", {
|
|
|
30571
30639
|
isError: true
|
|
30572
30640
|
};
|
|
30573
30641
|
}
|
|
30642
|
+
if (!fromParam) {
|
|
30643
|
+
updateCachedAutoName(newName);
|
|
30644
|
+
}
|
|
30574
30645
|
return {
|
|
30575
30646
|
content: [{ type: "text", text: JSON.stringify({ old_name: oldName, new_name: newName, renamed: true }) }]
|
|
30576
30647
|
};
|
package/dist/index.js
CHANGED
|
@@ -3426,6 +3426,7 @@ function heartbeat(agent, status, metadata) {
|
|
|
3426
3426
|
const db2 = getDb();
|
|
3427
3427
|
const metadataJson = metadata ? JSON.stringify(metadata) : null;
|
|
3428
3428
|
const resolvedStatus = status || "online";
|
|
3429
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
3429
3430
|
db2.prepare(`
|
|
3430
3431
|
INSERT INTO agent_presence (agent, status, last_seen_at, metadata)
|
|
3431
3432
|
VALUES (?, ?, strftime('%Y-%m-%dT%H:%M:%f', 'now'), ?)
|
|
@@ -3433,11 +3434,12 @@ function heartbeat(agent, status, metadata) {
|
|
|
3433
3434
|
status = excluded.status,
|
|
3434
3435
|
last_seen_at = excluded.last_seen_at,
|
|
3435
3436
|
metadata = excluded.metadata
|
|
3436
|
-
`).run(
|
|
3437
|
+
`).run(normalizedAgent, resolvedStatus, metadataJson);
|
|
3437
3438
|
}
|
|
3438
3439
|
function getPresence(agent) {
|
|
3439
3440
|
const db2 = getDb();
|
|
3440
|
-
const
|
|
3441
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
3442
|
+
const row = db2.prepare("SELECT * FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedAgent);
|
|
3441
3443
|
return row ? parsePresence(row) : null;
|
|
3442
3444
|
}
|
|
3443
3445
|
function listAgents(opts) {
|
|
@@ -3453,18 +3455,21 @@ function listAgents(opts) {
|
|
|
3453
3455
|
}
|
|
3454
3456
|
function removePresence(agent) {
|
|
3455
3457
|
const db2 = getDb();
|
|
3456
|
-
const
|
|
3458
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
3459
|
+
const result = db2.prepare("DELETE FROM agent_presence WHERE LOWER(agent) = ?").run(normalizedAgent);
|
|
3457
3460
|
return result.changes > 0;
|
|
3458
3461
|
}
|
|
3459
3462
|
function renameAgent(oldName, newName) {
|
|
3460
3463
|
const db2 = getDb();
|
|
3461
|
-
const
|
|
3464
|
+
const normalizedOld = oldName.trim().toLowerCase();
|
|
3465
|
+
const normalizedNew = newName.trim().toLowerCase();
|
|
3466
|
+
const existing = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedOld);
|
|
3462
3467
|
if (!existing)
|
|
3463
3468
|
return false;
|
|
3464
|
-
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(
|
|
3469
|
+
const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedNew);
|
|
3465
3470
|
if (conflict)
|
|
3466
|
-
throw new Error(`Agent "${
|
|
3467
|
-
db2.prepare("UPDATE agent_presence SET agent = ? WHERE agent = ?").run(
|
|
3471
|
+
throw new Error(`Agent "${normalizedNew}" already exists`);
|
|
3472
|
+
db2.prepare("UPDATE agent_presence SET agent = ? WHERE LOWER(agent) = ?").run(normalizedNew, normalizedOld);
|
|
3468
3473
|
return true;
|
|
3469
3474
|
}
|
|
3470
3475
|
export {
|
package/dist/lib/identity.d.ts
CHANGED
|
@@ -14,6 +14,10 @@ export declare function resolveIdentity(explicit?: string): string;
|
|
|
14
14
|
* Throws if no identity is set via flag or env.
|
|
15
15
|
*/
|
|
16
16
|
export declare function requireIdentity(explicit?: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Update the cached auto name after a successful rename.
|
|
19
|
+
*/
|
|
20
|
+
export declare function updateCachedAutoName(newName: string): void;
|
|
17
21
|
/**
|
|
18
22
|
* Reset the cached auto name (for testing).
|
|
19
23
|
*/
|