@runcore-sh/runcore 0.4.0 → 0.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 (351) hide show
  1. package/dictionary.json +2 -2
  2. package/dist/activity/log.js +2 -2
  3. package/dist/activity/log.js.map +1 -1
  4. package/dist/agents/governed-spawn.d.ts.map +1 -1
  5. package/dist/cli.js +101 -11
  6. package/dist/cli.js.map +1 -1
  7. package/dist/extensions/cache.d.ts +57 -0
  8. package/dist/extensions/cache.d.ts.map +1 -0
  9. package/dist/extensions/cache.js +173 -0
  10. package/dist/extensions/cache.js.map +1 -0
  11. package/dist/extensions/client.d.ts +55 -0
  12. package/dist/extensions/client.d.ts.map +1 -0
  13. package/dist/extensions/client.js +120 -0
  14. package/dist/extensions/client.js.map +1 -0
  15. package/dist/extensions/index.d.ts +13 -0
  16. package/dist/extensions/index.d.ts.map +1 -0
  17. package/dist/extensions/index.js +12 -0
  18. package/dist/extensions/index.js.map +1 -0
  19. package/dist/extensions/loader.d.ts +50 -0
  20. package/dist/extensions/loader.d.ts.map +1 -0
  21. package/dist/extensions/loader.js +166 -0
  22. package/dist/extensions/loader.js.map +1 -0
  23. package/dist/extensions/manifest.d.ts +38 -0
  24. package/dist/extensions/manifest.d.ts.map +1 -0
  25. package/dist/extensions/manifest.js +17 -0
  26. package/dist/extensions/manifest.js.map +1 -0
  27. package/dist/extensions/stubs.d.ts +27 -0
  28. package/dist/extensions/stubs.d.ts.map +1 -0
  29. package/dist/extensions/stubs.js +45 -0
  30. package/dist/extensions/stubs.js.map +1 -0
  31. package/dist/lib/audit.js +2 -2
  32. package/dist/lib/audit.js.map +1 -1
  33. package/dist/lib/brain-migrate.d.ts +21 -0
  34. package/dist/lib/brain-migrate.d.ts.map +1 -0
  35. package/dist/lib/brain-migrate.js +137 -0
  36. package/dist/lib/brain-migrate.js.map +1 -0
  37. package/dist/lib/paths.d.ts +27 -0
  38. package/dist/lib/paths.d.ts.map +1 -1
  39. package/dist/lib/paths.js +65 -0
  40. package/dist/lib/paths.js.map +1 -1
  41. package/dist/llm/call-log.d.ts +40 -0
  42. package/dist/llm/call-log.d.ts.map +1 -0
  43. package/dist/llm/call-log.js +35 -0
  44. package/dist/llm/call-log.js.map +1 -0
  45. package/dist/llm/complete.d.ts +6 -0
  46. package/dist/llm/complete.d.ts.map +1 -1
  47. package/dist/llm/complete.js +27 -0
  48. package/dist/llm/complete.js.map +1 -1
  49. package/dist/mcp-server.js +118 -2
  50. package/dist/mcp-server.js.map +1 -1
  51. package/dist/memory/file-backed.d.ts +4 -0
  52. package/dist/memory/file-backed.d.ts.map +1 -1
  53. package/dist/memory/file-backed.js +4 -0
  54. package/dist/memory/file-backed.js.map +1 -1
  55. package/dist/memory/vector-index.d.ts +4 -12
  56. package/dist/memory/vector-index.d.ts.map +1 -1
  57. package/dist/memory/vector-index.js +11 -93
  58. package/dist/memory/vector-index.js.map +1 -1
  59. package/dist/search/brain-docs.d.ts +17 -7
  60. package/dist/search/brain-docs.d.ts.map +1 -1
  61. package/dist/search/brain-docs.js +170 -52
  62. package/dist/search/brain-docs.js.map +1 -1
  63. package/dist/search/brain-rag.d.ts +45 -0
  64. package/dist/search/brain-rag.d.ts.map +1 -0
  65. package/dist/search/brain-rag.js +275 -0
  66. package/dist/search/brain-rag.js.map +1 -0
  67. package/dist/search/chunker.d.ts +24 -0
  68. package/dist/search/chunker.d.ts.map +1 -0
  69. package/dist/search/chunker.js +95 -0
  70. package/dist/search/chunker.js.map +1 -0
  71. package/dist/search/embedder.d.ts +16 -0
  72. package/dist/search/embedder.d.ts.map +1 -0
  73. package/dist/search/embedder.js +108 -0
  74. package/dist/search/embedder.js.map +1 -0
  75. package/dist/search/file-watcher.d.ts +11 -0
  76. package/dist/search/file-watcher.d.ts.map +1 -0
  77. package/dist/search/file-watcher.js +86 -0
  78. package/dist/search/file-watcher.js.map +1 -0
  79. package/dist/server.d.ts.map +1 -1
  80. package/dist/server.js +814 -472
  81. package/dist/server.js.map +1 -1
  82. package/dist/sessions/store.d.ts +9 -0
  83. package/dist/sessions/store.d.ts.map +1 -1
  84. package/dist/sessions/store.js.map +1 -1
  85. package/dist/settings.d.ts +26 -0
  86. package/dist/settings.d.ts.map +1 -1
  87. package/dist/settings.js +78 -2
  88. package/dist/settings.js.map +1 -1
  89. package/dist/tracing/init.d.ts +1 -1
  90. package/dist/tracing/init.d.ts.map +1 -1
  91. package/dist/utils/logger.js +2 -2
  92. package/dist/utils/logger.js.map +1 -1
  93. package/module-tiers.json +164 -0
  94. package/package.json +9 -13
  95. package/public/avatar/cache/1184385ec5522b57.mp4 +0 -0
  96. package/public/avatar/cache/1f15f6a1ebd7e439.mp4 +0 -0
  97. package/public/avatar/cache/2c7e47ff0bdeb8d1.mp4 +0 -0
  98. package/public/avatar/cache/5f308566f7abb8f2.mp4 +0 -0
  99. package/public/avatar/cache/62f9cfba848d724e.mp4 +0 -0
  100. package/public/avatar/cache/6d64e657e6bf2aab.mp4 +0 -0
  101. package/public/avatar/cache/763ad0349e0b6f26.mp4 +0 -0
  102. package/public/avatar/cache/81a516cfd461b2b9.mp4 +0 -0
  103. package/public/avatar/cache/9366de15fd6910ca.mp4 +0 -0
  104. package/public/avatar/cache/ade41a846b283895.mp4 +0 -0
  105. package/public/avatar/cache/b6066e5c65383eec.mp4 +0 -0
  106. package/public/avatar/cache/edadb75d37891fc7.mp4 +0 -0
  107. package/public/avatar/cache/f0ae159640621dd9.mp4 +0 -0
  108. package/public/avatar/cache/fc2e5419adf29d96.mp4 +0 -0
  109. package/public/index.html +379 -59
  110. package/dist/agents/autonomous.js +0 -749
  111. package/dist/agents/autonomous.js.map +0 -1
  112. package/dist/agents/commit.js +0 -113
  113. package/dist/agents/commit.js.map +0 -1
  114. package/dist/agents/continue.js +0 -158
  115. package/dist/agents/continue.js.map +0 -1
  116. package/dist/agents/cooldown.js +0 -397
  117. package/dist/agents/cooldown.js.map +0 -1
  118. package/dist/agents/dedup-guard.js +0 -131
  119. package/dist/agents/dedup-guard.js.map +0 -1
  120. package/dist/agents/feed.js +0 -176
  121. package/dist/agents/feed.js.map +0 -1
  122. package/dist/agents/governance.js +0 -292
  123. package/dist/agents/governance.js.map +0 -1
  124. package/dist/agents/governed-spawn.js +0 -192
  125. package/dist/agents/governed-spawn.js.map +0 -1
  126. package/dist/agents/heartbeat.js +0 -324
  127. package/dist/agents/heartbeat.js.map +0 -1
  128. package/dist/agents/instance-manager.js +0 -850
  129. package/dist/agents/instance-manager.js.map +0 -1
  130. package/dist/agents/issue-reporter.js +0 -123
  131. package/dist/agents/issue-reporter.js.map +0 -1
  132. package/dist/agents/issues.js +0 -141
  133. package/dist/agents/issues.js.map +0 -1
  134. package/dist/agents/locks.js +0 -234
  135. package/dist/agents/locks.js.map +0 -1
  136. package/dist/agents/memory.js +0 -93
  137. package/dist/agents/memory.js.map +0 -1
  138. package/dist/agents/monitor.js +0 -235
  139. package/dist/agents/monitor.js.map +0 -1
  140. package/dist/agents/orchestration.js +0 -715
  141. package/dist/agents/orchestration.js.map +0 -1
  142. package/dist/agents/recover.js +0 -166
  143. package/dist/agents/recover.js.map +0 -1
  144. package/dist/agents/reflection.js +0 -199
  145. package/dist/agents/reflection.js.map +0 -1
  146. package/dist/agents/runtime/bus.js +0 -174
  147. package/dist/agents/runtime/bus.js.map +0 -1
  148. package/dist/agents/runtime/config.js +0 -101
  149. package/dist/agents/runtime/config.js.map +0 -1
  150. package/dist/agents/runtime/driver.js +0 -214
  151. package/dist/agents/runtime/driver.js.map +0 -1
  152. package/dist/agents/runtime/errors.js +0 -40
  153. package/dist/agents/runtime/errors.js.map +0 -1
  154. package/dist/agents/runtime/index.js +0 -54
  155. package/dist/agents/runtime/index.js.map +0 -1
  156. package/dist/agents/runtime/lifecycle.js +0 -116
  157. package/dist/agents/runtime/lifecycle.js.map +0 -1
  158. package/dist/agents/runtime/manager.js +0 -948
  159. package/dist/agents/runtime/manager.js.map +0 -1
  160. package/dist/agents/runtime/registry.js +0 -195
  161. package/dist/agents/runtime/registry.js.map +0 -1
  162. package/dist/agents/runtime/resources.js +0 -146
  163. package/dist/agents/runtime/resources.js.map +0 -1
  164. package/dist/agents/runtime/types.js +0 -24
  165. package/dist/agents/runtime/types.js.map +0 -1
  166. package/dist/agents/spawn-policy.js +0 -202
  167. package/dist/agents/spawn-policy.js.map +0 -1
  168. package/dist/agents/spawn.js +0 -970
  169. package/dist/agents/spawn.js.map +0 -1
  170. package/dist/agents/triage.js +0 -81
  171. package/dist/agents/triage.js.map +0 -1
  172. package/dist/agents/workflow.js +0 -543
  173. package/dist/agents/workflow.js.map +0 -1
  174. package/dist/avatar/client.js +0 -172
  175. package/dist/avatar/client.js.map +0 -1
  176. package/dist/avatar/sidecar.js +0 -125
  177. package/dist/avatar/sidecar.js.map +0 -1
  178. package/dist/browser/sessions.js +0 -122
  179. package/dist/browser/sessions.js.map +0 -1
  180. package/dist/capabilities/definitions/browser.js +0 -242
  181. package/dist/capabilities/definitions/browser.js.map +0 -1
  182. package/dist/channels/whatsapp.js +0 -200
  183. package/dist/channels/whatsapp.js.map +0 -1
  184. package/dist/credentials/store.js +0 -189
  185. package/dist/credentials/store.js.map +0 -1
  186. package/dist/files/deep-index.js +0 -337
  187. package/dist/files/deep-index.js.map +0 -1
  188. package/dist/files/extract.js +0 -33
  189. package/dist/files/extract.js.map +0 -1
  190. package/dist/files/gdrive.js +0 -246
  191. package/dist/files/gdrive.js.map +0 -1
  192. package/dist/github/client.js +0 -408
  193. package/dist/github/client.js.map +0 -1
  194. package/dist/github/commit-analysis.js +0 -276
  195. package/dist/github/commit-analysis.js.map +0 -1
  196. package/dist/github/contributor-stats.js +0 -119
  197. package/dist/github/contributor-stats.js.map +0 -1
  198. package/dist/github/issue-sla.js +0 -220
  199. package/dist/github/issue-sla.js.map +0 -1
  200. package/dist/github/issue-triage.js +0 -286
  201. package/dist/github/issue-triage.js.map +0 -1
  202. package/dist/github/pr-readiness.js +0 -197
  203. package/dist/github/pr-readiness.js.map +0 -1
  204. package/dist/github/pr-review.js +0 -410
  205. package/dist/github/pr-review.js.map +0 -1
  206. package/dist/github/release-notes.js +0 -227
  207. package/dist/github/release-notes.js.map +0 -1
  208. package/dist/github/repo-health.js +0 -303
  209. package/dist/github/repo-health.js.map +0 -1
  210. package/dist/github/retry.js +0 -117
  211. package/dist/github/retry.js.map +0 -1
  212. package/dist/github/types.js +0 -8
  213. package/dist/github/types.js.map +0 -1
  214. package/dist/github/webhooks.js +0 -153
  215. package/dist/github/webhooks.js.map +0 -1
  216. package/dist/google/auth.js +0 -325
  217. package/dist/google/auth.js.map +0 -1
  218. package/dist/google/calendar-timer.js +0 -91
  219. package/dist/google/calendar-timer.js.map +0 -1
  220. package/dist/google/calendar.js +0 -270
  221. package/dist/google/calendar.js.map +0 -1
  222. package/dist/google/docs.js +0 -309
  223. package/dist/google/docs.js.map +0 -1
  224. package/dist/google/gmail-send.js +0 -219
  225. package/dist/google/gmail-send.js.map +0 -1
  226. package/dist/google/gmail-timer.js +0 -223
  227. package/dist/google/gmail-timer.js.map +0 -1
  228. package/dist/google/gmail.js +0 -470
  229. package/dist/google/gmail.js.map +0 -1
  230. package/dist/google/plugin.js +0 -169
  231. package/dist/google/plugin.js.map +0 -1
  232. package/dist/google/tasks-timer.js +0 -107
  233. package/dist/google/tasks-timer.js.map +0 -1
  234. package/dist/google/tasks.js +0 -331
  235. package/dist/google/tasks.js.map +0 -1
  236. package/dist/google/temporal.js +0 -176
  237. package/dist/google/temporal.js.map +0 -1
  238. package/dist/integrations/gate.js +0 -100
  239. package/dist/integrations/gate.js.map +0 -1
  240. package/dist/integrations/github.js +0 -331
  241. package/dist/integrations/github.js.map +0 -1
  242. package/dist/integrations/google-tasks.js +0 -432
  243. package/dist/integrations/google-tasks.js.map +0 -1
  244. package/dist/mdns.js +0 -110
  245. package/dist/mdns.js.map +0 -1
  246. package/dist/notifications/channel.js +0 -83
  247. package/dist/notifications/channel.js.map +0 -1
  248. package/dist/notifications/channels/adapter.js +0 -55
  249. package/dist/notifications/channels/adapter.js.map +0 -1
  250. package/dist/notifications/channels/index.js +0 -6
  251. package/dist/notifications/channels/index.js.map +0 -1
  252. package/dist/notifications/channels/log.js +0 -29
  253. package/dist/notifications/channels/log.js.map +0 -1
  254. package/dist/notifications/email.js +0 -72
  255. package/dist/notifications/email.js.map +0 -1
  256. package/dist/notifications/engine.js +0 -198
  257. package/dist/notifications/engine.js.map +0 -1
  258. package/dist/notifications/index.js +0 -24
  259. package/dist/notifications/index.js.map +0 -1
  260. package/dist/notifications/phone.js +0 -48
  261. package/dist/notifications/phone.js.map +0 -1
  262. package/dist/notifications/sms.js +0 -65
  263. package/dist/notifications/sms.js.map +0 -1
  264. package/dist/notifications/types.js +0 -14
  265. package/dist/notifications/types.js.map +0 -1
  266. package/dist/notifications/webhook.js +0 -65
  267. package/dist/notifications/webhook.js.map +0 -1
  268. package/dist/resend/inbox.js +0 -199
  269. package/dist/resend/inbox.js.map +0 -1
  270. package/dist/resend/webhooks.js +0 -244
  271. package/dist/resend/webhooks.js.map +0 -1
  272. package/dist/search/browse.js +0 -225
  273. package/dist/search/browse.js.map +0 -1
  274. package/dist/search/perplexity.js +0 -41
  275. package/dist/search/perplexity.js.map +0 -1
  276. package/dist/slack/channels.js +0 -277
  277. package/dist/slack/channels.js.map +0 -1
  278. package/dist/slack/client.js +0 -468
  279. package/dist/slack/client.js.map +0 -1
  280. package/dist/slack/retry.js +0 -100
  281. package/dist/slack/retry.js.map +0 -1
  282. package/dist/slack/types.js +0 -52
  283. package/dist/slack/types.js.map +0 -1
  284. package/dist/slack/webhooks.js +0 -285
  285. package/dist/slack/webhooks.js.map +0 -1
  286. package/dist/stt/client.js +0 -66
  287. package/dist/stt/client.js.map +0 -1
  288. package/dist/stt/sidecar.js +0 -115
  289. package/dist/stt/sidecar.js.map +0 -1
  290. package/dist/tracing/bridge.js +0 -70
  291. package/dist/tracing/bridge.js.map +0 -1
  292. package/dist/tracing/correlation.js +0 -49
  293. package/dist/tracing/correlation.js.map +0 -1
  294. package/dist/tracing/index.js +0 -18
  295. package/dist/tracing/index.js.map +0 -1
  296. package/dist/tracing/init.js +0 -81
  297. package/dist/tracing/init.js.map +0 -1
  298. package/dist/tracing/instrument.js +0 -145
  299. package/dist/tracing/instrument.js.map +0 -1
  300. package/dist/tracing/middleware.js +0 -69
  301. package/dist/tracing/middleware.js.map +0 -1
  302. package/dist/tracing/tracer.js +0 -327
  303. package/dist/tracing/tracer.js.map +0 -1
  304. package/dist/tts/client.js +0 -48
  305. package/dist/tts/client.js.map +0 -1
  306. package/dist/tts/sidecar.js +0 -148
  307. package/dist/tts/sidecar.js.map +0 -1
  308. package/dist/twilio/call.js +0 -79
  309. package/dist/twilio/call.js.map +0 -1
  310. package/dist/vault/matcher.js +0 -197
  311. package/dist/vault/matcher.js.map +0 -1
  312. package/dist/vault/personal.js +0 -163
  313. package/dist/vault/personal.js.map +0 -1
  314. package/dist/vault/policy.js +0 -159
  315. package/dist/vault/policy.js.map +0 -1
  316. package/dist/vault/store.js +0 -122
  317. package/dist/vault/store.js.map +0 -1
  318. package/dist/vault/transfer.js +0 -188
  319. package/dist/vault/transfer.js.map +0 -1
  320. package/dist/volumes/index.js +0 -2
  321. package/dist/volumes/index.js.map +0 -1
  322. package/dist/volumes/manager.js +0 -462
  323. package/dist/volumes/manager.js.map +0 -1
  324. package/dist/volumes/types.js +0 -8
  325. package/dist/volumes/types.js.map +0 -1
  326. package/dist/webhooks/config.js +0 -214
  327. package/dist/webhooks/config.js.map +0 -1
  328. package/dist/webhooks/event-log.js +0 -132
  329. package/dist/webhooks/event-log.js.map +0 -1
  330. package/dist/webhooks/handler.js +0 -103
  331. package/dist/webhooks/handler.js.map +0 -1
  332. package/dist/webhooks/handlers.js +0 -231
  333. package/dist/webhooks/handlers.js.map +0 -1
  334. package/dist/webhooks/index.js +0 -33
  335. package/dist/webhooks/index.js.map +0 -1
  336. package/dist/webhooks/mount.js +0 -400
  337. package/dist/webhooks/mount.js.map +0 -1
  338. package/dist/webhooks/registry.js +0 -143
  339. package/dist/webhooks/registry.js.map +0 -1
  340. package/dist/webhooks/relay.js +0 -53
  341. package/dist/webhooks/relay.js.map +0 -1
  342. package/dist/webhooks/retry.js +0 -270
  343. package/dist/webhooks/retry.js.map +0 -1
  344. package/dist/webhooks/router.js +0 -290
  345. package/dist/webhooks/router.js.map +0 -1
  346. package/dist/webhooks/twilio.js +0 -129
  347. package/dist/webhooks/twilio.js.map +0 -1
  348. package/dist/webhooks/types.js +0 -8
  349. package/dist/webhooks/types.js.map +0 -1
  350. package/dist/webhooks/verify.js +0 -154
  351. package/dist/webhooks/verify.js.map +0 -1
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Brain v2 migration — moves from 30+ top-level directories to 3:
3
+ * log/ ← append-only JSONL (memory, ops, metrics, ledger)
4
+ * files/ ← everything else (knowledge, identity, content, etc.)
5
+ * .config/ ← settings, access, locked paths
6
+ *
7
+ * Safe to run multiple times. Moves directories, doesn't copy.
8
+ * Creates symlinks from old paths to new locations for backward compat.
9
+ */
10
+ import { join } from "node:path";
11
+ import { rename, mkdir, cp, access } from "node:fs/promises";
12
+ import { BRAIN_DIR, LOG_DIR, FILES_DIR, CONFIG_DIR, isBrainV2 } from "./paths.js";
13
+ /** Directories that contain append-only JSONL data → move to log/ */
14
+ const TO_LOG = ["memory", "ops", "metrics", "ledger"];
15
+ /** Directories that contain searchable files → move to files/ */
16
+ const TO_FILES = [
17
+ "identity", "knowledge", "content", "operations", "skills",
18
+ "templates", "contacts", "calendar", "scheduling", "training",
19
+ "library", "dictionary", "browser", "registry", "channels",
20
+ "runtime", "calibration", "compliance", "membrane", "inference",
21
+ "db", "compost",
22
+ ];
23
+ /** Files/dirs that move to .config/ */
24
+ const TO_CONFIG = [
25
+ "settings.json", ".locked", ".access", ".core", ".ui",
26
+ "vault.policy.yaml",
27
+ ];
28
+ /** Directories that stay at top level (runtime state, not brain data) */
29
+ const STAYS = ["agents", "sessions", "vault", "volumes", "webhooks", "files"];
30
+ async function exists(path) {
31
+ try {
32
+ await access(path);
33
+ return true;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
39
+ async function moveIfExists(src, dest) {
40
+ if (!(await exists(src)))
41
+ return false;
42
+ if (await exists(dest)) {
43
+ // Dest already exists — merge by copying contents
44
+ try {
45
+ await cp(src, dest, { recursive: true, force: false, errorOnExist: false });
46
+ }
47
+ catch {
48
+ // If cp fails, skip — don't lose data
49
+ return false;
50
+ }
51
+ return true;
52
+ }
53
+ // Ensure parent exists
54
+ const parent = join(dest, "..");
55
+ await mkdir(parent, { recursive: true });
56
+ try {
57
+ await rename(src, dest);
58
+ return true;
59
+ }
60
+ catch {
61
+ // Cross-device rename — fall back to copy
62
+ try {
63
+ await cp(src, dest, { recursive: true });
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ }
71
+ /**
72
+ * Migrate a brain directory from legacy layout to v2.
73
+ * Safe to run multiple times — skips already-migrated items.
74
+ */
75
+ export async function migrateBrainToV2() {
76
+ const result = { migrated: [], skipped: [], errors: [], alreadyV2: false };
77
+ if (isBrainV2()) {
78
+ result.alreadyV2 = true;
79
+ return result;
80
+ }
81
+ // Create v2 directories
82
+ await mkdir(LOG_DIR, { recursive: true });
83
+ await mkdir(FILES_DIR, { recursive: true });
84
+ await mkdir(CONFIG_DIR, { recursive: true });
85
+ // Move log directories
86
+ for (const dir of TO_LOG) {
87
+ const src = join(BRAIN_DIR, dir);
88
+ const dest = join(LOG_DIR, dir);
89
+ try {
90
+ if (await moveIfExists(src, dest)) {
91
+ result.migrated.push(`${dir} → log/${dir}`);
92
+ }
93
+ else {
94
+ result.skipped.push(dir);
95
+ }
96
+ }
97
+ catch (err) {
98
+ result.errors.push(`${dir}: ${err instanceof Error ? err.message : String(err)}`);
99
+ }
100
+ }
101
+ // Move files directories
102
+ for (const dir of TO_FILES) {
103
+ const src = join(BRAIN_DIR, dir);
104
+ const dest = join(FILES_DIR, dir);
105
+ try {
106
+ if (await moveIfExists(src, dest)) {
107
+ result.migrated.push(`${dir} → files/${dir}`);
108
+ }
109
+ else {
110
+ result.skipped.push(dir);
111
+ }
112
+ }
113
+ catch (err) {
114
+ result.errors.push(`${dir}: ${err instanceof Error ? err.message : String(err)}`);
115
+ }
116
+ }
117
+ // Move config items
118
+ for (const item of TO_CONFIG) {
119
+ const src = join(BRAIN_DIR, item);
120
+ const dest = join(CONFIG_DIR, item);
121
+ try {
122
+ if (await moveIfExists(src, dest)) {
123
+ result.migrated.push(`${item} → .config/${item}`);
124
+ }
125
+ else {
126
+ result.skipped.push(item);
127
+ }
128
+ }
129
+ catch (err) {
130
+ result.errors.push(`${item}: ${err instanceof Error ? err.message : String(err)}`);
131
+ }
132
+ }
133
+ // Write a marker so isBrainV2() detects the migration
134
+ // (LOG_DIR existence is the marker — it was just created)
135
+ return result;
136
+ }
137
+ //# sourceMappingURL=brain-migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brain-migrate.js","sourceRoot":"","sources":["../../src/lib/brain-migrate.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,34 @@
5
5
  * Packages are code only, no data ever. The brain lives outside the package,
6
6
  * configured via CORE_BRAIN_DIR (or DASH_BRAIN_DIR) environment variable.
7
7
  * Default: process.cwd() + "brain" for backward compatibility.
8
+ *
9
+ * Brain structure (v2 — simplified):
10
+ * brain/
11
+ * log/ ← append-only JSONL. The trail. Never rewrite.
12
+ * files/ ← everything else. Searchable. Flat or shallow.
13
+ * .config/ ← settings, access policies, locked paths. Plumbing.
14
+ *
15
+ * Legacy paths (memory/, ops/, knowledge/, identity/, etc.) are resolved
16
+ * with fallback for backward compatibility during migration.
8
17
  */
9
18
  /** Absolute path to the brain data directory. */
10
19
  export declare const BRAIN_DIR: string;
20
+ /** Append-only JSONL — the audit trail, memory, activity, metrics. */
21
+ export declare const LOG_DIR: string;
22
+ /** Everything else — notes, research, identity, templates, contacts. Searchable. */
23
+ export declare const FILES_DIR: string;
24
+ /** Settings, access policies, locked paths. Plumbing. */
25
+ export declare const CONFIG_DIR: string;
26
+ /**
27
+ * Resolve a brain subdirectory, checking v2 structure first, falling back to legacy.
28
+ * Use this for any path that might exist under old OR new layout.
29
+ *
30
+ * Example: resolveBrainDir("memory") → brain/log (if migrated) or brain/memory (legacy)
31
+ */
32
+ export declare function resolveBrainDir(subdir: string): string;
33
+ /**
34
+ * Detect whether this brain uses v2 structure.
35
+ * True if brain/log/ exists. False means legacy layout.
36
+ */
37
+ export declare function isBrainV2(): boolean;
11
38
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,iDAAiD;AACjD,eAAO,MAAM,SAAS,EAAE,MAEvB,CAAC"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,iDAAiD;AACjD,eAAO,MAAM,SAAS,EAAE,MAEvB,CAAC;AAIF,sEAAsE;AACtE,eAAO,MAAM,OAAO,EAAE,MAA+B,CAAC;AAEtD,oFAAoF;AACpF,eAAO,MAAM,SAAS,EAAE,MAAiC,CAAC;AAE1D,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,MAAmC,CAAC;AAe7D;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAqBtD;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC"}
package/dist/lib/paths.js CHANGED
@@ -5,9 +5,74 @@
5
5
  * Packages are code only, no data ever. The brain lives outside the package,
6
6
  * configured via CORE_BRAIN_DIR (or DASH_BRAIN_DIR) environment variable.
7
7
  * Default: process.cwd() + "brain" for backward compatibility.
8
+ *
9
+ * Brain structure (v2 — simplified):
10
+ * brain/
11
+ * log/ ← append-only JSONL. The trail. Never rewrite.
12
+ * files/ ← everything else. Searchable. Flat or shallow.
13
+ * .config/ ← settings, access policies, locked paths. Plumbing.
14
+ *
15
+ * Legacy paths (memory/, ops/, knowledge/, identity/, etc.) are resolved
16
+ * with fallback for backward compatibility during migration.
8
17
  */
9
18
  import { resolve, join } from "node:path";
19
+ import { existsSync } from "node:fs";
10
20
  import { resolveEnv } from "../instance.js";
11
21
  /** Absolute path to the brain data directory. */
12
22
  export const BRAIN_DIR = resolve(resolveEnv("BRAIN_DIR") ?? join(process.cwd(), "brain"));
23
+ // ── v2 structure ──────────────────────────────────────────────────────────────
24
+ /** Append-only JSONL — the audit trail, memory, activity, metrics. */
25
+ export const LOG_DIR = join(BRAIN_DIR, "log");
26
+ /** Everything else — notes, research, identity, templates, contacts. Searchable. */
27
+ export const FILES_DIR = join(BRAIN_DIR, "files");
28
+ /** Settings, access policies, locked paths. Plumbing. */
29
+ export const CONFIG_DIR = join(BRAIN_DIR, ".config");
30
+ // ── Legacy path resolution ────────────────────────────────────────────────────
31
+ /** Map of legacy directory names to their v2 parent. */
32
+ const LEGACY_TO_LOG = ["memory", "ops", "metrics", "ledger"];
33
+ const LEGACY_TO_FILES = [
34
+ "identity", "knowledge", "content", "operations", "skills",
35
+ "templates", "contacts", "calendar", "scheduling", "training",
36
+ "agents", "library", "dictionary", "browser", "sessions",
37
+ "registry", "channels", "vault", "files", "runtime",
38
+ "calibration", "compliance", "membrane", "inference", "db",
39
+ "compost",
40
+ ];
41
+ /**
42
+ * Resolve a brain subdirectory, checking v2 structure first, falling back to legacy.
43
+ * Use this for any path that might exist under old OR new layout.
44
+ *
45
+ * Example: resolveBrainDir("memory") → brain/log (if migrated) or brain/memory (legacy)
46
+ */
47
+ export function resolveBrainDir(subdir) {
48
+ // Check v2 structure first
49
+ if (LEGACY_TO_LOG.includes(subdir)) {
50
+ const v2 = join(LOG_DIR, subdir);
51
+ if (existsSync(v2))
52
+ return v2;
53
+ // Fall back to legacy flat path
54
+ const legacy = join(BRAIN_DIR, subdir);
55
+ if (existsSync(legacy))
56
+ return legacy;
57
+ return v2; // default to v2 for new files
58
+ }
59
+ if (LEGACY_TO_FILES.includes(subdir)) {
60
+ const v2 = join(FILES_DIR, subdir);
61
+ if (existsSync(v2))
62
+ return v2;
63
+ const legacy = join(BRAIN_DIR, subdir);
64
+ if (existsSync(legacy))
65
+ return legacy;
66
+ return v2;
67
+ }
68
+ // Unknown subdir — check under brain/ directly
69
+ return join(BRAIN_DIR, subdir);
70
+ }
71
+ /**
72
+ * Detect whether this brain uses v2 structure.
73
+ * True if brain/log/ exists. False means legacy layout.
74
+ */
75
+ export function isBrainV2() {
76
+ return existsSync(LOG_DIR);
77
+ }
13
78
  //# sourceMappingURL=paths.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,iDAAiD;AACjD,MAAM,CAAC,MAAM,SAAS,GAAW,OAAO,CACtC,UAAU,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CACxD,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,iDAAiD;AACjD,MAAM,CAAC,MAAM,SAAS,GAAW,OAAO,CACtC,UAAU,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CACxD,CAAC;AAEF,iFAAiF;AAEjF,sEAAsE;AACtE,MAAM,CAAC,MAAM,OAAO,GAAW,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAEtD,oFAAoF;AACpF,MAAM,CAAC,MAAM,SAAS,GAAW,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAE1D,yDAAyD;AACzD,MAAM,CAAC,MAAM,UAAU,GAAW,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAE7D,iFAAiF;AAEjF,wDAAwD;AACxD,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAC;AACtE,MAAM,eAAe,GAAG;IACtB,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ;IAC1D,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU;IAC7D,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU;IACxD,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS;IACnD,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI;IAC1D,SAAS;CACD,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,2BAA2B;IAC3B,IAAK,aAAmC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1D,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,UAAU,CAAC,EAAE,CAAC;YAAE,OAAO,EAAE,CAAC;QAC9B,gCAAgC;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACvC,IAAI,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACtC,OAAO,EAAE,CAAC,CAAC,8BAA8B;IAC3C,CAAC;IAED,IAAK,eAAqC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACnC,IAAI,UAAU,CAAC,EAAE,CAAC;YAAE,OAAO,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACvC,IAAI,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,+CAA+C;IAC/C,OAAO,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * LLM call log — append-only JSONL receipt for every LLM call.
3
+ *
4
+ * Records the mechanical state of each call: which provider, which model,
5
+ * how it was resolved, how long it took. No prompts, no responses, no content.
6
+ * Just the state of the machine at the time of the turn.
7
+ *
8
+ * Writes to brain/memory/llm-calls.jsonl (data lives in brain, not code).
9
+ */
10
+ export interface LlmCallEntry {
11
+ /** ISO timestamp */
12
+ ts: string;
13
+ /** "stream" or "complete" */
14
+ mode: "stream" | "complete";
15
+ /** Provider that actually handled the call */
16
+ provider: string;
17
+ /** Model that was actually used */
18
+ model: string;
19
+ /** How the provider was resolved: "settings", "env", "taskRoute", "fallback", "privateMode" */
20
+ routeSource?: string;
21
+ /** Task type if routed via taskRoutes */
22
+ taskType?: string;
23
+ /** Agent ID if this call was made by a spawned agent */
24
+ agentId?: string;
25
+ /** Duration in ms */
26
+ durationMs: number;
27
+ /** Estimated input tokens (chars/4) */
28
+ inputTokens?: number;
29
+ /** Estimated output tokens (chars/4) */
30
+ outputTokens?: number;
31
+ /** Whether the call succeeded */
32
+ ok: boolean;
33
+ /** Error message on failure (no stack traces) */
34
+ error?: string;
35
+ }
36
+ /**
37
+ * Append a call receipt to the log. Fire-and-forget — never throws.
38
+ */
39
+ export declare function logLlmCall(entry: LlmCallEntry): Promise<void>;
40
+ //# sourceMappingURL=call-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-log.d.ts","sourceRoot":"","sources":["../../src/llm/call-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAYH,MAAM,WAAW,YAAY;IAC3B,oBAAoB;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,6BAA6B;IAC7B,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,+FAA+F;IAC/F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAanE"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * LLM call log — append-only JSONL receipt for every LLM call.
3
+ *
4
+ * Records the mechanical state of each call: which provider, which model,
5
+ * how it was resolved, how long it took. No prompts, no responses, no content.
6
+ * Just the state of the machine at the time of the turn.
7
+ *
8
+ * Writes to brain/memory/llm-calls.jsonl (data lives in brain, not code).
9
+ */
10
+ import { appendFile, mkdir } from "node:fs/promises";
11
+ import { join } from "node:path";
12
+ import { BRAIN_DIR } from "../lib/paths.js";
13
+ import { createLogger } from "../utils/logger.js";
14
+ const log = createLogger("llm.call-log");
15
+ const LOG_PATH = join(BRAIN_DIR, "memory", "llm-calls.jsonl");
16
+ let ensuredDir = false;
17
+ /**
18
+ * Append a call receipt to the log. Fire-and-forget — never throws.
19
+ */
20
+ export async function logLlmCall(entry) {
21
+ try {
22
+ if (!ensuredDir) {
23
+ await mkdir(join(BRAIN_DIR, "memory"), { recursive: true });
24
+ ensuredDir = true;
25
+ }
26
+ const line = JSON.stringify(entry) + "\n";
27
+ await appendFile(LOG_PATH, line, "utf-8");
28
+ }
29
+ catch (err) {
30
+ log.warn("Failed to write call log", {
31
+ error: err instanceof Error ? err.message : String(err),
32
+ });
33
+ }
34
+ }
35
+ //# sourceMappingURL=call-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-log.js","sourceRoot":"","sources":["../../src/llm/call-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;AAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAC9D,IAAI,UAAU,GAAG,KAAK,CAAC;AA6BvB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAmB;IAClD,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QAC1C,MAAM,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE;YACnC,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -14,6 +14,12 @@ export interface CompleteChatOptions {
14
14
  noCache?: boolean;
15
15
  /** Override default TTL for this request (ms). */
16
16
  cacheTTLMs?: number;
17
+ /** How the provider/model was resolved (for call log). */
18
+ routeSource?: string;
19
+ /** Task type if routed via taskRoutes (for call log). */
20
+ taskType?: string;
21
+ /** Agent ID if called by a spawned agent (for call log). */
22
+ agentId?: string;
17
23
  }
18
24
  /**
19
25
  * Non-streaming chat completion. Returns the full assistant response as a string.
@@ -1 +1 @@
1
- {"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../src/llm/complete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAWzD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF"}
1
+ {"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../src/llm/complete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAYzD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF"}
@@ -11,6 +11,7 @@ import { withRetry } from "./retry.js";
11
11
  import { rehydrateResponse } from "./redact.js";
12
12
  import { createLogger } from "../utils/logger.js";
13
13
  import { recordLlmRequest } from "../metrics/collector.js";
14
+ import { logLlmCall } from "./call-log.js";
14
15
  const log = createLogger("llm");
15
16
  /**
16
17
  * Non-streaming chat completion. Returns the full assistant response as a string.
@@ -57,6 +58,12 @@ async function completeChatUncached(options) {
57
58
  const durationMs = Math.round(performance.now() - startMs);
58
59
  const outputTokens = Math.ceil(result.length / 4);
59
60
  recordLlmRequest(options.provider, model, durationMs, inputTokens, outputTokens, true);
61
+ logLlmCall({
62
+ ts: new Date().toISOString(), mode: "complete",
63
+ provider: options.provider, model,
64
+ routeSource: options.routeSource, taskType: options.taskType, agentId: options.agentId,
65
+ durationMs, inputTokens, outputTokens, ok: true,
66
+ });
60
67
  return result;
61
68
  }
62
69
  catch (err) {
@@ -81,11 +88,31 @@ async function completeChatUncached(options) {
81
88
  // Also record the original provider's failure
82
89
  const failDurationMs = Math.round(fallbackStartMs - startMs);
83
90
  recordLlmRequest(options.provider, model, failDurationMs, inputTokens, 0, false);
91
+ // Log both: the failed cloud call and the successful fallback
92
+ logLlmCall({
93
+ ts: new Date().toISOString(), mode: "complete",
94
+ provider: options.provider, model,
95
+ routeSource: options.routeSource, taskType: options.taskType, agentId: options.agentId,
96
+ durationMs: failDurationMs, inputTokens, ok: false, error: "credits_exhausted",
97
+ });
98
+ logLlmCall({
99
+ ts: new Date().toISOString(), mode: "complete",
100
+ provider: "ollama", model: ollama.defaultUtilityModel,
101
+ routeSource: "fallback", taskType: options.taskType, agentId: options.agentId,
102
+ durationMs: fallbackDurationMs, inputTokens, outputTokens: fallbackOutputTokens, ok: true,
103
+ });
84
104
  return fallbackResult;
85
105
  }
86
106
  }
87
107
  const durationMs = Math.round(performance.now() - startMs);
88
108
  recordLlmRequest(options.provider, model, durationMs, inputTokens, 0, false);
109
+ logLlmCall({
110
+ ts: new Date().toISOString(), mode: "complete",
111
+ provider: options.provider, model,
112
+ routeSource: options.routeSource, taskType: options.taskType, agentId: options.agentId,
113
+ durationMs, inputTokens, ok: false,
114
+ error: err instanceof Error ? err.message : String(err),
115
+ });
89
116
  throw err;
90
117
  }
91
118
  }
@@ -1 +1 @@
1
- {"version":3,"file":"complete.js","sourceRoot":"","sources":["../../src/llm/complete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;AAYhC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC1D,OAAO,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/E,CAAC;AAED,qFAAqF;AACrF,SAAS,cAAc,CAAC,QAA0B;IAChD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;YAAE,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;aACxD,CAAC;YACJ,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC9B,IAAI,MAAM,IAAI,KAAK;oBAAE,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,oBAAoB,CAAC,OAA4B;IAC9D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,mBAAmB,CAAC;IAE5D,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE;QAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,KAAK;QACZ,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;KACtC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,CACzB,GAAG,EAAE;YACH,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC5C,OAAO,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACzE,CAAC,EACD,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAC1D,CAAC;QACF,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClD,gBAAgB,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;QACvF,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,0EAA0E;QAC1E,IAAI,GAAG,YAAY,QAAQ,IAAI,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACnF,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;YACnD,IAAI,eAAe,EAAE,CAAC;gBACpB,GAAG,CAAC,IAAI,CAAC,0DAA0D,EAAE;oBACnE,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,MAAM,EAAE,GAAG,CAAC,UAAU;iBACvB,CAAC,CAAC;gBACH,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;gBAC1C,MAAM,WAAW,GAAG,MAAM,SAAS,CACjC,GAAG,EAAE;oBACH,MAAM,eAAe,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;oBACrD,OAAO,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;gBAC3E,CAAC,EACD,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAC1D,CAAC;gBACF,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;gBACtD,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,eAAe,CAAC,CAAC;gBAC3E,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAClE,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,IAAI,CAAC,CAAC;gBACpH,8CAA8C;gBAC9C,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,OAAO,CAAC,CAAC;gBAC7D,gBAAgB,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;gBACjF,OAAO,cAAc,CAAC;YACxB,CAAC;QACH,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC;QAC3D,gBAAgB,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC7E,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"complete.js","sourceRoot":"","sources":["../../src/llm/complete.ts"],"names":[],"mappings":"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"}
@@ -24,9 +24,10 @@ import { sendAlert } from "./alert.js";
24
24
  import { Crystallizer, scoreEntry } from "./crystallizer.js";
25
25
  import { createCredentialStore } from "./credentials/store.js";
26
26
  import { readSessionKey, isDpapiAvailable } from "./lib/dpapi.js";
27
+ import { BrainRAG } from "./search/brain-rag.js";
27
28
  // ── Helpers ──────────────────────────────────────────────────────────────────
28
- import { BRAIN_DIR } from "./lib/paths.js";
29
- const MEMORY_DIR = join(BRAIN_DIR, "memory");
29
+ import { BRAIN_DIR, resolveBrainDir } from "./lib/paths.js";
30
+ const MEMORY_DIR = resolveBrainDir("memory");
30
31
  /** Log to stderr so stdout stays clean for MCP protocol. */
31
32
  function log(msg) {
32
33
  process.stderr.write(`[core-brain-mcp] ${msg}\n`);
@@ -108,6 +109,16 @@ async function main() {
108
109
  });
109
110
  await crystallizer.init();
110
111
  log(`Open loops loaded: ${crystallizer.list("open").length} active`);
112
+ // 6b. Initialize Brain RAG (semantic file search)
113
+ const mcpRag = new BrainRAG();
114
+ await mcpRag.load(); // Load existing embeddings (fast, no Ollama needed)
115
+ log(`Brain RAG loaded: ${mcpRag.ready ? "ready" : "empty"}`);
116
+ // Background index — catch up on any changed files
117
+ mcpRag.indexAll().then((r) => {
118
+ log(`Brain RAG index: ${r.indexed} indexed, ${r.skipped} skipped, ${r.errors} errors`);
119
+ }).catch((err) => {
120
+ log(`Brain RAG index failed: ${err instanceof Error ? err.message : String(err)}`);
121
+ });
111
122
  // 6. Create MCP server
112
123
  const mcp = new McpServer({
113
124
  name: "core-brain",
@@ -259,6 +270,111 @@ async function main() {
259
270
  };
260
271
  }
261
272
  }));
273
+ mcp.tool("files_search", "Search brain files (notes, research, identity, templates, protocols — everything except logs) by keyword. Returns matching filenames with context snippets.", {
274
+ query: z.string().min(1).max(500).describe("Search query — keywords to find in brain files"),
275
+ max: z.number().int().min(1).max(20).optional().describe("Max results (default 10)"),
276
+ }, async ({ query, max }) => runWithAuditContext({ caller: "mcp:files_search", channel: "mcp" }, async () => {
277
+ const maxResults = max ?? 10;
278
+ const terms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 1);
279
+ if (terms.length === 0) {
280
+ return { content: [{ type: "text", text: "No search terms provided." }] };
281
+ }
282
+ // Scan all non-log directories for readable files (md, yaml, yml, json, txt)
283
+ const searchExts = new Set([".md", ".yaml", ".yml", ".json", ".txt", ".jsonl"]);
284
+ const skipDirs = new Set(["log", ".config", "ops", "metrics", ".obsidian", ".git", "node_modules"]);
285
+ const hits = [];
286
+ async function scanDir(dir, rel) {
287
+ let entries;
288
+ try {
289
+ entries = await readdir(dir);
290
+ }
291
+ catch {
292
+ return;
293
+ }
294
+ for (const name of entries) {
295
+ if (name.startsWith(".") && rel === "") {
296
+ // Skip hidden dirs at top level except .config
297
+ if (skipDirs.has(name))
298
+ continue;
299
+ }
300
+ if (skipDirs.has(name))
301
+ continue;
302
+ const full = join(dir, name);
303
+ const childRel = rel ? `${rel}/${name}` : name;
304
+ try {
305
+ const s = await stat(full);
306
+ if (s.isDirectory()) {
307
+ // Don't recurse into JSONL-heavy log dirs
308
+ if (name === "memory" || name === "logs" || name === "tasks" || name === "daily" || name === "hourly")
309
+ continue;
310
+ await scanDir(full, childRel);
311
+ }
312
+ else {
313
+ const ext = name.substring(name.lastIndexOf(".")).toLowerCase();
314
+ if (!searchExts.has(ext))
315
+ continue;
316
+ if (isLocked(childRel))
317
+ continue;
318
+ // Skip large JSONL files (those are log data, not knowledge)
319
+ if (ext === ".jsonl" && s.size > 100_000)
320
+ continue;
321
+ const content = await readBrainFile(full);
322
+ const lower = content.toLowerCase();
323
+ let score = 0;
324
+ for (const term of terms) {
325
+ const idx = lower.indexOf(term);
326
+ if (idx !== -1) {
327
+ score++;
328
+ // Bonus for title/filename match
329
+ if (name.toLowerCase().includes(term))
330
+ score += 2;
331
+ }
332
+ // Match against full relative path (catches parent directory names)
333
+ if (childRel.toLowerCase().includes(term))
334
+ score += 2;
335
+ }
336
+ if (score > 0) {
337
+ // Extract a snippet around the first match
338
+ const firstTerm = terms.find((t) => lower.includes(t));
339
+ const matchIdx = lower.indexOf(firstTerm);
340
+ const start = Math.max(0, matchIdx - 80);
341
+ const end = Math.min(content.length, matchIdx + 120);
342
+ const snippet = (start > 0 ? "..." : "") +
343
+ content.substring(start, end).replace(/\n/g, " ").trim() +
344
+ (end < content.length ? "..." : "");
345
+ hits.push({ relPath: childRel, score, snippet });
346
+ }
347
+ }
348
+ }
349
+ catch {
350
+ continue;
351
+ }
352
+ }
353
+ }
354
+ await scanDir(BRAIN_DIR, "");
355
+ // If keyword search found nothing, try semantic search via RAG
356
+ if (hits.length === 0 && mcpRag?.ready) {
357
+ try {
358
+ const ragResults = await mcpRag.query(query, maxResults);
359
+ if (ragResults.length > 0) {
360
+ const result = ragResults.map((r) => `📄 ${r.filePath} (semantic score: ${r.score.toFixed(3)}, section: ${r.heading})${r.siblings ? `\n Also in directory: ${r.siblings.join(", ")}` : ""}`).join("\n\n");
361
+ return {
362
+ content: [{ type: "text", text: `Keyword search found nothing. Semantic search found ${ragResults.length} file(s):\n\n${result}` }],
363
+ };
364
+ }
365
+ }
366
+ catch { /* semantic search failed — fall through */ }
367
+ }
368
+ if (hits.length === 0) {
369
+ return { content: [{ type: "text", text: `No files matched: "${query}"` }] };
370
+ }
371
+ hits.sort((a, b) => b.score - a.score);
372
+ const top = hits.slice(0, maxResults);
373
+ const result = top.map((h) => `📄 ${h.relPath} (score: ${h.score})\n ${h.snippet}`).join("\n\n");
374
+ return {
375
+ content: [{ type: "text", text: `Found ${hits.length} file(s) matching "${query}":\n\n${result}` }],
376
+ };
377
+ }));
262
378
  mcp.tool("get_settings", "Return safe subset of Core settings (no keys or secrets)", {}, async () => {
263
379
  const s = getSettings();
264
380
  const safe = {