@tenex-chat/backend 0.9.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 (427) hide show
  1. package/README.md +194 -0
  2. package/dist/backend-wrapper.cjs +3 -0
  3. package/dist/src/index.js +331928 -0
  4. package/package.json +103 -0
  5. package/src/agents/AgentRegistry.ts +418 -0
  6. package/src/agents/AgentStorage.ts +1133 -0
  7. package/src/agents/ConfigResolver.ts +229 -0
  8. package/src/agents/agent-installer.ts +236 -0
  9. package/src/agents/agent-loader.ts +241 -0
  10. package/src/agents/constants.ts +82 -0
  11. package/src/agents/errors.ts +48 -0
  12. package/src/agents/execution/AgentExecutor.ts +561 -0
  13. package/src/agents/execution/ExecutionContextFactory.ts +112 -0
  14. package/src/agents/execution/MessageCompiler.ts +597 -0
  15. package/src/agents/execution/MessageSyncer.ts +100 -0
  16. package/src/agents/execution/PostCompletionChecker.ts +278 -0
  17. package/src/agents/execution/ProgressMonitor.ts +50 -0
  18. package/src/agents/execution/RALResolver.ts +177 -0
  19. package/src/agents/execution/SessionManager.ts +181 -0
  20. package/src/agents/execution/StreamCallbacks.ts +312 -0
  21. package/src/agents/execution/StreamExecutionHandler.ts +579 -0
  22. package/src/agents/execution/StreamSetup.ts +313 -0
  23. package/src/agents/execution/ToolEventHandlers.ts +239 -0
  24. package/src/agents/execution/ToolExecutionTracker.ts +498 -0
  25. package/src/agents/execution/ToolResultUtils.ts +97 -0
  26. package/src/agents/execution/ToolSupervisionWrapper.ts +174 -0
  27. package/src/agents/execution/constants.ts +16 -0
  28. package/src/agents/execution/index.ts +3 -0
  29. package/src/agents/execution/types.ts +96 -0
  30. package/src/agents/execution/utils.ts +26 -0
  31. package/src/agents/index.ts +4 -0
  32. package/src/agents/script-installer.ts +266 -0
  33. package/src/agents/supervision/SupervisorLLMService.ts +253 -0
  34. package/src/agents/supervision/SupervisorOrchestrator.ts +471 -0
  35. package/src/agents/supervision/heuristics/ConsecutiveToolsWithoutTodoHeuristic.ts +73 -0
  36. package/src/agents/supervision/heuristics/DelegationClaimHeuristic.ts +80 -0
  37. package/src/agents/supervision/heuristics/HeuristicRegistry.ts +114 -0
  38. package/src/agents/supervision/heuristics/PendingTodosHeuristic.ts +93 -0
  39. package/src/agents/supervision/heuristics/SilentAgentHeuristic.ts +54 -0
  40. package/src/agents/supervision/heuristics/index.ts +5 -0
  41. package/src/agents/supervision/index.ts +28 -0
  42. package/src/agents/supervision/registerHeuristics.ts +110 -0
  43. package/src/agents/supervision/supervisionHealthCheck.ts +123 -0
  44. package/src/agents/supervision/types.ts +171 -0
  45. package/src/agents/tool-names.ts +46 -0
  46. package/src/agents/tool-normalization.ts +184 -0
  47. package/src/agents/types/index.ts +2 -0
  48. package/src/agents/types/runtime.ts +74 -0
  49. package/src/agents/types/storage.ts +145 -0
  50. package/src/commands/agent/import/index.ts +6 -0
  51. package/src/commands/agent/import/openclaw-distiller.ts +57 -0
  52. package/src/commands/agent/import/openclaw-reader.ts +141 -0
  53. package/src/commands/agent/import/openclaw.ts +154 -0
  54. package/src/commands/agent/index.ts +6 -0
  55. package/src/commands/agent.ts +215 -0
  56. package/src/commands/daemon.ts +198 -0
  57. package/src/commands/doctor.ts +134 -0
  58. package/src/commands/setup/embed.ts +228 -0
  59. package/src/commands/setup/global-system-prompt.ts +223 -0
  60. package/src/commands/setup/image.ts +179 -0
  61. package/src/commands/setup/index.ts +16 -0
  62. package/src/commands/setup/interactive.ts +95 -0
  63. package/src/commands/setup/llm.ts +38 -0
  64. package/src/commands/setup/onboarding.ts +294 -0
  65. package/src/commands/setup/providers.ts +27 -0
  66. package/src/constants.ts +34 -0
  67. package/src/conversations/ConversationDiskReader.ts +148 -0
  68. package/src/conversations/ConversationRegistry.ts +728 -0
  69. package/src/conversations/ConversationStore.ts +868 -0
  70. package/src/conversations/MessageBuilder.ts +866 -0
  71. package/src/conversations/executionTime.ts +62 -0
  72. package/src/conversations/formatters/DelegationXmlFormatter.ts +64 -0
  73. package/src/conversations/formatters/ThreadedConversationFormatter.ts +303 -0
  74. package/src/conversations/formatters/index.ts +9 -0
  75. package/src/conversations/formatters/utils/MessageFormatter.ts +46 -0
  76. package/src/conversations/formatters/utils/TimestampFormatter.ts +56 -0
  77. package/src/conversations/formatters/utils/TreeBuilder.ts +131 -0
  78. package/src/conversations/formatters/utils/TreeRenderer.ts +49 -0
  79. package/src/conversations/index.ts +2 -0
  80. package/src/conversations/persistence/ToolMessageStorage.ts +143 -0
  81. package/src/conversations/search/ConversationIndexManager.ts +393 -0
  82. package/src/conversations/search/QueryParser.ts +114 -0
  83. package/src/conversations/search/SearchEngine.ts +175 -0
  84. package/src/conversations/search/SnippetExtractor.ts +345 -0
  85. package/src/conversations/search/embeddings/ConversationEmbeddingService.ts +484 -0
  86. package/src/conversations/search/embeddings/ConversationIndexingJob.ts +320 -0
  87. package/src/conversations/search/embeddings/IndexingStateManager.ts +338 -0
  88. package/src/conversations/search/embeddings/index.ts +18 -0
  89. package/src/conversations/search/index.ts +49 -0
  90. package/src/conversations/search/types.ts +124 -0
  91. package/src/conversations/services/CategoryManager.ts +160 -0
  92. package/src/conversations/services/ConversationResolver.ts +296 -0
  93. package/src/conversations/services/ConversationSummarizer.ts +234 -0
  94. package/src/conversations/services/MetadataDebounceManager.ts +188 -0
  95. package/src/conversations/services/index.ts +2 -0
  96. package/src/conversations/types.ts +148 -0
  97. package/src/conversations/utils/content-utils.ts +69 -0
  98. package/src/conversations/utils/image-placeholder.ts +281 -0
  99. package/src/conversations/utils/image-url-utils.ts +171 -0
  100. package/src/conversations/utils/multimodal-content.ts +90 -0
  101. package/src/conversations/utils/tool-result-truncator.ts +159 -0
  102. package/src/daemon/Daemon.ts +1883 -0
  103. package/src/daemon/ProjectRuntime.ts +657 -0
  104. package/src/daemon/RestartState.ts +152 -0
  105. package/src/daemon/RuntimeLifecycle.ts +268 -0
  106. package/src/daemon/SubscriptionManager.ts +305 -0
  107. package/src/daemon/UnixSocketTransport.ts +318 -0
  108. package/src/daemon/filters/SubscriptionFilterBuilder.ts +119 -0
  109. package/src/daemon/index.ts +9 -0
  110. package/src/daemon/routing/DaemonRouter.ts +491 -0
  111. package/src/daemon/types.ts +150 -0
  112. package/src/daemon/utils/routing-log.ts +76 -0
  113. package/src/daemon/utils/telemetry.ts +173 -0
  114. package/src/event-handler/agentDeletion.ts +383 -0
  115. package/src/event-handler/index.ts +749 -0
  116. package/src/event-handler/newConversation.ts +165 -0
  117. package/src/event-handler/project.ts +166 -0
  118. package/src/event-handler/reply.ts +18 -0
  119. package/src/events/NDKAgentDefinition.ts +292 -0
  120. package/src/events/NDKAgentLesson.ts +106 -0
  121. package/src/events/NDKEventMetadata.ts +34 -0
  122. package/src/events/NDKMCPTool.ts +60 -0
  123. package/src/events/NDKProjectStatus.ts +384 -0
  124. package/src/events/index.ts +4 -0
  125. package/src/index.ts +126 -0
  126. package/src/lib/agent-home.ts +334 -0
  127. package/src/lib/error-formatter.ts +200 -0
  128. package/src/lib/fs/filesystem.ts +128 -0
  129. package/src/lib/fs/index.ts +1 -0
  130. package/src/lib/json-parser.ts +30 -0
  131. package/src/lib/string.ts +15 -0
  132. package/src/lib/time.ts +74 -0
  133. package/src/llm/ChunkHandler.ts +277 -0
  134. package/src/llm/FinishHandler.ts +250 -0
  135. package/src/llm/LLMConfigEditor.ts +154 -0
  136. package/src/llm/LLMServiceFactory.ts +230 -0
  137. package/src/llm/MessageProcessor.ts +90 -0
  138. package/src/llm/RecordingState.ts +37 -0
  139. package/src/llm/StreamPublisher.ts +40 -0
  140. package/src/llm/TracingUtils.ts +77 -0
  141. package/src/llm/chunk-validators.ts +57 -0
  142. package/src/llm/constants.ts +6 -0
  143. package/src/llm/index.ts +12 -0
  144. package/src/llm/meta/MetaModelResolver.ts +352 -0
  145. package/src/llm/meta/index.ts +11 -0
  146. package/src/llm/middleware/flight-recorder.ts +188 -0
  147. package/src/llm/providers/MockProvider.ts +332 -0
  148. package/src/llm/providers/agent/ClaudeCodeProvider.ts +343 -0
  149. package/src/llm/providers/agent/ClaudeCodeToolsAdapter.ts +203 -0
  150. package/src/llm/providers/agent/CodexAppServerProvider.ts +214 -0
  151. package/src/llm/providers/agent/CodexAppServerToolsAdapter.ts +91 -0
  152. package/src/llm/providers/agent/index.ts +10 -0
  153. package/src/llm/providers/base/AgentProvider.ts +107 -0
  154. package/src/llm/providers/base/BaseProvider.ts +114 -0
  155. package/src/llm/providers/base/StandardProvider.ts +38 -0
  156. package/src/llm/providers/base/index.ts +9 -0
  157. package/src/llm/providers/index.ts +106 -0
  158. package/src/llm/providers/key-manager.ts +238 -0
  159. package/src/llm/providers/ollama-models.ts +105 -0
  160. package/src/llm/providers/openrouter-models.ts +102 -0
  161. package/src/llm/providers/provider-ids.ts +18 -0
  162. package/src/llm/providers/registry/ProviderRegistry.ts +414 -0
  163. package/src/llm/providers/registry/index.ts +7 -0
  164. package/src/llm/providers/standard/AnthropicProvider.ts +71 -0
  165. package/src/llm/providers/standard/OllamaProvider.ts +59 -0
  166. package/src/llm/providers/standard/OpenAIProvider.ts +44 -0
  167. package/src/llm/providers/standard/OpenRouterProvider.ts +103 -0
  168. package/src/llm/providers/standard/index.ts +10 -0
  169. package/src/llm/providers/types.ts +194 -0
  170. package/src/llm/providers/usage-metadata.ts +78 -0
  171. package/src/llm/service.ts +713 -0
  172. package/src/llm/types.ts +167 -0
  173. package/src/llm/utils/ConfigurationManager.ts +650 -0
  174. package/src/llm/utils/ConfigurationTester.ts +229 -0
  175. package/src/llm/utils/ModelSelector.ts +212 -0
  176. package/src/llm/utils/ProviderConfigUI.ts +177 -0
  177. package/src/llm/utils/claudeCodePromptCompiler.ts +141 -0
  178. package/src/llm/utils/codex-models.ts +53 -0
  179. package/src/llm/utils/context-window-cache.ts +30 -0
  180. package/src/llm/utils/models-dev-cache.ts +267 -0
  181. package/src/llm/utils/provider-setup.ts +50 -0
  182. package/src/llm/utils/tool-errors.ts +78 -0
  183. package/src/llm/utils/usage.ts +74 -0
  184. package/src/logging/EventRoutingLogger.ts +205 -0
  185. package/src/nostr/AgentEventDecoder.ts +357 -0
  186. package/src/nostr/AgentEventEncoder.ts +677 -0
  187. package/src/nostr/AgentProfilePublisher.ts +657 -0
  188. package/src/nostr/AgentPublisher.ts +437 -0
  189. package/src/nostr/BlossomService.ts +226 -0
  190. package/src/nostr/InterventionPublisher.ts +132 -0
  191. package/src/nostr/TagExtractor.ts +228 -0
  192. package/src/nostr/collectEvents.ts +83 -0
  193. package/src/nostr/constants.ts +38 -0
  194. package/src/nostr/encryption.ts +26 -0
  195. package/src/nostr/index.ts +31 -0
  196. package/src/nostr/keys.ts +17 -0
  197. package/src/nostr/kinds.ts +37 -0
  198. package/src/nostr/ndkClient.ts +72 -0
  199. package/src/nostr/relays.ts +43 -0
  200. package/src/nostr/trace-context.ts +39 -0
  201. package/src/nostr/types.ts +227 -0
  202. package/src/nostr/utils.ts +84 -0
  203. package/src/prompts/core/FragmentRegistry.ts +30 -0
  204. package/src/prompts/core/PromptBuilder.ts +98 -0
  205. package/src/prompts/core/index.ts +3 -0
  206. package/src/prompts/core/types.ts +13 -0
  207. package/src/prompts/fragments/00-global-system-prompt.ts +44 -0
  208. package/src/prompts/fragments/01-agent-identity.ts +69 -0
  209. package/src/prompts/fragments/02-agent-home-directory.ts +114 -0
  210. package/src/prompts/fragments/03-system-reminders-explanation.ts +14 -0
  211. package/src/prompts/fragments/04-relay-configuration.ts +38 -0
  212. package/src/prompts/fragments/05-delegation-chain.ts +45 -0
  213. package/src/prompts/fragments/06-agent-todos.ts +74 -0
  214. package/src/prompts/fragments/06-todo-usage-guidance.ts +34 -0
  215. package/src/prompts/fragments/07-meta-project-context.ts +234 -0
  216. package/src/prompts/fragments/08-active-conversations.ts +382 -0
  217. package/src/prompts/fragments/09-recent-conversations.ts +153 -0
  218. package/src/prompts/fragments/10-referenced-article.ts +21 -0
  219. package/src/prompts/fragments/11-nudges.ts +134 -0
  220. package/src/prompts/fragments/12-skills.ts +127 -0
  221. package/src/prompts/fragments/13-available-nudges.ts +122 -0
  222. package/src/prompts/fragments/15-available-agents.ts +53 -0
  223. package/src/prompts/fragments/16-stay-in-your-lane.ts +41 -0
  224. package/src/prompts/fragments/17-todo-before-delegation.ts +39 -0
  225. package/src/prompts/fragments/20-voice-mode.ts +62 -0
  226. package/src/prompts/fragments/22-scheduled-tasks.ts +175 -0
  227. package/src/prompts/fragments/24-retrieved-lessons.ts +26 -0
  228. package/src/prompts/fragments/25-rag-instructions.ts +333 -0
  229. package/src/prompts/fragments/26-mcp-resources.ts +237 -0
  230. package/src/prompts/fragments/27-memorized-reports.ts +77 -0
  231. package/src/prompts/fragments/28-agent-directed-monitoring.ts +32 -0
  232. package/src/prompts/fragments/29-rag-collections.ts +50 -0
  233. package/src/prompts/fragments/30-worktree-context.ts +98 -0
  234. package/src/prompts/fragments/31-agents-md-guidance.ts +96 -0
  235. package/src/prompts/fragments/32-process-metrics.ts +72 -0
  236. package/src/prompts/fragments/debug-mode.ts +48 -0
  237. package/src/prompts/fragments/delegation-completion.ts +44 -0
  238. package/src/prompts/fragments/index.ts +91 -0
  239. package/src/prompts/index.ts +21 -0
  240. package/src/prompts/utils/systemPromptBuilder.ts +777 -0
  241. package/src/scripts/migrate-prefix-index.ts +157 -0
  242. package/src/services/AgentDefinitionMonitor.ts +701 -0
  243. package/src/services/ConfigService.ts +723 -0
  244. package/src/services/CooldownRegistry.ts +199 -0
  245. package/src/services/LLMOperationsRegistry.ts +424 -0
  246. package/src/services/OwnerAgentListService.ts +354 -0
  247. package/src/services/PubkeyService.ts +308 -0
  248. package/src/services/agents/AgentMetadataStore.ts +72 -0
  249. package/src/services/agents/AgentResolution.ts +59 -0
  250. package/src/services/agents/EscalationService.ts +281 -0
  251. package/src/services/agents/NDKAgentDiscovery.ts +95 -0
  252. package/src/services/agents/index.ts +7 -0
  253. package/src/services/agents-md/AgentsMdService.ts +184 -0
  254. package/src/services/agents-md/SystemReminderInjector.ts +238 -0
  255. package/src/services/agents-md/index.ts +11 -0
  256. package/src/services/apns/APNsClient.ts +203 -0
  257. package/src/services/apns/APNsService.ts +358 -0
  258. package/src/services/apns/index.ts +11 -0
  259. package/src/services/apns/types.ts +80 -0
  260. package/src/services/compression/CompressionService.ts +445 -0
  261. package/src/services/compression/compression-schema.ts +28 -0
  262. package/src/services/compression/compression-types.ts +74 -0
  263. package/src/services/compression/compression-utils.ts +587 -0
  264. package/src/services/config/types.ts +394 -0
  265. package/src/services/dispatch/AgentDispatchService.ts +937 -0
  266. package/src/services/dispatch/AgentRouter.ts +181 -0
  267. package/src/services/dispatch/DelegationCompletionHandler.ts +232 -0
  268. package/src/services/embedding/EmbeddingProvider.ts +188 -0
  269. package/src/services/embedding/index.ts +5 -0
  270. package/src/services/event-context/EventContextService.ts +108 -0
  271. package/src/services/event-context/index.ts +2 -0
  272. package/src/services/heuristics/ContextBuilder.ts +106 -0
  273. package/src/services/heuristics/HeuristicEngine.ts +200 -0
  274. package/src/services/heuristics/formatters.ts +58 -0
  275. package/src/services/heuristics/index.ts +12 -0
  276. package/src/services/heuristics/rules/index.ts +25 -0
  277. package/src/services/heuristics/rules/todoBeforeDelegation.ts +69 -0
  278. package/src/services/heuristics/rules/todoReminderOnToolUse.ts +63 -0
  279. package/src/services/heuristics/types.ts +144 -0
  280. package/src/services/image/ImageGenerationService.ts +389 -0
  281. package/src/services/image/index.ts +12 -0
  282. package/src/services/intervention/InterventionService.ts +1352 -0
  283. package/src/services/intervention/index.ts +7 -0
  284. package/src/services/mcp/MCPManager.ts +683 -0
  285. package/src/services/mcp/McpNotificationDelivery.ts +139 -0
  286. package/src/services/mcp/McpSubscriptionService.ts +653 -0
  287. package/src/services/mcp/mcpInstaller.ts +130 -0
  288. package/src/services/nip46/Nip46SigningLog.ts +81 -0
  289. package/src/services/nip46/Nip46SigningService.ts +467 -0
  290. package/src/services/nip46/index.ts +4 -0
  291. package/src/services/nudge/NudgeService.ts +224 -0
  292. package/src/services/nudge/NudgeWhitelistService.ts +382 -0
  293. package/src/services/nudge/index.ts +5 -0
  294. package/src/services/nudge/types.ts +83 -0
  295. package/src/services/projects/ProjectContext.ts +672 -0
  296. package/src/services/projects/ProjectContextStore.ts +102 -0
  297. package/src/services/projects/index.ts +6 -0
  298. package/src/services/prompt-compiler/index.ts +15 -0
  299. package/src/services/prompt-compiler/prompt-compiler-service.ts +1143 -0
  300. package/src/services/pubkey-gate/PubkeyGateService.ts +93 -0
  301. package/src/services/pubkey-gate/index.ts +1 -0
  302. package/src/services/rag/EmbeddingProviderFactory.ts +292 -0
  303. package/src/services/rag/LanceDBMaintenanceService.ts +211 -0
  304. package/src/services/rag/RAGDatabaseService.ts +173 -0
  305. package/src/services/rag/RAGOperations.ts +682 -0
  306. package/src/services/rag/RAGService.ts +240 -0
  307. package/src/services/rag/RagSubscriptionService.ts +618 -0
  308. package/src/services/rag/rag-utils.ts +174 -0
  309. package/src/services/ral/PendingDelegationsRegistry.ts +168 -0
  310. package/src/services/ral/RALRegistry.ts +2782 -0
  311. package/src/services/ral/index.ts +4 -0
  312. package/src/services/ral/types.ts +292 -0
  313. package/src/services/reports/LocalReportStore.ts +380 -0
  314. package/src/services/reports/ReportEmbeddingService.ts +430 -0
  315. package/src/services/reports/ReportService.ts +440 -0
  316. package/src/services/reports/articleUtils.ts +52 -0
  317. package/src/services/reports/index.ts +7 -0
  318. package/src/services/scheduling/SchedulerService.ts +1057 -0
  319. package/src/services/scheduling/errors.ts +14 -0
  320. package/src/services/scheduling/index.ts +7 -0
  321. package/src/services/scheduling/utils.ts +77 -0
  322. package/src/services/search/SearchProviderRegistry.ts +78 -0
  323. package/src/services/search/UnifiedSearchService.ts +218 -0
  324. package/src/services/search/index.ts +47 -0
  325. package/src/services/search/projectFilter.ts +22 -0
  326. package/src/services/search/providers/ConversationSearchProvider.ts +48 -0
  327. package/src/services/search/providers/LessonSearchProvider.ts +75 -0
  328. package/src/services/search/providers/ReportSearchProvider.ts +49 -0
  329. package/src/services/search/types.ts +144 -0
  330. package/src/services/skill/SkillService.ts +482 -0
  331. package/src/services/skill/index.ts +2 -0
  332. package/src/services/skill/types.ts +70 -0
  333. package/src/services/status/OperationsStatusService.ts +276 -0
  334. package/src/services/status/ProjectStatusService.ts +522 -0
  335. package/src/services/status/index.ts +11 -0
  336. package/src/services/storage/PrefixKVStore.ts +242 -0
  337. package/src/services/storage/index.ts +1 -0
  338. package/src/services/system-reminder/SystemReminderUtils.ts +96 -0
  339. package/src/services/system-reminder/index.ts +7 -0
  340. package/src/services/trust-pubkeys/TrustPubkeyService.ts +325 -0
  341. package/src/services/trust-pubkeys/index.ts +2 -0
  342. package/src/telemetry/ConversationSpanManager.ts +111 -0
  343. package/src/telemetry/EventLoopMonitor.ts +206 -0
  344. package/src/telemetry/LLMSpanRegistry.ts +20 -0
  345. package/src/telemetry/NostrSpanProcessor.ts +89 -0
  346. package/src/telemetry/ToolCallSpanProcessor.ts +66 -0
  347. package/src/telemetry/diagnostics.ts +27 -0
  348. package/src/telemetry/setup.ts +120 -0
  349. package/src/tools/implementations/agents_discover.ts +121 -0
  350. package/src/tools/implementations/agents_hire.ts +127 -0
  351. package/src/tools/implementations/agents_list.ts +96 -0
  352. package/src/tools/implementations/agents_publish.ts +611 -0
  353. package/src/tools/implementations/agents_read.ts +173 -0
  354. package/src/tools/implementations/agents_write.ts +200 -0
  355. package/src/tools/implementations/ask.ts +411 -0
  356. package/src/tools/implementations/change_model.ts +141 -0
  357. package/src/tools/implementations/conversation_get.ts +661 -0
  358. package/src/tools/implementations/conversation_list.ts +377 -0
  359. package/src/tools/implementations/conversation_search.ts +370 -0
  360. package/src/tools/implementations/delegate.ts +327 -0
  361. package/src/tools/implementations/delegate_crossproject.ts +209 -0
  362. package/src/tools/implementations/delegate_followup.ts +300 -0
  363. package/src/tools/implementations/fs_edit.ts +162 -0
  364. package/src/tools/implementations/fs_glob.ts +182 -0
  365. package/src/tools/implementations/fs_grep.ts +513 -0
  366. package/src/tools/implementations/fs_read.ts +332 -0
  367. package/src/tools/implementations/fs_write.ts +113 -0
  368. package/src/tools/implementations/generate_image.ts +259 -0
  369. package/src/tools/implementations/home_fs.ts +515 -0
  370. package/src/tools/implementations/kill.ts +651 -0
  371. package/src/tools/implementations/learn.ts +166 -0
  372. package/src/tools/implementations/lesson-formatter.ts +38 -0
  373. package/src/tools/implementations/lesson_delete.ts +164 -0
  374. package/src/tools/implementations/lesson_get.ts +105 -0
  375. package/src/tools/implementations/lessons_list.ts +153 -0
  376. package/src/tools/implementations/mcp_resource_read.ts +161 -0
  377. package/src/tools/implementations/mcp_subscribe.ts +158 -0
  378. package/src/tools/implementations/mcp_subscription_stop.ts +85 -0
  379. package/src/tools/implementations/nostr_fetch.ts +149 -0
  380. package/src/tools/implementations/nostr_publish_as_user.ts +353 -0
  381. package/src/tools/implementations/project_list.ts +146 -0
  382. package/src/tools/implementations/rag_add_documents.ts +573 -0
  383. package/src/tools/implementations/rag_create_collection.ts +65 -0
  384. package/src/tools/implementations/rag_delete_collection.ts +68 -0
  385. package/src/tools/implementations/rag_list_collections.ts +77 -0
  386. package/src/tools/implementations/rag_query.ts +107 -0
  387. package/src/tools/implementations/rag_subscription_create.ts +105 -0
  388. package/src/tools/implementations/rag_subscription_delete.ts +80 -0
  389. package/src/tools/implementations/rag_subscription_get.ts +123 -0
  390. package/src/tools/implementations/rag_subscription_list.ts +128 -0
  391. package/src/tools/implementations/report_delete.ts +79 -0
  392. package/src/tools/implementations/report_read.ts +160 -0
  393. package/src/tools/implementations/report_write.ts +278 -0
  394. package/src/tools/implementations/reports_list.ts +77 -0
  395. package/src/tools/implementations/schedule_task.ts +104 -0
  396. package/src/tools/implementations/schedule_task_cancel.ts +62 -0
  397. package/src/tools/implementations/schedule_task_once.ts +128 -0
  398. package/src/tools/implementations/schedule_tasks_list.ts +79 -0
  399. package/src/tools/implementations/search.ts +160 -0
  400. package/src/tools/implementations/shell.ts +553 -0
  401. package/src/tools/implementations/todo.ts +260 -0
  402. package/src/tools/implementations/upload_blob.ts +381 -0
  403. package/src/tools/implementations/web_fetch.ts +153 -0
  404. package/src/tools/implementations/web_search.ts +250 -0
  405. package/src/tools/registry.ts +670 -0
  406. package/src/tools/types.ts +177 -0
  407. package/src/tools/utils.ts +256 -0
  408. package/src/types/event-ids.ts +320 -0
  409. package/src/types/index.ts +46 -0
  410. package/src/utils/agentFetcher.ts +107 -0
  411. package/src/utils/cli-error.ts +29 -0
  412. package/src/utils/conversation-id.ts +27 -0
  413. package/src/utils/conversation-utils.ts +1 -0
  414. package/src/utils/delegation-chain.ts +357 -0
  415. package/src/utils/error-handler.ts +42 -0
  416. package/src/utils/git/gitignore.ts +69 -0
  417. package/src/utils/git/index.ts +2 -0
  418. package/src/utils/git/initializeGitRepo.ts +204 -0
  419. package/src/utils/git/worktree.ts +260 -0
  420. package/src/utils/lessonFormatter.ts +70 -0
  421. package/src/utils/lessonTrust.ts +24 -0
  422. package/src/utils/lockfile.ts +123 -0
  423. package/src/utils/logger.ts +149 -0
  424. package/src/utils/nostr-entity-parser.ts +365 -0
  425. package/src/utils/process.ts +49 -0
  426. package/src/wrapper.ts +262 -0
  427. package/tsconfig.json +41 -0
@@ -0,0 +1,108 @@
1
+ import type { ConversationStore } from "@/conversations/ConversationStore";
2
+ import type { EventContext } from "@/nostr/types";
3
+ import type { ToolExecutionContext } from "@/tools/types";
4
+
5
+ export interface CreateEventContextOptions {
6
+ model?: string;
7
+ /** Incremental LLM runtime in milliseconds since last event was published */
8
+ llmRuntime?: number;
9
+ }
10
+
11
+ /**
12
+ * Resolve the correct recipient pubkey for a completion event from the delegation chain.
13
+ *
14
+ * This function looks up the conversation's delegation chain and returns the immediate
15
+ * delegator (second-to-last entry). This ensures completions route back up the delegation
16
+ * stack even when RAL state is lost (e.g., daemon restart) and the triggeringEvent
17
+ * is from a different source (e.g., user responding to an ask).
18
+ *
19
+ * Exception: when the chain origin's pubkey matches the triggering event's pubkey,
20
+ * the caller is interacting directly (not via delegation). In this case the function
21
+ * returns undefined so the caller falls back to triggeringEvent.pubkey, avoiding
22
+ * mis-routing the completion to the intermediate delegator.
23
+ *
24
+ * The delegation chain is persisted in the ConversationStore, so it survives restarts.
25
+ *
26
+ * Architecture note: This function is in services/event-context/ (layer 3) because
27
+ * it imports ConversationStore. AgentEventEncoder (layer 2, in nostr/) cannot import
28
+ * ConversationStore directly - instead, it receives the pre-resolved pubkey via
29
+ * EventContext.completionRecipientPubkey.
30
+ *
31
+ * @param conversationStore - The conversation store (may be undefined in MCP context)
32
+ * @param triggeringEventPubkey - The pubkey of the event that triggered this RAL (optional)
33
+ * @returns The immediate delegator's pubkey, or undefined when:
34
+ * - no delegation chain exists (or is too short)
35
+ * - the triggering event pubkey matches the chain origin (direct-interaction case)
36
+ */
37
+ export function resolveCompletionRecipient(
38
+ conversationStore: ConversationStore | undefined,
39
+ triggeringEventPubkey?: string
40
+ ): string | undefined {
41
+ if (!conversationStore) {
42
+ return undefined;
43
+ }
44
+
45
+ const delegationChain = conversationStore.metadata?.delegationChain;
46
+
47
+ if (delegationChain && delegationChain.length >= 2) {
48
+ // The delegation chain is ordered [origin, ..., delegator, current_agent]
49
+ // We want the second-to-last entry (the immediate delegator)
50
+ const immediateDelegator = delegationChain[delegationChain.length - 2];
51
+ const origin = delegationChain[0];
52
+
53
+ // If the chain origin directly triggered this RAL, the delegation is
54
+ // already complete. Route back to them directly (return undefined so
55
+ // the caller falls back to triggeringEvent.pubkey).
56
+ // In ask-resume, the original trigger is RESTORED to the delegator's
57
+ // message, so this condition is never true there.
58
+ if (triggeringEventPubkey && triggeringEventPubkey === origin.pubkey) {
59
+ return undefined;
60
+ }
61
+
62
+ return immediateDelegator.pubkey;
63
+ }
64
+
65
+ // No delegation chain or chain too short - caller should fall back to triggeringEvent.pubkey
66
+ return undefined;
67
+ }
68
+
69
+ /**
70
+ * Create EventContext for publishing events.
71
+ * Handles missing conversation context gracefully (e.g., in MCP context).
72
+ *
73
+ * For completion events, this function pre-resolves the completion recipient pubkey
74
+ * from the delegation chain stored in ConversationStore. This ensures completions
75
+ * route back to the immediate delegator even when:
76
+ * - RAL state is lost (e.g., daemon restart)
77
+ * - The triggeringEvent is from a different source (e.g., user responding to an ask)
78
+ *
79
+ * When the chain origin directly triggers the RAL (direct-interaction case), the
80
+ * resolved recipient is undefined and the completion routes to the triggering event's
81
+ * pubkey instead (see resolveCompletionRecipient for details).
82
+ */
83
+ export function createEventContext(
84
+ context: ToolExecutionContext,
85
+ options?: CreateEventContextOptions | string
86
+ ): EventContext {
87
+ // Support legacy call signature: createEventContext(context, model)
88
+ const opts: CreateEventContextOptions = typeof options === "string"
89
+ ? { model: options }
90
+ : options ?? {};
91
+
92
+ const conversation = context.getConversation?.();
93
+ const rootEventId = conversation?.getRootEventId() ?? context.triggeringEvent?.id;
94
+
95
+ // Resolve completion recipient from delegation chain (layer-3 operation)
96
+ // This pre-resolves the pubkey so AgentEventEncoder (layer 2) doesn't need to import ConversationStore
97
+ const completionRecipientPubkey = resolveCompletionRecipient(conversation, context.triggeringEvent?.pubkey);
98
+
99
+ return {
100
+ triggeringEvent: context.triggeringEvent,
101
+ rootEvent: rootEventId ? { id: rootEventId } : {},
102
+ conversationId: context.conversationId,
103
+ model: opts.model ?? context.agent.llmConfig,
104
+ ralNumber: context.ralNumber,
105
+ llmRuntime: opts.llmRuntime,
106
+ completionRecipientPubkey,
107
+ };
108
+ }
@@ -0,0 +1,2 @@
1
+ export { createEventContext, resolveCompletionRecipient } from "./EventContextService";
2
+ export type { CreateEventContextOptions } from "./EventContextService";
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Context Builder for Heuristics
3
+ *
4
+ * Builds O(1) precomputed context from RAL state and conversation data.
5
+ * CRITICAL: All operations must be O(1) - no expensive scans allowed.
6
+ */
7
+
8
+ import type { ConversationStore } from "@/conversations/ConversationStore";
9
+ import type { RALRegistry } from "@/services/ral/RALRegistry";
10
+ import type { HeuristicContext } from "./types";
11
+
12
+ /**
13
+ * Configuration for context builder
14
+ */
15
+ export interface ContextBuilderConfig {
16
+ /** Maximum recent tools to include in context (default: 10) */
17
+ maxRecentTools?: number;
18
+ }
19
+
20
+ /**
21
+ * Build heuristic context from current RAL state.
22
+ * All data is precomputed for O(1) access.
23
+ * BLOCKER 1 FIX: Uses O(1) precomputed summary from RALRegistry.
24
+ */
25
+ export function buildHeuristicContext(params: {
26
+ agentPubkey: string;
27
+ conversationId: string;
28
+ ralNumber: number;
29
+ toolName: string;
30
+ toolCallId: string;
31
+ toolArgs: unknown;
32
+ toolResult: unknown;
33
+ ralRegistry: RALRegistry;
34
+ conversationStore: ConversationStore;
35
+ currentBranch?: string;
36
+ config?: ContextBuilderConfig;
37
+ }): HeuristicContext {
38
+ const {
39
+ agentPubkey,
40
+ conversationId,
41
+ ralNumber,
42
+ toolName,
43
+ toolCallId,
44
+ toolArgs,
45
+ toolResult,
46
+ ralRegistry,
47
+ conversationStore,
48
+ currentBranch,
49
+ } = params;
50
+
51
+ // Get O(1) precomputed summary from RAL (BLOCKER 1 FIX)
52
+ const summary = ralRegistry.getHeuristicSummary(agentPubkey, conversationId, ralNumber) ?? {
53
+ recentTools: [],
54
+ flags: {
55
+ hasTodoWrite: false,
56
+ hasDelegation: false,
57
+ hasVerification: false,
58
+ hasGitAgentCommit: false,
59
+ },
60
+ pendingDelegationCount: 0,
61
+ };
62
+
63
+ // Build state from O(1) precomputed summary
64
+ const state = {
65
+ hasTodoWrite: summary.flags.hasTodoWrite,
66
+ hasDelegation: summary.flags.hasDelegation,
67
+
68
+ // O(1) counter from summary (no expensive scan)
69
+ pendingDelegationCount: summary.pendingDelegationCount,
70
+
71
+ // Current branch
72
+ currentBranch,
73
+
74
+ // Check if on worktree branch (heuristic: contains .worktrees or feature/)
75
+ isWorktreeBranch: currentBranch
76
+ ? currentBranch.includes("feature/") || currentBranch.includes(".worktrees")
77
+ : false,
78
+
79
+ // Check if verification was performed (tests, builds)
80
+ hasVerification: summary.flags.hasVerification,
81
+
82
+ // Check if git-agent was used (via delegation)
83
+ hasGitAgentCommit: summary.flags.hasGitAgentCommit,
84
+
85
+ // Total message count (O(1) - stored in ConversationStore)
86
+ messageCount: conversationStore.getMessageCount(),
87
+ };
88
+
89
+ // BLOCKER 3 FIX: Generate timestamp here, not in heuristics (for purity)
90
+ const evaluationTimestamp = Date.now();
91
+
92
+ return {
93
+ agentPubkey,
94
+ conversationId,
95
+ ralNumber,
96
+ evaluationTimestamp,
97
+ tool: {
98
+ name: toolName,
99
+ callId: toolCallId,
100
+ args: toolArgs,
101
+ result: toolResult,
102
+ },
103
+ state,
104
+ recentTools: summary.recentTools, // O(1) - bounded array from summary
105
+ };
106
+ }
@@ -0,0 +1,200 @@
1
+ /**
2
+ * HeuristicEngine - Core orchestration for reactive heuristic system
3
+ *
4
+ * Evaluates heuristics post-tool execution and manages violation state.
5
+ * CRITICAL: Hard error boundaries ensure single heuristic failure cannot crash pipeline.
6
+ */
7
+
8
+ import { logger } from "@/utils/logger";
9
+ import { formatViolations } from "./formatters";
10
+ import type {
11
+ Heuristic,
12
+ HeuristicContext,
13
+ HeuristicEngineConfig,
14
+ HeuristicViolation,
15
+ } from "./types";
16
+
17
+ /**
18
+ * HeuristicEngine orchestrates heuristic evaluation with strict error boundaries.
19
+ *
20
+ * Key guarantees:
21
+ * - Single heuristic failure CANNOT crash tool pipeline
22
+ * - All heuristics get O(1) precomputed context
23
+ * - Violations are stored in RALRegistry namespace
24
+ * - Max 3 warnings per LLM step
25
+ */
26
+ export class HeuristicEngine {
27
+ private heuristics: Map<string, Heuristic> = new Map();
28
+ private config: Required<HeuristicEngineConfig>;
29
+
30
+ constructor(config: HeuristicEngineConfig = {}) {
31
+ this.config = {
32
+ maxWarningsPerStep: config.maxWarningsPerStep ?? 3,
33
+ debug: config.debug ?? false,
34
+ };
35
+
36
+ if (this.config.debug) {
37
+ logger.info("[HeuristicEngine] Initialized", {
38
+ maxWarningsPerStep: this.config.maxWarningsPerStep,
39
+ });
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Register a heuristic for evaluation
45
+ */
46
+ register(heuristic: Heuristic): void {
47
+ if (this.heuristics.has(heuristic.id)) {
48
+ logger.warn("[HeuristicEngine] Duplicate heuristic ID - replacing", {
49
+ id: heuristic.id,
50
+ });
51
+ }
52
+
53
+ this.heuristics.set(heuristic.id, heuristic);
54
+
55
+ if (this.config.debug) {
56
+ logger.info("[HeuristicEngine] Registered heuristic", {
57
+ id: heuristic.id,
58
+ name: heuristic.name,
59
+ });
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Unregister a heuristic
65
+ */
66
+ unregister(heuristicId: string): void {
67
+ this.heuristics.delete(heuristicId);
68
+ }
69
+
70
+ /**
71
+ * Get all registered heuristics
72
+ */
73
+ getAll(): Heuristic[] {
74
+ return Array.from(this.heuristics.values());
75
+ }
76
+
77
+ /**
78
+ * Evaluate all heuristics against the current context.
79
+ * Each heuristic is wrapped in a hard try/catch boundary.
80
+ *
81
+ * @param context - Precomputed O(1) context
82
+ * @returns Array of violations (empty if all rules pass)
83
+ */
84
+ evaluate(context: HeuristicContext): HeuristicViolation[] {
85
+ const violations: HeuristicViolation[] = [];
86
+
87
+ for (const heuristic of this.heuristics.values()) {
88
+ const violation = this.evaluateSingle(heuristic, context);
89
+ if (violation) {
90
+ violations.push(violation);
91
+ }
92
+ }
93
+
94
+ return violations;
95
+ }
96
+
97
+
98
+ /**
99
+ * Evaluate a single heuristic with error boundary.
100
+ * CRITICAL: This method MUST NOT throw - it catches all errors.
101
+ */
102
+ private evaluateSingle(heuristic: Heuristic, context: HeuristicContext): HeuristicViolation | null {
103
+ try {
104
+ const violation = heuristic.evaluate(context);
105
+
106
+ if (violation && this.config.debug) {
107
+ logger.info("[HeuristicEngine] Violation detected", {
108
+ heuristicId: heuristic.id,
109
+ violationId: violation.id,
110
+ severity: violation.severity,
111
+ title: violation.title,
112
+ });
113
+ }
114
+
115
+ return violation;
116
+ } catch (error) {
117
+ // HARD ERROR BOUNDARY: Log but never throw
118
+ logger.error("[HeuristicEngine] Heuristic evaluation failed - skipping", {
119
+ heuristicId: heuristic.id,
120
+ error: error instanceof Error ? error.message : String(error),
121
+ stack: error instanceof Error ? error.stack : undefined,
122
+ });
123
+
124
+ return null;
125
+ }
126
+ }
127
+
128
+
129
+ /**
130
+ * Format violations for LLM injection.
131
+ * Sorts by severity (errors first) and limits to maxWarningsPerStep.
132
+ *
133
+ * @param violations - All detected violations
134
+ * @returns Markdown string for system message
135
+ */
136
+ formatForInjection(violations: HeuristicViolation[]): string {
137
+ if (violations.length === 0) {
138
+ return "";
139
+ }
140
+
141
+ // Sort: errors first, then by timestamp (most recent first)
142
+ const sorted = violations.sort((a, b) => {
143
+ if (a.severity !== b.severity) {
144
+ return a.severity === "error" ? -1 : 1;
145
+ }
146
+ return b.timestamp - a.timestamp;
147
+ });
148
+
149
+ // Limit to max warnings
150
+ const limited = sorted.slice(0, this.config.maxWarningsPerStep);
151
+
152
+ if (this.config.debug && limited.length < sorted.length) {
153
+ logger.info("[HeuristicEngine] Truncated violations for injection", {
154
+ total: sorted.length,
155
+ shown: limited.length,
156
+ hidden: sorted.length - limited.length,
157
+ });
158
+ }
159
+
160
+ return formatViolations(limited);
161
+ }
162
+
163
+ /**
164
+ * Get debug summary of current state
165
+ */
166
+ getDebugInfo(): {
167
+ registeredCount: number;
168
+ heuristics: Array<{ id: string; name: string }>;
169
+ config: Required<HeuristicEngineConfig>;
170
+ } {
171
+ return {
172
+ registeredCount: this.heuristics.size,
173
+ heuristics: Array.from(this.heuristics.values()).map((h) => ({
174
+ id: h.id,
175
+ name: h.name,
176
+ })),
177
+ config: this.config,
178
+ };
179
+ }
180
+ }
181
+
182
+ /** Global singleton instance */
183
+ let engineInstance: HeuristicEngine | null = null;
184
+
185
+ /**
186
+ * Get or create the global HeuristicEngine instance
187
+ */
188
+ export function getHeuristicEngine(config?: HeuristicEngineConfig): HeuristicEngine {
189
+ if (!engineInstance) {
190
+ engineInstance = new HeuristicEngine(config);
191
+ }
192
+ return engineInstance;
193
+ }
194
+
195
+ /**
196
+ * Reset the global instance (for testing)
197
+ */
198
+ export function resetHeuristicEngine(): void {
199
+ engineInstance = null;
200
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Formatters for heuristic violations
3
+ *
4
+ * Converts violations into markdown warnings for LLM context.
5
+ * Output is wrapped in <system-reminder> tags for consistent injection.
6
+ */
7
+
8
+ import { wrapInSystemReminder } from "@/services/system-reminder";
9
+ import type { HeuristicViolation } from "./types";
10
+
11
+ /**
12
+ * Format a single violation as a markdown warning block
13
+ */
14
+ export function formatViolation(violation: HeuristicViolation): string {
15
+ const icon = violation.severity === "error" ? "🚨" : "⚠️";
16
+ const severityLabel = violation.severity.toUpperCase();
17
+
18
+ return [
19
+ `${icon} **${severityLabel}: ${violation.title}**`,
20
+ "",
21
+ violation.message,
22
+ ].join("\n");
23
+ }
24
+
25
+ /**
26
+ * Format multiple violations into a single system reminder block.
27
+ * Output is wrapped in <system-reminder> tags for consistent injection
28
+ * and appending to user messages.
29
+ *
30
+ * @param violations - List of violations to format (max 3 recommended)
31
+ * @returns Content wrapped in system-reminder tags, ready for injection
32
+ */
33
+ export function formatViolations(violations: HeuristicViolation[]): string {
34
+ if (violations.length === 0) {
35
+ return "";
36
+ }
37
+
38
+ const formattedViolations = violations.map(formatViolation).join("\n\n---\n\n");
39
+
40
+ const content = [
41
+ "# Heuristic Reminders",
42
+ "",
43
+ "The following pattern violations were detected based on your recent actions:",
44
+ "",
45
+ formattedViolations,
46
+ "",
47
+ "Please address these before continuing.",
48
+ ].join("\n");
49
+
50
+ return wrapInSystemReminder(content);
51
+ }
52
+
53
+ /**
54
+ * Format a violation for debug logging (single line)
55
+ */
56
+ export function formatViolationForLog(violation: HeuristicViolation): string {
57
+ return `[${violation.severity}] ${violation.heuristicId}: ${violation.title}`;
58
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Heuristics System - Reactive Agent Guidance
3
+ *
4
+ * Provides real-time guidance to agents based on their actions.
5
+ * Heuristics are pure, synchronous functions that check rules
6
+ * and generate warnings when patterns are violated.
7
+ */
8
+
9
+ export { HeuristicEngine, getHeuristicEngine, resetHeuristicEngine } from "./HeuristicEngine";
10
+ export { formatViolation, formatViolations, formatViolationForLog } from "./formatters";
11
+ export * from "./types";
12
+ export * from "./rules";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Heuristic Rules Registry
3
+ *
4
+ * Exports all available heuristics for registration with the engine.
5
+ */
6
+
7
+ export { todoReminderOnToolUseHeuristic } from "./todoReminderOnToolUse";
8
+
9
+ // Note: todoBeforeDelegationHeuristic is deprecated - delegation now has hard enforcement
10
+ // at the tool level (delegate.ts, delegate_crossproject.ts) which blocks before heuristics run.
11
+ // Keeping the export for backward compatibility but not registering it.
12
+ export { todoBeforeDelegationHeuristic } from "./todoBeforeDelegation";
13
+
14
+ import type { Heuristic } from "../types";
15
+ import { todoReminderOnToolUseHeuristic } from "./todoReminderOnToolUse";
16
+
17
+ /**
18
+ * Get all default heuristics
19
+ */
20
+ export function getDefaultHeuristics(): Heuristic[] {
21
+ return [
22
+ // todoBeforeDelegationHeuristic removed - delegation is now hard-blocked at tool level
23
+ todoReminderOnToolUseHeuristic,
24
+ ];
25
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * TodoWrite Before Delegation Heuristic
3
+ *
4
+ * Ensures agents create a TODO list before delegating complex tasks.
5
+ * This helps track progress and provides clear task breakdown.
6
+ */
7
+
8
+ import type { Heuristic, HeuristicContext, HeuristicResult } from "../types";
9
+
10
+ const HEURISTIC_ID = "todo-before-delegation";
11
+
12
+ /**
13
+ * Tools that trigger delegation
14
+ */
15
+ const DELEGATION_TOOLS = new Set([
16
+ "mcp__tenex__delegate",
17
+ "mcp__tenex__delegate_crossproject",
18
+ ]);
19
+
20
+ /**
21
+ * Check if TodoWrite was called before delegation in this RAL
22
+ */
23
+ export const todoBeforeDelegationHeuristic: Heuristic = {
24
+ id: HEURISTIC_ID,
25
+ name: "TodoWrite Before Delegation",
26
+ description: "Agents should create a TODO list before delegating complex tasks",
27
+
28
+ evaluate(context: HeuristicContext): HeuristicResult {
29
+ // Only check if this is a delegation tool
30
+ if (!DELEGATION_TOOLS.has(context.tool.name)) {
31
+ return null;
32
+ }
33
+
34
+ // Check if TodoWrite was called in this RAL
35
+ if (context.state.hasTodoWrite) {
36
+ return null; // Rule satisfied
37
+ }
38
+
39
+ // Check recent tool history for TodoWrite
40
+ const hasTodoInRecent = context.recentTools.some(
41
+ (tool) => tool.name === "TodoWrite"
42
+ );
43
+
44
+ if (hasTodoInRecent) {
45
+ return null; // Rule satisfied
46
+ }
47
+
48
+ // Violation: Delegation without TODO
49
+ // BLOCKER 3 FIX: Use deterministic ID from context timestamp, not Date.now()
50
+ return {
51
+ id: `${HEURISTIC_ID}-${context.tool.callId}-${context.ralNumber}`,
52
+ heuristicId: HEURISTIC_ID,
53
+ title: "Missing TODO List Before Delegation",
54
+ severity: "warning",
55
+ timestamp: context.evaluationTimestamp,
56
+ message: [
57
+ "You are delegating a task without creating a TODO list first.",
58
+ "",
59
+ "**Why this matters:**",
60
+ "- TODO lists help track progress across multiple delegations",
61
+ "- They provide clear task breakdown for complex work",
62
+ "- They ensure nothing is forgotten after delegation completes",
63
+ "",
64
+ "**Recommended action:**",
65
+ "Use the `TodoWrite` tool to create a task list before delegating, unless this is a simple, single-step delegation.",
66
+ ].join("\n"),
67
+ };
68
+ },
69
+ };
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Todo Reminder on Tool Use Heuristic
3
+ *
4
+ * Injects a system reminder on ANY tool use (except todo_write variants)
5
+ * when the agent has no todos. This encourages proactive todo list creation.
6
+ */
7
+
8
+ import type { Heuristic, HeuristicContext, HeuristicResult } from "../types";
9
+
10
+ const HEURISTIC_ID = "todo-reminder-on-tool-use";
11
+
12
+ /**
13
+ * Tools that are exempt from the todo reminder
14
+ * These are the todo tools themselves (both naked and MCP-wrapped)
15
+ */
16
+ const TODO_TOOLS = new Set([
17
+ "todo_write",
18
+ "mcp__tenex__todo_write",
19
+ "TodoWrite", // Legacy name that might appear in recentTools
20
+ ]);
21
+
22
+ /**
23
+ * Inject a reminder to use todo_write on every non-todo tool call
24
+ * when the agent has no todos.
25
+ */
26
+ export const todoReminderOnToolUseHeuristic: Heuristic = {
27
+ id: HEURISTIC_ID,
28
+ name: "Todo Reminder on Tool Use",
29
+ description: "Reminds agents to create a todo list when using tools without one",
30
+
31
+ evaluate(context: HeuristicContext): HeuristicResult {
32
+ // Skip if this IS a todo tool
33
+ if (TODO_TOOLS.has(context.tool.name)) {
34
+ return null;
35
+ }
36
+
37
+ // Skip if agent already has todos (hasTodoWrite flag means they've called todo_write this RAL)
38
+ if (context.state.hasTodoWrite) {
39
+ return null;
40
+ }
41
+
42
+ // Violation: Using a tool without having created todos
43
+ // Note: The framework already injects heuristic violations as system messages,
44
+ // so no need to wrap in <system-reminder> tags here
45
+ return {
46
+ id: `${HEURISTIC_ID}-${context.tool.callId}`,
47
+ heuristicId: HEURISTIC_ID,
48
+ title: "Consider Creating a Todo List",
49
+ severity: "warning",
50
+ timestamp: context.evaluationTimestamp,
51
+ message: [
52
+ "You haven't created a todo list yet. Consider using `todo_write()` to track your work.",
53
+ "",
54
+ "Benefits of using todos:",
55
+ "- Shows your progress to observers",
56
+ "- Helps you stay organized",
57
+ "- Required before delegating to other agents",
58
+ "",
59
+ "Even a simple 1-2 item todo list is valuable!",
60
+ ].join("\n"),
61
+ };
62
+ },
63
+ };