@michael-joseph-miller/ant-bot 0.2.0 → 0.2.2
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/CHANGELOG.md +33 -0
- package/README.md +4 -4
- package/dist/{chunk-RMDMUCVS.js → chunk-F3D2K4WZ.js} +1 -1
- package/dist/{chunk-RMDMUCVS.js.map → chunk-F3D2K4WZ.js.map} +2 -2
- package/dist/index.js +3 -5
- package/dist/index.js.map +2 -2
- package/dist/server.js +77 -2
- package/dist/server.js.map +2 -2
- package/package.json +1 -1
- package/web/dist/assets/{index-nnI9BOXM.js → index-X8Gv7rgf.js} +2 -2
- package/web/dist/index.html +1 -1
package/dist/server.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
SettingsSchema,
|
|
19
19
|
UpdateBotRequest,
|
|
20
20
|
UpdateConnectorRequest
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-F3D2K4WZ.js";
|
|
22
22
|
import {
|
|
23
23
|
findWebDist,
|
|
24
24
|
nodeLocateDeps,
|
|
@@ -498,6 +498,28 @@ var Store = class {
|
|
|
498
498
|
this.db.prepare(`DELETE FROM routines WHERE bot_id=?`).run(id);
|
|
499
499
|
if (bot.threadId) this.db.prepare(`DELETE FROM threads WHERE id=?`).run(bot.threadId);
|
|
500
500
|
}
|
|
501
|
+
/**
|
|
502
|
+
* Clear a bot's conversation and its SDK session, keeping everything that defines the bot.
|
|
503
|
+
*
|
|
504
|
+
* Deliberately narrow. Memory, skills, connectors, routines and the bot's files all survive —
|
|
505
|
+
* those are the bot. What goes is the accumulated conversation: the messages in its thread and
|
|
506
|
+
* the `session_id` the SDK resumes from, which is what makes a turn carry prior context.
|
|
507
|
+
*
|
|
508
|
+
* Messages are deleted rather than the thread, so the thread id every other row points at
|
|
509
|
+
* stays valid; the FTS triggers keep the search index in step.
|
|
510
|
+
*/
|
|
511
|
+
resetBotSession(id) {
|
|
512
|
+
const bot = this.getBot(id);
|
|
513
|
+
if (!bot) return null;
|
|
514
|
+
let messagesDeleted = 0;
|
|
515
|
+
if (bot.threadId) {
|
|
516
|
+
const info = this.db.prepare(`DELETE FROM messages WHERE thread_id=?`).run(bot.threadId);
|
|
517
|
+
messagesDeleted = info.changes;
|
|
518
|
+
this.db.prepare(`UPDATE threads SET last_read_at=0 WHERE id=?`).run(bot.threadId);
|
|
519
|
+
}
|
|
520
|
+
this.db.prepare(`UPDATE bots SET session_id=NULL, attention='none' WHERE id=?`).run(id);
|
|
521
|
+
return { messagesDeleted };
|
|
522
|
+
}
|
|
501
523
|
duplicateBot(id) {
|
|
502
524
|
const src = this.getBot(id);
|
|
503
525
|
if (!src) return null;
|
|
@@ -1319,6 +1341,9 @@ async function* runTurn(req) {
|
|
|
1319
1341
|
switch (m.type) {
|
|
1320
1342
|
case "system":
|
|
1321
1343
|
if (m.subtype === "init" && m.session_id) yield { kind: "session", sessionId: m.session_id };
|
|
1344
|
+
if (m.subtype === "init" && Array.isArray(m.mcp_servers)) {
|
|
1345
|
+
yield { kind: "mcp_status", mcpStatus: m.mcp_servers };
|
|
1346
|
+
}
|
|
1322
1347
|
break;
|
|
1323
1348
|
case "stream_event": {
|
|
1324
1349
|
const ev = m.event;
|
|
@@ -1897,6 +1922,25 @@ Pick the one you need and install just it, e.g. ${args.source.replace(/^https?:\
|
|
|
1897
1922
|
case "session":
|
|
1898
1923
|
if (ev.sessionId) store.updateBot(bot.id, { sessionId: ev.sessionId });
|
|
1899
1924
|
break;
|
|
1925
|
+
// A connector that does not come up gives the bot no tools and no way to say why — it
|
|
1926
|
+
// simply behaves as though the connector were never assigned. Surfacing the SDK's own
|
|
1927
|
+
// verdict is the difference between "my bot ignores my connector" and a stated reason.
|
|
1928
|
+
case "mcp_status": {
|
|
1929
|
+
const bad = (ev.mcpStatus ?? []).filter((m) => m.status !== "connected");
|
|
1930
|
+
if (!bad.length) break;
|
|
1931
|
+
for (const m of bad) {
|
|
1932
|
+
log6.warn(`connector "${m.name}" did not connect for ${bot.slug}: ${m.status}${m.error ? ` \u2014 ${m.error}` : ""}`);
|
|
1933
|
+
}
|
|
1934
|
+
bus.publish({
|
|
1935
|
+
type: "notify",
|
|
1936
|
+
botId: bot.id,
|
|
1937
|
+
threadId: job.threadId,
|
|
1938
|
+
title: "Connector unavailable",
|
|
1939
|
+
body: bad.map((m) => `${m.name}: ${describeMcpStatus(m.status)}`).join("; "),
|
|
1940
|
+
level: "warn"
|
|
1941
|
+
});
|
|
1942
|
+
break;
|
|
1943
|
+
}
|
|
1900
1944
|
case "text":
|
|
1901
1945
|
if (ev.text) {
|
|
1902
1946
|
const cur = store.getMessage(msgId);
|
|
@@ -1960,6 +2004,20 @@ Pick the one you need and install just it, e.g. ${args.source.replace(/^https?:\
|
|
|
1960
2004
|
}
|
|
1961
2005
|
}
|
|
1962
2006
|
};
|
|
2007
|
+
function describeMcpStatus(status) {
|
|
2008
|
+
switch (status) {
|
|
2009
|
+
case "needs-auth":
|
|
2010
|
+
return "needs authentication \u2014 the server rejected the credentials it was given (or was given none)";
|
|
2011
|
+
case "failed":
|
|
2012
|
+
return "failed to start \u2014 check the command or URL with `antbot connector test`";
|
|
2013
|
+
case "pending":
|
|
2014
|
+
return "did not finish connecting in time";
|
|
2015
|
+
case "disabled":
|
|
2016
|
+
return "is disabled";
|
|
2017
|
+
default:
|
|
2018
|
+
return status;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
1963
2021
|
function summarizeTool(name, input) {
|
|
1964
2022
|
const o = input ?? {};
|
|
1965
2023
|
const s = (k) => typeof o[k] === "string" ? o[k] : "";
|
|
@@ -2660,6 +2718,17 @@ function registerCoreRoutes(f, app) {
|
|
|
2660
2718
|
store.deleteBot(req.params.id);
|
|
2661
2719
|
return { ok: true };
|
|
2662
2720
|
});
|
|
2721
|
+
f.post("/api/bots/:id/reset", async (req, reply) => {
|
|
2722
|
+
const bot = store.getBot(req.params.id);
|
|
2723
|
+
if (!bot) return reply.code(404).send({ error: "No such bot" });
|
|
2724
|
+
if (bot.state === "running" || bot.state === "queued") {
|
|
2725
|
+
return reply.code(409).send({ error: "This bot is working. Stop it first, then start fresh." });
|
|
2726
|
+
}
|
|
2727
|
+
const result = store.resetBotSession(bot.id);
|
|
2728
|
+
if (!result) return reply.code(404).send({ error: "No such bot" });
|
|
2729
|
+
if (bot.threadId) bus.publish({ type: "thread.updated", threadId: bot.threadId, botId: bot.id, threadId2: bot.threadId });
|
|
2730
|
+
return { ok: true, ...result };
|
|
2731
|
+
});
|
|
2663
2732
|
f.post("/api/bots/:id/duplicate", async (req, reply) => {
|
|
2664
2733
|
try {
|
|
2665
2734
|
const copy = store.duplicateBot(req.params.id);
|
|
@@ -2951,7 +3020,13 @@ async function probeConnector(config, opts = {}) {
|
|
|
2951
3020
|
return await probeStdio(config, timeoutMs);
|
|
2952
3021
|
}
|
|
2953
3022
|
if (type === "http") {
|
|
2954
|
-
|
|
3023
|
+
const result = await probeHttp(config, timeoutMs);
|
|
3024
|
+
const headers = config.headers ?? {};
|
|
3025
|
+
const authed = Object.keys(headers).some((h) => /^(authorization|x-api-key|api-key)$/i.test(h));
|
|
3026
|
+
if (result.ok && !authed) {
|
|
3027
|
+
result.authHint = "This server was reached without any credential. If it needs one, the tools will list here but a bot will still see none \u2014 add an Authorization header, e.g. {{secret:NAME}}.";
|
|
3028
|
+
}
|
|
3029
|
+
return result;
|
|
2955
3030
|
}
|
|
2956
3031
|
if (type === "sse") return failed("testing is not supported for sse connectors \u2014 assign it to a bot and run a turn");
|
|
2957
3032
|
return failed(`unknown transport: ${String(type)}`);
|