botinabox 2.3.2 → 2.4.1
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/channels/slack/index.d.ts +1 -1
- package/dist/chat-pipeline-BWrtVqEP.d.ts +652 -0
- package/dist/index.d.ts +332 -192
- package/dist/index.js +394 -65
- package/package.json +2 -3
package/dist/index.js
CHANGED
|
@@ -1991,6 +1991,374 @@ ${extractedTask.description ?? msg.body}`;
|
|
|
1991
1991
|
}
|
|
1992
1992
|
};
|
|
1993
1993
|
|
|
1994
|
+
// src/core/chat/chat-pipeline-v2.ts
|
|
1995
|
+
import { createHash as createHash2 } from "crypto";
|
|
1996
|
+
|
|
1997
|
+
// src/core/data/context-builder.ts
|
|
1998
|
+
async function buildSystemContext(db, options) {
|
|
1999
|
+
const opts = {
|
|
2000
|
+
users: true,
|
|
2001
|
+
agents: true,
|
|
2002
|
+
projects: true,
|
|
2003
|
+
clients: true,
|
|
2004
|
+
files: true,
|
|
2005
|
+
org: true,
|
|
2006
|
+
...options
|
|
2007
|
+
};
|
|
2008
|
+
const sections = [];
|
|
2009
|
+
if (opts.org) {
|
|
2010
|
+
const orgs = await db.query("org").catch(() => []);
|
|
2011
|
+
const org = orgs[0];
|
|
2012
|
+
if (org) {
|
|
2013
|
+
sections.push(`## Organization
|
|
2014
|
+
${org.name} \u2014 ${org.description ?? ""}`);
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
if (opts.users) {
|
|
2018
|
+
const users = await db.query("users").catch(() => []);
|
|
2019
|
+
if (users.length > 0) {
|
|
2020
|
+
const list = users.map((u) => `- ${u.name} (${u.role}${u.email ? `, ${u.email}` : ""})`).join("\n");
|
|
2021
|
+
sections.push(`## Users (${users.length})
|
|
2022
|
+
${list}`);
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
if (opts.clients) {
|
|
2026
|
+
const clients = await db.query("client").catch(() => []);
|
|
2027
|
+
if (clients.length > 0) {
|
|
2028
|
+
const list = clients.map((c) => `- ${c.name} (${c.status ?? "active"})`).join("\n");
|
|
2029
|
+
sections.push(`## Clients (${clients.length})
|
|
2030
|
+
${list}`);
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
if (opts.projects) {
|
|
2034
|
+
const projects = await db.query("project").catch(() => []);
|
|
2035
|
+
if (projects.length > 0) {
|
|
2036
|
+
const list = projects.map((p) => `- ${p.name} (${p.status ?? "unknown"})`).join("\n");
|
|
2037
|
+
sections.push(`## Projects (${projects.length})
|
|
2038
|
+
${list}`);
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
if (opts.files) {
|
|
2042
|
+
const files = await db.query("file").catch(() => []);
|
|
2043
|
+
if (files.length > 0) {
|
|
2044
|
+
const list = files.map(
|
|
2045
|
+
(f) => `- ${f.name}${f.file_path ? ` | path: ${f.file_path}` : ""}${f.access_level ? ` (${f.access_level})` : ""}`
|
|
2046
|
+
).join("\n");
|
|
2047
|
+
sections.push(`## Files (${files.length})
|
|
2048
|
+
${list}`);
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
if (opts.agents) {
|
|
2052
|
+
const agents = await db.query("agents").catch(() => []);
|
|
2053
|
+
if (agents.length > 0) {
|
|
2054
|
+
const list = agents.map((a) => `- ${a.name} (${a.role}, ${a.status})`).join("\n");
|
|
2055
|
+
sections.push(`## Agents (${agents.length})
|
|
2056
|
+
${list}`);
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
return sections.join("\n\n");
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
// src/core/chat/chat-pipeline-v2.ts
|
|
2063
|
+
var DEFAULT_DEDUP_WINDOW_MS2 = 5 * 60 * 1e3;
|
|
2064
|
+
var DEFAULT_MAX_ITERATIONS = 5;
|
|
2065
|
+
var DEFAULT_MAX_TOKENS = 4096;
|
|
2066
|
+
var DEFAULT_MAX_MESSAGES = 50;
|
|
2067
|
+
var DEFAULT_MAX_AGE_DAYS = 7;
|
|
2068
|
+
var ChatPipelineV2 = class {
|
|
2069
|
+
constructor(db, hooks, config) {
|
|
2070
|
+
this.db = db;
|
|
2071
|
+
this.hooks = hooks;
|
|
2072
|
+
this.config = config;
|
|
2073
|
+
this.channel = config.channel ?? "slack";
|
|
2074
|
+
this.messageFilter = config.messageFilter;
|
|
2075
|
+
this.dedupWindowMs = config.dedupWindowMs ?? DEFAULT_DEDUP_WINDOW_MS2;
|
|
2076
|
+
this.toolDefs = (config.tools ?? []).map((t) => t.definition);
|
|
2077
|
+
this.toolHandlers = new Map(
|
|
2078
|
+
(config.tools ?? []).map((t) => [t.definition.name, t.handler])
|
|
2079
|
+
);
|
|
2080
|
+
this.messageStore = new MessageStore(db, hooks);
|
|
2081
|
+
const simpleLlmCall = async (params) => {
|
|
2082
|
+
const result = await config.llmCall({
|
|
2083
|
+
model: params.model ?? config.model ?? "fast",
|
|
2084
|
+
messages: params.messages.map((m) => ({
|
|
2085
|
+
role: m.role,
|
|
2086
|
+
content: typeof m.content === "string" ? m.content : m.content.map((b) => "text" in b ? b.text : "").join("")
|
|
2087
|
+
})),
|
|
2088
|
+
system: params.system,
|
|
2089
|
+
maxTokens: params.maxTokens ?? 500
|
|
2090
|
+
});
|
|
2091
|
+
const text = result.content.filter((b) => b.type === "text").map((b) => b.text ?? "").join("");
|
|
2092
|
+
return { content: text };
|
|
2093
|
+
};
|
|
2094
|
+
this.responder = new ChatResponder(db, hooks, this.messageStore, {
|
|
2095
|
+
llmCall: simpleLlmCall,
|
|
2096
|
+
model: config.model ?? "fast",
|
|
2097
|
+
systemPrompt: config.systemPrompt
|
|
2098
|
+
});
|
|
2099
|
+
this.interpreter = new MessageInterpreter(db, hooks, {
|
|
2100
|
+
llmCall: simpleLlmCall,
|
|
2101
|
+
model: "fast",
|
|
2102
|
+
extractors: config.extractors
|
|
2103
|
+
});
|
|
2104
|
+
this.registerHandlers();
|
|
2105
|
+
}
|
|
2106
|
+
db;
|
|
2107
|
+
hooks;
|
|
2108
|
+
config;
|
|
2109
|
+
messageStore;
|
|
2110
|
+
responder;
|
|
2111
|
+
interpreter;
|
|
2112
|
+
channel;
|
|
2113
|
+
messageFilter;
|
|
2114
|
+
dedupWindowMs;
|
|
2115
|
+
threadChannelMap = /* @__PURE__ */ new Map();
|
|
2116
|
+
toolDefs;
|
|
2117
|
+
toolHandlers;
|
|
2118
|
+
/**
|
|
2119
|
+
* Resolve the channel ID for a thread (for response delivery).
|
|
2120
|
+
*/
|
|
2121
|
+
async resolveChannel(threadId, taskId) {
|
|
2122
|
+
if (taskId) {
|
|
2123
|
+
const mappings = await this.db.query("thread_task_map", { where: { task_id: taskId } });
|
|
2124
|
+
if (mappings.length > 0) return mappings[0].channel_id;
|
|
2125
|
+
}
|
|
2126
|
+
if (threadId) {
|
|
2127
|
+
const mappings = await this.db.query("thread_task_map", { where: { thread_ts: threadId } });
|
|
2128
|
+
if (mappings.length > 0) return mappings[0].channel_id;
|
|
2129
|
+
}
|
|
2130
|
+
return this.threadChannelMap.get(threadId);
|
|
2131
|
+
}
|
|
2132
|
+
registerHandlers() {
|
|
2133
|
+
this.hooks.register("message.inbound", async (ctx) => {
|
|
2134
|
+
const msg = ctx;
|
|
2135
|
+
if (msg.channel !== this.channel) return;
|
|
2136
|
+
if (this.messageFilter && !this.messageFilter(msg)) return;
|
|
2137
|
+
if (await this.isDuplicate(msg)) return;
|
|
2138
|
+
const channelId = msg.account ?? "";
|
|
2139
|
+
const threadTs = channelId || msg.threadId || msg.id;
|
|
2140
|
+
if (threadTs && channelId) {
|
|
2141
|
+
this.threadChannelMap.set(threadTs, channelId);
|
|
2142
|
+
}
|
|
2143
|
+
const msgWithThread = { ...msg, threadId: threadTs };
|
|
2144
|
+
const { messageId } = await this.messageStore.storeInbound(msgWithThread);
|
|
2145
|
+
await this.hooks.emit("typing.start", { channel: this.channel, threadId: threadTs });
|
|
2146
|
+
try {
|
|
2147
|
+
const history = await this.buildHistory(channelId);
|
|
2148
|
+
let systemPrompt = this.config.systemPrompt;
|
|
2149
|
+
if (this.config.includeSystemContext !== false) {
|
|
2150
|
+
const ctx2 = await buildSystemContext(this.db, this.config.systemContextOptions);
|
|
2151
|
+
if (ctx2) systemPrompt += `
|
|
2152
|
+
|
|
2153
|
+
${ctx2}`;
|
|
2154
|
+
}
|
|
2155
|
+
const { text, tasksDispatched } = await this.think(
|
|
2156
|
+
systemPrompt,
|
|
2157
|
+
history,
|
|
2158
|
+
msg.body,
|
|
2159
|
+
threadTs,
|
|
2160
|
+
channelId
|
|
2161
|
+
);
|
|
2162
|
+
await this.hooks.emit("typing.stop", { channel: this.channel, threadId: threadTs });
|
|
2163
|
+
if (text) {
|
|
2164
|
+
await this.responder.sendResponse({
|
|
2165
|
+
text,
|
|
2166
|
+
channel: this.channel,
|
|
2167
|
+
threadId: threadTs,
|
|
2168
|
+
source: "primary",
|
|
2169
|
+
skipFilter: true,
|
|
2170
|
+
skipRedundancyCheck: true
|
|
2171
|
+
});
|
|
2172
|
+
}
|
|
2173
|
+
void this.extractAsync(messageId);
|
|
2174
|
+
} catch (err) {
|
|
2175
|
+
await this.hooks.emit("typing.stop", { channel: this.channel, threadId: threadTs });
|
|
2176
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2177
|
+
console.error("[ChatPipelineV2] Pipeline error:", errMsg);
|
|
2178
|
+
await this.hooks.emit("pipeline.error", {
|
|
2179
|
+
messageId,
|
|
2180
|
+
error: errMsg
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
});
|
|
2184
|
+
this.hooks.register("run.completed", async (ctx) => {
|
|
2185
|
+
const taskId = ctx.taskId;
|
|
2186
|
+
if (!taskId) return;
|
|
2187
|
+
const task = await this.db.get("tasks", { id: taskId });
|
|
2188
|
+
const output = task?.result;
|
|
2189
|
+
if (!output) return;
|
|
2190
|
+
const mappings = await this.db.query("thread_task_map", { where: { task_id: taskId } });
|
|
2191
|
+
if (mappings.length === 0) return;
|
|
2192
|
+
const threadId = mappings[0].thread_ts;
|
|
2193
|
+
await this.responder.sendResponse({
|
|
2194
|
+
text: output,
|
|
2195
|
+
channel: this.channel,
|
|
2196
|
+
threadId,
|
|
2197
|
+
agentId: ctx.agentId,
|
|
2198
|
+
taskId,
|
|
2199
|
+
source: "agent",
|
|
2200
|
+
skipFilter: true,
|
|
2201
|
+
skipRedundancyCheck: true
|
|
2202
|
+
});
|
|
2203
|
+
}, { priority: 90 });
|
|
2204
|
+
}
|
|
2205
|
+
/**
|
|
2206
|
+
* Primary agent tool loop — adapted from ExecutionEngine pattern.
|
|
2207
|
+
*/
|
|
2208
|
+
async think(systemPrompt, history, currentMessage, threadTs, channelId) {
|
|
2209
|
+
const model = this.config.model ?? "claude-sonnet-4-6";
|
|
2210
|
+
const maxIterations = this.config.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
2211
|
+
const maxTokens = this.config.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
2212
|
+
const tasksDispatched = [];
|
|
2213
|
+
const messages = [
|
|
2214
|
+
...history,
|
|
2215
|
+
{ role: "user", content: currentMessage }
|
|
2216
|
+
];
|
|
2217
|
+
let finalText = "";
|
|
2218
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
2219
|
+
const params = {
|
|
2220
|
+
model,
|
|
2221
|
+
messages,
|
|
2222
|
+
system: systemPrompt,
|
|
2223
|
+
maxTokens
|
|
2224
|
+
};
|
|
2225
|
+
if (this.toolDefs.length > 0) {
|
|
2226
|
+
params.tools = this.toolDefs;
|
|
2227
|
+
params.tool_choice = { type: "auto" };
|
|
2228
|
+
}
|
|
2229
|
+
const response = await this.config.llmCall(params);
|
|
2230
|
+
const textBlocks = response.content.filter((b) => b.type === "text").map((b) => b.text ?? "");
|
|
2231
|
+
if (textBlocks.length > 0) finalText += textBlocks.join("");
|
|
2232
|
+
if (response.stop_reason !== "tool_use") break;
|
|
2233
|
+
const toolUseBlocks = response.content.filter((b) => b.type === "tool_use");
|
|
2234
|
+
const toolResults = [];
|
|
2235
|
+
for (const toolUse of toolUseBlocks) {
|
|
2236
|
+
const handler = this.toolHandlers.get(toolUse.name);
|
|
2237
|
+
if (handler) {
|
|
2238
|
+
try {
|
|
2239
|
+
const toolCtx = {
|
|
2240
|
+
taskId: "",
|
|
2241
|
+
agentId: "primary",
|
|
2242
|
+
hooks: this.hooks,
|
|
2243
|
+
db: this.db,
|
|
2244
|
+
resolveFilePath: this.config.resolveFilePath
|
|
2245
|
+
};
|
|
2246
|
+
const result = await handler(
|
|
2247
|
+
toolUse.input,
|
|
2248
|
+
toolCtx
|
|
2249
|
+
);
|
|
2250
|
+
if (toolUse.name === "dispatch_task" && result.includes("ID:")) {
|
|
2251
|
+
const idMatch = result.match(/ID:\s*([a-f0-9-]+)/);
|
|
2252
|
+
if (idMatch) {
|
|
2253
|
+
const taskId = idMatch[1];
|
|
2254
|
+
tasksDispatched.push(taskId);
|
|
2255
|
+
try {
|
|
2256
|
+
const existing = await this.db.query("thread_task_map", {
|
|
2257
|
+
where: { thread_ts: threadTs, channel_id: channelId }
|
|
2258
|
+
});
|
|
2259
|
+
if (existing.length > 0) {
|
|
2260
|
+
await this.db.update("thread_task_map", { id: existing[0].id }, { task_id: taskId });
|
|
2261
|
+
} else {
|
|
2262
|
+
await this.db.insert("thread_task_map", {
|
|
2263
|
+
thread_ts: threadTs,
|
|
2264
|
+
channel_id: channelId,
|
|
2265
|
+
task_id: taskId
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
} catch {
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
toolResults.push({
|
|
2273
|
+
type: "tool_result",
|
|
2274
|
+
id: toolUse.id,
|
|
2275
|
+
text: result
|
|
2276
|
+
});
|
|
2277
|
+
} catch (err) {
|
|
2278
|
+
toolResults.push({
|
|
2279
|
+
type: "tool_result",
|
|
2280
|
+
id: toolUse.id,
|
|
2281
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
messages.push({ role: "assistant", content: response.content });
|
|
2287
|
+
messages.push({ role: "user", content: toolResults });
|
|
2288
|
+
}
|
|
2289
|
+
return { text: finalText, tasksDispatched };
|
|
2290
|
+
}
|
|
2291
|
+
/**
|
|
2292
|
+
* Build conversation history from channel messages.
|
|
2293
|
+
* Includes BOTH user and assistant messages (unlike v1 which excluded bot messages).
|
|
2294
|
+
*/
|
|
2295
|
+
async buildHistory(channelId) {
|
|
2296
|
+
const maxMessages = this.config.history?.maxMessages ?? DEFAULT_MAX_MESSAGES;
|
|
2297
|
+
const maxAgeDays = this.config.history?.maxAgeDays ?? DEFAULT_MAX_AGE_DAYS;
|
|
2298
|
+
const includeAssistant = this.config.history?.includeAssistant !== false;
|
|
2299
|
+
const cutoff = new Date(Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3).toISOString();
|
|
2300
|
+
let rows;
|
|
2301
|
+
try {
|
|
2302
|
+
rows = await this.db.query("messages", {
|
|
2303
|
+
where: { channel: this.channel },
|
|
2304
|
+
orderBy: "created_at",
|
|
2305
|
+
orderDir: "desc",
|
|
2306
|
+
limit: maxMessages
|
|
2307
|
+
});
|
|
2308
|
+
rows.reverse();
|
|
2309
|
+
rows = rows.filter((r) => {
|
|
2310
|
+
const ts = r.created_at;
|
|
2311
|
+
return !ts || ts >= cutoff;
|
|
2312
|
+
});
|
|
2313
|
+
} catch {
|
|
2314
|
+
return [];
|
|
2315
|
+
}
|
|
2316
|
+
const messages = [];
|
|
2317
|
+
const maxChars = 16e3;
|
|
2318
|
+
let charCount = 0;
|
|
2319
|
+
for (const row of rows) {
|
|
2320
|
+
const body = row.body ?? "";
|
|
2321
|
+
const direction = row.direction;
|
|
2322
|
+
if (!includeAssistant && direction !== "inbound") continue;
|
|
2323
|
+
if (charCount + body.length > maxChars) break;
|
|
2324
|
+
messages.push({
|
|
2325
|
+
role: direction === "inbound" ? "user" : "assistant",
|
|
2326
|
+
content: body
|
|
2327
|
+
});
|
|
2328
|
+
charCount += body.length;
|
|
2329
|
+
}
|
|
2330
|
+
return messages;
|
|
2331
|
+
}
|
|
2332
|
+
/**
|
|
2333
|
+
* Dedup check (same as v1).
|
|
2334
|
+
*/
|
|
2335
|
+
async isDuplicate(msg) {
|
|
2336
|
+
const hash = createHash2("sha256").update(`${msg.from}:${msg.body}`).digest("hex");
|
|
2337
|
+
const cutoff = new Date(Date.now() - this.dedupWindowMs).toISOString();
|
|
2338
|
+
const recent = await this.db.query("message_dedup", { where: { content_hash: hash } });
|
|
2339
|
+
if (recent.some((r) => r.created_at > cutoff)) return true;
|
|
2340
|
+
await this.db.insert("message_dedup", {
|
|
2341
|
+
content_hash: hash,
|
|
2342
|
+
channel_id: msg.account ?? "",
|
|
2343
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2344
|
+
});
|
|
2345
|
+
return false;
|
|
2346
|
+
}
|
|
2347
|
+
/**
|
|
2348
|
+
* Async memory extraction (non-blocking, non-fatal).
|
|
2349
|
+
*/
|
|
2350
|
+
async extractAsync(messageId) {
|
|
2351
|
+
try {
|
|
2352
|
+
await this.interpreter.interpret(messageId);
|
|
2353
|
+
} catch (err) {
|
|
2354
|
+
await this.hooks.emit("interpretation.error", {
|
|
2355
|
+
messageId,
|
|
2356
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2357
|
+
});
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
};
|
|
2361
|
+
|
|
1994
2362
|
// src/core/chat/formatter.ts
|
|
1995
2363
|
function formatText(text, mode) {
|
|
1996
2364
|
switch (mode) {
|
|
@@ -3504,71 +3872,6 @@ ${c.instructions}` : null,
|
|
|
3504
3872
|
}
|
|
3505
3873
|
}
|
|
3506
3874
|
|
|
3507
|
-
// src/core/data/context-builder.ts
|
|
3508
|
-
async function buildSystemContext(db, options) {
|
|
3509
|
-
const opts = {
|
|
3510
|
-
users: true,
|
|
3511
|
-
agents: true,
|
|
3512
|
-
projects: true,
|
|
3513
|
-
clients: true,
|
|
3514
|
-
files: true,
|
|
3515
|
-
org: true,
|
|
3516
|
-
...options
|
|
3517
|
-
};
|
|
3518
|
-
const sections = [];
|
|
3519
|
-
if (opts.org) {
|
|
3520
|
-
const orgs = await db.query("org").catch(() => []);
|
|
3521
|
-
const org = orgs[0];
|
|
3522
|
-
if (org) {
|
|
3523
|
-
sections.push(`## Organization
|
|
3524
|
-
${org.name} \u2014 ${org.description ?? ""}`);
|
|
3525
|
-
}
|
|
3526
|
-
}
|
|
3527
|
-
if (opts.users) {
|
|
3528
|
-
const users = await db.query("users").catch(() => []);
|
|
3529
|
-
if (users.length > 0) {
|
|
3530
|
-
const list = users.map((u) => `- ${u.name} (${u.role}${u.email ? `, ${u.email}` : ""})`).join("\n");
|
|
3531
|
-
sections.push(`## Users (${users.length})
|
|
3532
|
-
${list}`);
|
|
3533
|
-
}
|
|
3534
|
-
}
|
|
3535
|
-
if (opts.clients) {
|
|
3536
|
-
const clients = await db.query("client").catch(() => []);
|
|
3537
|
-
if (clients.length > 0) {
|
|
3538
|
-
const list = clients.map((c) => `- ${c.name} (${c.status ?? "active"})`).join("\n");
|
|
3539
|
-
sections.push(`## Clients (${clients.length})
|
|
3540
|
-
${list}`);
|
|
3541
|
-
}
|
|
3542
|
-
}
|
|
3543
|
-
if (opts.projects) {
|
|
3544
|
-
const projects = await db.query("project").catch(() => []);
|
|
3545
|
-
if (projects.length > 0) {
|
|
3546
|
-
const list = projects.map((p) => `- ${p.name} (${p.status ?? "unknown"})`).join("\n");
|
|
3547
|
-
sections.push(`## Projects (${projects.length})
|
|
3548
|
-
${list}`);
|
|
3549
|
-
}
|
|
3550
|
-
}
|
|
3551
|
-
if (opts.files) {
|
|
3552
|
-
const files = await db.query("file").catch(() => []);
|
|
3553
|
-
if (files.length > 0) {
|
|
3554
|
-
const list = files.map(
|
|
3555
|
-
(f) => `- ${f.name}${f.file_path ? ` | path: ${f.file_path}` : ""}${f.access_level ? ` (${f.access_level})` : ""}`
|
|
3556
|
-
).join("\n");
|
|
3557
|
-
sections.push(`## Files (${files.length})
|
|
3558
|
-
${list}`);
|
|
3559
|
-
}
|
|
3560
|
-
}
|
|
3561
|
-
if (opts.agents) {
|
|
3562
|
-
const agents = await db.query("agents").catch(() => []);
|
|
3563
|
-
if (agents.length > 0) {
|
|
3564
|
-
const list = agents.map((a) => `- ${a.name} (${a.role}, ${a.status})`).join("\n");
|
|
3565
|
-
sections.push(`## Agents (${agents.length})
|
|
3566
|
-
${list}`);
|
|
3567
|
-
}
|
|
3568
|
-
}
|
|
3569
|
-
return sections.join("\n\n");
|
|
3570
|
-
}
|
|
3571
|
-
|
|
3572
3875
|
// src/core/security/sanitizer.ts
|
|
3573
3876
|
import { Buffer as Buffer2 } from "buffer";
|
|
3574
3877
|
var DEFAULT_FIELD_LIMIT = 65535;
|
|
@@ -6751,6 +7054,30 @@ var nativeTools = [
|
|
|
6751
7054
|
createAgentTool,
|
|
6752
7055
|
createProjectTool
|
|
6753
7056
|
];
|
|
7057
|
+
var coordinatorTools = [
|
|
7058
|
+
// Task management
|
|
7059
|
+
dispatchTaskTool,
|
|
7060
|
+
cancelTaskTool,
|
|
7061
|
+
reassignTaskTool,
|
|
7062
|
+
// Progress monitoring
|
|
7063
|
+
getTaskStatusTool,
|
|
7064
|
+
getActiveTasksTool,
|
|
7065
|
+
// Agent management + awareness
|
|
7066
|
+
listAgentsTool,
|
|
7067
|
+
getAgentStatusTool,
|
|
7068
|
+
getAgentDetailTool,
|
|
7069
|
+
createAgentTool,
|
|
7070
|
+
// Communication (coordinator is the user-facing gateway)
|
|
7071
|
+
sendMessageTool,
|
|
7072
|
+
addTaskCommentTool,
|
|
7073
|
+
// Conversational context
|
|
7074
|
+
readConversationTool,
|
|
7075
|
+
searchConversationTool,
|
|
7076
|
+
// Awareness (for routing decisions, not for doing work)
|
|
7077
|
+
listFilesTool,
|
|
7078
|
+
listProjectsTool,
|
|
7079
|
+
sendFileTool
|
|
7080
|
+
];
|
|
6754
7081
|
|
|
6755
7082
|
// src/core/orchestrator/user-registry.ts
|
|
6756
7083
|
import { v4 as uuidv4 } from "uuid";
|
|
@@ -7089,6 +7416,7 @@ export {
|
|
|
7089
7416
|
ChannelRegistry,
|
|
7090
7417
|
ChannelRegistryError,
|
|
7091
7418
|
ChatPipeline,
|
|
7419
|
+
ChatPipelineV2,
|
|
7092
7420
|
ChatResponder,
|
|
7093
7421
|
ChatSessionManager,
|
|
7094
7422
|
CircuitBreaker,
|
|
@@ -7147,6 +7475,7 @@ export {
|
|
|
7147
7475
|
chunkText,
|
|
7148
7476
|
classifyUpdate,
|
|
7149
7477
|
compareVersions,
|
|
7478
|
+
coordinatorTools,
|
|
7150
7479
|
createAgentTool,
|
|
7151
7480
|
createConfigRevision,
|
|
7152
7481
|
createDefaultLLMCall,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botinabox",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Bot in a Box — framework for building multi-agent bots",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -53,8 +53,7 @@
|
|
|
53
53
|
"build": "tsup",
|
|
54
54
|
"test": "vitest run",
|
|
55
55
|
"typecheck": "tsc --noEmit",
|
|
56
|
-
"
|
|
57
|
-
"prepublishOnly": "npm run build && npm run typecheck && npm test && npm run check-docs"
|
|
56
|
+
"prepublishOnly": "npm run build && npm run typecheck && npm test"
|
|
58
57
|
},
|
|
59
58
|
"dependencies": {
|
|
60
59
|
"@types/uuid": "^10.0.0",
|