talon-agent 4.6.1 → 5.0.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 (310) hide show
  1. package/README.md +3 -3
  2. package/package.json +2 -1
  3. package/prompts/README.md +2 -2
  4. package/prompts/system/memory-recall.md +16 -0
  5. package/src/app.ts +22 -7
  6. package/src/backend/claude-sdk/factory.ts +21 -41
  7. package/src/backend/claude-sdk/handler.ts +28 -7
  8. package/src/backend/claude-sdk/host/in-process.ts +147 -0
  9. package/src/backend/claude-sdk/one-shot.ts +1 -1
  10. package/src/backend/claude-sdk/options.ts +7 -6
  11. package/src/backend/claude-sdk/stream.ts +30 -3
  12. package/src/backend/claude-sdk/warm.ts +1 -1
  13. package/src/backend/codex/constants.ts +1 -1
  14. package/src/backend/codex/factory.ts +2 -2
  15. package/src/backend/codex/handler/events.ts +1 -1
  16. package/src/backend/codex/handler/message.ts +26 -12
  17. package/src/backend/codex/handler/rollout-accounting.ts +1 -1
  18. package/src/backend/codex/init.ts +1 -1
  19. package/src/backend/codex/mcp-config.ts +2 -2
  20. package/src/backend/codex/one-shot.ts +1 -1
  21. package/src/backend/kilo/handler/message.ts +4 -1
  22. package/src/backend/openai-agents/constants.ts +1 -1
  23. package/src/backend/openai-agents/factory.ts +2 -2
  24. package/src/backend/openai-agents/handler/events.ts +1 -1
  25. package/src/backend/openai-agents/handler/message.ts +8 -4
  26. package/src/backend/openai-agents/init.ts +1 -1
  27. package/src/backend/openai-agents/mcp-pool.ts +2 -2
  28. package/src/backend/opencode/handler/message.ts +4 -1
  29. package/src/backend/remote-server/chat-turn.ts +31 -23
  30. package/src/backend/remote-server/events.ts +3 -3
  31. package/src/backend/remote-server/factory.ts +6 -3
  32. package/src/backend/remote-server/index.ts +1 -1
  33. package/src/backend/remote-server/mcp.ts +1 -1
  34. package/src/backend/remote-server/one-shot.ts +1 -1
  35. package/src/backend/remote-server/server-bindings.ts +1 -1
  36. package/src/backend/remote-server/turn.ts +1 -1
  37. package/src/backend/runtime/cache/cache-metrics.ts +126 -0
  38. package/src/backend/{shared → runtime/cache}/cache-telemetry.ts +22 -2
  39. package/src/backend/{shared → runtime}/index.ts +34 -25
  40. package/src/backend/{shared → runtime/prompt}/delivery-contract.ts +1 -1
  41. package/src/backend/{shared → runtime/prompt}/prompt-format.ts +46 -2
  42. package/src/backend/{shared → runtime/prompt}/system-prompt.ts +4 -4
  43. package/src/backend/{shared → runtime/turn}/delivered-text.ts +1 -1
  44. package/src/backend/{shared → runtime/turn}/delivery.ts +3 -3
  45. package/src/backend/{shared → runtime/turn}/handle-retry.ts +5 -5
  46. package/src/backend/{shared → runtime/turn}/handler-to-events.ts +24 -10
  47. package/src/backend/{shared → runtime/turn}/handler-types.ts +7 -1
  48. package/src/backend/{shared → runtime/turn}/model-retry.ts +2 -2
  49. package/src/backend/{shared → runtime/turn}/result-events.ts +2 -2
  50. package/src/backend/{shared → runtime/turn}/stream-state.ts +2 -2
  51. package/src/backend/{shared → runtime/turn}/turn-interrupt.ts +2 -2
  52. package/src/backend/{shared → runtime/turn}/turn-phases.ts +6 -6
  53. package/src/bootstrap.ts +6 -21
  54. package/src/cli.ts +6 -3
  55. package/src/core/agent-runtime/README.md +15 -0
  56. package/src/core/agent-runtime/agent-host.ts +387 -0
  57. package/src/core/agent-runtime/capabilities.ts +11 -0
  58. package/src/core/agent-runtime/contract-tests.ts +92 -1
  59. package/src/core/agent-runtime/events.ts +1 -1
  60. package/src/core/background/{isolated-agent.ts → cron/isolated-agent.ts} +3 -3
  61. package/src/core/background/{job-health.ts → cron/job-health.ts} +1 -1
  62. package/src/core/background/{job-oneshot.ts → cron/job-oneshot.ts} +5 -5
  63. package/src/core/background/{job-prompt.ts → cron/job-prompt.ts} +1 -1
  64. package/src/core/background/{cron.ts → cron/scheduler.ts} +6 -6
  65. package/src/core/background/{cron-spec.ts → cron/spec.ts} +1 -1
  66. package/src/core/background/{dream.ts → dream/index.ts} +10 -15
  67. package/src/core/background/{plan-alerts.ts → pulse/plan-alerts.ts} +3 -3
  68. package/src/core/background/{pulse.ts → pulse/pulse.ts} +8 -5
  69. package/src/core/background/triggers/command.ts +2 -2
  70. package/src/{util → core/config}/harden.ts +1 -1
  71. package/src/core/config/index.ts +16 -12
  72. package/src/{util → core/daemon}/boot-timer.ts +15 -1
  73. package/src/core/daemon/pidfile.ts +1 -1
  74. package/src/core/daemon/resource-sampler.ts +121 -0
  75. package/src/{util → core/daemon}/respawn.ts +1 -1
  76. package/src/core/doctor/index.ts +1 -1
  77. package/src/core/engine/dispatcher.ts +16 -0
  78. package/src/core/engine/gateway-actions/cron.ts +2 -2
  79. package/src/core/engine/gateway-actions/fetch-url.ts +1 -1
  80. package/src/core/engine/gateway-actions/index.ts +4 -1
  81. package/src/core/engine/gateway-actions/memory.ts +335 -0
  82. package/src/core/engine/gateway-actions/native/exec-background.ts +129 -0
  83. package/src/core/engine/gateway-actions/native/exec-remote.ts +85 -0
  84. package/src/core/engine/gateway-actions/native/exec.ts +182 -0
  85. package/src/core/engine/gateway-actions/native/index.ts +46 -0
  86. package/src/core/engine/gateway-actions/native/params.ts +46 -0
  87. package/src/core/engine/gateway-actions/native/read.ts +182 -0
  88. package/src/core/engine/gateway-actions/native/results.ts +34 -0
  89. package/src/core/engine/gateway-actions/native/search.ts +212 -0
  90. package/src/core/engine/gateway-actions/native/shell.ts +39 -0
  91. package/src/core/engine/gateway-actions/native/teleport.ts +55 -0
  92. package/src/core/engine/gateway-actions/native/write.ts +170 -0
  93. package/src/core/engine/gateway.ts +0 -6
  94. package/src/core/frontend-runtime/builtins.ts +2 -2
  95. package/src/{util → core/frontend-runtime}/chat-id.ts +30 -0
  96. package/src/core/mcp-hub/index.ts +1 -1
  97. package/src/core/mcp-hub/talon-server.ts +1 -1
  98. package/src/core/memory/import.ts +3 -2
  99. package/src/core/memory/taps.ts +199 -0
  100. package/src/core/memory/turn-retrieval.ts +222 -0
  101. package/src/core/plugin/mcp.ts +1 -1
  102. package/src/core/prompt/assemble.ts +2 -12
  103. package/src/core/prompt/index.ts +2 -2
  104. package/src/core/prompt/invalidation.ts +1 -1
  105. package/src/core/{scripting/lua-runner.ts → scripts/lua.ts} +1 -1
  106. package/src/core/tasks/index.ts +1 -1
  107. package/src/core/tools/{chat.ts → chat/chat.ts} +1 -1
  108. package/src/core/tools/{cross-send.ts → chat/cross-send.ts} +1 -1
  109. package/src/core/tools/{history.ts → chat/history.ts} +2 -2
  110. package/src/core/tools/{media.ts → chat/media.ts} +1 -1
  111. package/src/core/tools/{members.ts → chat/members.ts} +2 -2
  112. package/src/core/tools/{messaging.ts → chat/messaging.ts} +2 -2
  113. package/src/core/tools/{moderation.ts → chat/moderation.ts} +2 -2
  114. package/src/core/tools/{stickers.ts → chat/stickers.ts} +2 -2
  115. package/src/core/tools/{whatsapp.ts → chat/whatsapp.ts} +1 -1
  116. package/src/core/tools/content/memory.ts +128 -0
  117. package/src/core/tools/{web.ts → content/web.ts} +1 -1
  118. package/src/core/tools/index.ts +21 -19
  119. package/src/core/tools/{admin.ts → ops/admin.ts} +1 -1
  120. package/src/core/tools/{bridge.ts → ops/bridge.ts} +2 -2
  121. package/src/core/tools/{goals.ts → ops/goals.ts} +2 -2
  122. package/src/core/tools/{mesh.ts → ops/mesh.ts} +1 -1
  123. package/src/core/tools/{models.ts → ops/models.ts} +1 -1
  124. package/src/core/tools/{native.ts → ops/native.ts} +1 -1
  125. package/src/core/tools/{scheduling.ts → ops/scheduling.ts} +1 -1
  126. package/src/core/tools/{scripts.ts → ops/scripts.ts} +1 -1
  127. package/src/core/tools/{skills.ts → ops/skills.ts} +1 -1
  128. package/src/core/tools/{triggers.ts → ops/triggers.ts} +1 -1
  129. package/src/core/tools/types.ts +1 -0
  130. package/src/{util → core/vfs}/workspace.ts +2 -2
  131. package/src/core/weaver/turn-cpu.ts +32 -0
  132. package/src/core/weaver/weaver.ts +36 -0
  133. package/src/frontend/discord/admin.ts +1 -1
  134. package/src/frontend/discord/callbacks/components/backend-select.ts +1 -1
  135. package/src/frontend/discord/callbacks/components/effort.ts +1 -1
  136. package/src/frontend/discord/callbacks/components/index.ts +1 -1
  137. package/src/frontend/discord/callbacks/components/pulse.ts +1 -1
  138. package/src/frontend/discord/callbacks/components/settings.ts +2 -2
  139. package/src/frontend/discord/callbacks/modals.ts +4 -1
  140. package/src/frontend/discord/commands/admin.ts +2 -36
  141. package/src/frontend/discord/commands/definitions.ts +0 -11
  142. package/src/frontend/discord/commands/info.ts +1 -1
  143. package/src/frontend/discord/commands/interaction.ts +1 -1
  144. package/src/frontend/discord/commands/router.ts +0 -3
  145. package/src/frontend/discord/commands/session.ts +8 -2
  146. package/src/frontend/discord/commands/settings.ts +2 -2
  147. package/src/frontend/discord/handlers/messages.ts +1 -1
  148. package/src/frontend/discord/handlers/state.ts +1 -1
  149. package/src/frontend/discord/middleware.ts +2 -26
  150. package/src/frontend/discord/ready.ts +1 -1
  151. package/src/frontend/discord/render.ts +41 -259
  152. package/src/frontend/discord/runtime.ts +1 -2
  153. package/src/frontend/native/{auth.ts → bridge/auth.ts} +2 -2
  154. package/src/frontend/native/{discovery.ts → bridge/discovery.ts} +3 -3
  155. package/src/frontend/native/{routes → bridge/routes}/chats.ts +1 -1
  156. package/src/frontend/native/{routes → bridge/routes}/daemon.ts +1 -1
  157. package/src/frontend/native/{routes → bridge/routes}/host.ts +6 -3
  158. package/src/frontend/native/{routes → bridge/routes}/pre-auth.ts +1 -1
  159. package/src/frontend/native/{server.ts → bridge/server.ts} +3 -3
  160. package/src/frontend/native/{tls.ts → bridge/tls.ts} +2 -2
  161. package/src/frontend/native/{chat-lifecycle.ts → chats/chat-lifecycle.ts} +3 -3
  162. package/src/frontend/native/{chat-wire.ts → chats/chat-wire.ts} +4 -4
  163. package/src/frontend/native/{chats.ts → chats/chats.ts} +4 -4
  164. package/src/frontend/native/{empty-chat-sweep.ts → chats/empty-chat-sweep.ts} +4 -4
  165. package/src/frontend/native/{history.ts → chats/history.ts} +7 -7
  166. package/src/frontend/native/{reset.ts → chats/reset.ts} +7 -7
  167. package/src/frontend/native/index.ts +13 -10
  168. package/src/frontend/native/{media.ts → media/media.ts} +3 -3
  169. package/src/frontend/native/runtime.ts +1 -1
  170. package/src/frontend/native/{control.ts → surface/control.ts} +4 -4
  171. package/src/frontend/native/{extensions.ts → surface/extensions.ts} +12 -9
  172. package/src/frontend/native/{handlers.ts → surface/handlers.ts} +19 -14
  173. package/src/frontend/native/{logs.ts → surface/logs.ts} +2 -2
  174. package/src/frontend/native/{memory.ts → surface/memory.ts} +2 -2
  175. package/src/frontend/native/{models.ts → surface/models.ts} +17 -10
  176. package/src/frontend/native/{settings.ts → surface/settings.ts} +9 -9
  177. package/src/frontend/native/{status.ts → surface/status.ts} +3 -3
  178. package/src/frontend/native/{actions.ts → turn/actions.ts} +7 -4
  179. package/src/frontend/native/{context.ts → turn/context.ts} +8 -8
  180. package/src/frontend/native/{emit.ts → turn/emit.ts} +7 -7
  181. package/src/frontend/native/{queue.ts → turn/queue.ts} +3 -3
  182. package/src/frontend/native/{turn-meta.ts → turn/turn-meta.ts} +2 -2
  183. package/src/frontend/native/{turn.ts → turn/turn.ts} +9 -9
  184. package/src/frontend/{shared → presentation}/format.ts +4 -3
  185. package/src/frontend/{shared → presentation}/model-commands.ts +1 -1
  186. package/src/frontend/{shared → presentation}/reasoning-levels.ts +12 -0
  187. package/src/frontend/presentation/reports.ts +493 -0
  188. package/src/frontend/{shared → presentation}/session-status.ts +36 -9
  189. package/src/frontend/{shared → presentation}/status-context.ts +101 -2
  190. package/src/frontend/teams/commands.ts +2 -2
  191. package/src/frontend/teams/turn.ts +1 -1
  192. package/src/frontend/telegram/admin/background.ts +1 -1
  193. package/src/frontend/telegram/admin/health.ts +1 -1
  194. package/src/frontend/telegram/admin/sessions.ts +1 -1
  195. package/src/frontend/telegram/callbacks/effort.ts +2 -2
  196. package/src/frontend/telegram/callbacks/metrics.ts +1 -1
  197. package/src/frontend/telegram/callbacks/model/backend.ts +1 -1
  198. package/src/frontend/telegram/callbacks/model/views.ts +1 -1
  199. package/src/frontend/telegram/callbacks/pulse.ts +1 -1
  200. package/src/frontend/telegram/callbacks/query.ts +1 -1
  201. package/src/frontend/telegram/callbacks/settings.ts +3 -3
  202. package/src/frontend/telegram/commands/admin.ts +6 -41
  203. package/src/frontend/telegram/commands/index.ts +1 -1
  204. package/src/frontend/telegram/commands/info.ts +2 -2
  205. package/src/frontend/telegram/commands/session.ts +9 -3
  206. package/src/frontend/telegram/commands/settings.ts +5 -3
  207. package/src/frontend/telegram/handlers/messages.ts +0 -10
  208. package/src/frontend/telegram/handlers/state.ts +1 -1
  209. package/src/frontend/telegram/index.ts +1 -5
  210. package/src/frontend/telegram/middleware.ts +1 -15
  211. package/src/frontend/telegram/model-menu.ts +1 -1
  212. package/src/frontend/telegram/render/html.ts +30 -0
  213. package/src/frontend/telegram/{helpers → render}/menu.ts +46 -19
  214. package/src/frontend/telegram/render/reports.ts +182 -0
  215. package/src/frontend/terminal/builtins/context.ts +2 -2
  216. package/src/frontend/terminal/builtins/session.ts +1 -1
  217. package/src/frontend/terminal/builtins/status.ts +2 -2
  218. package/src/frontend/terminal/index.ts +2 -2
  219. package/src/frontend/terminal/renderer.ts +1 -1
  220. package/src/frontend/whatsapp/access.ts +2 -2
  221. package/src/frontend/whatsapp/actions/history.ts +2 -2
  222. package/src/frontend/whatsapp/actions/messaging.ts +2 -2
  223. package/src/frontend/whatsapp/actions/moderation.ts +1 -1
  224. package/src/frontend/whatsapp/actions/send.ts +1 -1
  225. package/src/frontend/whatsapp/commands.ts +12 -6
  226. package/src/frontend/whatsapp/{connection.ts → connection/connection.ts} +5 -5
  227. package/src/frontend/whatsapp/{pairing-service.ts → connection/pairing-service.ts} +3 -3
  228. package/src/frontend/whatsapp/{wa-logger.ts → connection/wa-logger.ts} +2 -2
  229. package/src/frontend/whatsapp/index.ts +4 -4
  230. package/src/frontend/whatsapp/{inbound.ts → messages/inbound.ts} +15 -15
  231. package/src/frontend/whatsapp/{media-store.ts → messages/media-store.ts} +4 -4
  232. package/src/frontend/whatsapp/{message-store.ts → messages/message-store.ts} +1 -1
  233. package/src/frontend/whatsapp/{turn-recovery.ts → messages/turn-recovery.ts} +4 -4
  234. package/src/frontend/whatsapp/registry.ts +2 -2
  235. package/src/frontend/whatsapp/runtime.ts +1 -1
  236. package/src/index.ts +6 -3
  237. package/src/storage/db.ts +6 -1
  238. package/src/storage/memory.ts +59 -8
  239. package/src/storage/metrics.ts +38 -0
  240. package/src/storage/repositories/sessions-repo.ts +6 -0
  241. package/src/storage/session-record.ts +13 -2
  242. package/src/storage/sessions.ts +12 -0
  243. package/src/storage/sql/db.sql +5 -0
  244. package/src/storage/sql/schema.sql +4 -0
  245. package/src/storage/sql/sessions.sql +3 -3
  246. package/src/storage/sql/statements.generated.ts +10 -3
  247. package/src/storage/sql/turn-meta.sql +1 -1
  248. package/src/util/log.ts +1 -1
  249. package/src/util/paths.ts +0 -2
  250. package/src/util/runtime.ts +1 -1
  251. package/src/core/engine/gateway-actions/native.ts +0 -1035
  252. package/src/core/soul/README.md +0 -110
  253. package/src/core/soul/RESEARCH.md +0 -98
  254. package/src/core/soul/associative.ts +0 -98
  255. package/src/core/soul/centrality.ts +0 -98
  256. package/src/core/soul/cluster.ts +0 -83
  257. package/src/core/soul/compiler.ts +0 -207
  258. package/src/core/soul/consolidate.ts +0 -179
  259. package/src/core/soul/critic.ts +0 -162
  260. package/src/core/soul/dag.ts +0 -265
  261. package/src/core/soul/delta.ts +0 -123
  262. package/src/core/soul/drift.ts +0 -99
  263. package/src/core/soul/embedder.ts +0 -129
  264. package/src/core/soul/emergent-critic.ts +0 -96
  265. package/src/core/soul/forgetting.ts +0 -131
  266. package/src/core/soul/governance.ts +0 -93
  267. package/src/core/soul/hash.ts +0 -97
  268. package/src/core/soul/hdc.ts +0 -154
  269. package/src/core/soul/kernel.ts +0 -540
  270. package/src/core/soul/lattice.ts +0 -103
  271. package/src/core/soul/lens.ts +0 -110
  272. package/src/core/soul/projector.ts +0 -240
  273. package/src/core/soul/reflect.ts +0 -170
  274. package/src/core/soul/reflex.ts +0 -164
  275. package/src/core/soul/retrieve.ts +0 -146
  276. package/src/core/soul/salience.ts +0 -146
  277. package/src/core/soul/service.ts +0 -204
  278. package/src/core/soul/settings.ts +0 -47
  279. package/src/core/soul/signals.ts +0 -117
  280. package/src/core/soul/talon-embedder.ts +0 -80
  281. package/src/core/soul/taps.ts +0 -199
  282. package/src/core/soul/types.ts +0 -298
  283. package/src/core/soul/valence.ts +0 -83
  284. package/src/frontend/telegram/helpers/diagnostics.ts +0 -428
  285. package/src/frontend/telegram/helpers/format.ts +0 -42
  286. package/src/frontend/telegram/helpers/index.ts +0 -13
  287. package/src/util/cleanup-registry.ts +0 -36
  288. /package/src/backend/{shared → runtime}/frontends.ts +0 -0
  289. /package/src/backend/{shared → runtime}/metrics.ts +0 -0
  290. /package/src/backend/{shared → runtime}/sleep.ts +0 -0
  291. /package/src/backend/{shared → runtime/turn}/flow-violation.ts +0 -0
  292. /package/src/backend/{shared → runtime}/usage.ts +0 -0
  293. /package/src/{util/mcp-launcher.ts → core/mcp-hub/launcher.ts} +0 -0
  294. /package/src/{util → core/tools/content}/web-content.ts +0 -0
  295. /package/src/core/tools/{mcp-env.ts → ops/mcp-env.ts} +0 -0
  296. /package/src/{util → core/weaver}/session-name.ts +0 -0
  297. /package/src/frontend/native/{routes → bridge/routes}/index.ts +0 -0
  298. /package/src/frontend/native/{routes → bridge/routes}/memory.ts +0 -0
  299. /package/src/frontend/native/{routes → bridge/routes}/mesh.ts +0 -0
  300. /package/src/frontend/native/{routes → bridge/routes}/models.ts +0 -0
  301. /package/src/frontend/native/{routes → bridge/routes}/params.ts +0 -0
  302. /package/src/frontend/native/{routes → bridge/routes}/table.ts +0 -0
  303. /package/src/frontend/native/{tool-result.ts → turn/tool-result.ts} +0 -0
  304. /package/src/frontend/{shared → presentation}/access.ts +0 -0
  305. /package/src/frontend/{shared → presentation}/plan-usage-report.ts +0 -0
  306. /package/src/frontend/whatsapp/{auth-state.ts → connection/auth-state.ts} +0 -0
  307. /package/src/frontend/whatsapp/{identity.ts → connection/identity.ts} +0 -0
  308. /package/src/frontend/whatsapp/{pairing-lock.ts → connection/pairing-lock.ts} +0 -0
  309. /package/src/frontend/whatsapp/{pairing.ts → connection/pairing.ts} +0 -0
  310. /package/src/frontend/whatsapp/{pins.ts → messages/pins.ts} +0 -0
@@ -11,9 +11,9 @@
11
11
  * also what covers windows the plan reports no reset for).
12
12
  */
13
13
 
14
- import { getPooledBackend } from "../engine/backend-controller/index.js";
15
- import { log, logWarn } from "../../util/log.js";
16
- import { formatSmartTimestamp } from "../../util/time.js";
14
+ import { getPooledBackend } from "../../engine/backend-controller/index.js";
15
+ import { log, logWarn } from "../../../util/log.js";
16
+ import { formatSmartTimestamp } from "../../../util/time.js";
17
17
 
18
18
  const CHECK_INTERVAL_MS = 5 * 60_000;
19
19
 
@@ -8,16 +8,19 @@
8
8
  * Knows nothing about the backend or frontend — uses the dispatcher.
9
9
  */
10
10
 
11
- import { execute, getActiveCount } from "../engine/dispatcher.js";
11
+ import { execute, getActiveCount } from "../../engine/dispatcher.js";
12
12
  import {
13
13
  setChatPulse,
14
14
  getRegisteredPulseChats,
15
15
  getChatSettings,
16
16
  setPulseLastCheckMsgId,
17
- } from "../../storage/chat-settings.js";
18
- import { getRecentHistory, getLatestMessageId } from "../../storage/history.js";
19
- import { log, logError } from "../../util/log.js";
20
- import { formatSmartTimestamp } from "../../util/time.js";
17
+ } from "../../../storage/chat-settings.js";
18
+ import {
19
+ getRecentHistory,
20
+ getLatestMessageId,
21
+ } from "../../../storage/history.js";
22
+ import { log, logError } from "../../../util/log.js";
23
+ import { formatSmartTimestamp } from "../../../util/time.js";
21
24
 
22
25
  // ── State ────────────────────────────────────────────────────────────────────
23
26
 
@@ -6,8 +6,8 @@
6
6
 
7
7
  import { spawnSync } from "node:child_process";
8
8
  import type { Trigger } from "../../../storage/triggers.js";
9
- import { selfInvocation } from "../../../util/mcp-launcher.js";
10
- import { LUA_RUN_SUBCOMMAND } from "../../scripting/lua-runner.js";
9
+ import { selfInvocation } from "../../mcp-hub/launcher.js";
10
+ import { LUA_RUN_SUBCOMMAND } from "../../scripts/lua.js";
11
11
 
12
12
  export function commandForLanguage(
13
13
  lang: Trigger["language"],
@@ -14,7 +14,7 @@
14
14
  */
15
15
 
16
16
  import { chmodSync } from "node:fs";
17
- import { dirs, files } from "./paths.js";
17
+ import { dirs, files } from "../../util/paths.js";
18
18
 
19
19
  const OWNER_DIR = 0o700;
20
20
  const OWNER_FILE = 0o600;
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, mkdirSync } from "node:fs";
2
2
  import writeFileAtomic from "write-file-atomic";
3
3
  import { z } from "zod";
4
4
  import { dirs, files as pathFiles } from "../../util/paths.js";
5
- import { hardenTalonPermissions } from "../../util/harden.js";
5
+ import { hardenTalonPermissions } from "./harden.js";
6
6
  import { setTimezone } from "../../util/time.js";
7
7
  import { BACKEND_IDS } from "../agent-runtime/model-ref.js";
8
8
  import { REASONING_LEVEL_ORDER } from "../models/reasoning-levels.js";
@@ -557,16 +557,11 @@ const configSchema = z.object({
557
557
  // Playwright — headless browser automation via MCP
558
558
  playwright: playwrightConfigSchema.optional(),
559
559
 
560
- // Soul — compiled, self-organizing identity kernel (experimental).
561
- // Off by default; when enabled, the projected identity surface is injected
562
- // into the system prompt and the organic pass runs on the dream cadence.
563
- soul: z
564
- .object({
565
- enabled: z.boolean().default(false),
566
- /** Kernel persistence path (default: ~/.talon/data/soul.json) */
567
- path: z.string().min(1).optional(),
568
- })
569
- .optional(),
560
+ // Soul — the compiled identity kernel, removed in #953. The root schema
561
+ // is `.strict()`, so a key that simply disappeared would make every
562
+ // existing config.json fail to parse; accepted and ignored instead, with
563
+ // one warning at load so the operator knows to drop it.
564
+ soul: z.unknown().optional(),
570
565
 
571
566
  // Discord — discord.js v14-based frontend
572
567
  discord: discordConfigSchema.optional(),
@@ -741,6 +736,15 @@ export function loadConfig(): TalonConfig {
741
736
 
742
737
  const parsed = configSchema.parse(fileConfig);
743
738
 
739
+ // The soul kernel is gone (#953). Its config block still parses so an
740
+ // existing config.json keeps loading, but it no longer does anything —
741
+ // say so once rather than silently ignoring it.
742
+ if (parsed.soul !== undefined) {
743
+ console.warn(
744
+ `Ignoring "soul" in ${CONFIG_FILE}: the soul kernel was removed; its message taps now write to the memory store. Remove the key.`,
745
+ );
746
+ }
747
+
744
748
  // Unified memory section: mirror the selected backend onto the per-plugin
745
749
  // section the loaders consume (builtins.ts reads config.mempalace /
746
750
  // config.mem0). The memory section wins over a legacy section when both
@@ -827,7 +831,7 @@ export function primaryFrontend(config: TalonConfig): string {
827
831
  * the config. Multi-frontend deployments need per-chat prompt
828
832
  * flavours (a native-app chat must get native.md guidance, not the
829
833
  * telegram.md that `frontends[0]` happens to be) — the per-session
830
- * snapshot layer (backend/shared/system-prompt.ts) calls this with the
834
+ * snapshot layer (backend/runtime/prompt/system-prompt.ts) calls this with the
831
835
  * chat's owning frontend and freezes the result per session.
832
836
  */
833
837
  export function buildSystemPromptPartsFor(
@@ -4,7 +4,9 @@
4
4
  * has an answer in the log instead of a profiler session.
5
5
  */
6
6
 
7
- const phases: { label: string; ms: number }[] = [];
7
+ export type BootPhaseSample = { label: string; ms: number };
8
+
9
+ const phases: BootPhaseSample[] = [];
8
10
 
9
11
  /** Run one startup phase and remember how long it took. */
10
12
  export async function bootPhase<T>(
@@ -25,6 +27,18 @@ export function bootReport(now = Math.round(process.uptime() * 1000)): string {
25
27
  return parts.length ? `${now}ms (${parts.join(", ")})` : `${now}ms`;
26
28
  }
27
29
 
30
+ /**
31
+ * The recorded phases, in the order they completed.
32
+ *
33
+ * `util/` is a leaf (.dependency-cruiser.cjs: util-is-a-leaf), so this
34
+ * module cannot write to the metrics store itself. It hands the samples
35
+ * out instead and `core/daemon/resource-sampler.ts` turns them into
36
+ * `boot.<phase>_ms` histograms.
37
+ */
38
+ export function bootPhases(): readonly BootPhaseSample[] {
39
+ return phases;
40
+ }
41
+
28
42
  /** Test seam. */
29
43
  export function resetBootPhases(): void {
30
44
  phases.length = 0;
@@ -11,7 +11,7 @@
11
11
  * gateway may fall back to a different port on EADDRINUSE, so the
12
12
  * port is only known at runtime).
13
13
  * - Removal is guarded by pid. During a `/restart` handoff
14
- * (util/respawn.ts) the successor overwrites the file with its own
14
+ * (./respawn.ts) the successor overwrites the file with its own
15
15
  * pid *before* the dying parent finishes its graceful shutdown — an
16
16
  * unconditional unlink there would orphan the new daemon, making
17
17
  * `talon stop`/`talon restart` report "not running" and spawn
@@ -0,0 +1,121 @@
1
+ /**
2
+ * The daemon's accounting of its own resources — boot cost and resident
3
+ * memory. Measurement only: nothing here changes a prompt byte or a
4
+ * turn's behaviour.
5
+ *
6
+ * Why these numbers exist (docs/ts-migration-plan.md, Phase 0 — Measure):
7
+ * the migration plan's entry gate is "numbers in hand", and its kill
8
+ * criterion is stated in terms of the control plane's share of a turn plus
9
+ * "RSS is acceptable". Neither can be argued without a baseline, and the
10
+ * metrics store had latency and tokens but nothing about the process
11
+ * itself.
12
+ *
13
+ * - `boot.total_ms` — process start → frontends listening. The figure
14
+ * `Ready in …` already logs, kept as a distribution so successive
15
+ * restarts can be compared instead of grepped.
16
+ * - `boot.<phase>_ms` — each awaited startup phase (`./boot-timer.ts`
17
+ * records them), so a slow boot names its own culprit.
18
+ * - `boot.rss_mb` / `boot.heap_mb` — what the process costs the moment
19
+ * it is serving, before any turn has run. The floor an alternative
20
+ * runtime or language would have to beat.
21
+ * - `rss.mb`, `heap_used.mb`, `external.mb`, `handles.count` — the same
22
+ * picture sampled every minute for the process lifetime, which is what
23
+ * answers "idle RSS" and "does it creep?" (the Phase 1 soak log asks
24
+ * exactly this and is currently filled in by hand).
25
+ *
26
+ * Sampling must never throw: this runs on a timer inside a live daemon,
27
+ * and a metric that can take the process down is worse than no metric.
28
+ */
29
+
30
+ import { bootPhases } from "./boot-timer.js";
31
+ import { recordHistogram } from "../../storage/metrics.js";
32
+
33
+ /** One minute. Idle RSS moves slowly; a tighter loop would only add noise. */
34
+ const SAMPLE_INTERVAL_MS = 60_000;
35
+
36
+ const BYTES_PER_MB = 1024 * 1024;
37
+
38
+ let timer: ReturnType<typeof setInterval> | null = null;
39
+
40
+ function mb(bytes: number): number {
41
+ return Math.round(bytes / BYTES_PER_MB);
42
+ }
43
+
44
+ /**
45
+ * `frontends start` → `boot.frontends_start_ms`. Phase labels are prose
46
+ * ("backend + dispatcher"), metric names are not.
47
+ */
48
+ function slug(label: string): string {
49
+ return (
50
+ label
51
+ .toLowerCase()
52
+ .replace(/[^a-z0-9]+/g, "_")
53
+ .replace(/^_+|_+$/g, "") || "unnamed"
54
+ );
55
+ }
56
+
57
+ /** How many active handles the runtime reports, when it can report it. */
58
+ function activeResourceCount(): number | undefined {
59
+ // Node 18.11+ / Bun. Absent on older runtimes, and there is no cheap
60
+ // supported substitute — the metric is simply skipped there.
61
+ const read = (process as { getActiveResourcesInfo?: () => readonly string[] })
62
+ .getActiveResourcesInfo;
63
+ if (typeof read !== "function") return undefined;
64
+ const info = read.call(process);
65
+ return Array.isArray(info) ? info.length : undefined;
66
+ }
67
+
68
+ /** Record one resident-memory sample. Safe to call at any time. */
69
+ function sampleResources(): void {
70
+ try {
71
+ const mem = process.memoryUsage();
72
+ recordHistogram("rss.mb", mb(mem.rss));
73
+ recordHistogram("heap_used.mb", mb(mem.heapUsed));
74
+ recordHistogram("external.mb", mb(mem.external));
75
+ const handles = activeResourceCount();
76
+ if (handles !== undefined) recordHistogram("handles.count", handles);
77
+ } catch {
78
+ // A failed sample is a missing data point, never a failed daemon.
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Fold the boot into the metrics store: the total, every phase the boot
84
+ * timer recorded, and the memory the process holds now that it is serving.
85
+ *
86
+ * `totalMs` defaults to process uptime — the same figure `bootReport()`
87
+ * prints, so the log line and the histogram cannot disagree.
88
+ */
89
+ export function recordBootMetrics(
90
+ totalMs = Math.round(process.uptime() * 1000),
91
+ ): void {
92
+ try {
93
+ recordHistogram("boot.total_ms", totalMs);
94
+ for (const phase of bootPhases()) {
95
+ recordHistogram(`boot.${slug(phase.label)}_ms`, phase.ms);
96
+ }
97
+ const mem = process.memoryUsage();
98
+ recordHistogram("boot.rss_mb", mb(mem.rss));
99
+ recordHistogram("boot.heap_mb", mb(mem.heapUsed));
100
+ } catch {
101
+ // As above: measurement never breaks the boot it is measuring.
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Start the idle sampler. Unref'd, so it never holds the event loop open
107
+ * and never keeps a daemon alive that is otherwise done. Idempotent —
108
+ * a second call is a no-op rather than a second timer.
109
+ */
110
+ export function startResourceSampler(): void {
111
+ if (timer) return;
112
+ timer = setInterval(sampleResources, SAMPLE_INTERVAL_MS);
113
+ timer.unref();
114
+ }
115
+
116
+ /** Stop the idle sampler (shutdown, and the test seam). */
117
+ export function stopResourceSampler(): void {
118
+ if (!timer) return;
119
+ clearInterval(timer);
120
+ timer = null;
121
+ }
@@ -29,7 +29,7 @@
29
29
  */
30
30
 
31
31
  import { spawn } from "node:child_process";
32
- import { log, logError } from "./log.js";
32
+ import { log, logError } from "../../util/log.js";
33
33
 
34
34
  let pendingReason: string | null = null;
35
35
 
@@ -423,7 +423,7 @@ export async function collectDoctorReport(opts: {
423
423
  // is which is the difference between "why didn't my prompt update?"
424
424
  // and a one-line answer.
425
425
  {
426
- const { promptSeedReport } = await import("../../util/workspace.js");
426
+ const { promptSeedReport } = await import("../vfs/workspace.js");
427
427
  try {
428
428
  const { tracking, edited } = promptSeedReport();
429
429
  if (tracking.length + edited.length > 0) {
@@ -10,6 +10,7 @@
10
10
 
11
11
  import type { ExecuteParams, ExecuteResult } from "../types.js";
12
12
  import { formatRelayBlock, takePendingRelay } from "./cross-chat-relay.js";
13
+ import { recordMessageSignal } from "../memory/taps.js";
13
14
  import { log } from "../../util/log.js";
14
15
  import { taskTable, type KillOutcome } from "../tasks/index.js";
15
16
  import { initWeaver, type Weaver, type WeaverDeps } from "../weaver/index.js";
@@ -71,9 +72,24 @@ export function stopAllTurns(): number {
71
72
  * Every turn for every frontend and every source funnels through here,
72
73
  * which makes it the one place a cross-chat reply can be folded in
73
74
  * without teaching each frontend about the relay.
75
+ *
76
+ * It is also where the memory tap lives, for the same reason: a
77
+ * directive is a directive whether it arrives over Telegram, Discord,
78
+ * WhatsApp, Teams, the native bridge or the terminal, and the tap used
79
+ * to see only one of them. Only `source: "message"` is tapped — a pulse,
80
+ * a cron job or a trigger is Talon prompting itself, and "always reply
81
+ * in one line" written by a scheduler is not standing human intent.
74
82
  */
75
83
  export async function execute(params: ExecuteParams): Promise<ExecuteResult> {
76
84
  if (!weaver) throw new Error("Dispatcher not initialized");
85
+ // Fire-and-forget: the tap is a synchronous store write that must not
86
+ // be able to delay or fail the turn (it swallows its own errors).
87
+ if (params.source === "message")
88
+ recordMessageSignal({
89
+ text: params.prompt,
90
+ chatKey: params.chatId,
91
+ ...(params.senderName ? { actor: params.senderName } : {}),
92
+ });
77
93
  const relayed = takePendingRelay(params.chatId);
78
94
  const prompt = relayed.length
79
95
  ? formatRelayBlock(relayed) + params.prompt
@@ -12,8 +12,8 @@ import {
12
12
  describeSchedule,
13
13
  nextRunAt,
14
14
  } from "../../../storage/cron.js";
15
- import { runJobNow } from "../../background/cron.js";
16
- import { parseCronSpec } from "../../background/cron-spec.js";
15
+ import { runJobNow } from "../../background/cron/scheduler.js";
16
+ import { parseCronSpec } from "../../background/cron/spec.js";
17
17
  import { log } from "../../../util/log.js";
18
18
  import type { Backend } from "../../agent-runtime/capabilities.js";
19
19
  import {
@@ -18,7 +18,7 @@ import {
18
18
  isHtmlContent,
19
19
  isTextContent,
20
20
  matchesBinaryKind,
21
- } from "../../../util/web-content.js";
21
+ } from "../../tools/content/web-content.js";
22
22
  import { dirs } from "../../../util/paths.js";
23
23
  import type { SharedActionHandlers } from "./types.js";
24
24
 
@@ -12,6 +12,7 @@
12
12
  * - `cron` — scheduled-job CRUD
13
13
  * - `triggers` — long-running watcher-script CRUD
14
14
  * - `goals` — persistent multi-turn objectives
15
+ * - `memory` — remember / recall / forget over the typed memory store
15
16
  * - `scripts` — reusable agent-authored scripts
16
17
  * - `skills` — markdown workflows
17
18
  * - `plugins` — plugin hot-reload
@@ -28,6 +29,7 @@ import { fetchUrlHandlers } from "./fetch-url.js";
28
29
  import { cronHandlers } from "./cron.js";
29
30
  import { triggerHandlers } from "./triggers.js";
30
31
  import { goalHandlers } from "./goals.js";
32
+ import { memoryHandlers } from "./memory.js";
31
33
  import { scriptHandlers } from "./scripts.js";
32
34
  import { skillHandlers } from "./skills.js";
33
35
  import { pluginHandlers } from "./plugins.js";
@@ -41,7 +43,7 @@ import {
41
43
  whatsappAccountHandlers,
42
44
  whatsappAccountChatFreeActions,
43
45
  } from "./whatsapp-account.js";
44
- import { nativeHandlers } from "./native.js";
46
+ import { nativeHandlers } from "./native/index.js";
45
47
 
46
48
  // Null-prototype so a request `action` of "toString" / "constructor" / etc.
47
49
  // can't resolve an inherited Object.prototype method — `handlers[action]` only
@@ -52,6 +54,7 @@ const handlers: SharedActionHandlers = Object.assign(Object.create(null), {
52
54
  ...cronHandlers,
53
55
  ...triggerHandlers,
54
56
  ...goalHandlers,
57
+ ...memoryHandlers,
55
58
  ...scriptHandlers,
56
59
  ...skillHandlers,
57
60
  ...pluginHandlers,