@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.
- package/README.md +194 -0
- package/dist/backend-wrapper.cjs +3 -0
- package/dist/src/index.js +331928 -0
- package/package.json +103 -0
- package/src/agents/AgentRegistry.ts +418 -0
- package/src/agents/AgentStorage.ts +1133 -0
- package/src/agents/ConfigResolver.ts +229 -0
- package/src/agents/agent-installer.ts +236 -0
- package/src/agents/agent-loader.ts +241 -0
- package/src/agents/constants.ts +82 -0
- package/src/agents/errors.ts +48 -0
- package/src/agents/execution/AgentExecutor.ts +561 -0
- package/src/agents/execution/ExecutionContextFactory.ts +112 -0
- package/src/agents/execution/MessageCompiler.ts +597 -0
- package/src/agents/execution/MessageSyncer.ts +100 -0
- package/src/agents/execution/PostCompletionChecker.ts +278 -0
- package/src/agents/execution/ProgressMonitor.ts +50 -0
- package/src/agents/execution/RALResolver.ts +177 -0
- package/src/agents/execution/SessionManager.ts +181 -0
- package/src/agents/execution/StreamCallbacks.ts +312 -0
- package/src/agents/execution/StreamExecutionHandler.ts +579 -0
- package/src/agents/execution/StreamSetup.ts +313 -0
- package/src/agents/execution/ToolEventHandlers.ts +239 -0
- package/src/agents/execution/ToolExecutionTracker.ts +498 -0
- package/src/agents/execution/ToolResultUtils.ts +97 -0
- package/src/agents/execution/ToolSupervisionWrapper.ts +174 -0
- package/src/agents/execution/constants.ts +16 -0
- package/src/agents/execution/index.ts +3 -0
- package/src/agents/execution/types.ts +96 -0
- package/src/agents/execution/utils.ts +26 -0
- package/src/agents/index.ts +4 -0
- package/src/agents/script-installer.ts +266 -0
- package/src/agents/supervision/SupervisorLLMService.ts +253 -0
- package/src/agents/supervision/SupervisorOrchestrator.ts +471 -0
- package/src/agents/supervision/heuristics/ConsecutiveToolsWithoutTodoHeuristic.ts +73 -0
- package/src/agents/supervision/heuristics/DelegationClaimHeuristic.ts +80 -0
- package/src/agents/supervision/heuristics/HeuristicRegistry.ts +114 -0
- package/src/agents/supervision/heuristics/PendingTodosHeuristic.ts +93 -0
- package/src/agents/supervision/heuristics/SilentAgentHeuristic.ts +54 -0
- package/src/agents/supervision/heuristics/index.ts +5 -0
- package/src/agents/supervision/index.ts +28 -0
- package/src/agents/supervision/registerHeuristics.ts +110 -0
- package/src/agents/supervision/supervisionHealthCheck.ts +123 -0
- package/src/agents/supervision/types.ts +171 -0
- package/src/agents/tool-names.ts +46 -0
- package/src/agents/tool-normalization.ts +184 -0
- package/src/agents/types/index.ts +2 -0
- package/src/agents/types/runtime.ts +74 -0
- package/src/agents/types/storage.ts +145 -0
- package/src/commands/agent/import/index.ts +6 -0
- package/src/commands/agent/import/openclaw-distiller.ts +57 -0
- package/src/commands/agent/import/openclaw-reader.ts +141 -0
- package/src/commands/agent/import/openclaw.ts +154 -0
- package/src/commands/agent/index.ts +6 -0
- package/src/commands/agent.ts +215 -0
- package/src/commands/daemon.ts +198 -0
- package/src/commands/doctor.ts +134 -0
- package/src/commands/setup/embed.ts +228 -0
- package/src/commands/setup/global-system-prompt.ts +223 -0
- package/src/commands/setup/image.ts +179 -0
- package/src/commands/setup/index.ts +16 -0
- package/src/commands/setup/interactive.ts +95 -0
- package/src/commands/setup/llm.ts +38 -0
- package/src/commands/setup/onboarding.ts +294 -0
- package/src/commands/setup/providers.ts +27 -0
- package/src/constants.ts +34 -0
- package/src/conversations/ConversationDiskReader.ts +148 -0
- package/src/conversations/ConversationRegistry.ts +728 -0
- package/src/conversations/ConversationStore.ts +868 -0
- package/src/conversations/MessageBuilder.ts +866 -0
- package/src/conversations/executionTime.ts +62 -0
- package/src/conversations/formatters/DelegationXmlFormatter.ts +64 -0
- package/src/conversations/formatters/ThreadedConversationFormatter.ts +303 -0
- package/src/conversations/formatters/index.ts +9 -0
- package/src/conversations/formatters/utils/MessageFormatter.ts +46 -0
- package/src/conversations/formatters/utils/TimestampFormatter.ts +56 -0
- package/src/conversations/formatters/utils/TreeBuilder.ts +131 -0
- package/src/conversations/formatters/utils/TreeRenderer.ts +49 -0
- package/src/conversations/index.ts +2 -0
- package/src/conversations/persistence/ToolMessageStorage.ts +143 -0
- package/src/conversations/search/ConversationIndexManager.ts +393 -0
- package/src/conversations/search/QueryParser.ts +114 -0
- package/src/conversations/search/SearchEngine.ts +175 -0
- package/src/conversations/search/SnippetExtractor.ts +345 -0
- package/src/conversations/search/embeddings/ConversationEmbeddingService.ts +484 -0
- package/src/conversations/search/embeddings/ConversationIndexingJob.ts +320 -0
- package/src/conversations/search/embeddings/IndexingStateManager.ts +338 -0
- package/src/conversations/search/embeddings/index.ts +18 -0
- package/src/conversations/search/index.ts +49 -0
- package/src/conversations/search/types.ts +124 -0
- package/src/conversations/services/CategoryManager.ts +160 -0
- package/src/conversations/services/ConversationResolver.ts +296 -0
- package/src/conversations/services/ConversationSummarizer.ts +234 -0
- package/src/conversations/services/MetadataDebounceManager.ts +188 -0
- package/src/conversations/services/index.ts +2 -0
- package/src/conversations/types.ts +148 -0
- package/src/conversations/utils/content-utils.ts +69 -0
- package/src/conversations/utils/image-placeholder.ts +281 -0
- package/src/conversations/utils/image-url-utils.ts +171 -0
- package/src/conversations/utils/multimodal-content.ts +90 -0
- package/src/conversations/utils/tool-result-truncator.ts +159 -0
- package/src/daemon/Daemon.ts +1883 -0
- package/src/daemon/ProjectRuntime.ts +657 -0
- package/src/daemon/RestartState.ts +152 -0
- package/src/daemon/RuntimeLifecycle.ts +268 -0
- package/src/daemon/SubscriptionManager.ts +305 -0
- package/src/daemon/UnixSocketTransport.ts +318 -0
- package/src/daemon/filters/SubscriptionFilterBuilder.ts +119 -0
- package/src/daemon/index.ts +9 -0
- package/src/daemon/routing/DaemonRouter.ts +491 -0
- package/src/daemon/types.ts +150 -0
- package/src/daemon/utils/routing-log.ts +76 -0
- package/src/daemon/utils/telemetry.ts +173 -0
- package/src/event-handler/agentDeletion.ts +383 -0
- package/src/event-handler/index.ts +749 -0
- package/src/event-handler/newConversation.ts +165 -0
- package/src/event-handler/project.ts +166 -0
- package/src/event-handler/reply.ts +18 -0
- package/src/events/NDKAgentDefinition.ts +292 -0
- package/src/events/NDKAgentLesson.ts +106 -0
- package/src/events/NDKEventMetadata.ts +34 -0
- package/src/events/NDKMCPTool.ts +60 -0
- package/src/events/NDKProjectStatus.ts +384 -0
- package/src/events/index.ts +4 -0
- package/src/index.ts +126 -0
- package/src/lib/agent-home.ts +334 -0
- package/src/lib/error-formatter.ts +200 -0
- package/src/lib/fs/filesystem.ts +128 -0
- package/src/lib/fs/index.ts +1 -0
- package/src/lib/json-parser.ts +30 -0
- package/src/lib/string.ts +15 -0
- package/src/lib/time.ts +74 -0
- package/src/llm/ChunkHandler.ts +277 -0
- package/src/llm/FinishHandler.ts +250 -0
- package/src/llm/LLMConfigEditor.ts +154 -0
- package/src/llm/LLMServiceFactory.ts +230 -0
- package/src/llm/MessageProcessor.ts +90 -0
- package/src/llm/RecordingState.ts +37 -0
- package/src/llm/StreamPublisher.ts +40 -0
- package/src/llm/TracingUtils.ts +77 -0
- package/src/llm/chunk-validators.ts +57 -0
- package/src/llm/constants.ts +6 -0
- package/src/llm/index.ts +12 -0
- package/src/llm/meta/MetaModelResolver.ts +352 -0
- package/src/llm/meta/index.ts +11 -0
- package/src/llm/middleware/flight-recorder.ts +188 -0
- package/src/llm/providers/MockProvider.ts +332 -0
- package/src/llm/providers/agent/ClaudeCodeProvider.ts +343 -0
- package/src/llm/providers/agent/ClaudeCodeToolsAdapter.ts +203 -0
- package/src/llm/providers/agent/CodexAppServerProvider.ts +214 -0
- package/src/llm/providers/agent/CodexAppServerToolsAdapter.ts +91 -0
- package/src/llm/providers/agent/index.ts +10 -0
- package/src/llm/providers/base/AgentProvider.ts +107 -0
- package/src/llm/providers/base/BaseProvider.ts +114 -0
- package/src/llm/providers/base/StandardProvider.ts +38 -0
- package/src/llm/providers/base/index.ts +9 -0
- package/src/llm/providers/index.ts +106 -0
- package/src/llm/providers/key-manager.ts +238 -0
- package/src/llm/providers/ollama-models.ts +105 -0
- package/src/llm/providers/openrouter-models.ts +102 -0
- package/src/llm/providers/provider-ids.ts +18 -0
- package/src/llm/providers/registry/ProviderRegistry.ts +414 -0
- package/src/llm/providers/registry/index.ts +7 -0
- package/src/llm/providers/standard/AnthropicProvider.ts +71 -0
- package/src/llm/providers/standard/OllamaProvider.ts +59 -0
- package/src/llm/providers/standard/OpenAIProvider.ts +44 -0
- package/src/llm/providers/standard/OpenRouterProvider.ts +103 -0
- package/src/llm/providers/standard/index.ts +10 -0
- package/src/llm/providers/types.ts +194 -0
- package/src/llm/providers/usage-metadata.ts +78 -0
- package/src/llm/service.ts +713 -0
- package/src/llm/types.ts +167 -0
- package/src/llm/utils/ConfigurationManager.ts +650 -0
- package/src/llm/utils/ConfigurationTester.ts +229 -0
- package/src/llm/utils/ModelSelector.ts +212 -0
- package/src/llm/utils/ProviderConfigUI.ts +177 -0
- package/src/llm/utils/claudeCodePromptCompiler.ts +141 -0
- package/src/llm/utils/codex-models.ts +53 -0
- package/src/llm/utils/context-window-cache.ts +30 -0
- package/src/llm/utils/models-dev-cache.ts +267 -0
- package/src/llm/utils/provider-setup.ts +50 -0
- package/src/llm/utils/tool-errors.ts +78 -0
- package/src/llm/utils/usage.ts +74 -0
- package/src/logging/EventRoutingLogger.ts +205 -0
- package/src/nostr/AgentEventDecoder.ts +357 -0
- package/src/nostr/AgentEventEncoder.ts +677 -0
- package/src/nostr/AgentProfilePublisher.ts +657 -0
- package/src/nostr/AgentPublisher.ts +437 -0
- package/src/nostr/BlossomService.ts +226 -0
- package/src/nostr/InterventionPublisher.ts +132 -0
- package/src/nostr/TagExtractor.ts +228 -0
- package/src/nostr/collectEvents.ts +83 -0
- package/src/nostr/constants.ts +38 -0
- package/src/nostr/encryption.ts +26 -0
- package/src/nostr/index.ts +31 -0
- package/src/nostr/keys.ts +17 -0
- package/src/nostr/kinds.ts +37 -0
- package/src/nostr/ndkClient.ts +72 -0
- package/src/nostr/relays.ts +43 -0
- package/src/nostr/trace-context.ts +39 -0
- package/src/nostr/types.ts +227 -0
- package/src/nostr/utils.ts +84 -0
- package/src/prompts/core/FragmentRegistry.ts +30 -0
- package/src/prompts/core/PromptBuilder.ts +98 -0
- package/src/prompts/core/index.ts +3 -0
- package/src/prompts/core/types.ts +13 -0
- package/src/prompts/fragments/00-global-system-prompt.ts +44 -0
- package/src/prompts/fragments/01-agent-identity.ts +69 -0
- package/src/prompts/fragments/02-agent-home-directory.ts +114 -0
- package/src/prompts/fragments/03-system-reminders-explanation.ts +14 -0
- package/src/prompts/fragments/04-relay-configuration.ts +38 -0
- package/src/prompts/fragments/05-delegation-chain.ts +45 -0
- package/src/prompts/fragments/06-agent-todos.ts +74 -0
- package/src/prompts/fragments/06-todo-usage-guidance.ts +34 -0
- package/src/prompts/fragments/07-meta-project-context.ts +234 -0
- package/src/prompts/fragments/08-active-conversations.ts +382 -0
- package/src/prompts/fragments/09-recent-conversations.ts +153 -0
- package/src/prompts/fragments/10-referenced-article.ts +21 -0
- package/src/prompts/fragments/11-nudges.ts +134 -0
- package/src/prompts/fragments/12-skills.ts +127 -0
- package/src/prompts/fragments/13-available-nudges.ts +122 -0
- package/src/prompts/fragments/15-available-agents.ts +53 -0
- package/src/prompts/fragments/16-stay-in-your-lane.ts +41 -0
- package/src/prompts/fragments/17-todo-before-delegation.ts +39 -0
- package/src/prompts/fragments/20-voice-mode.ts +62 -0
- package/src/prompts/fragments/22-scheduled-tasks.ts +175 -0
- package/src/prompts/fragments/24-retrieved-lessons.ts +26 -0
- package/src/prompts/fragments/25-rag-instructions.ts +333 -0
- package/src/prompts/fragments/26-mcp-resources.ts +237 -0
- package/src/prompts/fragments/27-memorized-reports.ts +77 -0
- package/src/prompts/fragments/28-agent-directed-monitoring.ts +32 -0
- package/src/prompts/fragments/29-rag-collections.ts +50 -0
- package/src/prompts/fragments/30-worktree-context.ts +98 -0
- package/src/prompts/fragments/31-agents-md-guidance.ts +96 -0
- package/src/prompts/fragments/32-process-metrics.ts +72 -0
- package/src/prompts/fragments/debug-mode.ts +48 -0
- package/src/prompts/fragments/delegation-completion.ts +44 -0
- package/src/prompts/fragments/index.ts +91 -0
- package/src/prompts/index.ts +21 -0
- package/src/prompts/utils/systemPromptBuilder.ts +777 -0
- package/src/scripts/migrate-prefix-index.ts +157 -0
- package/src/services/AgentDefinitionMonitor.ts +701 -0
- package/src/services/ConfigService.ts +723 -0
- package/src/services/CooldownRegistry.ts +199 -0
- package/src/services/LLMOperationsRegistry.ts +424 -0
- package/src/services/OwnerAgentListService.ts +354 -0
- package/src/services/PubkeyService.ts +308 -0
- package/src/services/agents/AgentMetadataStore.ts +72 -0
- package/src/services/agents/AgentResolution.ts +59 -0
- package/src/services/agents/EscalationService.ts +281 -0
- package/src/services/agents/NDKAgentDiscovery.ts +95 -0
- package/src/services/agents/index.ts +7 -0
- package/src/services/agents-md/AgentsMdService.ts +184 -0
- package/src/services/agents-md/SystemReminderInjector.ts +238 -0
- package/src/services/agents-md/index.ts +11 -0
- package/src/services/apns/APNsClient.ts +203 -0
- package/src/services/apns/APNsService.ts +358 -0
- package/src/services/apns/index.ts +11 -0
- package/src/services/apns/types.ts +80 -0
- package/src/services/compression/CompressionService.ts +445 -0
- package/src/services/compression/compression-schema.ts +28 -0
- package/src/services/compression/compression-types.ts +74 -0
- package/src/services/compression/compression-utils.ts +587 -0
- package/src/services/config/types.ts +394 -0
- package/src/services/dispatch/AgentDispatchService.ts +937 -0
- package/src/services/dispatch/AgentRouter.ts +181 -0
- package/src/services/dispatch/DelegationCompletionHandler.ts +232 -0
- package/src/services/embedding/EmbeddingProvider.ts +188 -0
- package/src/services/embedding/index.ts +5 -0
- package/src/services/event-context/EventContextService.ts +108 -0
- package/src/services/event-context/index.ts +2 -0
- package/src/services/heuristics/ContextBuilder.ts +106 -0
- package/src/services/heuristics/HeuristicEngine.ts +200 -0
- package/src/services/heuristics/formatters.ts +58 -0
- package/src/services/heuristics/index.ts +12 -0
- package/src/services/heuristics/rules/index.ts +25 -0
- package/src/services/heuristics/rules/todoBeforeDelegation.ts +69 -0
- package/src/services/heuristics/rules/todoReminderOnToolUse.ts +63 -0
- package/src/services/heuristics/types.ts +144 -0
- package/src/services/image/ImageGenerationService.ts +389 -0
- package/src/services/image/index.ts +12 -0
- package/src/services/intervention/InterventionService.ts +1352 -0
- package/src/services/intervention/index.ts +7 -0
- package/src/services/mcp/MCPManager.ts +683 -0
- package/src/services/mcp/McpNotificationDelivery.ts +139 -0
- package/src/services/mcp/McpSubscriptionService.ts +653 -0
- package/src/services/mcp/mcpInstaller.ts +130 -0
- package/src/services/nip46/Nip46SigningLog.ts +81 -0
- package/src/services/nip46/Nip46SigningService.ts +467 -0
- package/src/services/nip46/index.ts +4 -0
- package/src/services/nudge/NudgeService.ts +224 -0
- package/src/services/nudge/NudgeWhitelistService.ts +382 -0
- package/src/services/nudge/index.ts +5 -0
- package/src/services/nudge/types.ts +83 -0
- package/src/services/projects/ProjectContext.ts +672 -0
- package/src/services/projects/ProjectContextStore.ts +102 -0
- package/src/services/projects/index.ts +6 -0
- package/src/services/prompt-compiler/index.ts +15 -0
- package/src/services/prompt-compiler/prompt-compiler-service.ts +1143 -0
- package/src/services/pubkey-gate/PubkeyGateService.ts +93 -0
- package/src/services/pubkey-gate/index.ts +1 -0
- package/src/services/rag/EmbeddingProviderFactory.ts +292 -0
- package/src/services/rag/LanceDBMaintenanceService.ts +211 -0
- package/src/services/rag/RAGDatabaseService.ts +173 -0
- package/src/services/rag/RAGOperations.ts +682 -0
- package/src/services/rag/RAGService.ts +240 -0
- package/src/services/rag/RagSubscriptionService.ts +618 -0
- package/src/services/rag/rag-utils.ts +174 -0
- package/src/services/ral/PendingDelegationsRegistry.ts +168 -0
- package/src/services/ral/RALRegistry.ts +2782 -0
- package/src/services/ral/index.ts +4 -0
- package/src/services/ral/types.ts +292 -0
- package/src/services/reports/LocalReportStore.ts +380 -0
- package/src/services/reports/ReportEmbeddingService.ts +430 -0
- package/src/services/reports/ReportService.ts +440 -0
- package/src/services/reports/articleUtils.ts +52 -0
- package/src/services/reports/index.ts +7 -0
- package/src/services/scheduling/SchedulerService.ts +1057 -0
- package/src/services/scheduling/errors.ts +14 -0
- package/src/services/scheduling/index.ts +7 -0
- package/src/services/scheduling/utils.ts +77 -0
- package/src/services/search/SearchProviderRegistry.ts +78 -0
- package/src/services/search/UnifiedSearchService.ts +218 -0
- package/src/services/search/index.ts +47 -0
- package/src/services/search/projectFilter.ts +22 -0
- package/src/services/search/providers/ConversationSearchProvider.ts +48 -0
- package/src/services/search/providers/LessonSearchProvider.ts +75 -0
- package/src/services/search/providers/ReportSearchProvider.ts +49 -0
- package/src/services/search/types.ts +144 -0
- package/src/services/skill/SkillService.ts +482 -0
- package/src/services/skill/index.ts +2 -0
- package/src/services/skill/types.ts +70 -0
- package/src/services/status/OperationsStatusService.ts +276 -0
- package/src/services/status/ProjectStatusService.ts +522 -0
- package/src/services/status/index.ts +11 -0
- package/src/services/storage/PrefixKVStore.ts +242 -0
- package/src/services/storage/index.ts +1 -0
- package/src/services/system-reminder/SystemReminderUtils.ts +96 -0
- package/src/services/system-reminder/index.ts +7 -0
- package/src/services/trust-pubkeys/TrustPubkeyService.ts +325 -0
- package/src/services/trust-pubkeys/index.ts +2 -0
- package/src/telemetry/ConversationSpanManager.ts +111 -0
- package/src/telemetry/EventLoopMonitor.ts +206 -0
- package/src/telemetry/LLMSpanRegistry.ts +20 -0
- package/src/telemetry/NostrSpanProcessor.ts +89 -0
- package/src/telemetry/ToolCallSpanProcessor.ts +66 -0
- package/src/telemetry/diagnostics.ts +27 -0
- package/src/telemetry/setup.ts +120 -0
- package/src/tools/implementations/agents_discover.ts +121 -0
- package/src/tools/implementations/agents_hire.ts +127 -0
- package/src/tools/implementations/agents_list.ts +96 -0
- package/src/tools/implementations/agents_publish.ts +611 -0
- package/src/tools/implementations/agents_read.ts +173 -0
- package/src/tools/implementations/agents_write.ts +200 -0
- package/src/tools/implementations/ask.ts +411 -0
- package/src/tools/implementations/change_model.ts +141 -0
- package/src/tools/implementations/conversation_get.ts +661 -0
- package/src/tools/implementations/conversation_list.ts +377 -0
- package/src/tools/implementations/conversation_search.ts +370 -0
- package/src/tools/implementations/delegate.ts +327 -0
- package/src/tools/implementations/delegate_crossproject.ts +209 -0
- package/src/tools/implementations/delegate_followup.ts +300 -0
- package/src/tools/implementations/fs_edit.ts +162 -0
- package/src/tools/implementations/fs_glob.ts +182 -0
- package/src/tools/implementations/fs_grep.ts +513 -0
- package/src/tools/implementations/fs_read.ts +332 -0
- package/src/tools/implementations/fs_write.ts +113 -0
- package/src/tools/implementations/generate_image.ts +259 -0
- package/src/tools/implementations/home_fs.ts +515 -0
- package/src/tools/implementations/kill.ts +651 -0
- package/src/tools/implementations/learn.ts +166 -0
- package/src/tools/implementations/lesson-formatter.ts +38 -0
- package/src/tools/implementations/lesson_delete.ts +164 -0
- package/src/tools/implementations/lesson_get.ts +105 -0
- package/src/tools/implementations/lessons_list.ts +153 -0
- package/src/tools/implementations/mcp_resource_read.ts +161 -0
- package/src/tools/implementations/mcp_subscribe.ts +158 -0
- package/src/tools/implementations/mcp_subscription_stop.ts +85 -0
- package/src/tools/implementations/nostr_fetch.ts +149 -0
- package/src/tools/implementations/nostr_publish_as_user.ts +353 -0
- package/src/tools/implementations/project_list.ts +146 -0
- package/src/tools/implementations/rag_add_documents.ts +573 -0
- package/src/tools/implementations/rag_create_collection.ts +65 -0
- package/src/tools/implementations/rag_delete_collection.ts +68 -0
- package/src/tools/implementations/rag_list_collections.ts +77 -0
- package/src/tools/implementations/rag_query.ts +107 -0
- package/src/tools/implementations/rag_subscription_create.ts +105 -0
- package/src/tools/implementations/rag_subscription_delete.ts +80 -0
- package/src/tools/implementations/rag_subscription_get.ts +123 -0
- package/src/tools/implementations/rag_subscription_list.ts +128 -0
- package/src/tools/implementations/report_delete.ts +79 -0
- package/src/tools/implementations/report_read.ts +160 -0
- package/src/tools/implementations/report_write.ts +278 -0
- package/src/tools/implementations/reports_list.ts +77 -0
- package/src/tools/implementations/schedule_task.ts +104 -0
- package/src/tools/implementations/schedule_task_cancel.ts +62 -0
- package/src/tools/implementations/schedule_task_once.ts +128 -0
- package/src/tools/implementations/schedule_tasks_list.ts +79 -0
- package/src/tools/implementations/search.ts +160 -0
- package/src/tools/implementations/shell.ts +553 -0
- package/src/tools/implementations/todo.ts +260 -0
- package/src/tools/implementations/upload_blob.ts +381 -0
- package/src/tools/implementations/web_fetch.ts +153 -0
- package/src/tools/implementations/web_search.ts +250 -0
- package/src/tools/registry.ts +670 -0
- package/src/tools/types.ts +177 -0
- package/src/tools/utils.ts +256 -0
- package/src/types/event-ids.ts +320 -0
- package/src/types/index.ts +46 -0
- package/src/utils/agentFetcher.ts +107 -0
- package/src/utils/cli-error.ts +29 -0
- package/src/utils/conversation-id.ts +27 -0
- package/src/utils/conversation-utils.ts +1 -0
- package/src/utils/delegation-chain.ts +357 -0
- package/src/utils/error-handler.ts +42 -0
- package/src/utils/git/gitignore.ts +69 -0
- package/src/utils/git/index.ts +2 -0
- package/src/utils/git/initializeGitRepo.ts +204 -0
- package/src/utils/git/worktree.ts +260 -0
- package/src/utils/lessonFormatter.ts +70 -0
- package/src/utils/lessonTrust.ts +24 -0
- package/src/utils/lockfile.ts +123 -0
- package/src/utils/logger.ts +149 -0
- package/src/utils/nostr-entity-parser.ts +365 -0
- package/src/utils/process.ts +49 -0
- package/src/wrapper.ts +262 -0
- 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,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
|
+
};
|