@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,160 @@
|
|
|
1
|
+
import type { ToolExecutionContext } from "@/tools/types";
|
|
2
|
+
import { getLocalReportStore, InvalidSlugError } from "@/services/reports";
|
|
3
|
+
import type { AISdkTool } from "@/tools/types";
|
|
4
|
+
import { logger } from "@/utils/logger";
|
|
5
|
+
import { tool } from "ai";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { nip19 } from "nostr-tools";
|
|
8
|
+
|
|
9
|
+
const reportReadSchema = z.object({
|
|
10
|
+
identifier: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe("The report identifier - can be a slug (e.g., 'my-report'), an naddr (e.g., 'naddr1...'), or a nostr: URI (e.g., 'nostr:naddr1...')"),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
type ReportReadInput = z.infer<typeof reportReadSchema>;
|
|
16
|
+
|
|
17
|
+
interface ReportReadOutput {
|
|
18
|
+
success: boolean;
|
|
19
|
+
slug?: string;
|
|
20
|
+
content?: string;
|
|
21
|
+
message?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Core implementation of report reading functionality
|
|
26
|
+
* Reads exclusively from local file storage
|
|
27
|
+
*/
|
|
28
|
+
async function executeReportRead(
|
|
29
|
+
input: ReportReadInput,
|
|
30
|
+
context: ToolExecutionContext
|
|
31
|
+
): Promise<ReportReadOutput> {
|
|
32
|
+
const { identifier } = input;
|
|
33
|
+
|
|
34
|
+
logger.info("📖 Reading report from local storage", {
|
|
35
|
+
identifier,
|
|
36
|
+
agent: context.agent.name,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const localStore = getLocalReportStore();
|
|
40
|
+
|
|
41
|
+
// Clean the identifier - extract slug if it's an naddr or has nostr: prefix
|
|
42
|
+
let slug = identifier;
|
|
43
|
+
|
|
44
|
+
// Remove nostr: prefix if present
|
|
45
|
+
if (slug.startsWith("nostr:")) {
|
|
46
|
+
slug = slug.slice(6);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// If it looks like an naddr, decode it to extract the slug (d-tag)
|
|
50
|
+
// Reports are NDKArticle events (kind 30023)
|
|
51
|
+
if (slug.startsWith("naddr1")) {
|
|
52
|
+
try {
|
|
53
|
+
const decoded = nip19.decode(slug);
|
|
54
|
+
if (decoded.type === "naddr") {
|
|
55
|
+
// Verify this is a report (kind 30023) - NDKArticle
|
|
56
|
+
if (decoded.data.kind !== 30023) {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
message: `Invalid naddr kind ${decoded.data.kind} - report_read only accepts kind 30023 (NDKArticle) naddrs. Got: ${identifier}`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (decoded.data.identifier) {
|
|
63
|
+
slug = decoded.data.identifier;
|
|
64
|
+
logger.debug("📖 Decoded naddr to slug", {
|
|
65
|
+
originalIdentifier: identifier,
|
|
66
|
+
extractedSlug: slug,
|
|
67
|
+
kind: decoded.data.kind,
|
|
68
|
+
agent: context.agent.name,
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
message: `Invalid naddr format - missing identifier (d-tag) in: ${identifier}`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
message: `Invalid naddr format - could not extract report slug from: ${identifier}`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
} catch (decodeError) {
|
|
83
|
+
logger.warn("📖 Failed to decode naddr identifier", {
|
|
84
|
+
identifier,
|
|
85
|
+
error: decodeError instanceof Error ? decodeError.message : String(decodeError),
|
|
86
|
+
agent: context.agent.name,
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
message: `Failed to decode naddr identifier: ${identifier}. Please provide a valid slug or naddr.`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Validate the slug for path safety
|
|
96
|
+
try {
|
|
97
|
+
localStore.validateSlug(slug);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (error instanceof InvalidSlugError) {
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
message: error.message,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Read from local storage
|
|
109
|
+
const content = await localStore.readReport(slug);
|
|
110
|
+
|
|
111
|
+
if (!content) {
|
|
112
|
+
logger.info("📭 No local report found", {
|
|
113
|
+
slug,
|
|
114
|
+
path: localStore.getReportPath(slug),
|
|
115
|
+
agent: context.agent.name,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
success: false,
|
|
120
|
+
message: `No report found with slug: ${slug}. The report may not have been written yet or synced from Nostr.`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
logger.info("✅ Report read successfully from local storage", {
|
|
125
|
+
slug,
|
|
126
|
+
contentLength: content.length,
|
|
127
|
+
agent: context.agent.name,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
success: true,
|
|
132
|
+
slug,
|
|
133
|
+
content,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Create an AI SDK tool for reading reports
|
|
139
|
+
*/
|
|
140
|
+
export function createReportReadTool(context: ToolExecutionContext): AISdkTool {
|
|
141
|
+
const aiTool = tool({
|
|
142
|
+
description: "Read a report by slug identifier",
|
|
143
|
+
|
|
144
|
+
inputSchema: reportReadSchema,
|
|
145
|
+
|
|
146
|
+
execute: async (input: ReportReadInput) => {
|
|
147
|
+
return await executeReportRead(input, context);
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
Object.defineProperty(aiTool, "getHumanReadableContent", {
|
|
152
|
+
value: ({ identifier }: ReportReadInput) => {
|
|
153
|
+
return `Reading report: ${identifier}`;
|
|
154
|
+
},
|
|
155
|
+
enumerable: false,
|
|
156
|
+
configurable: true,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return aiTool as AISdkTool;
|
|
160
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import type { ToolExecutionContext } from "@/tools/types";
|
|
2
|
+
import { PendingDelegationsRegistry } from "@/services/ral";
|
|
3
|
+
import { ReportService, getLocalReportStore, InvalidSlugError } from "@/services/reports";
|
|
4
|
+
import { getReportEmbeddingService } from "@/services/reports/ReportEmbeddingService";
|
|
5
|
+
import { getProjectContext } from "@/services/projects";
|
|
6
|
+
import type { AISdkTool } from "@/tools/types";
|
|
7
|
+
import { logger } from "@/utils/logger";
|
|
8
|
+
import { tool } from "ai";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
|
|
11
|
+
const reportWriteSchema = z.object({
|
|
12
|
+
slug: z.string().describe("The slug identifier for the article, used as the d-tag"),
|
|
13
|
+
title: z.string().describe("The title of the report"),
|
|
14
|
+
summary: z.string().describe("A one-line summary of the report"),
|
|
15
|
+
content: z.string().describe("The full content of the report in markdown format"),
|
|
16
|
+
hashtags: z
|
|
17
|
+
.array(z.string())
|
|
18
|
+
.default([])
|
|
19
|
+
.describe("Array of hashtags to add to the article (without the # prefix)"),
|
|
20
|
+
memorize: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.default(false)
|
|
23
|
+
.describe(
|
|
24
|
+
"When true, the report content will be automatically added to this agent's system prompt as persistent context. Use this for reports that are fundamental to your role (e.g., architecture decisions, domain knowledge, project conventions) that you want to always have available."
|
|
25
|
+
),
|
|
26
|
+
memorize_team: z
|
|
27
|
+
.boolean()
|
|
28
|
+
.default(false)
|
|
29
|
+
.describe(
|
|
30
|
+
"⚠️ HIGH CONTEXT COST - When true, the report content will be injected into the system prompt of ALL agents in the project, not just the authoring agent. Use ONLY for SHORT documents that are critical for EVERY agent to know. Examples: critical project-wide conventions, emergency procedures, or announcements that affect all agents. NEVER use for long documents or agent-specific information."
|
|
31
|
+
),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
type ReportWriteInput = z.infer<typeof reportWriteSchema>;
|
|
35
|
+
type ReportWriteOutput = {
|
|
36
|
+
success: boolean;
|
|
37
|
+
articleId: string;
|
|
38
|
+
slug: string;
|
|
39
|
+
message: string;
|
|
40
|
+
/** Addressable event references for a-tagging on the tool use event */
|
|
41
|
+
referencedAddressableEvents: string[];
|
|
42
|
+
/** Warning messages for non-fatal issues (e.g., local write failed but Nostr succeeded) */
|
|
43
|
+
warnings?: string[];
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Format report content for local storage with metadata header
|
|
48
|
+
*/
|
|
49
|
+
function formatReportContent(data: {
|
|
50
|
+
title: string;
|
|
51
|
+
summary: string;
|
|
52
|
+
content: string;
|
|
53
|
+
hashtags?: string[];
|
|
54
|
+
}): string {
|
|
55
|
+
const lines: string[] = [];
|
|
56
|
+
|
|
57
|
+
// Add title
|
|
58
|
+
lines.push(`# ${data.title}`);
|
|
59
|
+
lines.push("");
|
|
60
|
+
|
|
61
|
+
// Add summary
|
|
62
|
+
if (data.summary) {
|
|
63
|
+
lines.push(`> ${data.summary}`);
|
|
64
|
+
lines.push("");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Add hashtags if present
|
|
68
|
+
if (data.hashtags && data.hashtags.length > 0) {
|
|
69
|
+
lines.push(`**Tags:** ${data.hashtags.map((t) => `#${t}`).join(" ")}`);
|
|
70
|
+
lines.push("");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
lines.push("---");
|
|
74
|
+
lines.push("");
|
|
75
|
+
|
|
76
|
+
// Add content
|
|
77
|
+
lines.push(data.content);
|
|
78
|
+
|
|
79
|
+
return lines.join("\n");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Core implementation - extracted from existing execute function
|
|
83
|
+
async function executeReportWrite(
|
|
84
|
+
input: ReportWriteInput,
|
|
85
|
+
context: ToolExecutionContext
|
|
86
|
+
): Promise<ReportWriteOutput> {
|
|
87
|
+
const { slug, title, summary, content, hashtags, memorize, memorize_team } = input;
|
|
88
|
+
|
|
89
|
+
logger.info("📝 Writing report", {
|
|
90
|
+
slug,
|
|
91
|
+
title,
|
|
92
|
+
memorize,
|
|
93
|
+
memorize_team,
|
|
94
|
+
agent: context.agent.name,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const reportService = new ReportService();
|
|
98
|
+
const localStore = getLocalReportStore();
|
|
99
|
+
|
|
100
|
+
// Step 1: Validate slug BEFORE publishing to Nostr
|
|
101
|
+
// This prevents orphaned Nostr reports that can't be read back locally
|
|
102
|
+
try {
|
|
103
|
+
localStore.validateSlug(slug);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (error instanceof InvalidSlugError) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Invalid report slug "${slug}": ${error.message}. ` +
|
|
108
|
+
"Slugs can only contain alphanumeric characters, hyphens, and underscores.",
|
|
109
|
+
{ cause: error }
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Step 2: Publish to Nostr
|
|
116
|
+
const result = await reportService.writeReport(
|
|
117
|
+
{
|
|
118
|
+
slug,
|
|
119
|
+
title,
|
|
120
|
+
summary,
|
|
121
|
+
content,
|
|
122
|
+
hashtags,
|
|
123
|
+
memorize,
|
|
124
|
+
memorizeTeam: memorize_team,
|
|
125
|
+
},
|
|
126
|
+
context.agent
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// Step 3: Save to local storage
|
|
130
|
+
// Format the content for local storage
|
|
131
|
+
const formattedContent = formatReportContent({ title, summary, content, hashtags });
|
|
132
|
+
|
|
133
|
+
// The created_at is now (since we just published)
|
|
134
|
+
const createdAt = Math.floor(Date.now() / 1000);
|
|
135
|
+
|
|
136
|
+
// Try to save locally, but don't fail if Nostr publish succeeded
|
|
137
|
+
let localWriteFailed = false;
|
|
138
|
+
let localWriteError: string | undefined;
|
|
139
|
+
try {
|
|
140
|
+
await localStore.writeReport(slug, formattedContent, {
|
|
141
|
+
addressableRef: result.addressableRef,
|
|
142
|
+
createdAt,
|
|
143
|
+
slug,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
logger.info("📁 Report saved to local storage", {
|
|
147
|
+
slug,
|
|
148
|
+
path: localStore.getReportPath(slug),
|
|
149
|
+
});
|
|
150
|
+
} catch (localError) {
|
|
151
|
+
// Nostr publish succeeded but local save failed - log warning but don't throw
|
|
152
|
+
localWriteFailed = true;
|
|
153
|
+
localWriteError = localError instanceof Error ? localError.message : String(localError);
|
|
154
|
+
logger.warn("⚠️ Report published to Nostr but local save failed", {
|
|
155
|
+
slug,
|
|
156
|
+
error: localWriteError,
|
|
157
|
+
nostrId: result.encodedId,
|
|
158
|
+
});
|
|
159
|
+
// Continue - the report is live on Nostr and will be hydrated later
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Step 4: Index in RAG for semantic search
|
|
163
|
+
try {
|
|
164
|
+
const projectCtx = getProjectContext();
|
|
165
|
+
const projectTagId = projectCtx.project.tagId();
|
|
166
|
+
const reportEmbeddingService = getReportEmbeddingService();
|
|
167
|
+
|
|
168
|
+
const publishedAt = Math.floor(Date.now() / 1000);
|
|
169
|
+
await reportEmbeddingService.indexReport(
|
|
170
|
+
{ slug, title, summary, content, hashtags, publishedAt },
|
|
171
|
+
projectTagId,
|
|
172
|
+
context.agent.pubkey,
|
|
173
|
+
context.agent.name
|
|
174
|
+
);
|
|
175
|
+
} catch (ragError) {
|
|
176
|
+
// Don't fail the tool if RAG indexing fails
|
|
177
|
+
const ragMessage = ragError instanceof Error ? ragError.message : String(ragError);
|
|
178
|
+
logger.warn("Failed to index report in RAG", { slug, error: ragMessage });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let memorizeMessage = "";
|
|
182
|
+
if (memorize_team) {
|
|
183
|
+
memorizeMessage = " ⚠️ This report has been team-memorized and will be included in the system prompt of ALL agents in the project.";
|
|
184
|
+
} else if (memorize) {
|
|
185
|
+
memorizeMessage = " This report has been memorized and will be included in your system prompt.";
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
logger.info("✅ Report written successfully", {
|
|
189
|
+
slug,
|
|
190
|
+
articleId: result.encodedId,
|
|
191
|
+
addressableRef: result.addressableRef,
|
|
192
|
+
memorize,
|
|
193
|
+
memorize_team,
|
|
194
|
+
agent: context.agent.name,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Register with PendingDelegationsRegistry for a-tag correlation
|
|
198
|
+
PendingDelegationsRegistry.registerAddressable(
|
|
199
|
+
context.agent.pubkey,
|
|
200
|
+
context.conversationId,
|
|
201
|
+
result.addressableRef
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
// Build warnings array if there were any non-fatal issues
|
|
205
|
+
const warnings: string[] = [];
|
|
206
|
+
if (localWriteFailed) {
|
|
207
|
+
warnings.push(
|
|
208
|
+
`Local write failed (${localWriteError}). Report is published to Nostr and will be hydrated from subscription.`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
success: true,
|
|
214
|
+
articleId: `nostr:${result.encodedId}`,
|
|
215
|
+
slug,
|
|
216
|
+
message: `Report "${title}" published successfully.${memorizeMessage}`,
|
|
217
|
+
// Include addressable reference for ToolExecutionTracker to add as a-tag
|
|
218
|
+
referencedAddressableEvents: [result.addressableRef],
|
|
219
|
+
// Include warnings if any non-fatal issues occurred
|
|
220
|
+
...(warnings.length > 0 && { warnings }),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// AI SDK tool factory
|
|
225
|
+
export function createReportWriteTool(context: ToolExecutionContext): AISdkTool {
|
|
226
|
+
return tool({
|
|
227
|
+
description: `Write reports and documentation as NDKArticle events. Use for creating persistent documentation ABOUT THE PROJECT, such as:
|
|
228
|
+
- Architecture documentation
|
|
229
|
+
- Implementation plans
|
|
230
|
+
- Project summaries
|
|
231
|
+
- Design decisions
|
|
232
|
+
- Technical specifications
|
|
233
|
+
- API documentation
|
|
234
|
+
- Team guidelines and conventions
|
|
235
|
+
|
|
236
|
+
Reports are stored on Nostr network and accessible via slug. Updates existing reports with same slug. Supports markdown format and hashtags for categorization. Reports can be read back with report_read or listed with reports_list.
|
|
237
|
+
|
|
238
|
+
**CRITICAL:** Only use this for content ABOUT THE PROJECT. For content about your behavior or patterns in how you work, use lesson_learn instead.
|
|
239
|
+
|
|
240
|
+
**NEVER use for:**
|
|
241
|
+
- Behavioral patterns or workflows
|
|
242
|
+
- User preferences or communication styles
|
|
243
|
+
- Debugging approaches or work patterns
|
|
244
|
+
- "I've learned to..." statements about your approach
|
|
245
|
+
|
|
246
|
+
**Memorize Parameter**: Set memorize=true when the report contains information that is fundamental to your role and should always be available in your system prompt. Use this for:
|
|
247
|
+
- Core architectural decisions you need to reference frequently
|
|
248
|
+
- Domain knowledge essential to your function
|
|
249
|
+
- Project conventions or patterns you must follow consistently
|
|
250
|
+
- Any content you want persisted across all future conversations
|
|
251
|
+
|
|
252
|
+
When memorize=true, a "memorize" tag is added to the article and the content will be automatically injected into your system prompt.
|
|
253
|
+
|
|
254
|
+
**Memorize Team Parameter** (⚠️ USE WITH EXTREME CAUTION):
|
|
255
|
+
Set memorize_team=true ONLY when the report MUST be visible to EVERY agent in the project.
|
|
256
|
+
|
|
257
|
+
⚠️ **HIGH CONTEXT WINDOW COST** - This injects content into ALL agents' system prompts!
|
|
258
|
+
|
|
259
|
+
**ONLY use memorize_team for:**
|
|
260
|
+
- Critical project-wide conventions that ALL agents must follow
|
|
261
|
+
- Emergency procedures or time-sensitive announcements
|
|
262
|
+
- Extremely short (<500 chars) shared context that every agent needs
|
|
263
|
+
|
|
264
|
+
**NEVER use memorize_team for:**
|
|
265
|
+
- Long documents (architecture docs, specs, etc.)
|
|
266
|
+
- Agent-specific information
|
|
267
|
+
- Content that only some agents need
|
|
268
|
+
- General documentation (use regular reports instead)
|
|
269
|
+
|
|
270
|
+
When memorize_team=true, a "memorize_team" tag is added and the content will be injected into the system prompt of ALL agents.
|
|
271
|
+
|
|
272
|
+
See also: lesson_learn (for behavioral insights)`,
|
|
273
|
+
inputSchema: reportWriteSchema,
|
|
274
|
+
execute: async (input: ReportWriteInput) => {
|
|
275
|
+
return await executeReportWrite(input, context);
|
|
276
|
+
},
|
|
277
|
+
}) as AISdkTool;
|
|
278
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { AISdkTool, ToolExecutionContext } from "@/tools/types";
|
|
2
|
+
import { ReportService } from "@/services/reports";
|
|
3
|
+
import { getProjectContext } from "@/services/projects";
|
|
4
|
+
import { logger } from "@/utils/logger";
|
|
5
|
+
import { tool } from "ai";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
const reportsListSchema = z.object({});
|
|
9
|
+
|
|
10
|
+
type ReportsListInput = z.infer<typeof reportsListSchema>;
|
|
11
|
+
|
|
12
|
+
type ReportSummary = {
|
|
13
|
+
slug: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
summary?: string;
|
|
16
|
+
author: string;
|
|
17
|
+
publishedAt?: number;
|
|
18
|
+
hashtags?: string[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type ReportsListOutput = {
|
|
22
|
+
success: boolean;
|
|
23
|
+
reports: ReportSummary[];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Core implementation - extracted from existing execute function
|
|
27
|
+
async function executeReportsList(
|
|
28
|
+
_input: ReportsListInput,
|
|
29
|
+
context: ToolExecutionContext
|
|
30
|
+
): Promise<ReportsListOutput> {
|
|
31
|
+
logger.info("📚 Listing reports", {
|
|
32
|
+
agent: context.agent.name,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const reportService = new ReportService();
|
|
36
|
+
const projectCtx = getProjectContext();
|
|
37
|
+
|
|
38
|
+
// Fetch all reports in the project
|
|
39
|
+
const rawReports = await reportService.listReports();
|
|
40
|
+
|
|
41
|
+
// Transform reports: remove id, convert author hex pubkey to slug
|
|
42
|
+
const reports: ReportSummary[] = rawReports.map((report) => {
|
|
43
|
+
// Try to resolve author pubkey to agent slug
|
|
44
|
+
const agent = projectCtx.getAgentByPubkey(report.author);
|
|
45
|
+
const authorSlug = agent?.slug ?? report.author;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
slug: report.slug,
|
|
49
|
+
title: report.title,
|
|
50
|
+
summary: report.summary,
|
|
51
|
+
author: authorSlug,
|
|
52
|
+
publishedAt: report.publishedAt,
|
|
53
|
+
hashtags: report.hashtags,
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
logger.info("✅ Reports listed successfully", {
|
|
58
|
+
total: reports.length,
|
|
59
|
+
agent: context.agent.name,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
reports,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// AI SDK tool factory
|
|
69
|
+
export function createReportsListTool(context: ToolExecutionContext): AISdkTool {
|
|
70
|
+
return tool({
|
|
71
|
+
description: "List NDKArticle reports from agents in the project",
|
|
72
|
+
inputSchema: reportsListSchema,
|
|
73
|
+
execute: async (input: ReportsListInput) => {
|
|
74
|
+
return await executeReportsList(input, context);
|
|
75
|
+
},
|
|
76
|
+
}) as AISdkTool;
|
|
77
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { ToolExecutionContext } from "@/tools/types";
|
|
2
|
+
import { SchedulerService } from "@/services/scheduling";
|
|
3
|
+
import type { AISdkTool } from "@/tools/types";
|
|
4
|
+
import { resolveAgentSlug } from "@/services/agents";
|
|
5
|
+
import { logger } from "@/utils/logger";
|
|
6
|
+
import { tool } from "ai";
|
|
7
|
+
import * as cron from "node-cron";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a tool for scheduling tasks using cron notation
|
|
12
|
+
*/
|
|
13
|
+
export function createScheduleTaskTool(context: ToolExecutionContext): AISdkTool {
|
|
14
|
+
const aiTool = tool({
|
|
15
|
+
description:
|
|
16
|
+
"Schedule a task using cron notation (e.g., '0 9 * * *' for daily at 9am, '*/5 * * * *' for every 5 minutes)",
|
|
17
|
+
inputSchema: z.object({
|
|
18
|
+
title: z
|
|
19
|
+
.string()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("A human-readable title for the scheduled task (e.g., 'Daily standup reminder')"),
|
|
22
|
+
prompt: z.string().describe("The prompt to execute when the task runs"),
|
|
23
|
+
schedule: z
|
|
24
|
+
.string()
|
|
25
|
+
.describe(
|
|
26
|
+
"Cron expression for scheduling (e.g., '0 9 * * *' for daily at 9am, '0 * * * *' for hourly)"
|
|
27
|
+
),
|
|
28
|
+
targetAgent: z
|
|
29
|
+
.string()
|
|
30
|
+
.nullable()
|
|
31
|
+
.describe(
|
|
32
|
+
"Target agent slug (e.g., 'architect', 'claude-code'). Only agent slugs are accepted."
|
|
33
|
+
),
|
|
34
|
+
}),
|
|
35
|
+
execute: async ({ title, prompt, schedule, targetAgent }) => {
|
|
36
|
+
// Validate cron expression - throw for invalid input (consistent with delegate tool)
|
|
37
|
+
if (!cron.validate(schedule)) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Invalid cron expression: ${schedule}. Examples: '0 9 * * *' (daily at 9am), '*/5 * * * *' (every 5 minutes), '0 0 * * 0' (weekly on Sunday)`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Resolve target agent to pubkey if specified - throw for invalid slugs (consistent with delegate tool)
|
|
44
|
+
let toPubkey: string;
|
|
45
|
+
if (targetAgent) {
|
|
46
|
+
const resolution = resolveAgentSlug(targetAgent);
|
|
47
|
+
if (!resolution.pubkey) {
|
|
48
|
+
const availableSlugsStr = resolution.availableSlugs.length > 0
|
|
49
|
+
? `Available agent slugs: ${resolution.availableSlugs.join(", ")}`
|
|
50
|
+
: "No agents available in the current project context.";
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Invalid agent slug: "${targetAgent}". Only agent slugs are accepted. ${availableSlugsStr}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
toPubkey = resolution.pubkey;
|
|
56
|
+
} else {
|
|
57
|
+
// Default to self if no target specified
|
|
58
|
+
toPubkey = context.agent.pubkey;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const schedulerService = SchedulerService.getInstance();
|
|
62
|
+
|
|
63
|
+
// The agent scheduling the task is always the current agent
|
|
64
|
+
const fromPubkey = context.agent.pubkey;
|
|
65
|
+
|
|
66
|
+
// Add task to scheduler with both pubkeys and optional title
|
|
67
|
+
const taskId = await schedulerService.addTask(
|
|
68
|
+
schedule,
|
|
69
|
+
prompt,
|
|
70
|
+
fromPubkey,
|
|
71
|
+
toPubkey,
|
|
72
|
+
undefined, // projectId - let it be resolved from context
|
|
73
|
+
title
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
logger.info(
|
|
77
|
+
`Successfully created scheduled task ${taskId} with cron schedule: ${schedule}`
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
success: true,
|
|
82
|
+
taskId,
|
|
83
|
+
message: `Task scheduled successfully with ID: ${taskId}`,
|
|
84
|
+
title,
|
|
85
|
+
schedule,
|
|
86
|
+
prompt,
|
|
87
|
+
targetAgent: targetAgent || "self",
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Attach getHumanReadableContent as non-enumerable property
|
|
93
|
+
Object.defineProperty(aiTool, "getHumanReadableContent", {
|
|
94
|
+
value: (args: { title?: string; prompt: string; schedule: string; targetAgent?: string }) => {
|
|
95
|
+
const target = args.targetAgent ? ` for ${args.targetAgent}` : "";
|
|
96
|
+
const titlePart = args.title ? `'${args.title}' ` : "";
|
|
97
|
+
return `Scheduling task ${titlePart}with cron '${args.schedule}'${target}: ${args.prompt}`;
|
|
98
|
+
},
|
|
99
|
+
enumerable: false,
|
|
100
|
+
configurable: true,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return aiTool as AISdkTool;
|
|
104
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { SchedulerService } from "@/services/scheduling";
|
|
2
|
+
import type { ToolExecutionContext } from "@/tools/types";
|
|
3
|
+
import type { AISdkTool } from "@/tools/types";
|
|
4
|
+
import { logger } from "@/utils/logger";
|
|
5
|
+
import { tool } from "ai";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates a tool for canceling scheduled tasks
|
|
10
|
+
*/
|
|
11
|
+
export function createCancelScheduledTaskTool(_context: ToolExecutionContext): AISdkTool {
|
|
12
|
+
const aiTool = tool({
|
|
13
|
+
description: "Cancel a scheduled task (recurring or one-off) by its ID",
|
|
14
|
+
inputSchema: z.object({
|
|
15
|
+
taskId: z.string().describe("The ID of the task to cancel"),
|
|
16
|
+
}),
|
|
17
|
+
execute: async ({ taskId }) => {
|
|
18
|
+
try {
|
|
19
|
+
const schedulerService = SchedulerService.getInstance();
|
|
20
|
+
|
|
21
|
+
// Remove task from scheduler
|
|
22
|
+
const success = await schedulerService.removeTask(taskId);
|
|
23
|
+
|
|
24
|
+
if (!success) {
|
|
25
|
+
return {
|
|
26
|
+
success: false,
|
|
27
|
+
error: `Task ${taskId} not found or could not be removed`,
|
|
28
|
+
taskId,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
logger.info(`Successfully cancelled scheduled task ${taskId}`);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
success: true,
|
|
36
|
+
message: `Task ${taskId} cancelled successfully`,
|
|
37
|
+
taskId,
|
|
38
|
+
};
|
|
39
|
+
} catch (error: unknown) {
|
|
40
|
+
logger.error(`Failed to cancel scheduled task ${taskId}:`, error);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
success: false,
|
|
44
|
+
error:
|
|
45
|
+
error instanceof Error ? error.message : "Failed to cancel scheduled task",
|
|
46
|
+
taskId,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Attach getHumanReadableContent as non-enumerable property
|
|
53
|
+
Object.defineProperty(aiTool, "getHumanReadableContent", {
|
|
54
|
+
value: (args: { taskId: string }) => {
|
|
55
|
+
return `Canceling scheduled task ${args.taskId}`;
|
|
56
|
+
},
|
|
57
|
+
enumerable: false,
|
|
58
|
+
configurable: true,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return aiTool as AISdkTool;
|
|
62
|
+
}
|