talon-agent 1.12.0 → 1.34.0

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 (451) hide show
  1. package/README.md +111 -52
  2. package/package.json +39 -12
  3. package/prompts/README.md +112 -0
  4. package/prompts/base.md +12 -12
  5. package/prompts/discord.md +10 -47
  6. package/prompts/heartbeat.md +23 -8
  7. package/prompts/identity.md +12 -22
  8. package/prompts/native.md +23 -0
  9. package/prompts/system/contract-text-or-tools.md +8 -0
  10. package/prompts/system/contract-text-preferred.md +5 -0
  11. package/prompts/system/contract-tool-only.md +10 -0
  12. package/prompts/system/cron.md +3 -0
  13. package/prompts/system/daily-memory.md +3 -0
  14. package/prompts/system/goals.md +7 -0
  15. package/prompts/system/heartbeat-agent.md +44 -0
  16. package/prompts/system/persistent-memory.md +8 -0
  17. package/prompts/system/skills.md +9 -0
  18. package/prompts/system/triggers.md +5 -0
  19. package/prompts/system/workspace.md +9 -0
  20. package/prompts/teams.md +4 -14
  21. package/prompts/telegram.md +17 -89
  22. package/src/app.ts +278 -0
  23. package/src/backend/claude-sdk/constants.ts +22 -10
  24. package/src/backend/claude-sdk/factory.ts +79 -22
  25. package/src/backend/claude-sdk/handler.ts +431 -160
  26. package/src/backend/claude-sdk/index.ts +6 -2
  27. package/src/backend/claude-sdk/mcp-ready.ts +54 -0
  28. package/src/backend/claude-sdk/model-drift.ts +65 -0
  29. package/src/backend/claude-sdk/model-provider.ts +12 -6
  30. package/src/backend/claude-sdk/models/convert.ts +169 -0
  31. package/src/backend/claude-sdk/models/discovery.ts +203 -0
  32. package/src/backend/claude-sdk/models/index.ts +18 -0
  33. package/src/backend/claude-sdk/models/parsing.ts +264 -0
  34. package/src/backend/claude-sdk/models/static.ts +45 -0
  35. package/src/backend/claude-sdk/one-shot.ts +19 -13
  36. package/src/backend/claude-sdk/options.ts +228 -104
  37. package/src/backend/claude-sdk/state.ts +1 -1
  38. package/src/backend/claude-sdk/stream.ts +153 -45
  39. package/src/backend/claude-sdk/warm.ts +12 -5
  40. package/src/backend/codex/auth.ts +216 -40
  41. package/src/backend/codex/constants.ts +63 -22
  42. package/src/backend/codex/discovery.ts +427 -0
  43. package/src/backend/codex/factory.ts +63 -33
  44. package/src/backend/codex/handler/events.ts +239 -0
  45. package/src/backend/codex/handler/index.ts +15 -0
  46. package/src/backend/codex/handler/message.ts +669 -0
  47. package/src/backend/codex/handler/state.ts +14 -0
  48. package/src/backend/codex/handler/usage.ts +68 -0
  49. package/src/backend/codex/index.ts +2 -2
  50. package/src/backend/codex/init.ts +92 -11
  51. package/src/backend/codex/mcp-config.ts +89 -62
  52. package/src/backend/codex/models.ts +305 -54
  53. package/src/backend/codex/oauth-incompat.ts +302 -0
  54. package/src/backend/codex/one-shot.ts +91 -8
  55. package/src/backend/codex/state.ts +54 -3
  56. package/src/backend/codex/token-usage.ts +434 -0
  57. package/src/backend/kilo/factory.ts +60 -35
  58. package/src/backend/kilo/handler/index.ts +13 -0
  59. package/src/backend/kilo/handler/message.ts +317 -0
  60. package/src/backend/kilo/handler/state.ts +14 -0
  61. package/src/backend/kilo/handler/turn.ts +321 -0
  62. package/src/backend/kilo/index.ts +5 -5
  63. package/src/backend/kilo/model-provider.ts +26 -168
  64. package/src/backend/kilo/models/index.ts +52 -0
  65. package/src/backend/kilo/one-shot.ts +20 -142
  66. package/src/backend/kilo/server.ts +14 -21
  67. package/src/backend/openai-agents/builtins.ts +215 -114
  68. package/src/backend/openai-agents/constants.ts +41 -15
  69. package/src/backend/openai-agents/discovery.ts +332 -0
  70. package/src/backend/openai-agents/factory.ts +66 -28
  71. package/src/backend/openai-agents/handler/events.ts +170 -0
  72. package/src/backend/openai-agents/handler/index.ts +13 -0
  73. package/src/backend/openai-agents/handler/message.ts +527 -0
  74. package/src/backend/openai-agents/handler/state.ts +13 -0
  75. package/src/backend/openai-agents/index.ts +22 -4
  76. package/src/backend/openai-agents/init.ts +51 -88
  77. package/src/backend/openai-agents/mcp-pool.ts +252 -0
  78. package/src/backend/openai-agents/models.ts +118 -11
  79. package/src/backend/openai-agents/session.ts +277 -0
  80. package/src/backend/openai-agents/state.ts +82 -11
  81. package/src/backend/opencode/factory.ts +54 -25
  82. package/src/backend/opencode/handler/index.ts +13 -0
  83. package/src/backend/opencode/handler/message.ts +325 -0
  84. package/src/backend/opencode/handler/state.ts +14 -0
  85. package/src/backend/opencode/handler/turn.ts +304 -0
  86. package/src/backend/opencode/index.ts +2 -2
  87. package/src/backend/opencode/model-provider.ts +26 -168
  88. package/src/backend/opencode/models/index.ts +51 -0
  89. package/src/backend/opencode/one-shot.ts +20 -137
  90. package/src/backend/opencode/server.ts +12 -11
  91. package/src/backend/remote-server/client.ts +13 -6
  92. package/src/backend/remote-server/events.ts +59 -9
  93. package/src/backend/remote-server/lifecycle.ts +3 -1
  94. package/src/backend/remote-server/mcp.ts +52 -19
  95. package/src/backend/remote-server/model-catalog/catalog.ts +270 -0
  96. package/src/backend/remote-server/model-catalog/index.ts +100 -0
  97. package/src/backend/remote-server/model-catalog/presentation.ts +298 -0
  98. package/src/backend/remote-server/model-catalog/provider.ts +193 -0
  99. package/src/backend/remote-server/model-catalog/resolve.ts +225 -0
  100. package/src/backend/remote-server/model-catalog/types.ts +136 -0
  101. package/src/backend/remote-server/one-shot.ts +225 -0
  102. package/src/backend/remote-server/session-helpers.ts +3 -4
  103. package/src/backend/remote-server/state.ts +1 -1
  104. package/src/backend/shared/delivery-contract.ts +161 -0
  105. package/src/backend/shared/delivery.ts +49 -0
  106. package/src/backend/shared/flow-violation.ts +38 -7
  107. package/src/backend/shared/frontends.ts +66 -0
  108. package/src/backend/shared/handle-retry.ts +244 -0
  109. package/src/backend/shared/handler-to-events.ts +186 -0
  110. package/src/backend/shared/handler-types.ts +57 -0
  111. package/src/backend/shared/index.ts +51 -5
  112. package/src/backend/shared/metrics.ts +199 -0
  113. package/src/backend/shared/model-retry.ts +1 -1
  114. package/src/backend/shared/prompt-format.ts +69 -0
  115. package/src/backend/shared/session-name.ts +1 -1
  116. package/src/backend/shared/stream-state.ts +36 -2
  117. package/src/backend/shared/system-prompt.ts +200 -23
  118. package/src/bootstrap.ts +338 -38
  119. package/src/cli/chat.ts +49 -0
  120. package/src/cli/config-view.ts +100 -0
  121. package/src/cli/config.ts +105 -0
  122. package/src/cli/context.ts +23 -0
  123. package/src/cli/daemon.ts +95 -0
  124. package/src/cli/doctor.ts +53 -0
  125. package/src/cli/index.ts +139 -0
  126. package/src/cli/logs.ts +60 -0
  127. package/src/cli/menu.ts +104 -0
  128. package/src/cli/setup.ts +455 -0
  129. package/src/cli/status.ts +75 -0
  130. package/src/cli.ts +20 -1211
  131. package/src/core/agent-runtime/README.md +173 -0
  132. package/src/{backend/registry.ts → core/agent-runtime/backend-registry.ts} +15 -6
  133. package/src/core/agent-runtime/capabilities.ts +330 -0
  134. package/src/core/agent-runtime/contract-tests.ts +378 -0
  135. package/src/core/agent-runtime/events.ts +291 -0
  136. package/src/core/agent-runtime/index.ts +62 -0
  137. package/src/core/agent-runtime/model-ref.ts +130 -0
  138. package/src/core/background/cron.ts +469 -0
  139. package/src/core/{dream.ts → background/dream.ts} +118 -53
  140. package/src/core/background/heartbeat/agent.ts +333 -0
  141. package/src/core/background/heartbeat/index.ts +25 -0
  142. package/src/core/background/heartbeat/scheduler.ts +211 -0
  143. package/src/core/background/heartbeat/state.ts +153 -0
  144. package/src/core/background/index.ts +21 -0
  145. package/src/core/background/isolated-agent.ts +115 -0
  146. package/src/core/background/job-health.ts +140 -0
  147. package/src/core/background/job-oneshot.ts +165 -0
  148. package/src/core/background/job-prompt.ts +54 -0
  149. package/src/core/{pulse.ts → background/pulse.ts} +6 -5
  150. package/src/core/background/triggers/command.ts +60 -0
  151. package/src/core/background/triggers/exit.ts +202 -0
  152. package/src/core/background/triggers/index.ts +38 -0
  153. package/src/core/background/triggers/output.ts +142 -0
  154. package/src/core/background/triggers/resume.ts +127 -0
  155. package/src/core/background/triggers/spawn.ts +282 -0
  156. package/src/core/background/triggers/state.ts +52 -0
  157. package/src/core/constants.ts +57 -28
  158. package/src/core/daemon/control.ts +229 -0
  159. package/src/core/daemon/discovery.ts +169 -0
  160. package/src/core/daemon/pidfile.ts +98 -0
  161. package/src/core/doctor.ts +459 -0
  162. package/src/core/engine/backend-controller/holders.ts +17 -0
  163. package/src/core/engine/backend-controller/index.ts +71 -0
  164. package/src/core/engine/backend-controller/legacy.ts +111 -0
  165. package/src/core/engine/backend-controller/pool.ts +296 -0
  166. package/src/core/engine/backend-controller/rebind.ts +205 -0
  167. package/src/core/engine/backend-controller/state.ts +150 -0
  168. package/src/core/engine/backend-controller/types.ts +51 -0
  169. package/src/core/engine/dispatcher.ts +68 -0
  170. package/src/core/engine/gateway-actions/cron.ts +518 -0
  171. package/src/core/engine/gateway-actions/fetch-url.ts +120 -0
  172. package/src/core/engine/gateway-actions/goals.ts +178 -0
  173. package/src/core/engine/gateway-actions/history.ts +53 -0
  174. package/src/core/engine/gateway-actions/index.ts +60 -0
  175. package/src/core/engine/gateway-actions/models.ts +120 -0
  176. package/src/core/engine/gateway-actions/plugins.ts +83 -0
  177. package/src/core/engine/gateway-actions/scripts.ts +127 -0
  178. package/src/core/engine/gateway-actions/shared.ts +66 -0
  179. package/src/core/engine/gateway-actions/skills.ts +120 -0
  180. package/src/core/engine/gateway-actions/triggers.ts +237 -0
  181. package/src/core/engine/gateway-actions/types.ts +18 -0
  182. package/src/core/{gateway.ts → engine/gateway.ts} +223 -60
  183. package/src/core/engine/index.ts +20 -0
  184. package/src/core/engine/model-audit.ts +121 -0
  185. package/src/core/errors.ts +68 -6
  186. package/src/core/mcp-hub/children.ts +254 -0
  187. package/src/core/mcp-hub/index.ts +335 -0
  188. package/src/core/mcp-hub/proxy-server.ts +45 -0
  189. package/src/core/mcp-hub/talon-server.ts +71 -0
  190. package/src/core/memory/retrieval.ts +90 -0
  191. package/src/core/models/active-model.ts +441 -0
  192. package/src/core/{models.ts → models/catalog.ts} +6 -0
  193. package/src/core/models/index.ts +17 -0
  194. package/src/core/models/reasoning-levels.ts +57 -0
  195. package/src/core/plugin/actions.ts +32 -0
  196. package/src/core/plugin/builtins.ts +162 -0
  197. package/src/core/plugin/index.ts +37 -0
  198. package/src/core/plugin/loader.ts +289 -0
  199. package/src/core/plugin/mcp.ts +86 -0
  200. package/src/core/plugin/registry.ts +124 -0
  201. package/src/core/plugin/types.ts +126 -0
  202. package/src/core/prompt/assemble.ts +273 -0
  203. package/src/core/prompt/disk-prompts.ts +41 -0
  204. package/src/core/prompt/embed.ts +107 -0
  205. package/src/core/prompt/embedded-prompts.ts +85 -0
  206. package/src/core/prompt/index.ts +30 -0
  207. package/src/core/prompt/templates.ts +124 -0
  208. package/src/core/prompt/workspace-listing.ts +91 -0
  209. package/src/core/scripting/lua-runner.ts +210 -0
  210. package/src/core/scripts/runner.ts +125 -0
  211. package/src/core/soul/README.md +110 -0
  212. package/src/core/soul/RESEARCH.md +98 -0
  213. package/src/core/soul/associative.ts +98 -0
  214. package/src/core/soul/centrality.ts +98 -0
  215. package/src/core/soul/cluster.ts +83 -0
  216. package/src/core/soul/compiler.ts +207 -0
  217. package/src/core/soul/consolidate.ts +179 -0
  218. package/src/core/soul/critic.ts +159 -0
  219. package/src/core/soul/dag.ts +265 -0
  220. package/src/core/soul/delta.ts +123 -0
  221. package/src/core/soul/drift.ts +99 -0
  222. package/src/core/soul/embedder.ts +129 -0
  223. package/src/core/soul/emergent-critic.ts +96 -0
  224. package/src/core/soul/forgetting.ts +131 -0
  225. package/src/core/soul/governance.ts +93 -0
  226. package/src/core/soul/hash.ts +97 -0
  227. package/src/core/soul/hdc.ts +154 -0
  228. package/src/core/soul/index.ts +140 -0
  229. package/src/core/soul/kernel.ts +540 -0
  230. package/src/core/soul/lattice.ts +103 -0
  231. package/src/core/soul/lens.ts +110 -0
  232. package/src/core/soul/projector.ts +240 -0
  233. package/src/core/soul/reflect.ts +170 -0
  234. package/src/core/soul/reflex.ts +164 -0
  235. package/src/core/soul/retrieve.ts +146 -0
  236. package/src/core/soul/salience.ts +142 -0
  237. package/src/core/soul/service.ts +204 -0
  238. package/src/core/soul/settings.ts +47 -0
  239. package/src/core/soul/signals.ts +117 -0
  240. package/src/core/soul/talon-embedder.ts +80 -0
  241. package/src/core/soul/taps.ts +199 -0
  242. package/src/core/soul/types.ts +298 -0
  243. package/src/core/soul/valence.ts +83 -0
  244. package/src/core/tools/goals.ts +117 -0
  245. package/src/core/tools/index.ts +10 -0
  246. package/src/core/tools/mcp-env.ts +94 -0
  247. package/src/core/tools/mcp-server.ts +27 -4
  248. package/src/core/tools/messaging.ts +122 -29
  249. package/src/core/tools/models.ts +39 -0
  250. package/src/core/tools/scheduling.ts +133 -14
  251. package/src/core/tools/schemas.ts +16 -4
  252. package/src/core/tools/scripts.ts +78 -0
  253. package/src/core/tools/skills.ts +90 -0
  254. package/src/core/tools/stickers.ts +1 -1
  255. package/src/core/tools/triggers.ts +19 -3
  256. package/src/core/tools/types.ts +6 -6
  257. package/src/core/types.ts +62 -112
  258. package/src/core/update/self-update.ts +269 -0
  259. package/src/core/weaver/index.ts +10 -0
  260. package/src/core/weaver/loom.ts +125 -0
  261. package/src/core/weaver/thread-session.ts +51 -0
  262. package/src/core/weaver/thread.ts +196 -0
  263. package/src/core/weaver/weaver.ts +357 -0
  264. package/src/frontend/discord/actions/chat-info.ts +268 -0
  265. package/src/frontend/discord/actions/index.ts +77 -0
  266. package/src/frontend/discord/actions/media.ts +190 -0
  267. package/src/frontend/discord/actions/messaging.ts +277 -0
  268. package/src/frontend/discord/actions/shared.ts +100 -0
  269. package/src/frontend/discord/actions/types.ts +33 -0
  270. package/src/frontend/discord/admin.ts +13 -23
  271. package/src/frontend/discord/callbacks/autocomplete.ts +55 -0
  272. package/src/frontend/discord/{callbacks.ts → callbacks/components.ts} +150 -190
  273. package/src/frontend/discord/callbacks/index.ts +14 -0
  274. package/src/frontend/discord/callbacks/modals.ts +76 -0
  275. package/src/frontend/discord/callbacks/shared.ts +22 -0
  276. package/src/frontend/discord/commands/admin.ts +88 -0
  277. package/src/frontend/discord/commands/definitions.ts +200 -0
  278. package/src/frontend/discord/commands/index.ts +19 -0
  279. package/src/frontend/discord/commands/info.ts +106 -0
  280. package/src/frontend/discord/commands/router.ts +149 -0
  281. package/src/frontend/discord/commands/session.ts +89 -0
  282. package/src/frontend/discord/commands/settings.ts +405 -0
  283. package/src/frontend/discord/commands/shared.ts +50 -0
  284. package/src/frontend/discord/formatting.ts +8 -34
  285. package/src/frontend/discord/handlers/access.ts +248 -0
  286. package/src/frontend/discord/handlers/context.ts +161 -0
  287. package/src/frontend/discord/handlers/delivery.ts +94 -0
  288. package/src/frontend/discord/handlers/index.ts +34 -0
  289. package/src/frontend/discord/handlers/messages.ts +120 -0
  290. package/src/frontend/discord/handlers/queue.ts +135 -0
  291. package/src/frontend/discord/handlers/registry.ts +29 -0
  292. package/src/frontend/discord/handlers/state.ts +94 -0
  293. package/src/frontend/discord/helpers.ts +46 -57
  294. package/src/frontend/discord/index.ts +10 -7
  295. package/src/frontend/discord/middleware.ts +2 -2
  296. package/src/frontend/native/actions.ts +133 -0
  297. package/src/frontend/native/chats.ts +146 -0
  298. package/src/frontend/native/discovery.ts +50 -0
  299. package/src/frontend/native/index.ts +1227 -0
  300. package/src/frontend/native/logs.ts +95 -0
  301. package/src/frontend/native/protocol.ts +253 -0
  302. package/src/frontend/native/server.ts +612 -0
  303. package/src/frontend/native/settings.ts +205 -0
  304. package/src/frontend/native/turn-meta.ts +43 -0
  305. package/src/frontend/shared/format.ts +51 -0
  306. package/src/frontend/shared/reasoning-levels.ts +46 -0
  307. package/src/frontend/shared/session-status.ts +189 -0
  308. package/src/frontend/shared/status-context.ts +125 -0
  309. package/src/frontend/teams/actions.ts +7 -5
  310. package/src/frontend/teams/formatting.ts +7 -18
  311. package/src/frontend/teams/graph.ts +2 -1
  312. package/src/frontend/teams/index.ts +76 -54
  313. package/src/frontend/telegram/actions/chat-info.ts +323 -0
  314. package/src/frontend/telegram/actions/index.ts +68 -0
  315. package/src/frontend/telegram/actions/media.ts +224 -0
  316. package/src/frontend/telegram/actions/messaging.ts +295 -0
  317. package/src/frontend/telegram/actions/shared.ts +58 -0
  318. package/src/frontend/telegram/actions/types.ts +31 -0
  319. package/src/frontend/telegram/admin.ts +12 -22
  320. package/src/frontend/telegram/callbacks/effort.ts +68 -0
  321. package/src/frontend/telegram/callbacks/index.ts +68 -0
  322. package/src/frontend/telegram/callbacks/model.ts +311 -0
  323. package/src/frontend/telegram/callbacks/pulse.ts +50 -0
  324. package/src/frontend/telegram/callbacks/settings.ts +177 -0
  325. package/src/frontend/telegram/callbacks/shared.ts +71 -0
  326. package/src/frontend/telegram/commands/admin.ts +226 -0
  327. package/src/frontend/telegram/commands/definitions.ts +60 -0
  328. package/src/frontend/telegram/commands/index.ts +39 -0
  329. package/src/frontend/telegram/commands/info.ts +125 -0
  330. package/src/frontend/telegram/commands/session.ts +77 -0
  331. package/src/frontend/telegram/commands/settings.ts +345 -0
  332. package/src/frontend/telegram/commands/state.ts +34 -0
  333. package/src/frontend/telegram/formatting.ts +14 -25
  334. package/src/frontend/telegram/handlers/access.ts +287 -0
  335. package/src/frontend/telegram/handlers/context.ts +210 -0
  336. package/src/frontend/telegram/handlers/delivery.ts +236 -0
  337. package/src/frontend/telegram/handlers/index.ts +39 -0
  338. package/src/frontend/telegram/handlers/messages.ts +477 -0
  339. package/src/frontend/telegram/handlers/queue.ts +241 -0
  340. package/src/frontend/telegram/handlers/state.ts +75 -0
  341. package/src/frontend/telegram/helpers/diagnostics.ts +188 -0
  342. package/src/frontend/telegram/helpers/format.ts +41 -0
  343. package/src/frontend/telegram/helpers/index.ts +13 -0
  344. package/src/frontend/telegram/{helpers.ts → helpers/menu.ts} +209 -210
  345. package/src/frontend/telegram/index.ts +24 -27
  346. package/src/frontend/telegram/middleware.ts +16 -3
  347. package/src/frontend/telegram/model-callbacks.ts +14 -0
  348. package/src/frontend/telegram/model-menu.ts +317 -0
  349. package/src/frontend/telegram/sticker-library.ts +178 -0
  350. package/src/frontend/telegram/userbot.ts +2 -44
  351. package/src/frontend/terminal/commands.ts +47 -41
  352. package/src/frontend/terminal/index.ts +46 -31
  353. package/src/frontend/terminal/input.ts +5 -0
  354. package/src/frontend/terminal/renderer.ts +4 -2
  355. package/src/index.ts +13 -171
  356. package/src/login.ts +3 -2
  357. package/src/native/blake3-wasm-bytes.ts +7 -0
  358. package/src/native/blake3.ts +234 -0
  359. package/src/native/htmlents-wasm-bytes.ts +7 -0
  360. package/src/native/htmlents.ts +56 -0
  361. package/src/native/prelude.d.mts +168 -0
  362. package/src/native/prelude.mjs +1561 -0
  363. package/src/native/registry.ts +142 -0
  364. package/src/native/runtime.ts +164 -0
  365. package/src/native/scheduler-core/gleam.d.mts +2 -0
  366. package/src/native/scheduler-core/gleam.mjs +1 -0
  367. package/src/native/scheduler-core/scheduler_core.d.mts +76 -0
  368. package/src/native/scheduler-core/scheduler_core.mjs +252 -0
  369. package/src/native/scheduler-core.ts +124 -0
  370. package/src/native/sqlguard-wasm-bytes.ts +7 -0
  371. package/src/native/sqlguard.ts +107 -0
  372. package/src/native/strsim-wasm-bytes.ts +7 -0
  373. package/src/native/strsim.ts +98 -0
  374. package/src/native/textops-wasm-bytes.ts +7 -0
  375. package/src/native/textops.ts +83 -0
  376. package/src/native/warden.ts +287 -0
  377. package/src/plugins/github/index.ts +1 -1
  378. package/src/plugins/mempalace/index.ts +1 -1
  379. package/src/plugins/playwright/index.ts +1 -1
  380. package/src/storage/chat-settings.ts +335 -85
  381. package/src/storage/cron-store.ts +266 -109
  382. package/src/storage/daily-log.ts +15 -3
  383. package/src/storage/db.ts +206 -0
  384. package/src/storage/goal-store.ts +186 -0
  385. package/src/storage/history.ts +137 -188
  386. package/src/storage/kv.ts +52 -0
  387. package/src/storage/legacy-import.ts +47 -0
  388. package/src/storage/media-index.ts +118 -61
  389. package/src/storage/repositories/chat-settings-repo.ts +60 -0
  390. package/src/storage/repositories/cron-repo.ts +128 -0
  391. package/src/storage/repositories/goals-repo.ts +122 -0
  392. package/src/storage/repositories/history-repo.ts +207 -0
  393. package/src/storage/repositories/kv-repo.ts +25 -0
  394. package/src/storage/repositories/media-index-repo.ts +147 -0
  395. package/src/storage/repositories/scripts-repo.ts +81 -0
  396. package/src/storage/repositories/sessions-repo.ts +129 -0
  397. package/src/storage/repositories/triggers-repo.ts +158 -0
  398. package/src/storage/repositories/turn-meta-repo.ts +32 -0
  399. package/src/storage/scheduled-store.ts +84 -0
  400. package/src/storage/script-store.ts +198 -0
  401. package/src/storage/sessions.ts +227 -102
  402. package/src/storage/skill-store.ts +325 -0
  403. package/src/storage/sql/README.md +18 -0
  404. package/src/storage/sql/chat-settings.sql +11 -0
  405. package/src/storage/sql/cron.sql +40 -0
  406. package/src/storage/sql/db.sql +11 -0
  407. package/src/storage/sql/embed.ts +118 -0
  408. package/src/storage/sql/goals.sql +41 -0
  409. package/src/storage/sql/history.sql +83 -0
  410. package/src/storage/sql/kv.sql +11 -0
  411. package/src/storage/sql/media-index.sql +45 -0
  412. package/src/storage/sql/schema.sql +233 -0
  413. package/src/storage/sql/scripts.sql +28 -0
  414. package/src/storage/sql/sessions.sql +22 -0
  415. package/src/storage/sql/statements.generated.ts +500 -0
  416. package/src/storage/sql/triggers.sql +69 -0
  417. package/src/storage/sql/turn-meta.sql +24 -0
  418. package/src/storage/sticker-store.ts +141 -0
  419. package/src/storage/trigger-store.ts +104 -126
  420. package/src/storage/turn-meta.ts +118 -0
  421. package/src/util/chat-id.ts +30 -0
  422. package/src/util/config.ts +313 -195
  423. package/src/util/fs-path.ts +32 -0
  424. package/src/util/log.ts +53 -31
  425. package/src/util/mcp-launcher.ts +351 -33
  426. package/src/util/paths.ts +45 -17
  427. package/src/util/tail-file.ts +24 -0
  428. package/src/util/workspace.ts +161 -10
  429. package/tsconfig.json +1 -0
  430. package/src/backend/claude-sdk/models.ts +0 -501
  431. package/src/backend/codex/handler.ts +0 -595
  432. package/src/backend/kilo/handler.ts +0 -707
  433. package/src/backend/kilo/models.ts +0 -762
  434. package/src/backend/openai-agents/handler.ts +0 -539
  435. package/src/backend/openai-agents/mcp.ts +0 -139
  436. package/src/backend/opencode/handler.ts +0 -663
  437. package/src/backend/opencode/models.ts +0 -741
  438. package/src/core/cron.ts +0 -184
  439. package/src/core/dispatcher.ts +0 -144
  440. package/src/core/gateway-actions.ts +0 -603
  441. package/src/core/heartbeat.ts +0 -575
  442. package/src/core/plugin.ts +0 -776
  443. package/src/core/triggers.ts +0 -640
  444. package/src/frontend/discord/actions.ts +0 -729
  445. package/src/frontend/discord/commands.ts +0 -1036
  446. package/src/frontend/discord/handlers.ts +0 -798
  447. package/src/frontend/telegram/actions.ts +0 -731
  448. package/src/frontend/telegram/callbacks.ts +0 -419
  449. package/src/frontend/telegram/commands.ts +0 -642
  450. package/src/frontend/telegram/handlers.ts +0 -1352
  451. package/src/util/mcp-launcher.mjs +0 -140
@@ -0,0 +1,206 @@
1
+ /**
2
+ * SQLite connection + schema setup — the high-performance data
3
+ * layer's entry point.
4
+ *
5
+ * One database at ~/.talon/data/talon.db, opened through the runtime's
6
+ * built-in SQLite: `node:sqlite` (stable since Node 23.4) under node,
7
+ * `bun:sqlite` under bun — so compiled single binaries need no native
8
+ * addon and there is nothing on disk to resolve. The heavy lifting —
9
+ * storage engine, indexes, FTS5 full-text search — is battle-tested C,
10
+ * orchestrated from TypeScript.
11
+ *
12
+ * Layering (keep it this way):
13
+ * - sql/schema.sql all DDL, idempotent, ensured on open
14
+ * - sql/<store>.sql every statement for one store
15
+ * - sql/statements.generated.ts committed embed of the above
16
+ * (`npm run build:sql`, see sql/embed.ts)
17
+ * - repositories/<store>.ts statement execution for one store, typed rows
18
+ * - <store>.ts public API + domain logic, ZERO SQL
19
+ * - db.ts (this file) connection, pragmas, schema setup
20
+ *
21
+ * Why this over the JSON stores it replaces: transactional row writes
22
+ * instead of rewrite-the-whole-file flush timers, indexed reads instead
23
+ * of in-memory scans (so retention needn't be capped), and FTS5 where
24
+ * stores need real search.
25
+ */
26
+
27
+ import { mkdirSync } from "node:fs";
28
+ import { dirname } from "node:path";
29
+ import { files } from "../util/paths.js";
30
+ import { log, logError } from "../util/log.js";
31
+ import { SCHEMA, dbSql } from "./sql/statements.generated.js";
32
+
33
+ /**
34
+ * The driver surface the repositories use — the intersection of
35
+ * node:sqlite's DatabaseSync and bun:sqlite's Database, which are
36
+ * API-compatible for exactly this set (verified empirically: prepared
37
+ * statements with positional params, identical row object shapes,
38
+ * multi-statement exec, FTS5 virtual tables).
39
+ */
40
+ export type SqlStatement = {
41
+ get(...params: unknown[]): unknown;
42
+ all(...params: unknown[]): unknown[];
43
+ run(...params: unknown[]): unknown;
44
+ };
45
+ export type SqlDatabase = {
46
+ prepare(sql: string): SqlStatement;
47
+ exec(sql: string): void;
48
+ close(): void;
49
+ };
50
+
51
+ // bun (≤1.3.x) does not implement node:sqlite — a compiled binary dies
52
+ // at startup with "No such built-in module: node:sqlite". Both
53
+ // runtimes ship a native SQLite builtin, so pick at load time. The
54
+ // non-literal import specifier keeps tsc and bundlers from trying to
55
+ // resolve the module that doesn't exist on the other runtime.
56
+ const IS_BUN = typeof (globalThis as { Bun?: unknown }).Bun !== "undefined";
57
+ const sqliteModule = (await import(
58
+ IS_BUN ? "bun:sqlite" : "node:sqlite"
59
+ )) as Record<string, new (path: string) => SqlDatabase>;
60
+ const Database = IS_BUN ? sqliteModule.Database : sqliteModule.DatabaseSync;
61
+
62
+ let db: SqlDatabase | null = null;
63
+
64
+ /**
65
+ * Apply the complete schema. Every statement is IF NOT EXISTS, so this
66
+ * is a no-op on an up-to-date database and creates exactly what's
67
+ * missing on a fresh or older one.
68
+ *
69
+ * Column reconciliation runs first: `ALTER TABLE … ADD COLUMN` has no
70
+ * IF NOT EXISTS form, so columns added to already-shipped tables
71
+ * (media_index.content_hash) are ensured by attempting the ALTER and
72
+ * swallowing the two expected failures — "duplicate column name"
73
+ * (column already there) and "no such table" (fresh database; the
74
+ * CREATE TABLE in schema.sql includes the column).
75
+ */
76
+ function ensureSchema(database: SqlDatabase): void {
77
+ const row = database
78
+ .prepare(
79
+ "SELECT COUNT(*) AS tables FROM sqlite_master WHERE type = 'table'",
80
+ )
81
+ .get() as { tables: number };
82
+ try {
83
+ database.exec(dbSql.addMediaContentHashColumn);
84
+ } catch {
85
+ /* duplicate column or no such table — both mean nothing to do */
86
+ }
87
+ database.exec("BEGIN");
88
+ try {
89
+ database.exec(SCHEMA);
90
+ database.exec("COMMIT");
91
+ } catch (err) {
92
+ database.exec("ROLLBACK");
93
+ throw err;
94
+ }
95
+ if (row.tables === 0) log("db", "Initialized database schema");
96
+ }
97
+
98
+ function defaultPath(): string {
99
+ // Test isolation: the vitest setup file points every worker at a
100
+ // throwaway database so suites never touch ~/.talon/data/talon.db.
101
+ return process.env.TALON_DB_PATH || files.database;
102
+ }
103
+
104
+ /**
105
+ * Open (or return) the process-wide database. The first call wins the
106
+ * path; tests pass an explicit tmp path and call closeDatabase() in
107
+ * teardown.
108
+ */
109
+ export function getDatabase(path: string = defaultPath()): SqlDatabase {
110
+ if (db) return db;
111
+ mkdirSync(dirname(path), { recursive: true });
112
+ const database = new Database(path);
113
+ try {
114
+ // WAL: readers don't block the writer, and crash recovery is
115
+ // journal-based instead of "hope the rename was atomic".
116
+ database.exec("PRAGMA journal_mode = WAL");
117
+ database.exec("PRAGMA synchronous = NORMAL");
118
+ database.exec("PRAGMA foreign_keys = ON");
119
+ ensureSchema(database);
120
+ } catch (err) {
121
+ // Setup failed — close the handle so a retry doesn't leak one
122
+ // open file descriptor (and WAL sidecar) per attempt.
123
+ try {
124
+ database.close();
125
+ } catch {
126
+ /* already closed */
127
+ }
128
+ throw err;
129
+ }
130
+ db = database;
131
+ return database;
132
+ }
133
+
134
+ let transactionDepth = 0;
135
+
136
+ /**
137
+ * Best-effort rollback: a ROLLBACK that itself throws (database closed,
138
+ * I/O error) must not mask the original error from `fn`, and must not
139
+ * skip the depth bookkeeping — a stuck depth would silently turn every
140
+ * later top-level transaction into a savepoint.
141
+ */
142
+ function tryExec(database: SqlDatabase, sql: string): void {
143
+ try {
144
+ database.exec(sql);
145
+ } catch (err) {
146
+ logError("db", `Transaction cleanup failed (${sql})`, err);
147
+ }
148
+ }
149
+
150
+ /** Run `fn` inside a transaction; rolls back on throw. Nested calls use SAVEPOINTs. */
151
+ export function inTransaction<T>(fn: () => T): T {
152
+ const database = getDatabase();
153
+ if (transactionDepth > 0) {
154
+ const sp = `sp${transactionDepth}`;
155
+ database.exec(`SAVEPOINT "${sp}"`);
156
+ transactionDepth++;
157
+ try {
158
+ const result = fn();
159
+ database.exec(`RELEASE "${sp}"`);
160
+ return result;
161
+ } catch (err) {
162
+ tryExec(database, `ROLLBACK TO "${sp}"`);
163
+ tryExec(database, `RELEASE "${sp}"`);
164
+ throw err;
165
+ } finally {
166
+ transactionDepth--;
167
+ }
168
+ }
169
+ database.exec("BEGIN");
170
+ transactionDepth++;
171
+ try {
172
+ const result = fn();
173
+ database.exec("COMMIT");
174
+ return result;
175
+ } catch (err) {
176
+ tryExec(database, "ROLLBACK");
177
+ throw err;
178
+ } finally {
179
+ transactionDepth--;
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Compact the WAL into the main database file. SQLite commits on
185
+ * every write, so there is no dirty buffer to flush — the shutdown
186
+ * and fatal-error paths call this once for the whole database
187
+ * (replacing the per-store flush functions of the JSON era).
188
+ */
189
+ export function flushDatabase(): void {
190
+ if (!db) return;
191
+ try {
192
+ db.exec(dbSql.walCheckpoint);
193
+ } catch {
194
+ /* shutting down — best effort */
195
+ }
196
+ }
197
+
198
+ export function closeDatabase(): void {
199
+ if (!db) return;
200
+ try {
201
+ db.close();
202
+ } catch {
203
+ /* already closed */
204
+ }
205
+ db = null;
206
+ }
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Persistent goal store — multi-turn objectives the agent commits to
3
+ * and pursues across sessions.
4
+ *
5
+ * Goals are the agency primitive: a chat conversation (or the agent
6
+ * itself) records "keep an eye on X" / "finish Y by Friday" here, and
7
+ * the heartbeat agent reads the open set on every run to decide what
8
+ * to make progress on. Each goal carries a rolling last-progress note
9
+ * so a heartbeat can pick up where the previous one left off.
10
+ *
11
+ * SQLite-backed (see repositories/goals-repo.ts for the statements;
12
+ * this module holds the domain API and validation — no SQL here).
13
+ * Goals are low-frequency data: reads go straight to the database,
14
+ * no in-memory cache.
15
+ */
16
+
17
+ import { randomUUID } from "node:crypto";
18
+ import * as repo from "./repositories/goals-repo.js";
19
+
20
+ export type GoalStatus = "active" | "paused" | "completed" | "abandoned";
21
+ export type GoalPriority = "low" | "normal" | "high";
22
+
23
+ export type Goal = {
24
+ id: string;
25
+ /** Chat the goal belongs to — progress reports route back here. */
26
+ chatId: string;
27
+ title: string;
28
+ description?: string;
29
+ status: GoalStatus;
30
+ priority: GoalPriority;
31
+ createdAt: number;
32
+ updatedAt: number;
33
+ /** Optional soft deadline (unix ms). */
34
+ dueAt?: number;
35
+ /** Rolling note from the last progress update. */
36
+ lastProgressNote?: string;
37
+ lastProgressAt?: number;
38
+ };
39
+
40
+ export const GOAL_STATUSES: readonly GoalStatus[] = [
41
+ "active",
42
+ "paused",
43
+ "completed",
44
+ "abandoned",
45
+ ];
46
+ export const GOAL_PRIORITIES: readonly GoalPriority[] = [
47
+ "low",
48
+ "normal",
49
+ "high",
50
+ ];
51
+
52
+ /** Statuses that count as "open" — shown to the heartbeat and listings. */
53
+ export const OPEN_GOAL_STATUSES: readonly GoalStatus[] = ["active", "paused"];
54
+
55
+ export const MAX_OPEN_GOALS_PER_CHAT = 25;
56
+ export const MAX_TITLE_LENGTH = 200;
57
+ export const MAX_DESCRIPTION_LENGTH = 2_000;
58
+ export const MAX_PROGRESS_NOTE_LENGTH = 1_000;
59
+
60
+ // ── Validation ──────────────────────────────────────────────────────────────
61
+
62
+ export function isGoalStatus(value: unknown): value is GoalStatus {
63
+ return GOAL_STATUSES.includes(value as GoalStatus);
64
+ }
65
+
66
+ export function isGoalPriority(value: unknown): value is GoalPriority {
67
+ return GOAL_PRIORITIES.includes(value as GoalPriority);
68
+ }
69
+
70
+ export function validateTitle(title: string): string | null {
71
+ if (!title.trim()) return "Goal title must not be empty";
72
+ if (title.length > MAX_TITLE_LENGTH)
73
+ return `Goal title too long (max ${MAX_TITLE_LENGTH} chars)`;
74
+ return null;
75
+ }
76
+
77
+ export function validateDescription(
78
+ description: string | undefined,
79
+ ): string | null {
80
+ if (description && description.length > MAX_DESCRIPTION_LENGTH)
81
+ return `Goal description too long (max ${MAX_DESCRIPTION_LENGTH} chars)`;
82
+ return null;
83
+ }
84
+
85
+ export function validateProgressNote(note: string | undefined): string | null {
86
+ if (note && note.length > MAX_PROGRESS_NOTE_LENGTH)
87
+ return `Progress note too long (max ${MAX_PROGRESS_NOTE_LENGTH} chars)`;
88
+ return null;
89
+ }
90
+
91
+ // ── ID generation ───────────────────────────────────────────────────────────
92
+
93
+ export function generateGoalId(): string {
94
+ return `goal_${randomUUID()}`;
95
+ }
96
+
97
+ // ── CRUD ────────────────────────────────────────────────────────────────────
98
+
99
+ export function addGoal(goal: Goal): void {
100
+ repo.upsert(goal);
101
+ }
102
+
103
+ export function getGoal(id: string): Goal | undefined {
104
+ return repo.get(id);
105
+ }
106
+
107
+ /** All goals for one chat, optionally filtered by status. */
108
+ export function getGoalsForChat(
109
+ chatId: string,
110
+ statuses?: readonly GoalStatus[],
111
+ ): Goal[] {
112
+ return repo.listByChat(chatId, statuses);
113
+ }
114
+
115
+ /** Open (active + paused) goals across every chat — the heartbeat's view. */
116
+ export function getOpenGoals(): Goal[] {
117
+ return repo.listByStatus(OPEN_GOAL_STATUSES);
118
+ }
119
+
120
+ export function countOpenGoalsForChat(chatId: string): number {
121
+ return repo.countByChatAndStatus(chatId, OPEN_GOAL_STATUSES);
122
+ }
123
+
124
+ /**
125
+ * Apply a partial update. `updatedAt` is always bumped; a progress
126
+ * note also stamps `lastProgressAt`. `dueAt: null` clears the
127
+ * deadline (undefined leaves it untouched). Returns the updated
128
+ * goal, or undefined when the id doesn't exist.
129
+ */
130
+ export function updateGoal(
131
+ id: string,
132
+ updates: Partial<
133
+ Pick<Goal, "title" | "description" | "status" | "priority">
134
+ > & { dueAt?: number | null; progressNote?: string },
135
+ ): Goal | undefined {
136
+ const existing = repo.get(id);
137
+ if (!existing) return undefined;
138
+ const now = Date.now();
139
+ const next: Goal = {
140
+ ...existing,
141
+ ...(updates.title !== undefined ? { title: updates.title } : {}),
142
+ ...(updates.description !== undefined
143
+ ? { description: updates.description }
144
+ : {}),
145
+ ...(updates.status !== undefined ? { status: updates.status } : {}),
146
+ ...(updates.priority !== undefined ? { priority: updates.priority } : {}),
147
+ ...(updates.dueAt !== undefined
148
+ ? { dueAt: updates.dueAt ?? undefined }
149
+ : {}),
150
+ ...(updates.progressNote !== undefined
151
+ ? { lastProgressNote: updates.progressNote, lastProgressAt: now }
152
+ : {}),
153
+ updatedAt: now,
154
+ };
155
+ repo.upsert(next);
156
+ return next;
157
+ }
158
+
159
+ export function deleteGoal(id: string): boolean {
160
+ return repo.remove(id);
161
+ }
162
+
163
+ // ── Formatting ──────────────────────────────────────────────────────────────
164
+
165
+ /**
166
+ * Render one goal as a compact multi-line block — shared by the
167
+ * `list_goals` tool output and the heartbeat prompt section so both
168
+ * surfaces describe goals identically.
169
+ */
170
+ export function formatGoal(
171
+ goal: Goal,
172
+ opts?: { withChatId?: boolean },
173
+ ): string {
174
+ const lines = [
175
+ `- ${goal.title} [${goal.status}${goal.priority !== "normal" ? `, ${goal.priority} priority` : ""}]`,
176
+ ` ID: ${goal.id}${opts?.withChatId ? ` | Chat: ${goal.chatId}` : ""}`,
177
+ ];
178
+ if (goal.description) lines.push(` Detail: ${goal.description}`);
179
+ if (goal.dueAt) lines.push(` Due: ${new Date(goal.dueAt).toISOString()}`);
180
+ lines.push(
181
+ goal.lastProgressNote
182
+ ? ` Last progress (${goal.lastProgressAt ? new Date(goal.lastProgressAt).toISOString() : "unknown"}): ${goal.lastProgressNote}`
183
+ : ` Last progress: none recorded yet (created ${new Date(goal.createdAt).toISOString()})`,
184
+ );
185
+ return lines.join("\n");
186
+ }