@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,114 @@
|
|
|
1
|
+
import { readdirSync } from "node:fs";
|
|
2
|
+
import type { AgentInstance } from "@/agents/types/runtime";
|
|
3
|
+
import {
|
|
4
|
+
ensureAgentHomeDirectory,
|
|
5
|
+
getAgentHomeDirectory,
|
|
6
|
+
getAgentHomeInjectedFiles,
|
|
7
|
+
} from "@/lib/agent-home";
|
|
8
|
+
|
|
9
|
+
// Re-export for convenience (used by tests)
|
|
10
|
+
export { getAgentHomeDirectory } from "@/lib/agent-home";
|
|
11
|
+
import { logger } from "@/utils/logger";
|
|
12
|
+
import type { PromptFragment } from "../core/types";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Maximum number of entries to show in the home directory listing.
|
|
16
|
+
* Prevents prompt bloat if an agent has many files.
|
|
17
|
+
*/
|
|
18
|
+
const MAX_LISTING_ENTRIES = 50;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Arguments for the agent home directory fragment.
|
|
22
|
+
*/
|
|
23
|
+
interface AgentHomeDirectoryArgs {
|
|
24
|
+
agent: AgentInstance;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Build the home directory listing with proper error handling.
|
|
29
|
+
* Creates the directory if it doesn't exist and returns a formatted listing.
|
|
30
|
+
*/
|
|
31
|
+
function buildHomeListing(homeDir: string, agentPubkey: string): string {
|
|
32
|
+
// Try to create the directory using the shared helper
|
|
33
|
+
if (!ensureAgentHomeDirectory(agentPubkey)) {
|
|
34
|
+
return "(home directory unavailable)";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Try to list the directory contents
|
|
38
|
+
try {
|
|
39
|
+
const entries = readdirSync(homeDir, { withFileTypes: true }).sort((a, b) =>
|
|
40
|
+
a.name.localeCompare(b.name)
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (entries.length === 0) {
|
|
44
|
+
return "(empty)";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const totalCount = entries.length;
|
|
48
|
+
const displayEntries = entries.slice(0, MAX_LISTING_ENTRIES);
|
|
49
|
+
const lines = displayEntries.map((entry) => ` ${entry.name}${entry.isDirectory() ? "/" : ""}`);
|
|
50
|
+
|
|
51
|
+
if (totalCount > MAX_LISTING_ENTRIES) {
|
|
52
|
+
lines.push(` ...and ${totalCount - MAX_LISTING_ENTRIES} more`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return lines.join("\n");
|
|
56
|
+
} catch (error) {
|
|
57
|
+
logger.warn("Failed to list agent home dir:", error);
|
|
58
|
+
return "(unable to read directory)";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Agent home directory fragment.
|
|
64
|
+
* Provides agents with a personal workspace directory for notes, scripts, and other files.
|
|
65
|
+
* Also auto-injects contents of files starting with '+' into the prompt.
|
|
66
|
+
*/
|
|
67
|
+
export const agentHomeDirectoryFragment: PromptFragment<AgentHomeDirectoryArgs> = {
|
|
68
|
+
id: "agent-home-directory",
|
|
69
|
+
priority: 2, // Right after agent-identity (priority 1)
|
|
70
|
+
template: ({ agent }) => {
|
|
71
|
+
const homeDir = getAgentHomeDirectory(agent.pubkey);
|
|
72
|
+
const listing = buildHomeListing(homeDir, agent.pubkey);
|
|
73
|
+
const injectedFiles = getAgentHomeInjectedFiles(agent.pubkey);
|
|
74
|
+
|
|
75
|
+
const parts: string[] = [];
|
|
76
|
+
|
|
77
|
+
parts.push("## Your Home Directory\n");
|
|
78
|
+
parts.push(`You have a personal home directory at: \`${homeDir}\``);
|
|
79
|
+
parts.push("");
|
|
80
|
+
parts.push("**Current contents:**");
|
|
81
|
+
parts.push("```");
|
|
82
|
+
parts.push(listing);
|
|
83
|
+
parts.push("```");
|
|
84
|
+
parts.push("");
|
|
85
|
+
parts.push(
|
|
86
|
+
"Feel free to use this space for notes, helper scripts, temporary files, or any personal workspace needs. " +
|
|
87
|
+
"Use descriptive names for your files so you can easily find them later."
|
|
88
|
+
);
|
|
89
|
+
parts.push("");
|
|
90
|
+
parts.push(
|
|
91
|
+
"**Auto-injected files:** Files starting with `+` (e.g., `+NOTES.md`) are automatically injected into your system prompt. " +
|
|
92
|
+
"Use these for: critical reminders, preferences, or frequently-referenced notes."
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// Inject +prefixed file contents
|
|
96
|
+
if (injectedFiles.length > 0) {
|
|
97
|
+
parts.push("");
|
|
98
|
+
parts.push("### Injected File Contents\n");
|
|
99
|
+
|
|
100
|
+
for (const file of injectedFiles) {
|
|
101
|
+
parts.push(`**${file.filename}:**`);
|
|
102
|
+
if (file.truncated) {
|
|
103
|
+
parts.push("*(truncated to 1500 characters)*");
|
|
104
|
+
}
|
|
105
|
+
parts.push("```");
|
|
106
|
+
parts.push(file.content);
|
|
107
|
+
parts.push("```");
|
|
108
|
+
parts.push("");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return parts.join("\n");
|
|
113
|
+
},
|
|
114
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PromptFragment } from "../core/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Explains <system-reminder> tags that agents encounter in tool results and user messages.
|
|
5
|
+
* Always included — agents need this context before encountering any actual reminders.
|
|
6
|
+
*/
|
|
7
|
+
export const systemRemindersExplanationFragment: PromptFragment<Record<string, never>> = {
|
|
8
|
+
id: "system-reminders-explanation",
|
|
9
|
+
priority: 3,
|
|
10
|
+
template: () => {
|
|
11
|
+
return `## System Reminders
|
|
12
|
+
Tool results and user messages may include \`<system-reminder>\` tags. These contain dynamic information from the system — behavioral guidance, context updates, and state notifications. They bear no direct relation to the specific tool results or user messages in which they appear. Follow the instructions within them.`;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getRelayUrls } from "@/nostr/relays";
|
|
2
|
+
import type { PromptFragment } from "../core/types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Default relay URL used when no relays are configured.
|
|
6
|
+
* This mirrors the default in src/nostr/relays.ts
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_RELAY_URL = "wss://tenex.chat";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Relay configuration fragment.
|
|
12
|
+
* Provides agents with information about the configured Nostr relays.
|
|
13
|
+
* This helps agents understand where Nostr events are being published and received.
|
|
14
|
+
*/
|
|
15
|
+
export const relayConfigurationFragment: PromptFragment<Record<string, never>> = {
|
|
16
|
+
id: "relay-configuration",
|
|
17
|
+
priority: 4, // After global-system-prompt (3), before delegation-chain (5)
|
|
18
|
+
template: () => {
|
|
19
|
+
const relays = getRelayUrls();
|
|
20
|
+
const isDefault = relays.length === 1 && relays[0] === DEFAULT_RELAY_URL;
|
|
21
|
+
|
|
22
|
+
const parts: string[] = [];
|
|
23
|
+
|
|
24
|
+
parts.push("## Nostr Relay Configuration\n");
|
|
25
|
+
|
|
26
|
+
if (isDefault) {
|
|
27
|
+
parts.push("Using default relay:");
|
|
28
|
+
} else {
|
|
29
|
+
parts.push(`Connected to ${relays.length} relay${relays.length > 1 ? "s" : ""}:`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (const relay of relays) {
|
|
33
|
+
parts.push(`- ${relay}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return parts.join("\n");
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation Chain Fragment
|
|
3
|
+
*
|
|
4
|
+
* This fragment displays the delegation chain in the system prompt, showing
|
|
5
|
+
* agents their position in the multi-agent workflow hierarchy.
|
|
6
|
+
*
|
|
7
|
+
* Example output:
|
|
8
|
+
* ## Delegation Chain
|
|
9
|
+
* ```
|
|
10
|
+
* [User -> architect-orchestrator] [conversation 4f69d3302cf2]
|
|
11
|
+
* -> [architect-orchestrator -> execution-coordinator] [conversation 8a2bc1e45678]
|
|
12
|
+
* -> [execution-coordinator -> claude-code (you)] [conversation 1234567890ab]
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { DelegationChainEntry } from "@/conversations/types";
|
|
17
|
+
import type { PromptFragment } from "../core/types";
|
|
18
|
+
import { formatDelegationChain } from "@/utils/delegation-chain";
|
|
19
|
+
|
|
20
|
+
interface DelegationChainArgs {
|
|
21
|
+
/** The delegation chain entries (each with full conversation ID stored) */
|
|
22
|
+
delegationChain: DelegationChainEntry[];
|
|
23
|
+
/** The pubkey of the current agent (to mark with "(you)") */
|
|
24
|
+
currentAgentPubkey: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const delegationChainFragment: PromptFragment<DelegationChainArgs> = {
|
|
28
|
+
id: "delegation-chain",
|
|
29
|
+
priority: 5, // After identity (1) but before most other context
|
|
30
|
+
template: ({ delegationChain, currentAgentPubkey }) => {
|
|
31
|
+
if (!delegationChain || delegationChain.length === 0) {
|
|
32
|
+
return "";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const chainString = formatDelegationChain(delegationChain, currentAgentPubkey);
|
|
36
|
+
|
|
37
|
+
return `## Delegation Chain
|
|
38
|
+
\`\`\`
|
|
39
|
+
${chainString}
|
|
40
|
+
\`\`\`
|
|
41
|
+
|
|
42
|
+
This shows who initiated this request and how it reached you. The "(you)" marker indicates your position.
|
|
43
|
+
`;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { ConversationStore } from "@/conversations/ConversationStore";
|
|
2
|
+
import type { TodoItem } from "@/services/ral/types";
|
|
3
|
+
import type { PromptFragment } from "../core/types";
|
|
4
|
+
|
|
5
|
+
interface AgentTodosArgs {
|
|
6
|
+
conversation: ConversationStore;
|
|
7
|
+
agentPubkey: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function formatTodoItem(item: TodoItem): string {
|
|
11
|
+
const statusMarker: Record<string, string> = {
|
|
12
|
+
pending: "[ ]",
|
|
13
|
+
in_progress: "[~]",
|
|
14
|
+
done: "[x]",
|
|
15
|
+
skipped: "[-]",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
let line = `${statusMarker[item.status]} ${item.title} (id: ${item.id})`;
|
|
19
|
+
|
|
20
|
+
if (item.status === "skipped" && item.skipReason) {
|
|
21
|
+
line += ` (skipped: ${item.skipReason})`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return line;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const agentTodosFragment: PromptFragment<AgentTodosArgs> = {
|
|
28
|
+
id: "agent-todos",
|
|
29
|
+
priority: 6, // After phases (5), before other context
|
|
30
|
+
template: ({ conversation, agentPubkey }) => {
|
|
31
|
+
const todos = conversation.getTodos(agentPubkey);
|
|
32
|
+
|
|
33
|
+
if (todos.length === 0) {
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const parts: string[] = [];
|
|
38
|
+
const pending = todos.filter((t) => t.status === "pending");
|
|
39
|
+
const inProgress = todos.filter((t) => t.status === "in_progress");
|
|
40
|
+
const done = todos.filter((t) => t.status === "done");
|
|
41
|
+
const skipped = todos.filter((t) => t.status === "skipped");
|
|
42
|
+
|
|
43
|
+
parts.push("## Your Current Todo List");
|
|
44
|
+
parts.push("");
|
|
45
|
+
|
|
46
|
+
// Summary stats
|
|
47
|
+
parts.push(
|
|
48
|
+
`Status: ${pending.length} pending, ${inProgress.length} in progress, ${done.length} done, ${skipped.length} skipped`
|
|
49
|
+
);
|
|
50
|
+
parts.push("");
|
|
51
|
+
|
|
52
|
+
// List all items in order (array order is the source of truth)
|
|
53
|
+
for (const todo of todos) {
|
|
54
|
+
parts.push(formatTodoItem(todo));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
parts.push("");
|
|
58
|
+
parts.push("**Instructions:**");
|
|
59
|
+
parts.push(
|
|
60
|
+
"- Use `todo_write` to mark items as 'in_progress' when starting, 'done' when complete"
|
|
61
|
+
);
|
|
62
|
+
parts.push("- If skipping an item, set status='skipped' and provide a skip_reason");
|
|
63
|
+
parts.push("- Items with 'pending' status have not been started and require attention");
|
|
64
|
+
|
|
65
|
+
if (pending.length > 0) {
|
|
66
|
+
parts.push("");
|
|
67
|
+
parts.push(
|
|
68
|
+
`**ATTENTION:** You have ${pending.length} pending todo item(s) that need to be addressed.`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return parts.join("\n");
|
|
73
|
+
},
|
|
74
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PromptFragment } from "../core/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Static guidance about when to use todo tools.
|
|
5
|
+
* This is shown to all agents that have todo_add in their tools array.
|
|
6
|
+
* Complements 06-agent-todos.ts which shows the actual todo list.
|
|
7
|
+
*/
|
|
8
|
+
export const todoUsageGuidanceFragment: PromptFragment = {
|
|
9
|
+
id: "todo-usage-guidance",
|
|
10
|
+
priority: 6, // Same priority as agent-todos, shown before the list
|
|
11
|
+
template: () => `## Task Tracking with Todos
|
|
12
|
+
|
|
13
|
+
**IMPORTANT: Use \`todo_write()\` liberally and proactively!**
|
|
14
|
+
|
|
15
|
+
Creating a todo list helps you stay organized, shows your progress to observers, and ensures nothing gets forgotten. It's always better to have a simple todo list than none at all.
|
|
16
|
+
|
|
17
|
+
**Best Practice: Create todos EARLY in your work:**
|
|
18
|
+
- As soon as you receive a task, create a todo list
|
|
19
|
+
- Even 1-2 item lists are valuable for tracking progress
|
|
20
|
+
- Update your todos as you work (mark in_progress, done, add new items)
|
|
21
|
+
|
|
22
|
+
**Good candidates for todos:**
|
|
23
|
+
- Any task you'll spend more than a few seconds on
|
|
24
|
+
- Multi-step work (even just 2 steps)
|
|
25
|
+
- Tasks that involve file changes, tool calls, or research
|
|
26
|
+
- Work that others may want to observe or track
|
|
27
|
+
|
|
28
|
+
**Task management rules:**
|
|
29
|
+
- Only ONE task should be \`in_progress\` at a time
|
|
30
|
+
- Mark tasks \`done\` immediately after completing (don't batch completions)
|
|
31
|
+
- Use \`skipped\` with a reason if a task becomes irrelevant
|
|
32
|
+
- Keep your todo list updated as work progresses
|
|
33
|
+
`,
|
|
34
|
+
};
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import type { AgentInstance } from "@/agents/types";
|
|
2
|
+
import { agentStorage } from "@/agents/AgentStorage";
|
|
3
|
+
import { conversationRegistry } from "@/conversations/ConversationRegistry";
|
|
4
|
+
import { getDaemon } from "@/daemon";
|
|
5
|
+
import { RALRegistry } from "@/services/ral/RALRegistry";
|
|
6
|
+
import { getPubkeyService } from "@/services/PubkeyService";
|
|
7
|
+
import { logger } from "@/utils/logger";
|
|
8
|
+
import type { PromptFragment } from "../core/types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Meta-project context fragment - provides agents with awareness of
|
|
12
|
+
* their membership in OTHER projects and what's happening there.
|
|
13
|
+
*
|
|
14
|
+
* This enables cross-project awareness for agents that belong to multiple projects.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
interface MetaProjectContextArgs {
|
|
18
|
+
agent: AgentInstance;
|
|
19
|
+
currentProjectId?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface OtherProjectInfo {
|
|
23
|
+
projectId: string; // Full project ID: "31933:pubkey:dTag"
|
|
24
|
+
dTag: string; // Just the d-tag (human readable identifier)
|
|
25
|
+
title: string;
|
|
26
|
+
activeConversations: ActiveConversationSummary[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ActiveConversationSummary {
|
|
30
|
+
title: string;
|
|
31
|
+
agentName: string;
|
|
32
|
+
status: string; // "streaming", "running <tool>", "active"
|
|
33
|
+
duration: string; // "5m", "1h 30m"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const MAX_OTHER_PROJECTS = 5;
|
|
37
|
+
const MAX_CONVS_PER_PROJECT = 5;
|
|
38
|
+
const MAX_SUMMARY_LENGTH = 150;
|
|
39
|
+
const ELLIPSIS = "...";
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Sanitize text for safe inclusion in system prompt.
|
|
43
|
+
*/
|
|
44
|
+
function sanitizeForPrompt(text: string, maxLength: number = MAX_SUMMARY_LENGTH): string {
|
|
45
|
+
let sanitized = text
|
|
46
|
+
.replace(/[\r\n]+/g, " ")
|
|
47
|
+
.replace(/\s+/g, " ")
|
|
48
|
+
.trim();
|
|
49
|
+
|
|
50
|
+
if (sanitized.length > maxLength) {
|
|
51
|
+
sanitized = sanitized.substring(0, maxLength - ELLIPSIS.length) + ELLIPSIS;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return sanitized;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Format duration since a timestamp into a human-readable string.
|
|
59
|
+
*/
|
|
60
|
+
function formatDuration(startTimestampMs: number): string {
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
const durationMs = now - startTimestampMs;
|
|
63
|
+
const seconds = Math.floor(durationMs / 1000);
|
|
64
|
+
const minutes = Math.floor(seconds / 60);
|
|
65
|
+
const hours = Math.floor(minutes / 60);
|
|
66
|
+
|
|
67
|
+
if (hours > 0) {
|
|
68
|
+
const remainingMinutes = minutes % 60;
|
|
69
|
+
return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
|
|
70
|
+
}
|
|
71
|
+
if (minutes > 0) {
|
|
72
|
+
return `${minutes}m`;
|
|
73
|
+
}
|
|
74
|
+
return `${seconds}s`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Load other projects this agent belongs to and their active conversations.
|
|
79
|
+
*/
|
|
80
|
+
async function loadOtherProjectsContext(
|
|
81
|
+
agentPubkey: string,
|
|
82
|
+
currentProjectId?: string
|
|
83
|
+
): Promise<OtherProjectInfo[]> {
|
|
84
|
+
try {
|
|
85
|
+
// Get all project dTags where this agent is a member
|
|
86
|
+
const agentProjectDTags = await agentStorage.getAgentProjects(agentPubkey);
|
|
87
|
+
|
|
88
|
+
if (agentProjectDTags.length === 0) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Get daemon for known projects info
|
|
93
|
+
let daemon;
|
|
94
|
+
try {
|
|
95
|
+
daemon = getDaemon();
|
|
96
|
+
} catch {
|
|
97
|
+
// Daemon might not be available (e.g., in MCP-only mode or tests)
|
|
98
|
+
logger.debug("Meta-project context: daemon not available, skipping");
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const knownProjects = daemon.getKnownProjects();
|
|
103
|
+
const ralRegistry = RALRegistry.getInstance();
|
|
104
|
+
const pubkeyService = getPubkeyService();
|
|
105
|
+
|
|
106
|
+
// Build map of dTag -> full project info
|
|
107
|
+
const dTagToProjectId = new Map<string, { projectId: string; title: string }>();
|
|
108
|
+
for (const [projectId, project] of knownProjects) {
|
|
109
|
+
// projectId format: "31933:pubkey:dTag"
|
|
110
|
+
const parts = projectId.split(":");
|
|
111
|
+
const dTag = parts[2];
|
|
112
|
+
if (dTag && agentProjectDTags.includes(dTag)) {
|
|
113
|
+
const title = project.tagValue("title") || dTag;
|
|
114
|
+
dTagToProjectId.set(dTag, { projectId, title });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Filter out current project and limit
|
|
119
|
+
const otherProjectDTags = agentProjectDTags.filter(dTag => {
|
|
120
|
+
const info = dTagToProjectId.get(dTag);
|
|
121
|
+
return info && info.projectId !== currentProjectId;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const limitedDTags = otherProjectDTags.slice(0, MAX_OTHER_PROJECTS);
|
|
125
|
+
const results: OtherProjectInfo[] = [];
|
|
126
|
+
|
|
127
|
+
for (const dTag of limitedDTags) {
|
|
128
|
+
const projectInfo = dTagToProjectId.get(dTag);
|
|
129
|
+
if (!projectInfo) continue;
|
|
130
|
+
|
|
131
|
+
// Get active conversations for this project
|
|
132
|
+
const activeEntries = ralRegistry.getActiveEntriesForProject(projectInfo.projectId);
|
|
133
|
+
|
|
134
|
+
// Deduplicate by conversation and take most interesting entry
|
|
135
|
+
const conversationMap = new Map<string, typeof activeEntries[0]>();
|
|
136
|
+
for (const entry of activeEntries) {
|
|
137
|
+
const existing = conversationMap.get(entry.conversationId);
|
|
138
|
+
if (!existing ||
|
|
139
|
+
entry.isStreaming ||
|
|
140
|
+
(entry.currentTool && !existing.isStreaming) ||
|
|
141
|
+
entry.lastActivityAt > existing.lastActivityAt) {
|
|
142
|
+
conversationMap.set(entry.conversationId, entry);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Build conversation summaries
|
|
147
|
+
const activeConversations: ActiveConversationSummary[] = [];
|
|
148
|
+
let convCount = 0;
|
|
149
|
+
|
|
150
|
+
for (const [conversationId, entry] of conversationMap) {
|
|
151
|
+
if (convCount >= MAX_CONVS_PER_PROJECT) break;
|
|
152
|
+
|
|
153
|
+
// Get conversation title
|
|
154
|
+
let title = `Conversation ${conversationId.substring(0, 8)}...`;
|
|
155
|
+
const store = conversationRegistry.get(conversationId);
|
|
156
|
+
if (store) {
|
|
157
|
+
const metadata = store.getMetadata();
|
|
158
|
+
if (metadata.title) {
|
|
159
|
+
title = sanitizeForPrompt(metadata.title, 60);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Get agent name
|
|
164
|
+
const agentName = pubkeyService.getNameSync(entry.agentPubkey);
|
|
165
|
+
|
|
166
|
+
// Build status
|
|
167
|
+
let status: string;
|
|
168
|
+
if (entry.isStreaming) {
|
|
169
|
+
status = "streaming";
|
|
170
|
+
} else if (entry.currentTool) {
|
|
171
|
+
status = `running ${entry.currentTool}`;
|
|
172
|
+
} else {
|
|
173
|
+
status = "active";
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const duration = formatDuration(entry.createdAt);
|
|
177
|
+
|
|
178
|
+
activeConversations.push({
|
|
179
|
+
title,
|
|
180
|
+
agentName,
|
|
181
|
+
status,
|
|
182
|
+
duration,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
convCount++;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
results.push({
|
|
189
|
+
projectId: projectInfo.projectId,
|
|
190
|
+
dTag,
|
|
191
|
+
title: projectInfo.title,
|
|
192
|
+
activeConversations,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return results;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
logger.debug("Failed to load meta-project context", { error });
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export const metaProjectContextFragment: PromptFragment<MetaProjectContextArgs> = {
|
|
204
|
+
id: "meta-project-context",
|
|
205
|
+
priority: 7, // Between delegation-chain (5) and active-conversations (8)
|
|
206
|
+
template: async ({ agent, currentProjectId }) => {
|
|
207
|
+
const otherProjects = await loadOtherProjectsContext(agent.pubkey, currentProjectId);
|
|
208
|
+
|
|
209
|
+
if (otherProjects.length === 0) {
|
|
210
|
+
return ""; // No other projects to show
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const projectSections = otherProjects.map(project => {
|
|
214
|
+
const convLines = project.activeConversations.length > 0
|
|
215
|
+
? project.activeConversations.map(conv =>
|
|
216
|
+
` - "${conv.title}" - ${conv.agentName} (${conv.status}, ${conv.duration})`
|
|
217
|
+
).join("\n")
|
|
218
|
+
: " - No active conversations";
|
|
219
|
+
|
|
220
|
+
return `### Project: ${project.title}
|
|
221
|
+
- ID: ${project.dTag}
|
|
222
|
+
- Active conversations:
|
|
223
|
+
${convLines}`;
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
return `## Cross-Project Context
|
|
227
|
+
|
|
228
|
+
You are also a member of these other projects:
|
|
229
|
+
|
|
230
|
+
${projectSections.join("\n\n")}
|
|
231
|
+
|
|
232
|
+
---`;
|
|
233
|
+
},
|
|
234
|
+
};
|