botinabox 2.5.2 → 2.5.3

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.
Files changed (276) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +190 -190
  3. package/bin/botinabox.mjs +2 -2
  4. package/dist/{chunk-UACT2WXX.js → chunk-7AGWGYZC.js} +43 -5
  5. package/dist/cli.js +1 -1
  6. package/dist/connectors/google/index.d.ts +10 -1
  7. package/dist/connectors/google/index.js +1 -1
  8. package/dist/{gmail-connector-2FVYTQJH.js → gmail-connector-VP5FF56J.js} +2 -1
  9. package/package.json +100 -100
  10. package/dist/channels/discord/adapter.d.ts +0 -32
  11. package/dist/channels/discord/adapter.js +0 -70
  12. package/dist/channels/discord/inbound.d.ts +0 -25
  13. package/dist/channels/discord/inbound.js +0 -24
  14. package/dist/channels/discord/models.d.ts +0 -8
  15. package/dist/channels/discord/models.js +0 -5
  16. package/dist/channels/discord/outbound.d.ts +0 -14
  17. package/dist/channels/discord/outbound.js +0 -38
  18. package/dist/channels/slack/adapter.d.ts +0 -33
  19. package/dist/channels/slack/adapter.js +0 -74
  20. package/dist/channels/slack/inbound.d.ts +0 -59
  21. package/dist/channels/slack/inbound.js +0 -96
  22. package/dist/channels/slack/models.d.ts +0 -9
  23. package/dist/channels/slack/models.js +0 -5
  24. package/dist/channels/slack/outbound.d.ts +0 -12
  25. package/dist/channels/slack/outbound.js +0 -18
  26. package/dist/channels/slack/transcribe.d.ts +0 -41
  27. package/dist/channels/slack/transcribe.js +0 -106
  28. package/dist/channels/webhook/adapter.d.ts +0 -23
  29. package/dist/channels/webhook/adapter.js +0 -86
  30. package/dist/channels/webhook/hmac.d.ts +0 -13
  31. package/dist/channels/webhook/hmac.js +0 -26
  32. package/dist/channels/webhook/models.d.ts +0 -9
  33. package/dist/channels/webhook/models.js +0 -5
  34. package/dist/channels/webhook/server.d.ts +0 -20
  35. package/dist/channels/webhook/server.js +0 -91
  36. package/dist/chat-pipeline-BWrtVqEP.d.ts +0 -652
  37. package/dist/chat-pipeline-C-XlLGNl.d.ts +0 -648
  38. package/dist/chat-pipeline-CR1KF6eX.d.ts +0 -652
  39. package/dist/chat-pipeline-DisuC8SB.d.ts +0 -643
  40. package/dist/chunk-2LGXQPEA.js +0 -41
  41. package/dist/chunk-3X3YKI4T.js +0 -357
  42. package/dist/chunk-D47AIFOD.js +0 -351
  43. package/dist/chunk-DSNJKNEW.js +0 -328
  44. package/dist/chunk-GS2JFL6I.js +0 -144
  45. package/dist/chunk-J6S6QMUY.js +0 -144
  46. package/dist/chunk-QLA6YOFN.js +0 -22
  47. package/dist/cli/templates/config.yml.d.ts +0 -7
  48. package/dist/cli/templates/config.yml.js +0 -61
  49. package/dist/cli/templates/env.d.ts +0 -1
  50. package/dist/cli/templates/env.js +0 -30
  51. package/dist/cli/templates/index.ts.d.ts +0 -2
  52. package/dist/cli/templates/index.ts.js +0 -30
  53. package/dist/cli/templates/package.json.d.ts +0 -5
  54. package/dist/cli/templates/package.json.js +0 -28
  55. package/dist/connector-DDahQw-2.d.ts +0 -63
  56. package/dist/connectors/google/calendar-connector.d.ts +0 -40
  57. package/dist/connectors/google/calendar-connector.js +0 -243
  58. package/dist/connectors/google/gmail-connector.d.ts +0 -42
  59. package/dist/connectors/google/gmail-connector.js +0 -345
  60. package/dist/connectors/google/oauth.d.ts +0 -48
  61. package/dist/connectors/google/oauth.js +0 -112
  62. package/dist/connectors/google/types.d.ts +0 -78
  63. package/dist/connectors/google/types.js +0 -2
  64. package/dist/core/chat/auto-discovery.d.ts +0 -16
  65. package/dist/core/chat/auto-discovery.js +0 -54
  66. package/dist/core/chat/channel-registry.d.ts +0 -45
  67. package/dist/core/chat/channel-registry.js +0 -96
  68. package/dist/core/chat/chat-pipeline.d.ts +0 -113
  69. package/dist/core/chat/chat-pipeline.js +0 -395
  70. package/dist/core/chat/chat-responder.d.ts +0 -90
  71. package/dist/core/chat/chat-responder.js +0 -185
  72. package/dist/core/chat/formatter.d.ts +0 -11
  73. package/dist/core/chat/formatter.js +0 -60
  74. package/dist/core/chat/index.d.ts +0 -24
  75. package/dist/core/chat/index.js +0 -18
  76. package/dist/core/chat/message-interpreter.d.ts +0 -91
  77. package/dist/core/chat/message-interpreter.js +0 -166
  78. package/dist/core/chat/message-store.d.ts +0 -66
  79. package/dist/core/chat/message-store.js +0 -131
  80. package/dist/core/chat/notification-queue.d.ts +0 -34
  81. package/dist/core/chat/notification-queue.js +0 -111
  82. package/dist/core/chat/pipeline.d.ts +0 -38
  83. package/dist/core/chat/pipeline.js +0 -89
  84. package/dist/core/chat/policies.d.ts +0 -16
  85. package/dist/core/chat/policies.js +0 -25
  86. package/dist/core/chat/routing.d.ts +0 -17
  87. package/dist/core/chat/routing.js +0 -36
  88. package/dist/core/chat/session-key.d.ts +0 -30
  89. package/dist/core/chat/session-key.js +0 -65
  90. package/dist/core/chat/session-manager.d.ts +0 -17
  91. package/dist/core/chat/session-manager.js +0 -23
  92. package/dist/core/chat/text-chunker.d.ts +0 -9
  93. package/dist/core/chat/text-chunker.js +0 -48
  94. package/dist/core/chat/triage-router.d.ts +0 -75
  95. package/dist/core/chat/triage-router.js +0 -142
  96. package/dist/core/chat/types.d.ts +0 -5
  97. package/dist/core/chat/types.js +0 -5
  98. package/dist/core/config/defaults.d.ts +0 -2
  99. package/dist/core/config/defaults.js +0 -38
  100. package/dist/core/config/index.d.ts +0 -6
  101. package/dist/core/config/index.js +0 -4
  102. package/dist/core/config/interpolate.d.ts +0 -5
  103. package/dist/core/config/interpolate.js +0 -27
  104. package/dist/core/config/loader.d.ts +0 -24
  105. package/dist/core/config/loader.js +0 -59
  106. package/dist/core/config/schema.d.ts +0 -5
  107. package/dist/core/config/schema.js +0 -119
  108. package/dist/core/data/core-entity-contexts.d.ts +0 -14
  109. package/dist/core/data/core-entity-contexts.js +0 -197
  110. package/dist/core/data/core-migrations.d.ts +0 -5
  111. package/dist/core/data/core-migrations.js +0 -45
  112. package/dist/core/data/core-schema.d.ts +0 -6
  113. package/dist/core/data/core-schema.js +0 -454
  114. package/dist/core/data/data-store.d.ts +0 -67
  115. package/dist/core/data/data-store.js +0 -218
  116. package/dist/core/data/domain-entity-contexts.d.ts +0 -29
  117. package/dist/core/data/domain-entity-contexts.js +0 -321
  118. package/dist/core/data/domain-schema.d.ts +0 -36
  119. package/dist/core/data/domain-schema.js +0 -323
  120. package/dist/core/data/index.d.ts +0 -7
  121. package/dist/core/data/index.js +0 -7
  122. package/dist/core/data/types.d.ts +0 -111
  123. package/dist/core/data/types.js +0 -1
  124. package/dist/core/hooks/hook-bus.d.ts +0 -18
  125. package/dist/core/hooks/hook-bus.js +0 -120
  126. package/dist/core/hooks/index.d.ts +0 -2
  127. package/dist/core/hooks/index.js +0 -1
  128. package/dist/core/hooks/types.d.ts +0 -19
  129. package/dist/core/hooks/types.js +0 -1
  130. package/dist/core/index.d.ts +0 -4
  131. package/dist/core/index.js +0 -4
  132. package/dist/core/llm/auto-discovery.d.ts +0 -11
  133. package/dist/core/llm/auto-discovery.js +0 -49
  134. package/dist/core/llm/cost-tracker.d.ts +0 -6
  135. package/dist/core/llm/cost-tracker.js +0 -38
  136. package/dist/core/llm/index.d.ts +0 -4
  137. package/dist/core/llm/index.js +0 -3
  138. package/dist/core/llm/model-router.d.ts +0 -25
  139. package/dist/core/llm/model-router.js +0 -49
  140. package/dist/core/llm/provider-registry.d.ts +0 -9
  141. package/dist/core/llm/provider-registry.js +0 -25
  142. package/dist/core/llm/types.d.ts +0 -2
  143. package/dist/core/llm/types.js +0 -2
  144. package/dist/core/orchestrator/adapters/api-adapter.d.ts +0 -34
  145. package/dist/core/orchestrator/adapters/api-adapter.js +0 -88
  146. package/dist/core/orchestrator/adapters/cli-adapter.d.ts +0 -22
  147. package/dist/core/orchestrator/adapters/cli-adapter.js +0 -69
  148. package/dist/core/orchestrator/adapters/deterministic-adapter.d.ts +0 -35
  149. package/dist/core/orchestrator/adapters/deterministic-adapter.js +0 -75
  150. package/dist/core/orchestrator/adapters/env-whitelist.d.ts +0 -4
  151. package/dist/core/orchestrator/adapters/env-whitelist.js +0 -27
  152. package/dist/core/orchestrator/adapters/output-extractor.d.ts +0 -11
  153. package/dist/core/orchestrator/adapters/output-extractor.js +0 -59
  154. package/dist/core/orchestrator/adapters/process-manager.d.ts +0 -15
  155. package/dist/core/orchestrator/adapters/process-manager.js +0 -26
  156. package/dist/core/orchestrator/adapters/tool-loop.d.ts +0 -22
  157. package/dist/core/orchestrator/adapters/tool-loop.js +0 -66
  158. package/dist/core/orchestrator/agent-registry.d.ts +0 -31
  159. package/dist/core/orchestrator/agent-registry.js +0 -135
  160. package/dist/core/orchestrator/budget-controller.d.ts +0 -19
  161. package/dist/core/orchestrator/budget-controller.js +0 -73
  162. package/dist/core/orchestrator/chain-guard.d.ts +0 -14
  163. package/dist/core/orchestrator/chain-guard.js +0 -23
  164. package/dist/core/orchestrator/circuit-breaker.d.ts +0 -65
  165. package/dist/core/orchestrator/circuit-breaker.js +0 -159
  166. package/dist/core/orchestrator/claude-stream-parser.d.ts +0 -31
  167. package/dist/core/orchestrator/claude-stream-parser.js +0 -99
  168. package/dist/core/orchestrator/config-revisions.d.ts +0 -6
  169. package/dist/core/orchestrator/config-revisions.js +0 -17
  170. package/dist/core/orchestrator/dependency-resolver.d.ts +0 -20
  171. package/dist/core/orchestrator/dependency-resolver.js +0 -78
  172. package/dist/core/orchestrator/governance-gate.d.ts +0 -110
  173. package/dist/core/orchestrator/governance-gate.js +0 -170
  174. package/dist/core/orchestrator/learning-pipeline.d.ts +0 -109
  175. package/dist/core/orchestrator/learning-pipeline.js +0 -249
  176. package/dist/core/orchestrator/loop-detector.d.ts +0 -51
  177. package/dist/core/orchestrator/loop-detector.js +0 -133
  178. package/dist/core/orchestrator/ndjson-logger.d.ts +0 -6
  179. package/dist/core/orchestrator/ndjson-logger.js +0 -18
  180. package/dist/core/orchestrator/permission-relay.d.ts +0 -72
  181. package/dist/core/orchestrator/permission-relay.js +0 -164
  182. package/dist/core/orchestrator/run-manager.d.ts +0 -31
  183. package/dist/core/orchestrator/run-manager.js +0 -178
  184. package/dist/core/orchestrator/scheduler.d.ts +0 -70
  185. package/dist/core/orchestrator/scheduler.js +0 -198
  186. package/dist/core/orchestrator/secret-store.d.ts +0 -57
  187. package/dist/core/orchestrator/secret-store.js +0 -171
  188. package/dist/core/orchestrator/session-manager.d.ts +0 -13
  189. package/dist/core/orchestrator/session-manager.js +0 -66
  190. package/dist/core/orchestrator/task-queue.d.ts +0 -34
  191. package/dist/core/orchestrator/task-queue.js +0 -83
  192. package/dist/core/orchestrator/template-interpolate.d.ts +0 -5
  193. package/dist/core/orchestrator/template-interpolate.js +0 -18
  194. package/dist/core/orchestrator/user-registry.d.ts +0 -47
  195. package/dist/core/orchestrator/user-registry.js +0 -76
  196. package/dist/core/orchestrator/wakeup-queue.d.ts +0 -9
  197. package/dist/core/orchestrator/wakeup-queue.js +0 -45
  198. package/dist/core/orchestrator/workflow-engine.d.ts +0 -47
  199. package/dist/core/orchestrator/workflow-engine.js +0 -204
  200. package/dist/core/security/audit.d.ts +0 -20
  201. package/dist/core/security/audit.js +0 -33
  202. package/dist/core/security/column-validator.d.ts +0 -20
  203. package/dist/core/security/column-validator.js +0 -37
  204. package/dist/core/security/index.d.ts +0 -5
  205. package/dist/core/security/index.js +0 -5
  206. package/dist/core/security/process-env.d.ts +0 -13
  207. package/dist/core/security/process-env.js +0 -49
  208. package/dist/core/security/sanitizer.d.ts +0 -11
  209. package/dist/core/security/sanitizer.js +0 -39
  210. package/dist/core/security/types.d.ts +0 -11
  211. package/dist/core/security/types.js +0 -1
  212. package/dist/core/update/auto-update.d.ts +0 -21
  213. package/dist/core/update/auto-update.js +0 -102
  214. package/dist/core/update/backup-manager.d.ts +0 -7
  215. package/dist/core/update/backup-manager.js +0 -24
  216. package/dist/core/update/index.d.ts +0 -8
  217. package/dist/core/update/index.js +0 -6
  218. package/dist/core/update/migration-hooks.d.ts +0 -11
  219. package/dist/core/update/migration-hooks.js +0 -10
  220. package/dist/core/update/types.d.ts +0 -11
  221. package/dist/core/update/types.js +0 -1
  222. package/dist/core/update/update-checker.d.ts +0 -11
  223. package/dist/core/update/update-checker.js +0 -63
  224. package/dist/core/update/update-manager.d.ts +0 -25
  225. package/dist/core/update/update-manager.js +0 -101
  226. package/dist/core/update/version-utils.d.ts +0 -6
  227. package/dist/core/update/version-utils.js +0 -34
  228. package/dist/gmail-connector-MNUBRNFM.js +0 -6
  229. package/dist/gmail-connector-PS2VLGNE.js +0 -6
  230. package/dist/gmail-connector-ULSMN6X2.js +0 -6
  231. package/dist/gmail-connector-URRFX6A3.js +0 -6
  232. package/dist/inbound-AFBUPSPG.js +0 -10
  233. package/dist/inbound-AFOHYNUY.js +0 -6
  234. package/dist/inbound-CGIXRXGC.js +0 -8
  235. package/dist/inbound-MCOLRH6U.js +0 -10
  236. package/dist/inbound-SNEMBLGA.js +0 -6
  237. package/dist/inbound-ZJHAYVMF.js +0 -10
  238. package/dist/provider-qqJYv9nv.d.ts +0 -75
  239. package/dist/providers/anthropic/models.d.ts +0 -2
  240. package/dist/providers/anthropic/models.js +0 -29
  241. package/dist/providers/anthropic/provider.d.ts +0 -13
  242. package/dist/providers/anthropic/provider.js +0 -119
  243. package/dist/providers/anthropic/tool-converter.d.ts +0 -10
  244. package/dist/providers/anthropic/tool-converter.js +0 -7
  245. package/dist/providers/ollama/provider.d.ts +0 -17
  246. package/dist/providers/ollama/provider.js +0 -185
  247. package/dist/providers/openai/models.d.ts +0 -2
  248. package/dist/providers/openai/models.js +0 -29
  249. package/dist/providers/openai/provider.d.ts +0 -13
  250. package/dist/providers/openai/provider.js +0 -163
  251. package/dist/providers/openai/tool-converter.d.ts +0 -10
  252. package/dist/providers/openai/tool-converter.js +0 -10
  253. package/dist/shared/constants.d.ts +0 -50
  254. package/dist/shared/constants.js +0 -64
  255. package/dist/shared/index.d.ts +0 -14
  256. package/dist/shared/index.js +0 -14
  257. package/dist/shared/types/agent.d.ts +0 -36
  258. package/dist/shared/types/agent.js +0 -2
  259. package/dist/shared/types/channel.d.ts +0 -70
  260. package/dist/shared/types/channel.js +0 -2
  261. package/dist/shared/types/config.d.ts +0 -111
  262. package/dist/shared/types/config.js +0 -2
  263. package/dist/shared/types/connector.d.ts +0 -77
  264. package/dist/shared/types/connector.js +0 -2
  265. package/dist/shared/types/execution.d.ts +0 -29
  266. package/dist/shared/types/execution.js +0 -2
  267. package/dist/shared/types/provider.d.ts +0 -73
  268. package/dist/shared/types/provider.js +0 -2
  269. package/dist/shared/types/task.d.ts +0 -47
  270. package/dist/shared/types/task.js +0 -2
  271. package/dist/shared/types/workflow.d.ts +0 -39
  272. package/dist/shared/types/workflow.js +0 -2
  273. package/dist/shared/utils.d.ts +0 -6
  274. package/dist/shared/utils.js +0 -13
  275. package/dist/update-check.d.ts +0 -5
  276. package/dist/update-check.js +0 -56
@@ -1,23 +0,0 @@
1
- /**
2
- * ChatSessionManager — wraps orchestrator SessionManager with SessionKey-based lookup.
3
- * Story 4.3
4
- */
5
- import { SessionManager } from "../orchestrator/session-manager.js";
6
- export class ChatSessionManager {
7
- inner;
8
- constructor(db) {
9
- this.inner = new SessionManager(db);
10
- }
11
- async save(key, params) {
12
- return this.inner.save(key.agentId, key.channel, key.scope, params);
13
- }
14
- async load(key) {
15
- return this.inner.load(key.agentId, key.channel, key.scope);
16
- }
17
- async clear(key) {
18
- return this.inner.clear(key.agentId, key.channel, key.scope);
19
- }
20
- async shouldClear(session, opts) {
21
- return this.inner.shouldClear(session, opts);
22
- }
23
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * Text chunker — splits long text into chunks at natural boundaries.
3
- * Story 4.4
4
- */
5
- /**
6
- * Split text into chunks of at most maxLen characters.
7
- * Splits at paragraph boundaries first, then sentence, then word, then hard-cuts.
8
- */
9
- export declare function chunkText(text: string, maxLen: number): string[];
@@ -1,48 +0,0 @@
1
- /**
2
- * Text chunker — splits long text into chunks at natural boundaries.
3
- * Story 4.4
4
- */
5
- /**
6
- * Split text into chunks of at most maxLen characters.
7
- * Splits at paragraph boundaries first, then sentence, then word, then hard-cuts.
8
- */
9
- export function chunkText(text, maxLen) {
10
- if (maxLen <= 0)
11
- throw new Error("maxLen must be > 0");
12
- if (text.length <= maxLen)
13
- return [text];
14
- const chunks = [];
15
- function splitInto(segment) {
16
- if (segment.length <= maxLen) {
17
- if (segment.length > 0)
18
- chunks.push(segment);
19
- return;
20
- }
21
- // Try paragraph split (\n\n)
22
- const paraIdx = segment.lastIndexOf("\n\n", maxLen);
23
- if (paraIdx > 0) {
24
- chunks.push(segment.slice(0, paraIdx));
25
- splitInto(segment.slice(paraIdx + 2).trimStart());
26
- return;
27
- }
28
- // Try sentence split (". ")
29
- const sentIdx = segment.lastIndexOf(". ", maxLen);
30
- if (sentIdx > 0) {
31
- chunks.push(segment.slice(0, sentIdx + 1));
32
- splitInto(segment.slice(sentIdx + 2).trimStart());
33
- return;
34
- }
35
- // Try word split (" ")
36
- const wordIdx = segment.lastIndexOf(" ", maxLen);
37
- if (wordIdx > 0) {
38
- chunks.push(segment.slice(0, wordIdx));
39
- splitInto(segment.slice(wordIdx + 1));
40
- return;
41
- }
42
- // Hard cut
43
- chunks.push(segment.slice(0, maxLen));
44
- splitInto(segment.slice(maxLen));
45
- }
46
- splitInto(text);
47
- return chunks;
48
- }
@@ -1,75 +0,0 @@
1
- /**
2
- * TriageRouter — content-based routing with deterministic-first resolution.
3
- * Story 6.3
4
- *
5
- * Replaces the simple channel→agent binding with intelligent routing:
6
- * 1. Keyword/regex rules evaluated first (deterministic, ~4ms)
7
- * 2. LLM classification only for ambiguous messages (async, ~2-4s)
8
- * 3. Ownership chain logged for every routing decision
9
- *
10
- * Key constraint: specialists return to triage, never to another specialist.
11
- */
12
- import type { DataStore } from '../data/data-store.js';
13
- import type { HookBus } from '../hooks/hook-bus.js';
14
- import type { InboundMessage } from './types.js';
15
- export interface RoutingRule {
16
- /** Target agent slug */
17
- agentSlug: string;
18
- /** Keywords that trigger this rule (case-insensitive) */
19
- keywords?: string[];
20
- /** Regex patterns that trigger this rule */
21
- patterns?: string[];
22
- /** Priority — lower number wins ties. Default: 50 */
23
- priority?: number;
24
- }
25
- export interface RoutingDecision {
26
- timestamp: string;
27
- source: string;
28
- target: string;
29
- reason: string;
30
- method: 'deterministic' | 'llm';
31
- messageId?: string;
32
- channel?: string;
33
- }
34
- export interface TriageRouterConfig {
35
- /** Static routing rules evaluated deterministically */
36
- rules: RoutingRule[];
37
- /** Fallback agent if no rule matches and LLM is unavailable */
38
- fallbackAgent?: string;
39
- /** Whether to use LLM for ambiguous messages. Default: true */
40
- llmFallback?: boolean;
41
- /** Log decisions to the database. Default: true */
42
- persist?: boolean;
43
- }
44
- export declare class TriageRouter {
45
- private db;
46
- private hooks;
47
- private readonly rules;
48
- private readonly fallbackAgent?;
49
- private readonly llmFallback;
50
- private readonly persist;
51
- private readonly compiledRules;
52
- constructor(db: DataStore, hooks: HookBus, config: TriageRouterConfig);
53
- /**
54
- * Route an inbound message to the best agent.
55
- * Returns the agent slug and the routing decision.
56
- */
57
- route(msg: InboundMessage): Promise<{
58
- agentSlug: string | undefined;
59
- decision: RoutingDecision;
60
- }>;
61
- /**
62
- * Query the ownership chain for a given message or channel.
63
- */
64
- getDecisionHistory(filter?: {
65
- channel?: string;
66
- limit?: number;
67
- }): Promise<RoutingDecision[]>;
68
- /**
69
- * LLM classification — emits a hook for external LLM integration.
70
- * Returns agent slug + reason, or undefined if LLM is unavailable.
71
- */
72
- private classifyWithLLM;
73
- private buildDecision;
74
- private logDecision;
75
- }
@@ -1,142 +0,0 @@
1
- /**
2
- * TriageRouter — content-based routing with deterministic-first resolution.
3
- * Story 6.3
4
- *
5
- * Replaces the simple channel→agent binding with intelligent routing:
6
- * 1. Keyword/regex rules evaluated first (deterministic, ~4ms)
7
- * 2. LLM classification only for ambiguous messages (async, ~2-4s)
8
- * 3. Ownership chain logged for every routing decision
9
- *
10
- * Key constraint: specialists return to triage, never to another specialist.
11
- */
12
- export class TriageRouter {
13
- db;
14
- hooks;
15
- rules;
16
- fallbackAgent;
17
- llmFallback;
18
- persist;
19
- compiledRules;
20
- constructor(db, hooks, config) {
21
- this.db = db;
22
- this.hooks = hooks;
23
- this.rules = config.rules;
24
- this.fallbackAgent = config.fallbackAgent;
25
- this.llmFallback = config.llmFallback ?? true;
26
- this.persist = config.persist ?? true;
27
- // Pre-compile patterns for fast matching
28
- this.compiledRules = this.rules
29
- .sort((a, b) => (a.priority ?? 50) - (b.priority ?? 50))
30
- .map((rule) => ({
31
- rule,
32
- regexes: (rule.patterns ?? []).map((p) => new RegExp(p, 'i')),
33
- keywordSet: new Set((rule.keywords ?? []).map((k) => k.toLowerCase())),
34
- }));
35
- }
36
- /**
37
- * Route an inbound message to the best agent.
38
- * Returns the agent slug and the routing decision.
39
- */
40
- async route(msg) {
41
- const body = msg.body.toLowerCase();
42
- const words = new Set(body.split(/\s+/));
43
- // Phase 1: Deterministic — keyword + regex matching
44
- for (const { rule, regexes, keywordSet } of this.compiledRules) {
45
- // Keyword match
46
- for (const keyword of keywordSet) {
47
- if (words.has(keyword) || body.includes(keyword)) {
48
- const decision = this.buildDecision(rule.agentSlug, `keyword: '${keyword}'`, 'deterministic', msg);
49
- await this.logDecision(decision);
50
- return { agentSlug: rule.agentSlug, decision };
51
- }
52
- }
53
- // Regex match
54
- for (const regex of regexes) {
55
- if (regex.test(msg.body)) {
56
- const decision = this.buildDecision(rule.agentSlug, `pattern: ${regex.source}`, 'deterministic', msg);
57
- await this.logDecision(decision);
58
- return { agentSlug: rule.agentSlug, decision };
59
- }
60
- }
61
- }
62
- // Phase 2: LLM classification (if enabled)
63
- if (this.llmFallback) {
64
- const agentSlugs = this.rules.map((r) => r.agentSlug);
65
- const classified = await this.classifyWithLLM(msg, agentSlugs);
66
- if (classified) {
67
- const decision = this.buildDecision(classified.agentSlug, `llm: ${classified.reason}`, 'llm', msg);
68
- await this.logDecision(decision);
69
- return { agentSlug: classified.agentSlug, decision };
70
- }
71
- }
72
- // Phase 3: Fallback
73
- const decision = this.buildDecision(this.fallbackAgent, 'fallback: no rule matched', 'deterministic', msg);
74
- await this.logDecision(decision);
75
- return { agentSlug: this.fallbackAgent, decision };
76
- }
77
- /**
78
- * Query the ownership chain for a given message or channel.
79
- */
80
- async getDecisionHistory(filter) {
81
- const rows = await this.db.query('activity_log', {
82
- where: { event_type: 'triage_decision' },
83
- });
84
- let decisions = rows.map((r) => {
85
- try {
86
- return JSON.parse(r['payload']);
87
- }
88
- catch {
89
- return null;
90
- }
91
- }).filter((d) => d !== null);
92
- if (filter?.channel) {
93
- decisions = decisions.filter((d) => d.channel === filter.channel);
94
- }
95
- // Sort by timestamp descending
96
- decisions.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
97
- if (filter?.limit) {
98
- decisions = decisions.slice(0, filter.limit);
99
- }
100
- return decisions;
101
- }
102
- /**
103
- * LLM classification — emits a hook for external LLM integration.
104
- * Returns agent slug + reason, or undefined if LLM is unavailable.
105
- */
106
- async classifyWithLLM(msg, agentSlugs) {
107
- // Emit classification request — listeners provide the result
108
- const result = {};
109
- await this.hooks.emit('triage.classify', {
110
- message: msg,
111
- candidates: agentSlugs,
112
- respond: (slug, reason) => {
113
- result.agentSlug = slug;
114
- result.reason = reason;
115
- },
116
- });
117
- if (result.agentSlug && result.reason) {
118
- return { agentSlug: result.agentSlug, reason: result.reason };
119
- }
120
- return undefined;
121
- }
122
- buildDecision(target, reason, method, msg) {
123
- return {
124
- timestamp: new Date().toISOString(),
125
- source: 'triage',
126
- target: target ?? 'none',
127
- reason,
128
- method,
129
- messageId: msg.id,
130
- channel: msg.channel,
131
- };
132
- }
133
- async logDecision(decision) {
134
- if (!this.persist)
135
- return;
136
- await this.db.insert('activity_log', {
137
- event_type: 'triage_decision',
138
- payload: JSON.stringify(decision),
139
- });
140
- await this.hooks.emit('triage.routed', { decision });
141
- }
142
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * Chat types — re-exports from @botinabox/shared channel types.
3
- * Story 4.1
4
- */
5
- export type { ChatType, FormattingMode, ChannelCapabilities, ChannelMeta, InboundMessage, Attachment, OutboundPayload, SendResult, HealthStatus, ChannelConfig, ChannelAdapter, } from "../../shared/index.js";
@@ -1,5 +0,0 @@
1
- /**
2
- * Chat types — re-exports from @botinabox/shared channel types.
3
- * Story 4.1
4
- */
5
- export {};
@@ -1,2 +0,0 @@
1
- import type { BotConfig } from "../../shared/index.js";
2
- export declare const DEFAULT_CONFIG: BotConfig;
@@ -1,38 +0,0 @@
1
- export const DEFAULT_CONFIG = {
2
- data: {
3
- path: "./data/bot.db",
4
- walMode: true,
5
- },
6
- channels: {},
7
- agents: [],
8
- providers: {},
9
- models: {
10
- aliases: {
11
- fast: "claude-haiku-4-5",
12
- smart: "claude-opus-4-6",
13
- balanced: "claude-sonnet-4-6",
14
- },
15
- default: "smart",
16
- routing: {
17
- conversation: "fast",
18
- task_execution: "smart",
19
- classification: "fast",
20
- },
21
- fallbackChain: [],
22
- },
23
- entities: {},
24
- security: {
25
- fieldLengthLimits: { default: 65535 },
26
- },
27
- render: {
28
- outputDir: "./context",
29
- watchIntervalMs: 30_000,
30
- },
31
- updates: {
32
- policy: "auto-compatible",
33
- checkIntervalMs: 86_400_000,
34
- },
35
- budget: {
36
- warnPercent: 80,
37
- },
38
- };
@@ -1,6 +0,0 @@
1
- export { loadConfig, getConfig, initConfig, _resetConfig } from "./loader.js";
2
- export type { ConfigLoadError, ConfigLoadResult } from "./loader.js";
3
- export { interpolateEnv } from "./interpolate.js";
4
- export { validateConfig } from "./schema.js";
5
- export type { SchemaError } from "./schema.js";
6
- export { DEFAULT_CONFIG } from "./defaults.js";
@@ -1,4 +0,0 @@
1
- export { loadConfig, getConfig, initConfig, _resetConfig } from "./loader.js";
2
- export { interpolateEnv } from "./interpolate.js";
3
- export { validateConfig } from "./schema.js";
4
- export { DEFAULT_CONFIG } from "./defaults.js";
@@ -1,5 +0,0 @@
1
- /**
2
- * Interpolate ${ENV_VAR} references in YAML string values.
3
- * Recursively walks objects and arrays.
4
- */
5
- export declare function interpolateEnv(value: unknown, env?: Record<string, string | undefined>): unknown;
@@ -1,27 +0,0 @@
1
- /**
2
- * Interpolate ${ENV_VAR} references in YAML string values.
3
- * Recursively walks objects and arrays.
4
- */
5
- export function interpolateEnv(value, env = process.env) {
6
- if (typeof value === "string") {
7
- return value.replace(/\$\{([^}]+)\}/g, (_, name) => {
8
- const envVal = env[name];
9
- if (envVal === undefined) {
10
- // Leave the placeholder if env var is not set (don't silently swallow)
11
- return `\${${name}}`;
12
- }
13
- return envVal;
14
- });
15
- }
16
- if (Array.isArray(value)) {
17
- return value.map(item => interpolateEnv(item, env));
18
- }
19
- if (value !== null && typeof value === "object") {
20
- const result = {};
21
- for (const [k, v] of Object.entries(value)) {
22
- result[k] = interpolateEnv(v, env);
23
- }
24
- return result;
25
- }
26
- return value;
27
- }
@@ -1,24 +0,0 @@
1
- import type { BotConfig } from "../../shared/index.js";
2
- export interface ConfigLoadError {
3
- field: string;
4
- message: string;
5
- }
6
- export interface ConfigLoadResult {
7
- config: BotConfig;
8
- errors: ConfigLoadError[];
9
- }
10
- /**
11
- * Load and merge config from file, with env var interpolation and runtime overrides.
12
- * Merge order: defaults < config file < runtime overrides
13
- */
14
- export declare function loadConfig(opts?: {
15
- configPath?: string;
16
- overrides?: Partial<BotConfig>;
17
- env?: Record<string, string | undefined>;
18
- }): ConfigLoadResult;
19
- /** Get the loaded config singleton. Call loadConfig() first. */
20
- export declare function getConfig(): BotConfig;
21
- /** Initialize the config singleton. Returns errors if any. */
22
- export declare function initConfig(opts?: Parameters<typeof loadConfig>[0]): ConfigLoadError[];
23
- /** Reset the singleton (for testing) */
24
- export declare function _resetConfig(): void;
@@ -1,59 +0,0 @@
1
- import { readFileSync, existsSync } from "node:fs";
2
- import { parse as parseYaml } from "yaml";
3
- import { DEFAULT_CONFIG } from "./defaults.js";
4
- import { interpolateEnv } from "./interpolate.js";
5
- function deepMerge(base, override) {
6
- if (override === undefined || override === null)
7
- return base;
8
- if (base === undefined || base === null)
9
- return override;
10
- if (typeof base !== "object" || typeof override !== "object")
11
- return override;
12
- if (Array.isArray(override))
13
- return override;
14
- const result = { ...base };
15
- for (const [k, v] of Object.entries(override)) {
16
- if (v !== undefined) {
17
- result[k] = deepMerge(result[k], v);
18
- }
19
- }
20
- return result;
21
- }
22
- /**
23
- * Load and merge config from file, with env var interpolation and runtime overrides.
24
- * Merge order: defaults < config file < runtime overrides
25
- */
26
- export function loadConfig(opts) {
27
- const configPath = opts?.configPath ?? "botinabox.config.yml";
28
- const errors = [];
29
- let fileConfig = {};
30
- if (existsSync(configPath)) {
31
- try {
32
- const raw = readFileSync(configPath, "utf-8");
33
- const parsed = parseYaml(raw);
34
- fileConfig = interpolateEnv(parsed, opts?.env ?? process.env);
35
- }
36
- catch (err) {
37
- errors.push({ field: "configPath", message: `Failed to parse ${configPath}: ${String(err)}` });
38
- }
39
- }
40
- const merged = deepMerge(deepMerge(DEFAULT_CONFIG, fileConfig), opts?.overrides ?? {});
41
- return { config: Object.freeze(merged), errors };
42
- }
43
- let _config = null;
44
- /** Get the loaded config singleton. Call loadConfig() first. */
45
- export function getConfig() {
46
- if (!_config)
47
- throw new Error("Config not loaded — call loadConfig() first");
48
- return _config;
49
- }
50
- /** Initialize the config singleton. Returns errors if any. */
51
- export function initConfig(opts) {
52
- const { config, errors } = loadConfig(opts);
53
- _config = config;
54
- return errors;
55
- }
56
- /** Reset the singleton (for testing) */
57
- export function _resetConfig() {
58
- _config = null;
59
- }
@@ -1,5 +0,0 @@
1
- export interface SchemaError {
2
- path: string;
3
- message: string;
4
- }
5
- export declare function validateConfig(config: unknown): SchemaError[];
@@ -1,119 +0,0 @@
1
- import Ajv from "ajv";
2
- const ajv = new Ajv({ allErrors: true, coerceTypes: false });
3
- const BOT_CONFIG_SCHEMA = {
4
- type: "object",
5
- additionalProperties: true,
6
- properties: {
7
- data: {
8
- type: "object",
9
- required: ["path", "walMode"],
10
- properties: {
11
- path: { type: "string", minLength: 1 },
12
- walMode: { type: "boolean" },
13
- backupDir: { type: "string" },
14
- },
15
- },
16
- models: {
17
- type: "object",
18
- required: ["aliases", "default", "routing", "fallbackChain"],
19
- properties: {
20
- aliases: { type: "object", additionalProperties: { type: "string" } },
21
- default: { type: "string", minLength: 1 },
22
- routing: { type: "object", additionalProperties: { type: "string" } },
23
- fallbackChain: { type: "array", items: { type: "string" } },
24
- costLimit: {
25
- type: "object",
26
- properties: {
27
- perRunCents: { type: "number", minimum: 0 },
28
- },
29
- },
30
- },
31
- },
32
- security: {
33
- type: "object",
34
- properties: {
35
- fieldLengthLimits: { type: "object", additionalProperties: { type: "number" } },
36
- allowedFilePrefixes: { type: "array", items: { type: "string" } },
37
- },
38
- },
39
- render: {
40
- type: "object",
41
- required: ["outputDir", "watchIntervalMs"],
42
- properties: {
43
- outputDir: { type: "string", minLength: 1 },
44
- watchIntervalMs: { type: "number", minimum: 1000 },
45
- },
46
- },
47
- updates: {
48
- type: "object",
49
- required: ["policy", "checkIntervalMs"],
50
- properties: {
51
- policy: { type: "string", enum: ["auto-all", "auto-compatible", "auto-patch", "notify", "manual"] },
52
- checkIntervalMs: { type: "number", minimum: 60_000 },
53
- },
54
- },
55
- budget: {
56
- type: "object",
57
- required: ["warnPercent"],
58
- properties: {
59
- warnPercent: { type: "number", minimum: 1, maximum: 100 },
60
- globalMonthlyCents: { type: "number", minimum: 0 },
61
- },
62
- },
63
- agents: {
64
- type: "array",
65
- items: {
66
- type: "object",
67
- required: ["slug", "name", "adapter"],
68
- properties: {
69
- slug: { type: "string", minLength: 1, pattern: "^[a-z0-9-]+$" },
70
- name: { type: "string", minLength: 1 },
71
- adapter: { type: "string", minLength: 1 },
72
- model: { type: "string" },
73
- workdir: { type: "string" },
74
- maxConcurrentRuns: { type: "number", minimum: 1 },
75
- budgetMonthlyCents: { type: "number", minimum: 0 },
76
- canCreateAgents: { type: "boolean" },
77
- skipPermissions: { type: "boolean" },
78
- },
79
- },
80
- },
81
- channels: {
82
- type: "object",
83
- additionalProperties: {
84
- type: "object",
85
- required: ["enabled"],
86
- properties: {
87
- enabled: { type: "boolean" },
88
- },
89
- },
90
- },
91
- providers: {
92
- type: "object",
93
- additionalProperties: {
94
- type: "object",
95
- required: ["enabled"],
96
- properties: {
97
- enabled: { type: "boolean" },
98
- },
99
- },
100
- },
101
- },
102
- };
103
- let _validate = null;
104
- function getValidator() {
105
- if (!_validate) {
106
- _validate = ajv.compile(BOT_CONFIG_SCHEMA);
107
- }
108
- return _validate;
109
- }
110
- export function validateConfig(config) {
111
- const validate = getValidator();
112
- const valid = validate(config);
113
- if (valid)
114
- return [];
115
- return (validate.errors ?? []).map(err => ({
116
- path: err.instancePath || "/",
117
- message: err.message ?? "invalid",
118
- }));
119
- }
@@ -1,14 +0,0 @@
1
- import type { DataStore } from "./data-store.js";
2
- /**
3
- * Define default entity context rendering for botinabox core tables.
4
- * Call after defineCoreTables() and before or after init().
5
- *
6
- * Renders:
7
- * - agents/ — per-agent context (AGENT.md, PROJECTS.md if agent_project exists)
8
- * - users/ — per-user context (USER.md) — protected
9
- * - skills/ — per-skill context (SKILL.md)
10
- *
11
- * Apps can override by calling db.defineEntityContext() with the same table name
12
- * BEFORE calling defineCoreEntityContexts().
13
- */
14
- export declare function defineCoreEntityContexts(db: DataStore): void;