botinabox 2.4.3 → 2.5.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.
Files changed (276) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +190 -190
  3. package/bin/botinabox.mjs +1 -1
  4. package/dist/cli.js +0 -0
  5. package/dist/connectors/google/index.d.ts +67 -1
  6. package/dist/connectors/google/index.js +240 -0
  7. package/dist/index.js +19 -5
  8. package/package.json +100 -99
  9. package/dist/channels/discord/adapter.d.ts +0 -32
  10. package/dist/channels/discord/adapter.js +0 -70
  11. package/dist/channels/discord/inbound.d.ts +0 -25
  12. package/dist/channels/discord/inbound.js +0 -24
  13. package/dist/channels/discord/models.d.ts +0 -8
  14. package/dist/channels/discord/models.js +0 -5
  15. package/dist/channels/discord/outbound.d.ts +0 -14
  16. package/dist/channels/discord/outbound.js +0 -38
  17. package/dist/channels/slack/adapter.d.ts +0 -33
  18. package/dist/channels/slack/adapter.js +0 -74
  19. package/dist/channels/slack/inbound.d.ts +0 -59
  20. package/dist/channels/slack/inbound.js +0 -96
  21. package/dist/channels/slack/models.d.ts +0 -9
  22. package/dist/channels/slack/models.js +0 -5
  23. package/dist/channels/slack/outbound.d.ts +0 -12
  24. package/dist/channels/slack/outbound.js +0 -18
  25. package/dist/channels/slack/transcribe.d.ts +0 -41
  26. package/dist/channels/slack/transcribe.js +0 -106
  27. package/dist/channels/webhook/adapter.d.ts +0 -23
  28. package/dist/channels/webhook/adapter.js +0 -86
  29. package/dist/channels/webhook/hmac.d.ts +0 -13
  30. package/dist/channels/webhook/hmac.js +0 -26
  31. package/dist/channels/webhook/models.d.ts +0 -9
  32. package/dist/channels/webhook/models.js +0 -5
  33. package/dist/channels/webhook/server.d.ts +0 -20
  34. package/dist/channels/webhook/server.js +0 -91
  35. package/dist/chat-pipeline-C-XlLGNl.d.ts +0 -648
  36. package/dist/chat-pipeline-CR1KF6eX.d.ts +0 -652
  37. package/dist/chat-pipeline-DisuC8SB.d.ts +0 -643
  38. package/dist/chunk-2LGXQPEA.js +0 -41
  39. package/dist/chunk-3X3YKI4T.js +0 -357
  40. package/dist/chunk-D47AIFOD.js +0 -351
  41. package/dist/chunk-DSNJKNEW.js +0 -328
  42. package/dist/chunk-GS2JFL6I.js +0 -144
  43. package/dist/chunk-J6S6QMUY.js +0 -144
  44. package/dist/chunk-QLA6YOFN.js +0 -22
  45. package/dist/chunk-UACT2WXX.js +0 -381
  46. package/dist/cli/templates/config.yml.d.ts +0 -7
  47. package/dist/cli/templates/config.yml.js +0 -61
  48. package/dist/cli/templates/env.d.ts +0 -1
  49. package/dist/cli/templates/env.js +0 -30
  50. package/dist/cli/templates/index.ts.d.ts +0 -2
  51. package/dist/cli/templates/index.ts.js +0 -30
  52. package/dist/cli/templates/package.json.d.ts +0 -5
  53. package/dist/cli/templates/package.json.js +0 -28
  54. package/dist/connector-DDahQw-2.d.ts +0 -63
  55. package/dist/connectors/google/calendar-connector.d.ts +0 -40
  56. package/dist/connectors/google/calendar-connector.js +0 -243
  57. package/dist/connectors/google/gmail-connector.d.ts +0 -42
  58. package/dist/connectors/google/gmail-connector.js +0 -345
  59. package/dist/connectors/google/oauth.d.ts +0 -48
  60. package/dist/connectors/google/oauth.js +0 -112
  61. package/dist/connectors/google/types.d.ts +0 -78
  62. package/dist/connectors/google/types.js +0 -2
  63. package/dist/core/chat/auto-discovery.d.ts +0 -16
  64. package/dist/core/chat/auto-discovery.js +0 -54
  65. package/dist/core/chat/channel-registry.d.ts +0 -45
  66. package/dist/core/chat/channel-registry.js +0 -96
  67. package/dist/core/chat/chat-pipeline.d.ts +0 -113
  68. package/dist/core/chat/chat-pipeline.js +0 -395
  69. package/dist/core/chat/chat-responder.d.ts +0 -90
  70. package/dist/core/chat/chat-responder.js +0 -185
  71. package/dist/core/chat/formatter.d.ts +0 -11
  72. package/dist/core/chat/formatter.js +0 -60
  73. package/dist/core/chat/index.d.ts +0 -24
  74. package/dist/core/chat/index.js +0 -18
  75. package/dist/core/chat/message-interpreter.d.ts +0 -91
  76. package/dist/core/chat/message-interpreter.js +0 -166
  77. package/dist/core/chat/message-store.d.ts +0 -66
  78. package/dist/core/chat/message-store.js +0 -131
  79. package/dist/core/chat/notification-queue.d.ts +0 -34
  80. package/dist/core/chat/notification-queue.js +0 -111
  81. package/dist/core/chat/pipeline.d.ts +0 -38
  82. package/dist/core/chat/pipeline.js +0 -89
  83. package/dist/core/chat/policies.d.ts +0 -16
  84. package/dist/core/chat/policies.js +0 -25
  85. package/dist/core/chat/routing.d.ts +0 -17
  86. package/dist/core/chat/routing.js +0 -36
  87. package/dist/core/chat/session-key.d.ts +0 -30
  88. package/dist/core/chat/session-key.js +0 -65
  89. package/dist/core/chat/session-manager.d.ts +0 -17
  90. package/dist/core/chat/session-manager.js +0 -23
  91. package/dist/core/chat/text-chunker.d.ts +0 -9
  92. package/dist/core/chat/text-chunker.js +0 -48
  93. package/dist/core/chat/triage-router.d.ts +0 -75
  94. package/dist/core/chat/triage-router.js +0 -142
  95. package/dist/core/chat/types.d.ts +0 -5
  96. package/dist/core/chat/types.js +0 -5
  97. package/dist/core/config/defaults.d.ts +0 -2
  98. package/dist/core/config/defaults.js +0 -38
  99. package/dist/core/config/index.d.ts +0 -6
  100. package/dist/core/config/index.js +0 -4
  101. package/dist/core/config/interpolate.d.ts +0 -5
  102. package/dist/core/config/interpolate.js +0 -27
  103. package/dist/core/config/loader.d.ts +0 -24
  104. package/dist/core/config/loader.js +0 -59
  105. package/dist/core/config/schema.d.ts +0 -5
  106. package/dist/core/config/schema.js +0 -119
  107. package/dist/core/data/core-entity-contexts.d.ts +0 -14
  108. package/dist/core/data/core-entity-contexts.js +0 -197
  109. package/dist/core/data/core-migrations.d.ts +0 -5
  110. package/dist/core/data/core-migrations.js +0 -45
  111. package/dist/core/data/core-schema.d.ts +0 -6
  112. package/dist/core/data/core-schema.js +0 -454
  113. package/dist/core/data/data-store.d.ts +0 -67
  114. package/dist/core/data/data-store.js +0 -218
  115. package/dist/core/data/domain-entity-contexts.d.ts +0 -29
  116. package/dist/core/data/domain-entity-contexts.js +0 -321
  117. package/dist/core/data/domain-schema.d.ts +0 -36
  118. package/dist/core/data/domain-schema.js +0 -323
  119. package/dist/core/data/index.d.ts +0 -7
  120. package/dist/core/data/index.js +0 -7
  121. package/dist/core/data/types.d.ts +0 -111
  122. package/dist/core/data/types.js +0 -1
  123. package/dist/core/hooks/hook-bus.d.ts +0 -18
  124. package/dist/core/hooks/hook-bus.js +0 -120
  125. package/dist/core/hooks/index.d.ts +0 -2
  126. package/dist/core/hooks/index.js +0 -1
  127. package/dist/core/hooks/types.d.ts +0 -19
  128. package/dist/core/hooks/types.js +0 -1
  129. package/dist/core/index.d.ts +0 -4
  130. package/dist/core/index.js +0 -4
  131. package/dist/core/llm/auto-discovery.d.ts +0 -11
  132. package/dist/core/llm/auto-discovery.js +0 -49
  133. package/dist/core/llm/cost-tracker.d.ts +0 -6
  134. package/dist/core/llm/cost-tracker.js +0 -38
  135. package/dist/core/llm/index.d.ts +0 -4
  136. package/dist/core/llm/index.js +0 -3
  137. package/dist/core/llm/model-router.d.ts +0 -25
  138. package/dist/core/llm/model-router.js +0 -49
  139. package/dist/core/llm/provider-registry.d.ts +0 -9
  140. package/dist/core/llm/provider-registry.js +0 -25
  141. package/dist/core/llm/types.d.ts +0 -2
  142. package/dist/core/llm/types.js +0 -2
  143. package/dist/core/orchestrator/adapters/api-adapter.d.ts +0 -34
  144. package/dist/core/orchestrator/adapters/api-adapter.js +0 -88
  145. package/dist/core/orchestrator/adapters/cli-adapter.d.ts +0 -22
  146. package/dist/core/orchestrator/adapters/cli-adapter.js +0 -69
  147. package/dist/core/orchestrator/adapters/deterministic-adapter.d.ts +0 -35
  148. package/dist/core/orchestrator/adapters/deterministic-adapter.js +0 -75
  149. package/dist/core/orchestrator/adapters/env-whitelist.d.ts +0 -4
  150. package/dist/core/orchestrator/adapters/env-whitelist.js +0 -27
  151. package/dist/core/orchestrator/adapters/output-extractor.d.ts +0 -11
  152. package/dist/core/orchestrator/adapters/output-extractor.js +0 -59
  153. package/dist/core/orchestrator/adapters/process-manager.d.ts +0 -15
  154. package/dist/core/orchestrator/adapters/process-manager.js +0 -26
  155. package/dist/core/orchestrator/adapters/tool-loop.d.ts +0 -22
  156. package/dist/core/orchestrator/adapters/tool-loop.js +0 -66
  157. package/dist/core/orchestrator/agent-registry.d.ts +0 -31
  158. package/dist/core/orchestrator/agent-registry.js +0 -135
  159. package/dist/core/orchestrator/budget-controller.d.ts +0 -19
  160. package/dist/core/orchestrator/budget-controller.js +0 -73
  161. package/dist/core/orchestrator/chain-guard.d.ts +0 -14
  162. package/dist/core/orchestrator/chain-guard.js +0 -23
  163. package/dist/core/orchestrator/circuit-breaker.d.ts +0 -65
  164. package/dist/core/orchestrator/circuit-breaker.js +0 -159
  165. package/dist/core/orchestrator/claude-stream-parser.d.ts +0 -31
  166. package/dist/core/orchestrator/claude-stream-parser.js +0 -99
  167. package/dist/core/orchestrator/config-revisions.d.ts +0 -6
  168. package/dist/core/orchestrator/config-revisions.js +0 -17
  169. package/dist/core/orchestrator/dependency-resolver.d.ts +0 -20
  170. package/dist/core/orchestrator/dependency-resolver.js +0 -78
  171. package/dist/core/orchestrator/governance-gate.d.ts +0 -110
  172. package/dist/core/orchestrator/governance-gate.js +0 -170
  173. package/dist/core/orchestrator/learning-pipeline.d.ts +0 -109
  174. package/dist/core/orchestrator/learning-pipeline.js +0 -249
  175. package/dist/core/orchestrator/loop-detector.d.ts +0 -51
  176. package/dist/core/orchestrator/loop-detector.js +0 -133
  177. package/dist/core/orchestrator/ndjson-logger.d.ts +0 -6
  178. package/dist/core/orchestrator/ndjson-logger.js +0 -18
  179. package/dist/core/orchestrator/permission-relay.d.ts +0 -72
  180. package/dist/core/orchestrator/permission-relay.js +0 -164
  181. package/dist/core/orchestrator/run-manager.d.ts +0 -31
  182. package/dist/core/orchestrator/run-manager.js +0 -178
  183. package/dist/core/orchestrator/scheduler.d.ts +0 -70
  184. package/dist/core/orchestrator/scheduler.js +0 -198
  185. package/dist/core/orchestrator/secret-store.d.ts +0 -57
  186. package/dist/core/orchestrator/secret-store.js +0 -171
  187. package/dist/core/orchestrator/session-manager.d.ts +0 -13
  188. package/dist/core/orchestrator/session-manager.js +0 -66
  189. package/dist/core/orchestrator/task-queue.d.ts +0 -34
  190. package/dist/core/orchestrator/task-queue.js +0 -83
  191. package/dist/core/orchestrator/template-interpolate.d.ts +0 -5
  192. package/dist/core/orchestrator/template-interpolate.js +0 -18
  193. package/dist/core/orchestrator/user-registry.d.ts +0 -47
  194. package/dist/core/orchestrator/user-registry.js +0 -76
  195. package/dist/core/orchestrator/wakeup-queue.d.ts +0 -9
  196. package/dist/core/orchestrator/wakeup-queue.js +0 -45
  197. package/dist/core/orchestrator/workflow-engine.d.ts +0 -47
  198. package/dist/core/orchestrator/workflow-engine.js +0 -204
  199. package/dist/core/security/audit.d.ts +0 -20
  200. package/dist/core/security/audit.js +0 -33
  201. package/dist/core/security/column-validator.d.ts +0 -20
  202. package/dist/core/security/column-validator.js +0 -37
  203. package/dist/core/security/index.d.ts +0 -5
  204. package/dist/core/security/index.js +0 -5
  205. package/dist/core/security/process-env.d.ts +0 -13
  206. package/dist/core/security/process-env.js +0 -49
  207. package/dist/core/security/sanitizer.d.ts +0 -11
  208. package/dist/core/security/sanitizer.js +0 -39
  209. package/dist/core/security/types.d.ts +0 -11
  210. package/dist/core/security/types.js +0 -1
  211. package/dist/core/update/auto-update.d.ts +0 -21
  212. package/dist/core/update/auto-update.js +0 -102
  213. package/dist/core/update/backup-manager.d.ts +0 -7
  214. package/dist/core/update/backup-manager.js +0 -24
  215. package/dist/core/update/index.d.ts +0 -8
  216. package/dist/core/update/index.js +0 -6
  217. package/dist/core/update/migration-hooks.d.ts +0 -11
  218. package/dist/core/update/migration-hooks.js +0 -10
  219. package/dist/core/update/types.d.ts +0 -11
  220. package/dist/core/update/types.js +0 -1
  221. package/dist/core/update/update-checker.d.ts +0 -11
  222. package/dist/core/update/update-checker.js +0 -63
  223. package/dist/core/update/update-manager.d.ts +0 -25
  224. package/dist/core/update/update-manager.js +0 -101
  225. package/dist/core/update/version-utils.d.ts +0 -6
  226. package/dist/core/update/version-utils.js +0 -34
  227. package/dist/gmail-connector-2FVYTQJH.js +0 -6
  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,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;
@@ -1,197 +0,0 @@
1
- import { truncateAtWord } from "../../shared/utils.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 function defineCoreEntityContexts(db) {
15
- // --- Agents ---
16
- db.defineEntityContext("agents", {
17
- table: "agents",
18
- directory: "agents",
19
- slugColumn: "slug",
20
- indexFile: "agents/AGENTS.md",
21
- files: {
22
- "AGENT.md": {
23
- source: { type: "self" },
24
- render: (rows) => {
25
- const a = rows[0];
26
- if (!a)
27
- return "";
28
- return [
29
- `# ${a.name}`,
30
- "",
31
- a.role ? `**Role:** ${a.role}` : null,
32
- a.adapter ? `**Adapter:** ${a.adapter}` : null,
33
- a.status ? `**Status:** ${a.status}` : null,
34
- a.cwd ? `**Working Directory:** ${a.cwd}` : null,
35
- a.reports_to ? `**Reports To:** ${a.reports_to}` : null,
36
- "",
37
- ]
38
- .filter(Boolean)
39
- .join("\n");
40
- },
41
- },
42
- "SKILLS.md": {
43
- source: {
44
- type: "manyToMany",
45
- junctionTable: "agent_skills",
46
- localKey: "agent_id",
47
- remoteKey: "skill_id",
48
- remoteTable: "skills",
49
- },
50
- omitIfEmpty: true,
51
- render: (rows) => {
52
- if (!rows.length)
53
- return "";
54
- const lines = [`# Skills (${rows.length})`, ""];
55
- for (const s of rows) {
56
- lines.push(`## ${s.name}`);
57
- if (s.category)
58
- lines.push(`**Category:** ${s.category}`);
59
- if (s.description)
60
- lines.push("", s.description);
61
- if (s.definition)
62
- lines.push("", "```", s.definition, "```");
63
- lines.push("");
64
- }
65
- return lines.join("\n");
66
- },
67
- },
68
- "PLAYBOOKS.md": {
69
- source: {
70
- type: "manyToMany",
71
- junctionTable: "agent_playbooks",
72
- localKey: "agent_id",
73
- remoteKey: "playbook_id",
74
- remoteTable: "playbooks",
75
- },
76
- omitIfEmpty: true,
77
- render: (rows) => {
78
- if (!rows.length)
79
- return "";
80
- const lines = [`# Playbooks (${rows.length})`, ""];
81
- for (const pb of rows) {
82
- lines.push(`## ${pb.pattern ?? pb.name ?? "Unnamed"}`);
83
- if (pb.rule)
84
- lines.push("", pb.rule);
85
- lines.push("");
86
- }
87
- return lines.join("\n");
88
- },
89
- },
90
- },
91
- });
92
- // --- Users (protected) ---
93
- db.defineEntityContext("users", {
94
- table: "users",
95
- directory: "users",
96
- slugColumn: "id",
97
- protected: true,
98
- indexFile: "users/USERS.md",
99
- files: {
100
- "USER.md": {
101
- source: { type: "self" },
102
- render: (rows) => {
103
- const u = rows[0];
104
- if (!u)
105
- return "";
106
- return [
107
- `# ${u.name}`,
108
- "",
109
- u.role ? `**Role:** ${u.role}` : null,
110
- u.title ? `**Title:** ${u.title}` : null,
111
- u.email ? `**Email:** ${u.email}` : null,
112
- u.timezone ? `**Timezone:** ${u.timezone}` : null,
113
- "",
114
- ]
115
- .filter(Boolean)
116
- .join("\n");
117
- },
118
- },
119
- },
120
- });
121
- // --- Skills ---
122
- db.defineEntityContext("skills", {
123
- table: "skills",
124
- directory: "skills",
125
- slugColumn: "slug",
126
- indexFile: "skills/SKILLS.md",
127
- files: {
128
- "SKILL.md": {
129
- source: { type: "self" },
130
- render: (rows) => {
131
- const s = rows[0];
132
- if (!s)
133
- return "";
134
- return [
135
- `# ${s.name}`,
136
- "",
137
- s.category ? `**Category:** ${s.category}` : null,
138
- s.description ? `\n${s.description}` : null,
139
- s.definition ? `\n## Definition\n\n${s.definition}` : null,
140
- "",
141
- ]
142
- .filter(Boolean)
143
- .join("\n");
144
- },
145
- },
146
- },
147
- });
148
- // --- Messages ---
149
- db.defineEntityContext("messages", {
150
- table: "messages",
151
- directory: "messages",
152
- slugColumn: "id",
153
- indexFile: "messages/MESSAGES.md",
154
- indexRender: (rows) => {
155
- const active = rows.filter((r) => r.deleted_at == null);
156
- if (!active.length)
157
- return "# Messages\n\nNo messages.\n";
158
- const recent = active.slice(-100);
159
- const lines = recent.map((r) => {
160
- const dir = r.direction === "outbound" ? "→" : "←";
161
- const who = r.from_agent ?? r.from_user ?? "unknown";
162
- const time = (r.created_at ?? "").slice(0, 16);
163
- const preview = truncateAtWord(r.body ?? "", 80);
164
- return `- ${dir} **${who}** (${time}): ${preview}`;
165
- });
166
- return `# Messages\n\nLast ${lines.length} messages:\n\n${lines.join("\n")}\n`;
167
- },
168
- files: {
169
- "MESSAGE.md": {
170
- source: { type: "self" },
171
- render: (rows) => {
172
- const m = rows[0];
173
- if (!m)
174
- return "";
175
- return [
176
- "# Message",
177
- "",
178
- `**Direction:** ${m.direction}`,
179
- m.from_user ? `**From User:** ${m.from_user}` : null,
180
- m.from_agent ? `**From Agent:** ${m.from_agent}` : null,
181
- `**Channel:** ${m.channel}`,
182
- m.thread_id ? `**Thread:** ${m.thread_id}` : null,
183
- m.task_id ? `**Task:** ${m.task_id}` : null,
184
- `**Time:** ${m.created_at}`,
185
- "",
186
- "---",
187
- "",
188
- m.body,
189
- "",
190
- ]
191
- .filter(Boolean)
192
- .join("\n");
193
- },
194
- },
195
- },
196
- });
197
- }
@@ -1,5 +0,0 @@
1
- /** Initial migration set for core tables */
2
- export declare const CORE_MIGRATIONS: Array<{
3
- version: string;
4
- sql: string;
5
- }>;