@hailer/mcp 1.1.14 → 1.1.16
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/.claude/CLAUDE.md +370 -0
- package/.claude/agents/agent-ada-skill-builder.md +94 -0
- package/.claude/agents/agent-alejandro-function-fields.md +342 -0
- package/.claude/agents/agent-bjorn-config-audit.md +103 -0
- package/.claude/agents/agent-builder-agent-creator.md +130 -0
- package/.claude/agents/agent-code-simplifier.md +53 -0
- package/.claude/agents/agent-dmitri-activity-crud.md +159 -0
- package/.claude/agents/agent-giuseppe-app-builder.md +208 -0
- package/.claude/agents/agent-gunther-mcp-tools.md +39 -0
- package/.claude/agents/agent-helga-workflow-config.md +204 -0
- package/.claude/agents/agent-igor-activity-mover-automation.md +125 -0
- package/.claude/agents/agent-ingrid-doc-templates.md +261 -0
- package/.claude/agents/agent-ivan-monolith.md +154 -0
- package/.claude/agents/agent-kenji-data-reader.md +86 -0
- package/.claude/agents/agent-lars-code-inspector.md +102 -0
- package/.claude/agents/agent-marco-mockup-builder.md +110 -0
- package/.claude/agents/agent-marcus-api-documenter.md +323 -0
- package/.claude/agents/agent-marketplace-publisher.md +280 -0
- package/.claude/agents/agent-marketplace-reviewer.md +309 -0
- package/.claude/agents/agent-permissions-handler.md +208 -0
- package/.claude/agents/agent-simple-writer.md +48 -0
- package/.claude/agents/agent-svetlana-code-review.md +171 -0
- package/.claude/agents/agent-tanya-test-runner.md +333 -0
- package/.claude/agents/agent-ui-designer.md +100 -0
- package/.claude/agents/agent-viktor-sql-insights.md +212 -0
- package/.claude/agents/agent-web-search.md +55 -0
- package/.claude/agents/agent-yevgeni-discussions.md +45 -0
- package/.claude/agents/agent-zara-zapier.md +159 -0
- package/.claude/agents/ragnar.md +68 -0
- package/.claude/commands/app-squad.md +135 -0
- package/.claude/commands/audit-squad.md +158 -0
- package/.claude/commands/autoplan.md +563 -0
- package/.claude/commands/cleanup-squad.md +98 -0
- package/.claude/commands/config-squad.md +106 -0
- package/.claude/commands/crud-squad.md +87 -0
- package/.claude/commands/data-squad.md +97 -0
- package/.claude/commands/debug-squad.md +303 -0
- package/.claude/commands/doc-squad.md +65 -0
- package/.claude/commands/handoff.md +137 -0
- package/.claude/commands/health.md +49 -0
- package/.claude/commands/help.md +29 -0
- package/.claude/commands/help:agents.md +151 -0
- package/.claude/commands/help:commands.md +78 -0
- package/.claude/commands/help:faq.md +79 -0
- package/.claude/commands/help:plugins.md +50 -0
- package/.claude/commands/help:skills.md +93 -0
- package/.claude/commands/help:tools.md +75 -0
- package/.claude/commands/hotfix-squad.md +112 -0
- package/.claude/commands/integration-squad.md +82 -0
- package/.claude/commands/janitor-squad.md +167 -0
- package/.claude/commands/learn-auto.md +120 -0
- package/.claude/commands/learn.md +120 -0
- package/.claude/commands/mcp-list.md +27 -0
- package/.claude/commands/onboard-squad.md +140 -0
- package/.claude/commands/plan-workspace.md +732 -0
- package/.claude/commands/prd.md +130 -0
- package/.claude/commands/project-status.md +82 -0
- package/.claude/commands/publish.md +138 -0
- package/.claude/commands/recap.md +69 -0
- package/.claude/commands/restore.md +64 -0
- package/.claude/commands/review-squad.md +152 -0
- package/.claude/commands/save.md +24 -0
- package/.claude/commands/stats.md +19 -0
- package/.claude/commands/swarm.md +210 -0
- package/.claude/commands/tool-builder.md +39 -0
- package/.claude/commands/ws-pull.md +44 -0
- package/.claude/skills/SDK-activity-patterns/SKILL.md +428 -0
- package/.claude/skills/SDK-document-templates/SKILL.md +1033 -0
- package/.claude/skills/SDK-function-fields/SKILL.md +542 -0
- package/.claude/skills/SDK-generate-skill/SKILL.md +92 -0
- package/.claude/skills/SDK-init-skill/SKILL.md +127 -0
- package/.claude/skills/SDK-insight-queries/SKILL.md +787 -0
- package/.claude/skills/SDK-ws-config-skill/SKILL.md +1139 -0
- package/.claude/skills/agent-structure/SKILL.md +98 -0
- package/.claude/skills/api-documentation-patterns/SKILL.md +474 -0
- package/.claude/skills/chrome-mcp-reference/SKILL.md +370 -0
- package/.claude/skills/delegation-routing/SKILL.md +202 -0
- package/.claude/skills/frontend-design/SKILL.md +254 -0
- package/.claude/skills/hailer-activity-mover/SKILL.md +213 -0
- package/.claude/skills/hailer-api-client/SKILL.md +518 -0
- package/.claude/skills/hailer-app-builder/SKILL.md +1440 -0
- package/.claude/skills/hailer-apps-pictures/SKILL.md +269 -0
- package/.claude/skills/hailer-design-system/SKILL.md +231 -0
- package/.claude/skills/hailer-monolith-automations/SKILL.md +686 -0
- package/.claude/skills/hailer-permissions-system/SKILL.md +121 -0
- package/.claude/skills/hailer-project-protocol/SKILL.md +488 -0
- package/.claude/skills/hailer-rest-api/SKILL.md +61 -0
- package/.claude/skills/hailer-rest-api/hailer-activities.md +184 -0
- package/.claude/skills/hailer-rest-api/hailer-admin.md +473 -0
- package/.claude/skills/hailer-rest-api/hailer-calendar.md +256 -0
- package/.claude/skills/hailer-rest-api/hailer-feed.md +249 -0
- package/.claude/skills/hailer-rest-api/hailer-insights.md +195 -0
- package/.claude/skills/hailer-rest-api/hailer-messaging.md +276 -0
- package/.claude/skills/hailer-rest-api/hailer-workflows.md +283 -0
- package/.claude/skills/insight-join-patterns/SKILL.md +174 -0
- package/.claude/skills/integration-patterns/SKILL.md +421 -0
- package/.claude/skills/json-only-output/SKILL.md +72 -0
- package/.claude/skills/lsp-setup/SKILL.md +160 -0
- package/.claude/skills/mcp-direct-tools/SKILL.md +153 -0
- package/.claude/skills/optional-parameters/SKILL.md +72 -0
- package/.claude/skills/publish-hailer-app/SKILL.md +221 -0
- package/.claude/skills/testing-patterns/SKILL.md +630 -0
- package/.claude/skills/tool-builder/SKILL.md +250 -0
- package/.claude/skills/tool-parameter-usage/SKILL.md +126 -0
- package/.claude/skills/tool-response-verification/SKILL.md +92 -0
- package/.claude/skills/zapier-hailer-patterns/SKILL.md +581 -0
- package/.opencode/agent/agent-ada-skill-builder.md +35 -0
- package/.opencode/agent/agent-alejandro-function-fields.md +39 -0
- package/.opencode/agent/agent-bjorn-config-audit.md +36 -0
- package/.opencode/agent/agent-builder-agent-creator.md +39 -0
- package/.opencode/agent/agent-code-simplifier.md +31 -0
- package/.opencode/agent/agent-dmitri-activity-crud.md +40 -0
- package/.opencode/agent/agent-giuseppe-app-builder.md +37 -0
- package/.opencode/agent/agent-gunther-mcp-tools.md +39 -0
- package/.opencode/agent/agent-helga-workflow-config.md +204 -0
- package/.opencode/agent/agent-igor-activity-mover-automation.md +46 -0
- package/.opencode/agent/agent-ingrid-doc-templates.md +39 -0
- package/.opencode/agent/agent-ivan-monolith.md +46 -0
- package/.opencode/agent/agent-kenji-data-reader.md +53 -0
- package/.opencode/agent/agent-lars-code-inspector.md +28 -0
- package/.opencode/agent/agent-marco-mockup-builder.md +42 -0
- package/.opencode/agent/agent-marcus-api-documenter.md +53 -0
- package/.opencode/agent/agent-marketplace-publisher.md +44 -0
- package/.opencode/agent/agent-marketplace-reviewer.md +42 -0
- package/.opencode/agent/agent-permissions-handler.md +50 -0
- package/.opencode/agent/agent-simple-writer.md +45 -0
- package/.opencode/agent/agent-svetlana-code-review.md +39 -0
- package/.opencode/agent/agent-tanya-test-runner.md +57 -0
- package/.opencode/agent/agent-ui-designer.md +56 -0
- package/.opencode/agent/agent-viktor-sql-insights.md +34 -0
- package/.opencode/agent/agent-web-search.md +42 -0
- package/.opencode/agent/agent-yevgeni-discussions.md +37 -0
- package/.opencode/agent/agent-zara-zapier.md +53 -0
- package/.opencode/commands/app-squad.md +135 -0
- package/.opencode/commands/audit-squad.md +158 -0
- package/.opencode/commands/autoplan.md +563 -0
- package/.opencode/commands/cleanup-squad.md +98 -0
- package/.opencode/commands/config-squad.md +106 -0
- package/.opencode/commands/crud-squad.md +87 -0
- package/.opencode/commands/data-squad.md +97 -0
- package/.opencode/commands/debug-squad.md +303 -0
- package/.opencode/commands/doc-squad.md +65 -0
- package/.opencode/commands/handoff.md +137 -0
- package/.opencode/commands/health.md +49 -0
- package/.opencode/commands/help-agents.md +151 -0
- package/.opencode/commands/help-commands.md +32 -0
- package/.opencode/commands/help-faq.md +29 -0
- package/.opencode/commands/help-plugins.md +28 -0
- package/.opencode/commands/help-skills.md +7 -0
- package/.opencode/commands/help-tools.md +40 -0
- package/.opencode/commands/help.md +28 -0
- package/.opencode/commands/hotfix-squad.md +112 -0
- package/.opencode/commands/integration-squad.md +82 -0
- package/.opencode/commands/janitor-squad.md +167 -0
- package/.opencode/commands/learn-auto.md +120 -0
- package/.opencode/commands/learn.md +120 -0
- package/.opencode/commands/mcp-list.md +27 -0
- package/.opencode/commands/onboard-squad.md +140 -0
- package/.opencode/commands/plan-workspace.md +732 -0
- package/.opencode/commands/prd.md +131 -0
- package/.opencode/commands/project-status.md +82 -0
- package/.opencode/commands/publish.md +138 -0
- package/.opencode/commands/recap.md +69 -0
- package/.opencode/commands/restore.md +64 -0
- package/.opencode/commands/review-squad.md +152 -0
- package/.opencode/commands/save.md +24 -0
- package/.opencode/commands/stats.md +19 -0
- package/.opencode/commands/swarm.md +210 -0
- package/.opencode/commands/tool-builder.md +39 -0
- package/.opencode/commands/ws-pull.md +44 -0
- package/.opencode/opencode.json +21 -0
- package/dist/agents/bot-manager.d.ts +48 -0
- package/dist/agents/bot-manager.d.ts.map +1 -0
- package/dist/agents/bot-manager.js +254 -0
- package/dist/agents/bot-manager.js.map +1 -0
- package/dist/agents/bug-fixer/ai.d.ts +80 -0
- package/dist/agents/bug-fixer/ai.d.ts.map +1 -0
- package/dist/agents/bug-fixer/ai.js +466 -0
- package/dist/agents/bug-fixer/ai.js.map +1 -0
- package/dist/agents/bug-fixer/bot.d.ts +92 -0
- package/dist/agents/bug-fixer/bot.d.ts.map +1 -0
- package/dist/agents/bug-fixer/bot.js +687 -0
- package/dist/agents/bug-fixer/bot.js.map +1 -0
- package/dist/agents/bug-fixer/config.d.ts +21 -0
- package/dist/agents/bug-fixer/config.d.ts.map +1 -0
- package/dist/agents/bug-fixer/config.js +218 -0
- package/dist/agents/bug-fixer/config.js.map +1 -0
- package/dist/agents/bug-fixer/files.d.ts +67 -0
- package/dist/agents/bug-fixer/files.d.ts.map +1 -0
- package/dist/agents/bug-fixer/files.js +386 -0
- package/dist/agents/bug-fixer/files.js.map +1 -0
- package/dist/agents/bug-fixer/git.d.ts +48 -0
- package/dist/agents/bug-fixer/git.d.ts.map +1 -0
- package/dist/agents/bug-fixer/git.js +298 -0
- package/dist/agents/bug-fixer/git.js.map +1 -0
- package/dist/agents/bug-fixer/index.d.ts +103 -0
- package/dist/agents/bug-fixer/index.d.ts.map +1 -0
- package/dist/agents/bug-fixer/index.js +262 -0
- package/dist/agents/bug-fixer/index.js.map +1 -0
- package/dist/agents/bug-fixer/lsp.d.ts +113 -0
- package/dist/agents/bug-fixer/lsp.d.ts.map +1 -0
- package/dist/agents/bug-fixer/lsp.js +485 -0
- package/dist/agents/bug-fixer/lsp.js.map +1 -0
- package/dist/agents/bug-fixer/monitor.d.ts +123 -0
- package/dist/agents/bug-fixer/monitor.d.ts.map +1 -0
- package/dist/agents/bug-fixer/monitor.js +629 -0
- package/dist/agents/bug-fixer/monitor.js.map +1 -0
- package/dist/agents/bug-fixer/prompt.d.ts +5 -0
- package/dist/agents/bug-fixer/prompt.d.ts.map +1 -0
- package/dist/agents/bug-fixer/prompt.js +94 -0
- package/dist/agents/bug-fixer/prompt.js.map +1 -0
- package/dist/agents/bug-fixer/registries/pending-classification.d.ts +28 -0
- package/dist/agents/bug-fixer/registries/pending-classification.d.ts.map +1 -0
- package/dist/agents/bug-fixer/registries/pending-classification.js +50 -0
- package/dist/agents/bug-fixer/registries/pending-classification.js.map +1 -0
- package/dist/agents/bug-fixer/registries/pending-fix.d.ts +33 -0
- package/dist/agents/bug-fixer/registries/pending-fix.d.ts.map +1 -0
- package/dist/agents/bug-fixer/registries/pending-fix.js +64 -0
- package/dist/agents/bug-fixer/registries/pending-fix.js.map +1 -0
- package/dist/agents/bug-fixer/registries/pending.d.ts +27 -0
- package/dist/agents/bug-fixer/registries/pending.d.ts.map +1 -0
- package/dist/agents/bug-fixer/registries/pending.js +49 -0
- package/dist/agents/bug-fixer/registries/pending.js.map +1 -0
- package/dist/agents/bug-fixer/specialist-daemon.d.ts +88 -0
- package/dist/agents/bug-fixer/specialist-daemon.d.ts.map +1 -0
- package/dist/agents/bug-fixer/specialist-daemon.js +431 -0
- package/dist/agents/bug-fixer/specialist-daemon.js.map +1 -0
- package/dist/agents/bug-fixer/specialist.d.ts +47 -0
- package/dist/agents/bug-fixer/specialist.d.ts.map +1 -0
- package/dist/agents/bug-fixer/specialist.js +327 -0
- package/dist/agents/bug-fixer/specialist.js.map +1 -0
- package/dist/agents/bug-fixer/types.d.ts +123 -0
- package/dist/agents/bug-fixer/types.d.ts.map +1 -0
- package/dist/agents/bug-fixer/types.js +9 -0
- package/dist/agents/bug-fixer/types.js.map +1 -0
- package/dist/agents/factory.d.ts +172 -0
- package/dist/agents/factory.d.ts.map +1 -0
- package/dist/agents/factory.js +706 -0
- package/dist/agents/factory.js.map +1 -0
- package/dist/agents/hailer-expert/index.d.ts +8 -0
- package/dist/agents/hailer-expert/index.d.ts.map +1 -0
- package/dist/agents/hailer-expert/index.js +14 -0
- package/dist/agents/hailer-expert/index.js.map +1 -0
- package/dist/agents/hal/daemon.d.ts +174 -0
- package/dist/agents/hal/daemon.d.ts.map +1 -0
- package/dist/agents/hal/daemon.js +1385 -0
- package/dist/agents/hal/daemon.js.map +1 -0
- package/dist/agents/hal/definitions.d.ts +42 -0
- package/dist/agents/hal/definitions.d.ts.map +1 -0
- package/dist/agents/hal/definitions.js +300 -0
- package/dist/agents/hal/definitions.js.map +1 -0
- package/dist/agents/hal/index.d.ts +3 -0
- package/dist/agents/hal/index.d.ts.map +1 -0
- package/dist/agents/hal/index.js +8 -0
- package/dist/agents/hal/index.js.map +1 -0
- package/dist/agents/index.d.ts +18 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +48 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/shared/base.d.ts +253 -0
- package/dist/agents/shared/base.d.ts.map +1 -0
- package/dist/agents/shared/base.js +1122 -0
- package/dist/agents/shared/base.js.map +1 -0
- package/dist/agents/shared/schemas/action-schema.d.ts +62 -0
- package/dist/agents/shared/schemas/action-schema.d.ts.map +1 -0
- package/dist/agents/shared/schemas/action-schema.js +483 -0
- package/dist/agents/shared/schemas/action-schema.js.map +1 -0
- package/dist/agents/shared/services/agent-registry.d.ts +108 -0
- package/dist/agents/shared/services/agent-registry.d.ts.map +1 -0
- package/dist/agents/shared/services/agent-registry.js +469 -0
- package/dist/agents/shared/services/agent-registry.js.map +1 -0
- package/dist/agents/shared/services/conversation-manager.d.ts +57 -0
- package/dist/agents/shared/services/conversation-manager.d.ts.map +1 -0
- package/dist/agents/shared/services/conversation-manager.js +168 -0
- package/dist/agents/shared/services/conversation-manager.js.map +1 -0
- package/dist/agents/shared/services/mcp-client.d.ts +56 -0
- package/dist/agents/shared/services/mcp-client.d.ts.map +1 -0
- package/dist/agents/shared/services/mcp-client.js +124 -0
- package/dist/agents/shared/services/mcp-client.js.map +1 -0
- package/dist/agents/shared/services/message-classifier.d.ts +37 -0
- package/dist/agents/shared/services/message-classifier.d.ts.map +1 -0
- package/dist/agents/shared/services/message-classifier.js +203 -0
- package/dist/agents/shared/services/message-classifier.js.map +1 -0
- package/dist/agents/shared/services/message-formatter.d.ts +89 -0
- package/dist/agents/shared/services/message-formatter.d.ts.map +1 -0
- package/dist/agents/shared/services/message-formatter.js +390 -0
- package/dist/agents/shared/services/message-formatter.js.map +1 -0
- package/dist/agents/shared/services/session-logger.d.ts +162 -0
- package/dist/agents/shared/services/session-logger.d.ts.map +1 -0
- package/dist/agents/shared/services/session-logger.js +724 -0
- package/dist/agents/shared/services/session-logger.js.map +1 -0
- package/dist/agents/shared/services/structured-output-executor.d.ts +88 -0
- package/dist/agents/shared/services/structured-output-executor.d.ts.map +1 -0
- package/dist/agents/shared/services/structured-output-executor.js +296 -0
- package/dist/agents/shared/services/structured-output-executor.js.map +1 -0
- package/dist/agents/shared/services/token-billing.d.ts +72 -0
- package/dist/agents/shared/services/token-billing.d.ts.map +1 -0
- package/dist/agents/shared/services/token-billing.js +198 -0
- package/dist/agents/shared/services/token-billing.js.map +1 -0
- package/dist/agents/shared/services/tool-executor.d.ts +43 -0
- package/dist/agents/shared/services/tool-executor.d.ts.map +1 -0
- package/dist/agents/shared/services/tool-executor.js +175 -0
- package/dist/agents/shared/services/tool-executor.js.map +1 -0
- package/dist/agents/shared/services/typing-indicator.d.ts +24 -0
- package/dist/agents/shared/services/typing-indicator.d.ts.map +1 -0
- package/dist/agents/shared/services/typing-indicator.js +54 -0
- package/dist/agents/shared/services/typing-indicator.js.map +1 -0
- package/dist/agents/shared/services/workspace-schema-cache.d.ts +122 -0
- package/dist/agents/shared/services/workspace-schema-cache.d.ts.map +1 -0
- package/dist/agents/shared/services/workspace-schema-cache.js +507 -0
- package/dist/agents/shared/services/workspace-schema-cache.js.map +1 -0
- package/dist/agents/shared/specialist.d.ts +91 -0
- package/dist/agents/shared/specialist.d.ts.map +1 -0
- package/dist/agents/shared/specialist.js +399 -0
- package/dist/agents/shared/specialist.js.map +1 -0
- package/dist/agents/shared/tool-schema-loader.d.ts +65 -0
- package/dist/agents/shared/tool-schema-loader.d.ts.map +1 -0
- package/dist/agents/shared/tool-schema-loader.js +238 -0
- package/dist/agents/shared/tool-schema-loader.js.map +1 -0
- package/dist/agents/shared/types.d.ts +190 -0
- package/dist/agents/shared/types.d.ts.map +1 -0
- package/dist/agents/shared/types.js +13 -0
- package/dist/agents/shared/types.js.map +1 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js.map +1 -0
- package/dist/bot/bot-config.d.ts.map +1 -0
- package/dist/bot/bot-config.js.map +1 -0
- package/dist/bot/bot-manager.d.ts.map +1 -0
- package/dist/bot/bot-manager.js.map +1 -0
- package/dist/bot/bot.d.ts.map +1 -0
- package/dist/bot/bot.js.map +1 -0
- package/dist/bot/operation-logger.d.ts.map +1 -0
- package/dist/bot/operation-logger.js.map +1 -0
- package/dist/bot/services/__tests__/permission-guard.test.d.ts +2 -0
- package/dist/bot/services/__tests__/permission-guard.test.d.ts.map +1 -0
- package/dist/bot/services/__tests__/permission-guard.test.js +357 -0
- package/dist/bot/services/__tests__/permission-guard.test.js.map +1 -0
- package/dist/bot/services/conversation-manager.d.ts.map +1 -0
- package/dist/bot/services/conversation-manager.js.map +1 -0
- package/dist/bot/services/index.d.ts.map +1 -0
- package/dist/bot/services/index.js.map +1 -0
- package/dist/bot/services/message-classifier.d.ts.map +1 -0
- package/dist/bot/services/message-classifier.js.map +1 -0
- package/dist/bot/services/message-formatter.d.ts.map +1 -0
- package/dist/bot/services/message-formatter.js.map +1 -0
- package/dist/bot/services/permission-guard.d.ts.map +1 -0
- package/dist/bot/services/permission-guard.js.map +1 -0
- package/dist/bot/services/session-logger.d.ts.map +1 -0
- package/dist/bot/services/session-logger.js.map +1 -0
- package/dist/bot/services/token-billing.d.ts.map +1 -0
- package/dist/bot/services/token-billing.js.map +1 -0
- package/dist/bot/services/types.d.ts.map +1 -0
- package/dist/bot/services/types.js.map +1 -0
- package/dist/bot/services/typing-indicator.d.ts.map +1 -0
- package/dist/bot/services/typing-indicator.js.map +1 -0
- package/dist/bot/services/workspace-schema-cache.d.ts.map +1 -0
- package/dist/bot/services/workspace-schema-cache.js.map +1 -0
- package/dist/bot/tool-executor.d.ts.map +1 -0
- package/dist/bot/tool-executor.js.map +1 -0
- package/dist/bot/workspace-overview.d.ts.map +1 -0
- package/dist/bot/workspace-overview.js.map +1 -0
- package/dist/bot-config/constants.d.ts +42 -0
- package/dist/bot-config/constants.d.ts.map +1 -0
- package/dist/bot-config/constants.js +118 -0
- package/dist/bot-config/constants.js.map +1 -0
- package/dist/bot-config/context.d.ts +157 -0
- package/dist/bot-config/context.d.ts.map +1 -0
- package/dist/bot-config/context.js +475 -0
- package/dist/bot-config/context.js.map +1 -0
- package/dist/bot-config/index.d.ts +21 -0
- package/dist/bot-config/index.d.ts.map +1 -0
- package/dist/bot-config/index.js +104 -0
- package/dist/bot-config/index.js.map +1 -0
- package/dist/bot-config/loader.d.ts +28 -0
- package/dist/bot-config/loader.d.ts.map +1 -0
- package/dist/bot-config/loader.js +194 -0
- package/dist/bot-config/loader.js.map +1 -0
- package/dist/bot-config/persistence.d.ts +68 -0
- package/dist/bot-config/persistence.d.ts.map +1 -0
- package/dist/bot-config/persistence.js +261 -0
- package/dist/bot-config/persistence.js.map +1 -0
- package/dist/bot-config/state.d.ts +56 -0
- package/dist/bot-config/state.d.ts.map +1 -0
- package/dist/bot-config/state.js +197 -0
- package/dist/bot-config/state.js.map +1 -0
- package/dist/bot-config/tools.d.ts +28 -0
- package/dist/bot-config/tools.d.ts.map +1 -0
- package/dist/bot-config/tools.js +279 -0
- package/dist/bot-config/tools.js.map +1 -0
- package/dist/bot-config/types.d.ts +45 -0
- package/dist/bot-config/types.d.ts.map +1 -0
- package/dist/bot-config/types.js +9 -0
- package/dist/bot-config/types.js.map +1 -0
- package/dist/bot-config/webhooks.d.ts +27 -0
- package/dist/bot-config/webhooks.d.ts.map +1 -0
- package/dist/bot-config/webhooks.js +212 -0
- package/dist/bot-config/webhooks.js.map +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/agents/base.d.ts +207 -0
- package/dist/client/agents/base.d.ts.map +1 -0
- package/dist/client/agents/base.js +744 -0
- package/dist/client/agents/base.js.map +1 -0
- package/dist/client/agents/definitions.d.ts +53 -0
- package/dist/client/agents/definitions.d.ts.map +1 -0
- package/dist/client/agents/definitions.js +263 -0
- package/dist/client/agents/definitions.js.map +1 -0
- package/dist/client/agents/orchestrator.d.ts +141 -0
- package/dist/client/agents/orchestrator.d.ts.map +1 -0
- package/dist/client/agents/orchestrator.js +1062 -0
- package/dist/client/agents/orchestrator.js.map +1 -0
- package/dist/client/agents/specialist.d.ts +86 -0
- package/dist/client/agents/specialist.d.ts.map +1 -0
- package/dist/client/agents/specialist.js +340 -0
- package/dist/client/agents/specialist.js.map +1 -0
- package/dist/client/bot-entrypoint.d.ts +7 -0
- package/dist/client/bot-entrypoint.d.ts.map +1 -0
- package/dist/client/bot-entrypoint.js +103 -0
- package/dist/client/bot-entrypoint.js.map +1 -0
- package/dist/client/bot-manager.d.ts +44 -0
- package/dist/client/bot-manager.d.ts.map +1 -0
- package/dist/client/bot-manager.js +173 -0
- package/dist/client/bot-manager.js.map +1 -0
- package/dist/client/bot-runner.d.ts +35 -0
- package/dist/client/bot-runner.d.ts.map +1 -0
- package/dist/client/bot-runner.js +188 -0
- package/dist/client/bot-runner.js.map +1 -0
- package/dist/client/chat-agent-daemon.d.ts +464 -0
- package/dist/client/chat-agent-daemon.d.ts.map +1 -0
- package/dist/client/chat-agent-daemon.js +1774 -0
- package/dist/client/chat-agent-daemon.js.map +1 -0
- package/dist/client/daemon-factory.d.ts +106 -0
- package/dist/client/daemon-factory.d.ts.map +1 -0
- package/dist/client/daemon-factory.js +301 -0
- package/dist/client/daemon-factory.js.map +1 -0
- package/dist/client/factory.d.ts +111 -0
- package/dist/client/factory.d.ts.map +1 -0
- package/dist/client/factory.js +314 -0
- package/dist/client/factory.js.map +1 -0
- package/dist/client/index.d.ts +17 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +38 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/multi-bot-manager.d.ts +42 -0
- package/dist/client/multi-bot-manager.d.ts.map +1 -0
- package/dist/client/multi-bot-manager.js +161 -0
- package/dist/client/multi-bot-manager.js.map +1 -0
- package/dist/client/orchestrator-daemon.d.ts +87 -0
- package/dist/client/orchestrator-daemon.d.ts.map +1 -0
- package/dist/client/orchestrator-daemon.js +444 -0
- package/dist/client/orchestrator-daemon.js.map +1 -0
- package/dist/client/server.d.ts +8 -0
- package/dist/client/server.d.ts.map +1 -0
- package/dist/client/server.js +251 -0
- package/dist/client/server.js.map +1 -0
- package/dist/client/services/agent-registry.d.ts +108 -0
- package/dist/client/services/agent-registry.d.ts.map +1 -0
- package/dist/client/services/agent-registry.js +630 -0
- package/dist/client/services/agent-registry.js.map +1 -0
- package/dist/client/services/conversation-manager.d.ts +50 -0
- package/dist/client/services/conversation-manager.d.ts.map +1 -0
- package/dist/client/services/conversation-manager.js +136 -0
- package/dist/client/services/conversation-manager.js.map +1 -0
- package/dist/client/services/mcp-client.d.ts +48 -0
- package/dist/client/services/mcp-client.d.ts.map +1 -0
- package/dist/client/services/mcp-client.js +105 -0
- package/dist/client/services/mcp-client.js.map +1 -0
- package/dist/client/services/message-classifier.d.ts +37 -0
- package/dist/client/services/message-classifier.d.ts.map +1 -0
- package/dist/client/services/message-classifier.js +187 -0
- package/dist/client/services/message-classifier.js.map +1 -0
- package/dist/client/services/message-formatter.d.ts +84 -0
- package/dist/client/services/message-formatter.d.ts.map +1 -0
- package/dist/client/services/message-formatter.js +353 -0
- package/dist/client/services/message-formatter.js.map +1 -0
- package/dist/client/services/session-logger.d.ts +106 -0
- package/dist/client/services/session-logger.d.ts.map +1 -0
- package/dist/client/services/session-logger.js +446 -0
- package/dist/client/services/session-logger.js.map +1 -0
- package/dist/client/services/tool-executor.d.ts +41 -0
- package/dist/client/services/tool-executor.d.ts.map +1 -0
- package/dist/client/services/tool-executor.js +169 -0
- package/dist/client/services/tool-executor.js.map +1 -0
- package/dist/client/services/workspace-schema-cache.d.ts +149 -0
- package/dist/client/services/workspace-schema-cache.d.ts.map +1 -0
- package/dist/client/services/workspace-schema-cache.js +732 -0
- package/dist/client/services/workspace-schema-cache.js.map +1 -0
- package/dist/client/specialist-daemon.d.ts +77 -0
- package/dist/client/specialist-daemon.d.ts.map +1 -0
- package/dist/client/specialist-daemon.js +197 -0
- package/dist/client/specialist-daemon.js.map +1 -0
- package/dist/client/specialists.d.ts +53 -0
- package/dist/client/specialists.d.ts.map +1 -0
- package/dist/client/specialists.js +178 -0
- package/dist/client/specialists.js.map +1 -0
- package/dist/client/tool-schema-loader.d.ts +62 -0
- package/dist/client/tool-schema-loader.d.ts.map +1 -0
- package/dist/client/tool-schema-loader.js +232 -0
- package/dist/client/tool-schema-loader.js.map +1 -0
- package/dist/client/types.d.ts +327 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +121 -0
- package/dist/client/types.js.map +1 -0
- package/dist/commands/seed-config.d.ts +9 -0
- package/dist/commands/seed-config.d.ts.map +1 -0
- package/dist/commands/seed-config.js +392 -0
- package/dist/commands/seed-config.js.map +1 -0
- package/dist/commands/setup.d.ts +11 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +320 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js.map +1 -0
- package/dist/lib/discussion-lock.d.ts.map +1 -0
- package/dist/lib/discussion-lock.js.map +1 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/request-logger.d.ts.map +1 -0
- package/dist/lib/request-logger.js.map +1 -0
- package/dist/mcp/UserContextCache.d.ts.map +1 -0
- package/dist/mcp/UserContextCache.js.map +1 -0
- package/dist/mcp/auth.d.ts.map +1 -0
- package/dist/mcp/auth.js.map +1 -0
- package/dist/mcp/hailer-clients.d.ts.map +1 -0
- package/dist/mcp/hailer-clients.js.map +1 -0
- package/dist/mcp/session-store.d.ts.map +1 -0
- package/dist/mcp/session-store.js.map +1 -0
- package/dist/mcp/signal-handler.d.ts.map +1 -0
- package/dist/mcp/signal-handler.js.map +1 -0
- package/dist/mcp/tool-registry.d.ts.map +1 -0
- package/dist/mcp/tool-registry.js.map +1 -0
- package/dist/mcp/tools/__tests__/discussion-forward.test.d.ts +2 -0
- package/dist/mcp/tools/__tests__/discussion-forward.test.d.ts.map +1 -0
- package/dist/mcp/tools/__tests__/discussion-forward.test.js +218 -0
- package/dist/mcp/tools/__tests__/discussion-forward.test.js.map +1 -0
- package/dist/mcp/tools/activity.d.ts.map +1 -0
- package/dist/mcp/tools/activity.js.map +1 -0
- package/dist/mcp/tools/app-core.d.ts.map +1 -0
- package/dist/mcp/tools/app-core.js.map +1 -0
- package/dist/mcp/tools/app-marketplace.d.ts.map +1 -0
- package/dist/mcp/tools/app-marketplace.js.map +1 -0
- package/dist/mcp/tools/app-member.d.ts.map +1 -0
- package/dist/mcp/tools/app-member.js.map +1 -0
- package/dist/mcp/tools/app-scaffold.d.ts.map +1 -0
- package/dist/mcp/tools/app-scaffold.js.map +1 -0
- package/dist/mcp/tools/app.d.ts.map +1 -0
- package/dist/mcp/tools/app.js.map +1 -0
- package/dist/mcp/tools/bot-config/constants.d.ts.map +1 -0
- package/dist/mcp/tools/bot-config/constants.js.map +1 -0
- package/dist/mcp/tools/bot-config/core.d.ts.map +1 -0
- package/dist/mcp/tools/bot-config/core.js.map +1 -0
- package/dist/mcp/tools/bot-config/index.d.ts.map +1 -0
- package/dist/mcp/tools/bot-config/index.js.map +1 -0
- package/dist/mcp/tools/bot-config/tools.d.ts.map +1 -0
- package/dist/mcp/tools/bot-config/tools.js.map +1 -0
- package/dist/mcp/tools/bot-config/types.d.ts.map +1 -0
- package/dist/mcp/tools/bot-config/types.js.map +1 -0
- package/dist/mcp/tools/bug-fixer-tools.d.ts.map +1 -0
- package/dist/mcp/tools/bug-fixer-tools.js.map +1 -0
- package/dist/mcp/tools/company.d.ts.map +1 -0
- package/dist/mcp/tools/company.js.map +1 -0
- package/dist/mcp/tools/discussion.d.ts.map +1 -0
- package/dist/mcp/tools/discussion.js.map +1 -0
- package/dist/mcp/tools/document.d.ts.map +1 -0
- package/dist/mcp/tools/document.js.map +1 -0
- package/dist/mcp/tools/file.d.ts.map +1 -0
- package/dist/mcp/tools/file.js.map +1 -0
- package/dist/mcp/tools/insight.d.ts.map +1 -0
- package/dist/mcp/tools/insight.js.map +1 -0
- package/dist/mcp/tools/investigate.d.ts.map +1 -0
- package/dist/mcp/tools/investigate.js.map +1 -0
- package/dist/mcp/tools/user.d.ts.map +1 -0
- package/dist/mcp/tools/user.js.map +1 -0
- package/dist/mcp/tools/workflow-permissions.d.ts.map +1 -0
- package/dist/mcp/tools/workflow-permissions.js.map +1 -0
- package/dist/mcp/tools/workflow.d.ts.map +1 -0
- package/dist/mcp/tools/workflow.js.map +1 -0
- package/dist/mcp/utils/api-errors.d.ts.map +1 -0
- package/dist/mcp/utils/api-errors.js.map +1 -0
- package/dist/mcp/utils/data-transformers.d.ts.map +1 -0
- package/dist/mcp/utils/data-transformers.js.map +1 -0
- package/dist/mcp/utils/file-upload.d.ts.map +1 -0
- package/dist/mcp/utils/file-upload.js.map +1 -0
- package/dist/mcp/utils/hailer-api-client.d.ts.map +1 -0
- package/dist/mcp/utils/hailer-api-client.js.map +1 -0
- package/dist/mcp/utils/index.d.ts.map +1 -0
- package/dist/mcp/utils/index.js.map +1 -0
- package/dist/mcp/utils/logger.d.ts.map +1 -0
- package/dist/mcp/utils/logger.js.map +1 -0
- package/dist/mcp/utils/pagination.d.ts.map +1 -0
- package/dist/mcp/utils/pagination.js.map +1 -0
- package/dist/mcp/utils/response-builder.d.ts.map +1 -0
- package/dist/mcp/utils/response-builder.js.map +1 -0
- package/dist/mcp/utils/role-utils.d.ts.map +1 -0
- package/dist/mcp/utils/role-utils.js.map +1 -0
- package/dist/mcp/utils/tool-helpers.d.ts.map +1 -0
- package/dist/mcp/utils/tool-helpers.js.map +1 -0
- package/dist/mcp/utils/types.d.ts.map +1 -0
- package/dist/mcp/utils/types.js.map +1 -0
- package/dist/mcp/webhook-handler.d.ts.map +1 -0
- package/dist/mcp/webhook-handler.js.map +1 -0
- package/dist/mcp/workspace-cache.d.ts.map +1 -0
- package/dist/mcp/workspace-cache.js.map +1 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/modules/bug-reports/bug-config.d.ts +25 -0
- package/dist/modules/bug-reports/bug-config.d.ts.map +1 -0
- package/dist/modules/bug-reports/bug-config.js +187 -0
- package/dist/modules/bug-reports/bug-config.js.map +1 -0
- package/dist/modules/bug-reports/bug-monitor.d.ts +108 -0
- package/dist/modules/bug-reports/bug-monitor.d.ts.map +1 -0
- package/dist/modules/bug-reports/bug-monitor.js +510 -0
- package/dist/modules/bug-reports/bug-monitor.js.map +1 -0
- package/dist/modules/bug-reports/giuseppe-agent.d.ts +58 -0
- package/dist/modules/bug-reports/giuseppe-agent.d.ts.map +1 -0
- package/dist/modules/bug-reports/giuseppe-agent.js +467 -0
- package/dist/modules/bug-reports/giuseppe-agent.js.map +1 -0
- package/dist/modules/bug-reports/giuseppe-ai.d.ts +83 -0
- package/dist/modules/bug-reports/giuseppe-ai.d.ts.map +1 -0
- package/dist/modules/bug-reports/giuseppe-ai.js +466 -0
- package/dist/modules/bug-reports/giuseppe-ai.js.map +1 -0
- package/dist/modules/bug-reports/giuseppe-bot.d.ts +110 -0
- package/dist/modules/bug-reports/giuseppe-bot.d.ts.map +1 -0
- package/dist/modules/bug-reports/giuseppe-bot.js +804 -0
- package/dist/modules/bug-reports/giuseppe-bot.js.map +1 -0
- package/dist/modules/bug-reports/giuseppe-daemon.d.ts +80 -0
- package/dist/modules/bug-reports/giuseppe-daemon.d.ts.map +1 -0
- package/dist/modules/bug-reports/giuseppe-daemon.js +617 -0
- package/dist/modules/bug-reports/giuseppe-daemon.js.map +1 -0
- package/dist/modules/bug-reports/giuseppe-files.d.ts +64 -0
- package/dist/modules/bug-reports/giuseppe-files.d.ts.map +1 -0
- package/dist/modules/bug-reports/giuseppe-files.js +375 -0
- package/dist/modules/bug-reports/giuseppe-files.js.map +1 -0
- package/dist/modules/bug-reports/giuseppe-git.d.ts +48 -0
- package/dist/modules/bug-reports/giuseppe-git.d.ts.map +1 -0
- package/dist/modules/bug-reports/giuseppe-git.js +298 -0
- package/dist/modules/bug-reports/giuseppe-git.js.map +1 -0
- package/dist/modules/bug-reports/giuseppe-lsp.d.ts +113 -0
- package/dist/modules/bug-reports/giuseppe-lsp.d.ts.map +1 -0
- package/dist/modules/bug-reports/giuseppe-lsp.js +485 -0
- package/dist/modules/bug-reports/giuseppe-lsp.js.map +1 -0
- package/dist/modules/bug-reports/giuseppe-prompt.d.ts +5 -0
- package/dist/modules/bug-reports/giuseppe-prompt.d.ts.map +1 -0
- package/dist/modules/bug-reports/giuseppe-prompt.js +94 -0
- package/dist/modules/bug-reports/giuseppe-prompt.js.map +1 -0
- package/dist/modules/bug-reports/index.d.ts +77 -0
- package/dist/modules/bug-reports/index.d.ts.map +1 -0
- package/dist/modules/bug-reports/index.js +215 -0
- package/dist/modules/bug-reports/index.js.map +1 -0
- package/dist/modules/bug-reports/pending-classification-registry.d.ts +28 -0
- package/dist/modules/bug-reports/pending-classification-registry.d.ts.map +1 -0
- package/dist/modules/bug-reports/pending-classification-registry.js +50 -0
- package/dist/modules/bug-reports/pending-classification-registry.js.map +1 -0
- package/dist/modules/bug-reports/pending-fix-registry.d.ts +30 -0
- package/dist/modules/bug-reports/pending-fix-registry.d.ts.map +1 -0
- package/dist/modules/bug-reports/pending-fix-registry.js +42 -0
- package/dist/modules/bug-reports/pending-fix-registry.js.map +1 -0
- package/dist/modules/bug-reports/pending-registry.d.ts +27 -0
- package/dist/modules/bug-reports/pending-registry.d.ts.map +1 -0
- package/dist/modules/bug-reports/pending-registry.js +49 -0
- package/dist/modules/bug-reports/pending-registry.js.map +1 -0
- package/dist/modules/bug-reports/types.d.ts +123 -0
- package/dist/modules/bug-reports/types.d.ts.map +1 -0
- package/dist/modules/bug-reports/types.js +9 -0
- package/dist/modules/bug-reports/types.js.map +1 -0
- package/dist/plugins/bug-fixer/index.d.ts.map +1 -0
- package/dist/plugins/bug-fixer/index.js.map +1 -0
- package/dist/plugins/bug-fixer/tools.d.ts.map +1 -0
- package/dist/plugins/bug-fixer/tools.js.map +1 -0
- package/dist/plugins/vipunen/__tests__/tools.test.d.ts +10 -0
- package/dist/plugins/vipunen/__tests__/tools.test.d.ts.map +1 -0
- package/dist/plugins/vipunen/__tests__/tools.test.js +646 -0
- package/dist/plugins/vipunen/__tests__/tools.test.js.map +1 -0
- package/dist/plugins/vipunen/client.d.ts.map +1 -0
- package/dist/plugins/vipunen/client.js.map +1 -0
- package/dist/plugins/vipunen/index.d.ts.map +1 -0
- package/dist/plugins/vipunen/index.js.map +1 -0
- package/dist/plugins/vipunen/tools.d.ts.map +1 -0
- package/dist/plugins/vipunen/tools.js.map +1 -0
- package/dist/routes/agents.d.ts +44 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +311 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/services/agent-credential-store.d.ts +73 -0
- package/dist/services/agent-credential-store.d.ts.map +1 -0
- package/dist/services/agent-credential-store.js +212 -0
- package/dist/services/agent-credential-store.js.map +1 -0
- package/dist/stdio-server.d.ts.map +1 -0
- package/dist/stdio-server.js.map +1 -0
- package/dist/workspace/context.d.ts +148 -0
- package/dist/workspace/context.d.ts.map +1 -0
- package/dist/workspace/context.js +339 -0
- package/dist/workspace/context.js.map +1 -0
- package/dist/workspace/credentials.d.ts +55 -0
- package/dist/workspace/credentials.d.ts.map +1 -0
- package/dist/workspace/credentials.js +239 -0
- package/dist/workspace/credentials.js.map +1 -0
- package/dist/workspace/index.d.ts +21 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +45 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/loader.d.ts +27 -0
- package/dist/workspace/loader.d.ts.map +1 -0
- package/dist/workspace/loader.js +222 -0
- package/dist/workspace/loader.js.map +1 -0
- package/dist/workspace/schema.d.ts +37 -0
- package/dist/workspace/schema.d.ts.map +1 -0
- package/dist/workspace/schema.js +192 -0
- package/dist/workspace/schema.js.map +1 -0
- package/package.json +13 -1
- package/test-billing-server.js +0 -136
|
@@ -0,0 +1,1385 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Orchestrator Daemon (HAL) - OMNIPOTENT HAILER ASSISTANT
|
|
4
|
+
*
|
|
5
|
+
* The definitive Hailer expert with FULL ACCESS to all 39+ MCP tools.
|
|
6
|
+
* HAL handles EVERYTHING - from simple queries to complex multi-step operations.
|
|
7
|
+
*
|
|
8
|
+
* HAL can:
|
|
9
|
+
* - Full workflow management (create, configure, update fields/phases)
|
|
10
|
+
* - Complete activity operations (CRUD, single and bulk)
|
|
11
|
+
* - SQL insight creation, previewing, and analytics
|
|
12
|
+
* - App management, scaffolding, and deployment
|
|
13
|
+
* - Template and marketplace operations
|
|
14
|
+
* - Discussion management, file handling, user searches
|
|
15
|
+
* - Billing and workspace balance checks
|
|
16
|
+
* - Coordinate specialists for collaborative tasks (rare)
|
|
17
|
+
*
|
|
18
|
+
* Specialists exist but are RARELY needed - HAL handles everything himself first.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.OrchestratorDaemon = void 0;
|
|
22
|
+
const base_1 = require("../shared/base");
|
|
23
|
+
const definitions_1 = require("./definitions");
|
|
24
|
+
const logger_1 = require("../../lib/logger");
|
|
25
|
+
const pending_fix_1 = require("../bug-fixer/registries/pending-fix");
|
|
26
|
+
const pending_classification_1 = require("../bug-fixer/registries/pending-classification");
|
|
27
|
+
class OrchestratorDaemon extends base_1.ChatAgentDaemon {
|
|
28
|
+
orchestratorLogger;
|
|
29
|
+
specialists = new Map();
|
|
30
|
+
activeSpecialistsInDiscussion = new Map(); // discussionId -> Set<specialistUserId>
|
|
31
|
+
specialistUserIds = new Map(); // specialistKey -> userId
|
|
32
|
+
toolsUsedInCurrentMessage = false; // Track if tools were used in current message processing
|
|
33
|
+
lastToolsUsed = []; // Track which tools were used (for silent success detection)
|
|
34
|
+
lastToolsFailed = false; // Track if any tool failed (to allow error reporting)
|
|
35
|
+
// Tools that should NOT trigger confirmation messages back to source chat (on SUCCESS only)
|
|
36
|
+
static SILENT_SUCCESS_TOOLS = new Set(['join_discussion']);
|
|
37
|
+
// Cross-discussion memory - remembers recent activity context
|
|
38
|
+
lastKnownActivityId = null;
|
|
39
|
+
lastKnownActivityName = null;
|
|
40
|
+
lastKnownActivityTime = 0;
|
|
41
|
+
static CONTEXT_MEMORY_TIMEOUT = 5 * 60 * 1000; // 5 minutes
|
|
42
|
+
constructor(config) {
|
|
43
|
+
super(config);
|
|
44
|
+
this.orchestratorLogger = (0, logger_1.createLogger)({
|
|
45
|
+
component: "OrchestratorDaemon",
|
|
46
|
+
botId: config.botClient.userId,
|
|
47
|
+
});
|
|
48
|
+
// Register specialists from config (make copies to avoid cross-workspace contamination)
|
|
49
|
+
for (const [key, specialist] of Object.entries(definitions_1.SPECIALISTS)) {
|
|
50
|
+
// Clone the specialist so each orchestrator has its own instance
|
|
51
|
+
this.specialists.set(key, { ...specialist });
|
|
52
|
+
}
|
|
53
|
+
// Set specialist user IDs if provided
|
|
54
|
+
if (config.specialistUserIds) {
|
|
55
|
+
this.specialistUserIds = config.specialistUserIds;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Trigger HAL to respond in a discussion with specific context
|
|
60
|
+
* Used when bug monitor needs HAL to naturally inform users about Bug Fixer being disabled
|
|
61
|
+
*/
|
|
62
|
+
async respondWithContext(discussionId, activityId, contextMessage) {
|
|
63
|
+
this.orchestratorLogger.info('Triggering contextual response', { discussionId, activityId });
|
|
64
|
+
try {
|
|
65
|
+
// Join the discussion first using MCP tool
|
|
66
|
+
await this.callMcpTool("join_discussion", { activityId });
|
|
67
|
+
// Get workspace ID from bot client cache
|
|
68
|
+
const workspaceId = this.config.botClient.workspaceCache?.currentWorkspace?._id || '';
|
|
69
|
+
// Create a synthetic incoming message with the context
|
|
70
|
+
const syntheticMessage = {
|
|
71
|
+
id: `synthetic-${Date.now()}`,
|
|
72
|
+
discussionId,
|
|
73
|
+
linkedActivityId: activityId,
|
|
74
|
+
workspaceId,
|
|
75
|
+
content: contextMessage,
|
|
76
|
+
senderName: 'System',
|
|
77
|
+
senderId: 'system',
|
|
78
|
+
timestamp: Date.now(),
|
|
79
|
+
priority: 'high',
|
|
80
|
+
priorityReason: 'system_notification',
|
|
81
|
+
isReplyToBot: false,
|
|
82
|
+
isMention: false,
|
|
83
|
+
isDirectMessage: false,
|
|
84
|
+
};
|
|
85
|
+
// Process through normal LLM pipeline
|
|
86
|
+
// This will make HAL respond naturally with the context
|
|
87
|
+
await this['processMessage'](syntheticMessage);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
this.orchestratorLogger.error('Failed to respond with context', { error });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// ===== AGENT DIRECTORY OVERRIDES =====
|
|
94
|
+
/**
|
|
95
|
+
* Override agent name for Agent Directory
|
|
96
|
+
* Uses the actual Hailer user name from BotClient (set in workspace)
|
|
97
|
+
*/
|
|
98
|
+
getAgentName() {
|
|
99
|
+
// Use parent implementation which gets name from BotClient
|
|
100
|
+
return super.getAgentName();
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Override agent description for Agent Directory
|
|
104
|
+
*/
|
|
105
|
+
getAgentDescription() {
|
|
106
|
+
return "HAL - the omnipotent Hailer Assistant. Full access to 39+ MCP tools. Handles everything from simple queries to complex workflows, insights, and bulk operations. Can view apps but cannot create or manage them.";
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Override Position details for Orchestrator
|
|
110
|
+
*/
|
|
111
|
+
getPositionDetails() {
|
|
112
|
+
return {
|
|
113
|
+
name: "HAL - Omnipotent Hailer Assistant",
|
|
114
|
+
purpose: "THE definitive Hailer expert. Full access to 39+ MCP tools. Handles everything from simple queries to complex workflows, insights, bulk operations, and marketplace operations. Can view apps but cannot create or manage them.",
|
|
115
|
+
personaTone: "Sharp, efficient, and confident. Professional but approachable. Knows the platform inside and out.",
|
|
116
|
+
coreCapabilities: "- Full workflow management (create, configure, update fields/phases)\n- Complete activity operations (CRUD, bulk updates)\n- SQL insight creation and analytics\n- View apps (no creation or management)\n- Template and marketplace operations\n- Discussion management and file handling\n- User management and billing\n- Monitor all workspace discussions\n- Coordinate specialists for collaborative tasks (rare)",
|
|
117
|
+
boundaries: "- Never fabricate data - always use tools\n- Don't share credentials or sensitive config\n- Specialists available but rarely needed",
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Full Hailer Expert - HAL can do everything a Hailer power user can do
|
|
122
|
+
*/
|
|
123
|
+
getToolWhitelist() {
|
|
124
|
+
return [
|
|
125
|
+
// === WORKFLOW MANAGEMENT ===
|
|
126
|
+
"list_workflows",
|
|
127
|
+
"list_workflow_phases",
|
|
128
|
+
"get_workflow_schema",
|
|
129
|
+
"list_workflows_minimal",
|
|
130
|
+
"install_workflow",
|
|
131
|
+
"update_workflow_field",
|
|
132
|
+
"update_workflow_phase",
|
|
133
|
+
// === ACTIVITY OPERATIONS ===
|
|
134
|
+
"list_activities",
|
|
135
|
+
"show_activity_by_id",
|
|
136
|
+
"count_activities",
|
|
137
|
+
"create_activity",
|
|
138
|
+
"update_activity",
|
|
139
|
+
// === INSIGHT MANAGEMENT ===
|
|
140
|
+
"list_insights",
|
|
141
|
+
"create_insight",
|
|
142
|
+
"preview_insight",
|
|
143
|
+
"get_insight_data",
|
|
144
|
+
"update_insight",
|
|
145
|
+
// === APP MANAGEMENT ===
|
|
146
|
+
"list_apps", // View only
|
|
147
|
+
// === TEMPLATE & MARKETPLACE ===
|
|
148
|
+
"list_templates",
|
|
149
|
+
"get_template",
|
|
150
|
+
"create_template",
|
|
151
|
+
"install_template",
|
|
152
|
+
"publish_template",
|
|
153
|
+
"get_product",
|
|
154
|
+
"get_product_manifest",
|
|
155
|
+
"install_marketplace_app",
|
|
156
|
+
// === DISCUSSION TOOLS ===
|
|
157
|
+
"join_discussion",
|
|
158
|
+
"leave_discussion",
|
|
159
|
+
"add_discussion_message",
|
|
160
|
+
"invite_discussion_members",
|
|
161
|
+
"fetch_discussion_messages",
|
|
162
|
+
"fetch_previous_discussion_messages",
|
|
163
|
+
"get_activity_from_discussion",
|
|
164
|
+
"list_my_discussions",
|
|
165
|
+
// === USER & FILES ===
|
|
166
|
+
"search_workspace_users",
|
|
167
|
+
"download_file",
|
|
168
|
+
"upload_files",
|
|
169
|
+
// === BILLING ===
|
|
170
|
+
"get_workspace_balance",
|
|
171
|
+
// === ADVANCED ===
|
|
172
|
+
"test_function_field",
|
|
173
|
+
];
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get allowed actions for structured outputs mode
|
|
177
|
+
* Maps to the tool whitelist but includes meta actions
|
|
178
|
+
*/
|
|
179
|
+
getAllowedActions() {
|
|
180
|
+
return [
|
|
181
|
+
// Meta actions
|
|
182
|
+
"respond",
|
|
183
|
+
"ignore",
|
|
184
|
+
"invite_specialist",
|
|
185
|
+
// Same as tool whitelist
|
|
186
|
+
...this.getToolWhitelist(),
|
|
187
|
+
];
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Handle specialist invitation from structured outputs
|
|
191
|
+
* Translates action to existing specialist coordination logic
|
|
192
|
+
*/
|
|
193
|
+
async handleSpecialistInvite(specialistKey, context, originalMessage) {
|
|
194
|
+
const specialist = this.specialists.get(specialistKey);
|
|
195
|
+
if (!specialist) {
|
|
196
|
+
this.orchestratorLogger.warn("Unknown specialist requested", { specialistKey });
|
|
197
|
+
// Respond with error
|
|
198
|
+
await this.postResponse(originalMessage.discussionId, `I don't have a specialist available for "${specialistKey}". Available specialists: ${Array.from(this.specialists.keys()).join(", ")}`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Use existing specialist invitation logic
|
|
202
|
+
await this.inviteSpecialist(specialist, originalMessage.discussionId, context || "");
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Preprocess tool input - inject context for certain tools
|
|
206
|
+
* Uses cross-discussion memory to maintain context awareness
|
|
207
|
+
*/
|
|
208
|
+
preprocessToolInput(toolName, input) {
|
|
209
|
+
// Force compact output for schema tools (avoid verbose field dumps in discussions)
|
|
210
|
+
if (toolName === "get_workflow_schema") {
|
|
211
|
+
return { ...input, compact: true };
|
|
212
|
+
}
|
|
213
|
+
// Auto-inject sourceActivityId for join_discussion
|
|
214
|
+
if (toolName === "join_discussion") {
|
|
215
|
+
// Debug: Log current context state
|
|
216
|
+
this.orchestratorLogger.debug("join_discussion context check", {
|
|
217
|
+
currentLinkedActivityId: this.currentLinkedActivityId || "none",
|
|
218
|
+
lastKnownActivityId: this.lastKnownActivityId || "none",
|
|
219
|
+
inputSourceActivityId: input.sourceActivityId || "none",
|
|
220
|
+
currentDiscussionId: this.currentDiscussionId || "none",
|
|
221
|
+
});
|
|
222
|
+
if (!input.sourceActivityId) {
|
|
223
|
+
// First try current message's linked activity
|
|
224
|
+
const currentActivityId = this.currentLinkedActivityId;
|
|
225
|
+
// Fall back to recent memory if within timeout
|
|
226
|
+
const memoryStillValid = Date.now() - this.lastKnownActivityTime < OrchestratorDaemon.CONTEXT_MEMORY_TIMEOUT;
|
|
227
|
+
const sourceActivityId = currentActivityId || (memoryStillValid ? this.lastKnownActivityId : null);
|
|
228
|
+
if (sourceActivityId) {
|
|
229
|
+
this.orchestratorLogger.info("Auto-injected sourceActivityId", {
|
|
230
|
+
sourceActivityId,
|
|
231
|
+
fromCurrentMessage: !!currentActivityId,
|
|
232
|
+
fromMemory: !currentActivityId && !!sourceActivityId,
|
|
233
|
+
});
|
|
234
|
+
input = { ...input, sourceActivityId };
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
this.orchestratorLogger.debug("No sourceActivityId available to inject", {
|
|
238
|
+
currentLinkedActivityId: this.currentLinkedActivityId,
|
|
239
|
+
lastKnownActivityId: this.lastKnownActivityId,
|
|
240
|
+
memoryStillValid,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Always inject a default welcomeReason if user is being invited
|
|
245
|
+
// This ensures welcome messages are always posted
|
|
246
|
+
if (input.inviteUserId && !input.welcomeReason) {
|
|
247
|
+
const reason = this.lastKnownActivityName
|
|
248
|
+
? `Added from ${this.lastKnownActivityName} discussion`
|
|
249
|
+
: "Added to this discussion";
|
|
250
|
+
this.orchestratorLogger.debug("Auto-injected welcomeReason", { reason });
|
|
251
|
+
input = { ...input, welcomeReason: reason };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return input;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Override to detect tool failures for silent success feature
|
|
258
|
+
*/
|
|
259
|
+
async executeToolsAndContinue(toolUseBlocks, originalMessage) {
|
|
260
|
+
// Reset failure flag before executing tools
|
|
261
|
+
this.lastToolsFailed = false;
|
|
262
|
+
// Handle local tools (not sent to MCP)
|
|
263
|
+
const localToolResults = [];
|
|
264
|
+
const mcpToolBlocks = [];
|
|
265
|
+
for (const toolBlock of toolUseBlocks) {
|
|
266
|
+
if (toolBlock.name === 'trigger_bug_fixer_retry') {
|
|
267
|
+
// Handle locally - trigger Bug Fixer retry
|
|
268
|
+
const input = toolBlock.input;
|
|
269
|
+
const explanation = input.explanation || '';
|
|
270
|
+
const discussionId = originalMessage.discussionId;
|
|
271
|
+
const pendingFix = pending_fix_1.pendingFixRegistry.getPendingFix(discussionId);
|
|
272
|
+
if (!pendingFix) {
|
|
273
|
+
localToolResults.push({
|
|
274
|
+
type: 'tool_result',
|
|
275
|
+
tool_use_id: toolBlock.id,
|
|
276
|
+
content: 'No pending fix found for this discussion. The fix may have already been approved or cancelled.',
|
|
277
|
+
is_error: true,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
// Trigger the retry
|
|
282
|
+
const success = await pending_fix_1.pendingFixRegistry.triggerRetry(discussionId, explanation);
|
|
283
|
+
localToolResults.push({
|
|
284
|
+
type: 'tool_result',
|
|
285
|
+
tool_use_id: toolBlock.id,
|
|
286
|
+
content: success
|
|
287
|
+
? `✅ Triggered Bug Fixer retry with explanation: "${explanation.substring(0, 100)}...". Bug Fixer will analyze and apply a new fix.`
|
|
288
|
+
: '❌ Failed to trigger retry. Bug Fixer may not be available.',
|
|
289
|
+
is_error: !success,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
else if (toolBlock.name === 'confirm_bug_fix') {
|
|
294
|
+
// Handle locally - trigger Bug Fixer fix confirmation
|
|
295
|
+
const discussionId = originalMessage.discussionId;
|
|
296
|
+
const hasPending = pending_classification_1.pendingClassificationRegistry.has(discussionId);
|
|
297
|
+
if (!hasPending) {
|
|
298
|
+
localToolResults.push({
|
|
299
|
+
type: 'tool_result',
|
|
300
|
+
tool_use_id: toolBlock.id,
|
|
301
|
+
content: 'No pending classification found for this discussion. Bug Fixer may have already processed it.',
|
|
302
|
+
is_error: true,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
const success = await pending_classification_1.pendingClassificationRegistry.triggerFixIt(discussionId);
|
|
307
|
+
localToolResults.push({
|
|
308
|
+
type: 'tool_result',
|
|
309
|
+
tool_use_id: toolBlock.id,
|
|
310
|
+
content: success
|
|
311
|
+
? '✅ Triggered Bug Fixer to proceed with bug fix.'
|
|
312
|
+
: '❌ Failed to trigger fix. Bug Fixer may not be available.',
|
|
313
|
+
is_error: !success,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else if (toolBlock.name === 'decline_bug_report') {
|
|
318
|
+
// Handle locally - trigger Bug Fixer decline
|
|
319
|
+
const discussionId = originalMessage.discussionId;
|
|
320
|
+
const hasPending = pending_classification_1.pendingClassificationRegistry.has(discussionId);
|
|
321
|
+
if (!hasPending) {
|
|
322
|
+
localToolResults.push({
|
|
323
|
+
type: 'tool_result',
|
|
324
|
+
tool_use_id: toolBlock.id,
|
|
325
|
+
content: 'No pending classification found for this discussion. Bug Fixer may have already processed it.',
|
|
326
|
+
is_error: true,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
const success = await pending_classification_1.pendingClassificationRegistry.triggerNotABug(discussionId);
|
|
331
|
+
localToolResults.push({
|
|
332
|
+
type: 'tool_result',
|
|
333
|
+
tool_use_id: toolBlock.id,
|
|
334
|
+
content: success
|
|
335
|
+
? '✅ Marked as not a bug. Report moved to Declined.'
|
|
336
|
+
: '❌ Failed to decline. Bug Fixer may not be available.',
|
|
337
|
+
is_error: !success,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
// Send to MCP
|
|
343
|
+
mcpToolBlocks.push(toolBlock);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
// If we handled all tools locally, skip MCP execution
|
|
347
|
+
if (mcpToolBlocks.length === 0 && localToolResults.length > 0) {
|
|
348
|
+
const conversation = this.conversationManager.getConversation(originalMessage.discussionId);
|
|
349
|
+
conversation.push({
|
|
350
|
+
role: 'user',
|
|
351
|
+
content: localToolResults,
|
|
352
|
+
});
|
|
353
|
+
// Continue with LLM (with caching enabled)
|
|
354
|
+
const cachedConversation = this.conversationManager.prepareForCaching(conversation);
|
|
355
|
+
const response = await this.client.messages.create({
|
|
356
|
+
model: this.config.model || 'claude-haiku-4-5-20251001',
|
|
357
|
+
max_tokens: 2000,
|
|
358
|
+
system: this.getCachedSystemPrompt(),
|
|
359
|
+
messages: cachedConversation,
|
|
360
|
+
tools: this.getToolsWithBugFixerRetry(),
|
|
361
|
+
});
|
|
362
|
+
// Track and burn tokens for local tool handling
|
|
363
|
+
const sessionKey = this.currentLinkedActivityId || this.currentDiscussionId || "default";
|
|
364
|
+
const localSession = this.sessionLogger.getSession(sessionKey);
|
|
365
|
+
if (localSession && response.usage) {
|
|
366
|
+
const inputTokens = response.usage.input_tokens;
|
|
367
|
+
const outputTokens = response.usage.output_tokens;
|
|
368
|
+
const cacheCreationTokens = response.usage.cache_creation_input_tokens || 0;
|
|
369
|
+
const cacheReadTokens = response.usage.cache_read_input_tokens || 0;
|
|
370
|
+
localSession.metrics.inputTokens += inputTokens;
|
|
371
|
+
localSession.metrics.outputTokens += outputTokens;
|
|
372
|
+
localSession.metrics.cacheCreationTokens += cacheCreationTokens;
|
|
373
|
+
localSession.metrics.cacheReadTokens += cacheReadTokens;
|
|
374
|
+
localSession.metrics.apiCalls += 1;
|
|
375
|
+
localSession.lastActivityTime = Date.now();
|
|
376
|
+
// Burn tokens real-time (fire-and-forget)
|
|
377
|
+
if (this.tokenBilling && localSession.workspaceId) {
|
|
378
|
+
const cost = this.tokenBilling.calculateCost(inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens);
|
|
379
|
+
this.tokenBilling.burnTokens({
|
|
380
|
+
workspaceId: localSession.workspaceId,
|
|
381
|
+
inputTokens,
|
|
382
|
+
outputTokens,
|
|
383
|
+
cacheCreationTokens,
|
|
384
|
+
cacheReadTokens,
|
|
385
|
+
costUsd: cost,
|
|
386
|
+
sessionId: localSession.discussionId,
|
|
387
|
+
activityId: localSession.activityId,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
await this.handleLlmResponse(response, originalMessage);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
// If we have local results, add them to be processed together with MCP results
|
|
395
|
+
// (for now, just continue with original flow for MCP tools)
|
|
396
|
+
// Get current activity session
|
|
397
|
+
const sessionKey = this.currentLinkedActivityId || this.currentDiscussionId || "default";
|
|
398
|
+
const session = this.sessionLogger.getSession(sessionKey);
|
|
399
|
+
// Store the user's request that triggered these tool calls (for context)
|
|
400
|
+
if (session && !session.triggerRequest) {
|
|
401
|
+
session.triggerRequest = originalMessage.content.substring(0, 500);
|
|
402
|
+
session.requestedBy = originalMessage.senderName;
|
|
403
|
+
session.requestedById = originalMessage.senderId;
|
|
404
|
+
}
|
|
405
|
+
// Execute tools using the tool executor service
|
|
406
|
+
const toolResults = await this.toolExecutor.executeTools(toolUseBlocks, {
|
|
407
|
+
session,
|
|
408
|
+
preprocessToolInput: this.preprocessToolInput.bind(this),
|
|
409
|
+
});
|
|
410
|
+
// Check if any tool failed (detect various error patterns)
|
|
411
|
+
const anyToolFailed = toolResults.some(r => {
|
|
412
|
+
if (r.is_error)
|
|
413
|
+
return true;
|
|
414
|
+
// Check for error patterns in content (MCP tools return error text)
|
|
415
|
+
const content = r.content.toLowerCase();
|
|
416
|
+
return content.includes('error') || content.includes('failed') || content.includes('❌');
|
|
417
|
+
});
|
|
418
|
+
if (anyToolFailed) {
|
|
419
|
+
this.lastToolsFailed = true;
|
|
420
|
+
this.orchestratorLogger.debug("Tool failure detected", {
|
|
421
|
+
tools: this.lastToolsUsed,
|
|
422
|
+
failedCount: toolResults.filter(r => r.is_error).length,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
// Get conversation for this discussion
|
|
426
|
+
const conversation = this.conversationManager.getConversation(originalMessage.discussionId);
|
|
427
|
+
// Add tool results to conversation
|
|
428
|
+
conversation.push({
|
|
429
|
+
role: "user",
|
|
430
|
+
content: toolResults,
|
|
431
|
+
});
|
|
432
|
+
// Continue with LLM (with caching enabled)
|
|
433
|
+
const cachedConversation = this.conversationManager.prepareForCaching(conversation);
|
|
434
|
+
const response = await this.client.messages.create({
|
|
435
|
+
model: this.config.model || "claude-haiku-4-5-20251001",
|
|
436
|
+
max_tokens: 2000,
|
|
437
|
+
system: this.getCachedSystemPrompt(),
|
|
438
|
+
messages: cachedConversation,
|
|
439
|
+
tools: this.minimalTools,
|
|
440
|
+
});
|
|
441
|
+
// Track token usage in session (including cache stats for billing)
|
|
442
|
+
if (session && response.usage) {
|
|
443
|
+
const inputTokens = response.usage.input_tokens;
|
|
444
|
+
const outputTokens = response.usage.output_tokens;
|
|
445
|
+
const cacheCreationTokens = response.usage.cache_creation_input_tokens || 0;
|
|
446
|
+
const cacheReadTokens = response.usage.cache_read_input_tokens || 0;
|
|
447
|
+
session.metrics.inputTokens += inputTokens;
|
|
448
|
+
session.metrics.outputTokens += outputTokens;
|
|
449
|
+
session.metrics.cacheCreationTokens += cacheCreationTokens;
|
|
450
|
+
session.metrics.cacheReadTokens += cacheReadTokens;
|
|
451
|
+
session.metrics.apiCalls += 1;
|
|
452
|
+
session.lastActivityTime = Date.now();
|
|
453
|
+
// Burn tokens real-time (fire-and-forget) - inherited from base
|
|
454
|
+
if (this.tokenBilling && session.workspaceId) {
|
|
455
|
+
const cost = this.tokenBilling.calculateCost(inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens);
|
|
456
|
+
this.tokenBilling.burnTokens({
|
|
457
|
+
workspaceId: session.workspaceId,
|
|
458
|
+
inputTokens,
|
|
459
|
+
outputTokens,
|
|
460
|
+
cacheCreationTokens,
|
|
461
|
+
cacheReadTokens,
|
|
462
|
+
costUsd: cost,
|
|
463
|
+
sessionId: session.discussionId,
|
|
464
|
+
activityId: session.activityId,
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
// Recursively handle (might need more tools or finally respond)
|
|
469
|
+
await this.handleLlmResponse(response, originalMessage);
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Update cross-discussion memory when processing messages
|
|
473
|
+
* Call this when entering an activity discussion to remember context
|
|
474
|
+
*/
|
|
475
|
+
updateContextMemory(activityId, activityName) {
|
|
476
|
+
if (activityId) {
|
|
477
|
+
this.lastKnownActivityId = activityId;
|
|
478
|
+
this.lastKnownActivityName = activityName;
|
|
479
|
+
this.lastKnownActivityTime = Date.now();
|
|
480
|
+
this.orchestratorLogger.debug("Updated context memory", { activityId, activityName });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Override to update cross-discussion memory when entering activity discussions
|
|
485
|
+
*/
|
|
486
|
+
async extractIncomingMessage(signal) {
|
|
487
|
+
const message = await super.extractIncomingMessage(signal);
|
|
488
|
+
// Update context memory if this message is from an activity discussion
|
|
489
|
+
if (message?.linkedActivityId) {
|
|
490
|
+
this.updateContextMemory(message.linkedActivityId, message.linkedActivityName || null);
|
|
491
|
+
}
|
|
492
|
+
return message;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Register a specialist's Hailer user ID
|
|
496
|
+
* Called during initialization when we know the specialist bot's user ID
|
|
497
|
+
*/
|
|
498
|
+
registerSpecialistUserId(specialistKey, userId, displayName) {
|
|
499
|
+
this.specialistUserIds.set(specialistKey, userId);
|
|
500
|
+
const specialist = this.specialists.get(specialistKey);
|
|
501
|
+
if (specialist) {
|
|
502
|
+
specialist.botUserId = userId;
|
|
503
|
+
if (displayName) {
|
|
504
|
+
specialist.displayName = displayName;
|
|
505
|
+
}
|
|
506
|
+
this.orchestratorLogger.info("Specialist registered", {
|
|
507
|
+
key: specialistKey,
|
|
508
|
+
name: specialist.name,
|
|
509
|
+
displayName: specialist.displayName || specialist.name,
|
|
510
|
+
userId,
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Unregister a specialist (called when specialist is disabled/stopped)
|
|
516
|
+
* This prevents HAL from trying to invite a disabled specialist
|
|
517
|
+
*/
|
|
518
|
+
unregisterSpecialist(specialistKey) {
|
|
519
|
+
const specialist = this.specialists.get(specialistKey);
|
|
520
|
+
if (specialist) {
|
|
521
|
+
specialist.botUserId = undefined; // Mark as unavailable
|
|
522
|
+
this.orchestratorLogger.info("Specialist unregistered", {
|
|
523
|
+
key: specialistKey,
|
|
524
|
+
name: specialist.name,
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
this.specialistUserIds.delete(specialistKey);
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Mark a specialist as active in a discussion
|
|
531
|
+
*/
|
|
532
|
+
markSpecialistActive(discussionId, specialistUserId) {
|
|
533
|
+
if (!this.activeSpecialistsInDiscussion.has(discussionId)) {
|
|
534
|
+
this.activeSpecialistsInDiscussion.set(discussionId, new Set());
|
|
535
|
+
}
|
|
536
|
+
this.activeSpecialistsInDiscussion.get(discussionId).add(specialistUserId);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Invite a specialist to a discussion
|
|
540
|
+
* Always invites first (tool handles membership check), then tags
|
|
541
|
+
*/
|
|
542
|
+
async inviteSpecialist(specialist, discussionId, handoffContext) {
|
|
543
|
+
const specialistUserId = specialist.botUserId;
|
|
544
|
+
const displayName = specialist.displayName || specialist.name;
|
|
545
|
+
if (!specialistUserId) {
|
|
546
|
+
this.orchestratorLogger.warn("Specialist has no user ID", {
|
|
547
|
+
name: specialist.name,
|
|
548
|
+
});
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
try {
|
|
552
|
+
this.orchestratorLogger.info("Inviting specialist to discussion", {
|
|
553
|
+
name: specialist.name,
|
|
554
|
+
displayName,
|
|
555
|
+
userId: specialistUserId,
|
|
556
|
+
discussionId,
|
|
557
|
+
});
|
|
558
|
+
// Always call invite - the tool checks if already a member and handles gracefully
|
|
559
|
+
await this.callMcpTool("invite_discussion_members", {
|
|
560
|
+
discussionId,
|
|
561
|
+
userIds: [specialistUserId],
|
|
562
|
+
});
|
|
563
|
+
this.markSpecialistActive(discussionId, specialistUserId);
|
|
564
|
+
// Post handoff message with Hailer tag format using actual display name
|
|
565
|
+
await this.postResponse(discussionId, `[hailerTag|${displayName}](${specialistUserId}) - ${handoffContext}`);
|
|
566
|
+
this.orchestratorLogger.info("Specialist invited successfully", {
|
|
567
|
+
name: specialist.name,
|
|
568
|
+
displayName,
|
|
569
|
+
discussionId,
|
|
570
|
+
});
|
|
571
|
+
return true;
|
|
572
|
+
}
|
|
573
|
+
catch (error) {
|
|
574
|
+
this.orchestratorLogger.error("Failed to invite specialist", {
|
|
575
|
+
name: specialist.name,
|
|
576
|
+
displayName,
|
|
577
|
+
discussionId,
|
|
578
|
+
error: error instanceof Error ? error.message : String(error),
|
|
579
|
+
});
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Override getTools to include Bug Fixer retry tool when there's a pending fix
|
|
585
|
+
*/
|
|
586
|
+
getTools() {
|
|
587
|
+
// Always include the Bug Fixer retry tool so LLM knows about it
|
|
588
|
+
return this.getToolsWithBugFixerRetry();
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Get tools list with Bug Fixer retry tool added
|
|
592
|
+
*/
|
|
593
|
+
getToolsWithBugFixerRetry() {
|
|
594
|
+
const bugFixerRetryTool = {
|
|
595
|
+
name: 'trigger_bug_fixer_retry',
|
|
596
|
+
description: 'Trigger Bug Fixer to retry fixing a bug with new explanation. Use this after gathering enough info about what went wrong with the previous fix. Only works in discussions with a pending bug fix.',
|
|
597
|
+
input_schema: {
|
|
598
|
+
type: 'object',
|
|
599
|
+
properties: {
|
|
600
|
+
explanation: {
|
|
601
|
+
type: 'string',
|
|
602
|
+
description: 'Clear explanation of what is wrong with the current fix and what the expected behavior should be. Include: (1) what is broken, (2) expected vs actual behavior, (3) any specific details the user mentioned.',
|
|
603
|
+
},
|
|
604
|
+
},
|
|
605
|
+
required: ['explanation'],
|
|
606
|
+
},
|
|
607
|
+
};
|
|
608
|
+
const confirmBugFixTool = {
|
|
609
|
+
name: 'confirm_bug_fix',
|
|
610
|
+
description: 'Confirm that a bug report should be fixed. Use when user indicates they want the bug fixed (variations of "fix it", "yes fix", "please fix", etc.). Only works in discussions with a pending classification.',
|
|
611
|
+
input_schema: {
|
|
612
|
+
type: 'object',
|
|
613
|
+
properties: {},
|
|
614
|
+
required: [],
|
|
615
|
+
},
|
|
616
|
+
};
|
|
617
|
+
const declineBugReportTool = {
|
|
618
|
+
name: 'decline_bug_report',
|
|
619
|
+
description: 'Decline a bug report as not actually a bug. Use when user indicates it\'s not a bug (variations of "not a bug", "feature request", "not actually broken", etc.). Only works in discussions with a pending classification.',
|
|
620
|
+
input_schema: {
|
|
621
|
+
type: 'object',
|
|
622
|
+
properties: {},
|
|
623
|
+
required: [],
|
|
624
|
+
},
|
|
625
|
+
};
|
|
626
|
+
return [...this.minimalTools, bugFixerRetryTool, confirmBugFixTool, declineBugReportTool];
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Get pending fix context for a discussion (if any)
|
|
630
|
+
*/
|
|
631
|
+
getPendingFixContext(discussionId) {
|
|
632
|
+
const pendingFix = pending_fix_1.pendingFixRegistry.getPendingFix(discussionId);
|
|
633
|
+
if (!pendingFix) {
|
|
634
|
+
return '';
|
|
635
|
+
}
|
|
636
|
+
return `
|
|
637
|
+
<pending_bug_fix>
|
|
638
|
+
**IMPORTANT: This discussion has a pending bug fix from Bug Fixer!**
|
|
639
|
+
|
|
640
|
+
- Bug ID: ${pendingFix.bugId}
|
|
641
|
+
- State: ${pendingFix.state}
|
|
642
|
+
- Fix Summary: ${pendingFix.fixSummary}
|
|
643
|
+
|
|
644
|
+
**Your role:**
|
|
645
|
+
- If user says "approved" → Bug Fixer handles it automatically (you do nothing)
|
|
646
|
+
- If user expresses ANY dissatisfaction (denied, not working, still broken, etc.):
|
|
647
|
+
1. Ask what's wrong (if not clear)
|
|
648
|
+
2. Gather: what's broken + expected behavior
|
|
649
|
+
3. Use trigger_bug_fixer_retry tool with the explanation
|
|
650
|
+
|
|
651
|
+
**Remember:** You're gathering info for Bug Fixer. Be concise, ask ONE question at a time.
|
|
652
|
+
</pending_bug_fix>
|
|
653
|
+
`;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Get pending classification context for a discussion (if any)
|
|
657
|
+
*/
|
|
658
|
+
getPendingClassificationContext(discussionId) {
|
|
659
|
+
const pending = pending_classification_1.pendingClassificationRegistry.getPendingClassification(discussionId);
|
|
660
|
+
if (!pending) {
|
|
661
|
+
return '';
|
|
662
|
+
}
|
|
663
|
+
const classificationLabel = pending.classification === 'bug' ? 'Bug' :
|
|
664
|
+
pending.classification === 'feature_request' ? 'Feature Request' : 'Unclear';
|
|
665
|
+
return `
|
|
666
|
+
<pending_classification>
|
|
667
|
+
**IMPORTANT: Bug Fixer just classified this report and is waiting for user decision!**
|
|
668
|
+
|
|
669
|
+
- Bug: ${pending.bugName}
|
|
670
|
+
- App: ${pending.appName || pending.appId || 'Unknown'}
|
|
671
|
+
- Classification: ${classificationLabel}
|
|
672
|
+
- Reason: ${pending.reason}
|
|
673
|
+
|
|
674
|
+
**User options:**
|
|
675
|
+
- "fix it" → Bug Fixer will proceed to fix the bug
|
|
676
|
+
- "not a bug" → Report will be moved to Declined
|
|
677
|
+
|
|
678
|
+
**Your role - Use tools for user intent:**
|
|
679
|
+
- User wants to fix the bug → Call confirm_bug_fix tool
|
|
680
|
+
- User says it's not a bug / feature request → Call decline_bug_report tool
|
|
681
|
+
- User has questions → Help explain the classification
|
|
682
|
+
|
|
683
|
+
**Detecting intent (use tools, don't wait for exact words):**
|
|
684
|
+
- "fix it", "yes fix", "go ahead", "please fix", "fix this" → confirm_bug_fix
|
|
685
|
+
- "not a bug", "feature request", "not broken", "close it", "decline" → decline_bug_report
|
|
686
|
+
|
|
687
|
+
**Remember:** Use the tools to trigger actions. Don't tell user to type magic words.
|
|
688
|
+
</pending_classification>
|
|
689
|
+
`;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Get the STATIC portion of the system prompt (cacheable)
|
|
693
|
+
* This contains all content that doesn't change between calls for this bot instance
|
|
694
|
+
*/
|
|
695
|
+
getStaticSystemPrompt() {
|
|
696
|
+
const { firstName, lastName } = this.getAgentName();
|
|
697
|
+
const fullName = `${firstName} ${lastName}`.trim();
|
|
698
|
+
return `<identity>
|
|
699
|
+
You are ${fullName} - the OMNIPOTENT Hailer Assistant. The full Hailer expert.
|
|
700
|
+
Bot ID: ${this.botClient.userId}
|
|
701
|
+
|
|
702
|
+
You are THE definitive Hailer power user. You have FULL ACCESS to ALL Hailer capabilities:
|
|
703
|
+
workflows, activities, insights, apps, templates, marketplace, discussions, files, and more.
|
|
704
|
+
You handle EVERYTHING yourself - from simple queries to complex multi-step operations.
|
|
705
|
+
|
|
706
|
+
Specialists exist but are RARELY needed. You should ALWAYS try to solve tasks yourself first.
|
|
707
|
+
Only consider specialists for truly collaborative multi-person tasks that benefit from
|
|
708
|
+
parallel work or when you explicitly want to demonstrate specialist capabilities.
|
|
709
|
+
</identity>
|
|
710
|
+
|
|
711
|
+
<personality>
|
|
712
|
+
**BUSINESS MODE** (default):
|
|
713
|
+
- Professional, direct, competent
|
|
714
|
+
- Get things done efficiently
|
|
715
|
+
- Provide accurate information
|
|
716
|
+
- Confident in your full capabilities
|
|
717
|
+
|
|
718
|
+
**SARCASM MODE** (for ridiculous requests):
|
|
719
|
+
- Dry wit, not mean-spirited
|
|
720
|
+
- Still help after the gentle mockery
|
|
721
|
+
</personality>
|
|
722
|
+
|
|
723
|
+
<memory_awareness>
|
|
724
|
+
**When users ask about your memory or what you remember:**
|
|
725
|
+
|
|
726
|
+
You have access to the current discussion's message history. On each conversation:
|
|
727
|
+
- You load the last 15 messages from this discussion
|
|
728
|
+
- You remember everything said in THIS discussion thread
|
|
729
|
+
- Cross-session memory (what happened in OTHER discussions) is not available
|
|
730
|
+
|
|
731
|
+
**How to respond to "what do you remember?":**
|
|
732
|
+
- Keep it brief and positive
|
|
733
|
+
- Focus on what you CAN see (this discussion)
|
|
734
|
+
- Don't over-explain limitations
|
|
735
|
+
- If they want to reference past work, ask them to remind you of the context
|
|
736
|
+
|
|
737
|
+
**Good response:** "I can see our conversation in this thread. What specifically would you like me to recall or work on?"
|
|
738
|
+
|
|
739
|
+
**Bad response:** "That's a great question. Honestly, I don't have access to your previous conversation history with me..." (too verbose, focuses on limitations)
|
|
740
|
+
</memory_awareness>
|
|
741
|
+
|
|
742
|
+
<decision_framework>
|
|
743
|
+
For each message, decide:
|
|
744
|
+
|
|
745
|
+
1. **HIGH PRIORITY** (priority="high") - ALWAYS RESPOND:
|
|
746
|
+
- Direct messages (1:1) -> respond helpfully
|
|
747
|
+
- @mentions -> respond (even if just a greeting - acknowledge and ask how you can help)
|
|
748
|
+
- Replies to your messages -> respond
|
|
749
|
+
- **NEVER use <ignore/> for HIGH priority. Always acknowledge the user.**
|
|
750
|
+
|
|
751
|
+
2. **NORMAL PRIORITY** (general chat) - STRICT FILTERING:
|
|
752
|
+
|
|
753
|
+
**RESPOND ONLY IF the message:**
|
|
754
|
+
- Explicitly asks about Hailer (workflows, activities, insights, apps, discussions)
|
|
755
|
+
- Requests to find/list/create/update workspace data
|
|
756
|
+
- Discusses a specific activity, customer, project, or workflow by name
|
|
757
|
+
- You can genuinely help with workspace-related context
|
|
758
|
+
- Is a complex task needing specialist help
|
|
759
|
+
|
|
760
|
+
**IGNORE (output <ignore/>) for NORMAL priority if:**
|
|
761
|
+
- Random characters, gibberish, keyboard mashing (no real words, repeated patterns)
|
|
762
|
+
- General chit-chat unrelated to workspace ("how are you", jokes)
|
|
763
|
+
- Conversations between other users that don't need you
|
|
764
|
+
- Bare greetings without a question ("hi", "hey") - but NOT if HIGH priority!
|
|
765
|
+
- Off-topic discussions (sports, weather, personal chat)
|
|
766
|
+
- Anything you're uncertain about
|
|
767
|
+
|
|
768
|
+
**CRITICAL:** For NORMAL priority only - if no clear workspace-related question/task, output <ignore/>.
|
|
769
|
+
When in doubt about NORMAL priority, IGNORE. Your DEFAULT for normal priority is <ignore/>.
|
|
770
|
+
|
|
771
|
+
3. **RESPOND FORMAT** (only when you have something helpful):
|
|
772
|
+
<respond discussion="DISCUSSION_ID">
|
|
773
|
+
Your response
|
|
774
|
+
</respond>
|
|
775
|
+
|
|
776
|
+
4. **IGNORE FORMAT** (use liberally - this is your DEFAULT):
|
|
777
|
+
<ignore/>
|
|
778
|
+
</decision_framework>
|
|
779
|
+
|
|
780
|
+
<specialist_guidelines>
|
|
781
|
+
**YOU ARE THE EXPERT - Handle everything yourself first!**
|
|
782
|
+
|
|
783
|
+
You have FULL ACCESS to all 39+ MCP tools. You can do EVERYTHING:
|
|
784
|
+
- Create workflows, configure fields and phases
|
|
785
|
+
- Build insights with SQL queries
|
|
786
|
+
- Perform bulk operations on activities
|
|
787
|
+
- Generate reports and dashboards
|
|
788
|
+
- Manage apps and marketplace items
|
|
789
|
+
- Handle complex multi-step workflows
|
|
790
|
+
|
|
791
|
+
**When to HANDLE YOURSELF (almost always):**
|
|
792
|
+
- ALL workflow operations (create, configure, update)
|
|
793
|
+
- ALL insight creation (SQL queries, dashboards, reports)
|
|
794
|
+
- ALL bulk operations (even 100+ items)
|
|
795
|
+
- Complex multi-step data tasks
|
|
796
|
+
- Activity CRUD (single or bulk)
|
|
797
|
+
- File handling and attachments
|
|
798
|
+
- User searches and invitations
|
|
799
|
+
- Template and marketplace operations
|
|
800
|
+
- App management
|
|
801
|
+
|
|
802
|
+
**When specialists MIGHT help (rare):**
|
|
803
|
+
- User explicitly requests collaborative work with multiple bots
|
|
804
|
+
- Demonstrating specialist capabilities to users
|
|
805
|
+
- Long-running parallel tasks where multiple agents working simultaneously adds value
|
|
806
|
+
|
|
807
|
+
**DEFAULT BEHAVIOR:** Do it yourself. You're the Hailer expert.
|
|
808
|
+
|
|
809
|
+
<invite_syntax>
|
|
810
|
+
<invite specialist="specialistKey">
|
|
811
|
+
Clear description of what you need done.
|
|
812
|
+
Include relevant context from the conversation.
|
|
813
|
+
</invite>
|
|
814
|
+
</invite_syntax>
|
|
815
|
+
|
|
816
|
+
<invite_rules>
|
|
817
|
+
**CRITICAL: NEVER use tools to invite or tag specialists directly!**
|
|
818
|
+
- DO NOT use invite_discussion_members for specialists
|
|
819
|
+
- DO NOT use add_discussion_message with [hailerTag|...] for specialists
|
|
820
|
+
- ALWAYS use the <invite specialist="key">...</invite> XML pattern
|
|
821
|
+
|
|
822
|
+
The system will handle inviting the specialist to the discussion and tagging them.
|
|
823
|
+
If you try to invite/tag specialists directly via tools, they may not receive the message.
|
|
824
|
+
</invite_rules>
|
|
825
|
+
|
|
826
|
+
<handoff_rules>
|
|
827
|
+
If you DO invite a specialist (rare), include all gathered IDs:
|
|
828
|
+
|
|
829
|
+
<bad_handoff>
|
|
830
|
+
"Create an insight for the Injuries workflow showing player data"
|
|
831
|
+
</bad_handoff>
|
|
832
|
+
|
|
833
|
+
<good_handoff>
|
|
834
|
+
"Create insight for Injuries workflow:
|
|
835
|
+
- workflowId: 691ffdf84217e9e8434e56ad
|
|
836
|
+
- Fields: { name: 'playerName', fieldId: '691ffdf84217e9e8434e56b1' }, { name: 'injuryType', fieldId: '691ffdf84217e9e8434e56b2' }
|
|
837
|
+
- Query: SELECT name as \\"Activity\\", playerName, injuryType FROM injuries ORDER BY name"
|
|
838
|
+
</good_handoff>
|
|
839
|
+
|
|
840
|
+
<insight_field_format>
|
|
841
|
+
Always format fields as: { name: 'Column Name', fieldId: 'FIELD_ID' }
|
|
842
|
+
Use 'fieldId' not 'id' for the field identifier.
|
|
843
|
+
</insight_field_format>
|
|
844
|
+
</handoff_rules>
|
|
845
|
+
|
|
846
|
+
<after_invite>
|
|
847
|
+
1. I invite them to the discussion
|
|
848
|
+
2. I post your handoff message mentioning them
|
|
849
|
+
3. They see it and take action
|
|
850
|
+
</after_invite>
|
|
851
|
+
</specialist_guidelines>
|
|
852
|
+
|
|
853
|
+
<tagging_syntax>
|
|
854
|
+
To @mention someone in Hailer, use this format:
|
|
855
|
+
[hailerTag|Display Name](userId)
|
|
856
|
+
|
|
857
|
+
Example: [hailerTag|User Name](userId)
|
|
858
|
+
|
|
859
|
+
For specialists, use their display name and userId from the specialists list.
|
|
860
|
+
Do NOT use plain @mentions like "@hailerExpert" - they won't work.
|
|
861
|
+
</tagging_syntax>
|
|
862
|
+
|
|
863
|
+
<bug_fixer_autonomous>
|
|
864
|
+
**Bug Fixer - Autonomous Bug Fixer**
|
|
865
|
+
|
|
866
|
+
Bug Fixer is SPECIAL - he works AUTONOMOUSLY, not through invites!
|
|
867
|
+
|
|
868
|
+
**How Bug Fixer works:**
|
|
869
|
+
1. Users create a bug report in the "Bug Reports" workflow
|
|
870
|
+
2. Bug Fixer automatically detects new bugs and starts fixing them
|
|
871
|
+
3. He analyzes the code, generates a fix, tests it
|
|
872
|
+
4. He asks the user to verify with "approved" or "denied"
|
|
873
|
+
5. On "approved" → Bug Fixer publishes to production automatically
|
|
874
|
+
6. On "denied" or complaint → YOU (HAL) gather info, then trigger Bug Fixer retry
|
|
875
|
+
|
|
876
|
+
**YOUR ROLE IN BUG FIX DENIALS:**
|
|
877
|
+
When a discussion has a pending bug fix and the user expresses dissatisfaction:
|
|
878
|
+
1. YOU handle the conversation - ask what's wrong, what behavior they expected
|
|
879
|
+
2. Gather enough context: what's broken, expected vs actual behavior
|
|
880
|
+
3. Once you have clear info, use trigger_bug_fixer_retry tool to pass the explanation
|
|
881
|
+
4. Bug Fixer will receive your gathered info and retry the fix
|
|
882
|
+
|
|
883
|
+
**Detecting denial signals:**
|
|
884
|
+
- "denied", "not working", "still broken", "wrong", "doesn't work"
|
|
885
|
+
- Any complaint about the fix behavior
|
|
886
|
+
- User describing unexpected behavior
|
|
887
|
+
|
|
888
|
+
**Gathering info (ask ONE question at a time):**
|
|
889
|
+
- "What behavior are you seeing?"
|
|
890
|
+
- "What did you expect to happen instead?"
|
|
891
|
+
- "Is the issue consistent or intermittent?"
|
|
892
|
+
|
|
893
|
+
**When to trigger retry:**
|
|
894
|
+
Once you have: (1) what's wrong, (2) expected behavior → trigger the retry
|
|
895
|
+
|
|
896
|
+
**When someone mentions bugs (NEW bugs):**
|
|
897
|
+
- Tell them to create a bug report in "Bug Reports" workflow
|
|
898
|
+
- Explain Bug Fixer will pick it up automatically
|
|
899
|
+
- Offer to help create the bug report for them
|
|
900
|
+
</bug_fixer_autonomous>
|
|
901
|
+
|
|
902
|
+
<your_tools>
|
|
903
|
+
**YOU HAVE FULL ACCESS TO ALL 39+ HAILER MCP TOOLS:**
|
|
904
|
+
|
|
905
|
+
**WORKFLOW MANAGEMENT:**
|
|
906
|
+
- list_workflows, list_workflows_minimal - Browse all workflows
|
|
907
|
+
- list_workflow_phases - Get phases for a workflow
|
|
908
|
+
- get_workflow_schema - Get field definitions (use compact: true)
|
|
909
|
+
- install_workflow - Create new workflows from templates
|
|
910
|
+
- update_workflow_field - Modify field properties
|
|
911
|
+
- update_workflow_phase - Modify phase properties
|
|
912
|
+
|
|
913
|
+
**ACTIVITY OPERATIONS:**
|
|
914
|
+
- list_activities - Query activities with filters
|
|
915
|
+
- show_activity_by_id - Get full activity details
|
|
916
|
+
- count_activities - Get activity counts
|
|
917
|
+
- create_activity - Create single or BULK activities
|
|
918
|
+
- update_activity - Update single or BULK activities
|
|
919
|
+
|
|
920
|
+
**INSIGHT MANAGEMENT (SQL Analytics):**
|
|
921
|
+
- list_insights - Browse existing insights
|
|
922
|
+
- preview_insight - Test SQL queries before saving
|
|
923
|
+
- create_insight - Save new SQL insights
|
|
924
|
+
- get_insight_data - Execute and get results
|
|
925
|
+
- update_insight - Modify existing insights
|
|
926
|
+
|
|
927
|
+
**APP MANAGEMENT:**
|
|
928
|
+
- list_apps (view only)
|
|
929
|
+
|
|
930
|
+
**TEMPLATE & MARKETPLACE:**
|
|
931
|
+
- list_templates, get_template, create_template, install_template
|
|
932
|
+
- publish_template - Publish workspace as template
|
|
933
|
+
- get_product, get_product_manifest
|
|
934
|
+
- install_marketplace_app, publish_app
|
|
935
|
+
|
|
936
|
+
**DISCUSSION TOOLS:**
|
|
937
|
+
- join_discussion, leave_discussion
|
|
938
|
+
- add_discussion_message - Post messages
|
|
939
|
+
- invite_discussion_members - Add users to chats
|
|
940
|
+
- fetch_discussion_messages, fetch_previous_discussion_messages
|
|
941
|
+
- get_activity_from_discussion, list_my_discussions
|
|
942
|
+
|
|
943
|
+
**USER & FILES:**
|
|
944
|
+
- search_workspace_users - Find users by name
|
|
945
|
+
- upload_files, download_file - Handle file attachments
|
|
946
|
+
|
|
947
|
+
**BILLING:**
|
|
948
|
+
- get_workspace_balance - Check token balance
|
|
949
|
+
|
|
950
|
+
**ADVANCED:**
|
|
951
|
+
- test_function_field - Test computed field functions
|
|
952
|
+
|
|
953
|
+
**You are the FULL Hailer expert. Use these tools directly - no need to delegate!**
|
|
954
|
+
|
|
955
|
+
**CRITICAL for join_discussion when inviting users:**
|
|
956
|
+
ALWAYS pass these parameters from the incoming message:
|
|
957
|
+
- inviteUserId = user_id attribute
|
|
958
|
+
- sourceActivityId = activity_id attribute (creates "came from" link!)
|
|
959
|
+
- welcomeReason = why they're being invited
|
|
960
|
+
|
|
961
|
+
**join_discussion ID types:**
|
|
962
|
+
- HailerTags like [hailerTag|Name](ID) usually contain ACTIVITY IDs, not discussion IDs
|
|
963
|
+
- When user references an activity/player/customer by tag, use: activityId parameter
|
|
964
|
+
- Only use discussionId for direct discussion links (rare)
|
|
965
|
+
- The tool auto-detects: if discussionId fails, it tries as activityId
|
|
966
|
+
|
|
967
|
+
**SILENT SUCCESS for join_discussion:**
|
|
968
|
+
After successfully joining a discussion, do NOT post a confirmation message back to the source chat.
|
|
969
|
+
The action is self-evident (bot appears in target discussion). Only report ERRORS back to source chat.
|
|
970
|
+
|
|
971
|
+
**CRITICAL - Extract IDs from context:**
|
|
972
|
+
The <incoming> tag contains IDs. ALWAYS use them:
|
|
973
|
+
- activityId attribute → pass to show_activity_by_id, update_activity
|
|
974
|
+
- discussionId attribute → pass to get_activity_from_discussion, add_discussion_message
|
|
975
|
+
|
|
976
|
+
**NEVER call tools with empty parameters {}** - always extract from context first.
|
|
977
|
+
|
|
978
|
+
**update_activity formats:**
|
|
979
|
+
- Single mode: use \`activityId\` parameter
|
|
980
|
+
- Bulk mode (activities array): use \`_id\` inside each object, NOT \`activityId\`
|
|
981
|
+
|
|
982
|
+
**Field values must be plain:**
|
|
983
|
+
- numericunit: just the number → \`78\` (NOT \`{"type":"numericunit","value":78}\`)
|
|
984
|
+
- text: just the string → \`"hello"\`
|
|
985
|
+
- activitylink: just the ID → \`"abc123..."\`
|
|
986
|
+
</your_tools>
|
|
987
|
+
|
|
988
|
+
<file_handling>
|
|
989
|
+
**When users drop files in chat:**
|
|
990
|
+
|
|
991
|
+
The incoming message will contain file attachment info like:
|
|
992
|
+
\`[File attached: 1 file(s) - IDs: abc123...]\`
|
|
993
|
+
|
|
994
|
+
**To read a file:** Use \`download_file\` with the fileId to read its contents.
|
|
995
|
+
|
|
996
|
+
**To attach a file to an EXISTING activity:**
|
|
997
|
+
The Hailer API doesn't support adding files via update_activity. Instead:
|
|
998
|
+
1. Get the activity's discussion ID using \`show_activity_by_id\`
|
|
999
|
+
2. Join the discussion using \`join_discussion(activityId: "...")\`
|
|
1000
|
+
3. Post the file using \`add_discussion_message\` with the fileId:
|
|
1001
|
+
\`add_discussion_message(discussionId: "...", content: "Attaching file", fileIds: ["abc123"])\`
|
|
1002
|
+
|
|
1003
|
+
The file will appear in the activity's discussion thread.
|
|
1004
|
+
|
|
1005
|
+
**To attach a file to a NEW activity:**
|
|
1006
|
+
Use \`create_activity\` with the \`fileIds\` parameter - this works directly.
|
|
1007
|
+
|
|
1008
|
+
**Key point:** When a user drops a file, it's already uploaded to Hailer. Use the fileId directly - no need to re-upload.
|
|
1009
|
+
</file_handling>
|
|
1010
|
+
|
|
1011
|
+
<tagging>
|
|
1012
|
+
**Activity Tags:** #ACTIVITY_ID (24-char hex)
|
|
1013
|
+
- Correct: "Check out #691ffe874217e9e8434e57fc"
|
|
1014
|
+
- Wrong: "Check out #691ffe874217e9e8434e57fc (Name)" - name auto-displays
|
|
1015
|
+
|
|
1016
|
+
**User Mentions:** @"Full Name" or @userId
|
|
1017
|
+
</tagging>
|
|
1018
|
+
|
|
1019
|
+
<agentic_loop>
|
|
1020
|
+
**CRITICAL: The 'respond' action ENDS YOUR TURN!**
|
|
1021
|
+
|
|
1022
|
+
When you output {"action": "respond", ...}, your turn ENDS IMMEDIATELY.
|
|
1023
|
+
You CANNOT call any more tools after responding. There is NO "next turn".
|
|
1024
|
+
|
|
1025
|
+
**THIS WILL FAIL (you lose your turn before doing work):**
|
|
1026
|
+
{"action": "respond", "response_text": "Let me check that for you..."}
|
|
1027
|
+
→ Message posted, turn ends, NO tools called!
|
|
1028
|
+
|
|
1029
|
+
**THIS IS CORRECT (gather data FIRST, then respond):**
|
|
1030
|
+
1. {"action": "list_workflow_phases", "params": {...}} → get phases
|
|
1031
|
+
2. {"action": "get_workflow_schema", "params": {...}} → get fields
|
|
1032
|
+
3. {"action": "list_activities", "params": {...}} → get data
|
|
1033
|
+
4. {"action": "respond", "response_text": "Here are the 3 injured players: ..."} → FINAL answer
|
|
1034
|
+
|
|
1035
|
+
**FORBIDDEN response_text patterns:**
|
|
1036
|
+
- "Let me check..." / "I'll look into..." / "One moment..."
|
|
1037
|
+
- "Working on it..." / "I'm going to..."
|
|
1038
|
+
- ANY promise of future work
|
|
1039
|
+
|
|
1040
|
+
**ONLY respond when you have the ACTUAL ANSWER.**
|
|
1041
|
+
</agentic_loop>
|
|
1042
|
+
|
|
1043
|
+
<rules>
|
|
1044
|
+
- Be concise - snappy responses, not essays
|
|
1045
|
+
- Use your memory - reference past conversations
|
|
1046
|
+
- For HIGH priority: respond immediately with work, not promises
|
|
1047
|
+
- For NORMAL priority: your DEFAULT is "ignore" action. Only respond if clear workspace question.
|
|
1048
|
+
- **Gibberish test:** No recognizable words = "ignore" action
|
|
1049
|
+
- **Relevance test:** Is this about workflows/activities/insights? If not = "ignore" action
|
|
1050
|
+
- When inviting specialists, explain what's happening
|
|
1051
|
+
- **NEVER use "respond" until you have gathered ALL needed data via tool actions**
|
|
1052
|
+
</rules>`;
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Get the DYNAMIC portion of the system prompt (not cacheable)
|
|
1056
|
+
* This contains time-sensitive and per-call context
|
|
1057
|
+
*/
|
|
1058
|
+
getDynamicContext() {
|
|
1059
|
+
// Round time to 5-minute intervals to allow cache reuse
|
|
1060
|
+
// Without this, every request has a different timestamp, killing the cache
|
|
1061
|
+
const now = new Date();
|
|
1062
|
+
const fiveMinutes = 5 * 60 * 1000;
|
|
1063
|
+
const roundedTime = new Date(Math.floor(now.getTime() / fiveMinutes) * fiveMinutes);
|
|
1064
|
+
// Build specialist info for prompt - ONLY show available specialists
|
|
1065
|
+
const availableSpecialists = Array.from(this.specialists.entries())
|
|
1066
|
+
.filter(([_, spec]) => !!spec.botUserId);
|
|
1067
|
+
const specialistInfo = availableSpecialists.length > 0
|
|
1068
|
+
? availableSpecialists
|
|
1069
|
+
.map(([key, spec]) => {
|
|
1070
|
+
const mentionName = spec.displayName || spec.name;
|
|
1071
|
+
return `- **${spec.name}** (available)
|
|
1072
|
+
Tag with: [hailerTag|${mentionName}](${spec.botUserId})
|
|
1073
|
+
Key for invite tag: ${key}
|
|
1074
|
+
Expertise: ${spec.expertise.join(", ")}
|
|
1075
|
+
Triggers: ${spec.triggerKeywords.slice(0, 5).join(", ")}`;
|
|
1076
|
+
})
|
|
1077
|
+
.join("\n\n")
|
|
1078
|
+
: `**NO SPECIALISTS ARE CURRENTLY ENABLED.**
|
|
1079
|
+
DO NOT invent, fabricate, or mention any specialist names.
|
|
1080
|
+
DO NOT use <invite> tags. DO NOT claim to "hand off" to anyone.
|
|
1081
|
+
Handle all requests yourself or tell the user: "No specialists are enabled. You can enable them in AI Hub."`;
|
|
1082
|
+
return `<current_time>${roundedTime.toISOString()}</current_time>
|
|
1083
|
+
|
|
1084
|
+
<specialists>
|
|
1085
|
+
${specialistInfo}
|
|
1086
|
+
</specialists>
|
|
1087
|
+
|
|
1088
|
+
${this.currentDiscussionId ? this.getPendingFixContext(this.currentDiscussionId) : ''}
|
|
1089
|
+
${this.currentDiscussionId ? this.getPendingClassificationContext(this.currentDiscussionId) : ''}`;
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Override system prompt to combine static and dynamic parts
|
|
1093
|
+
* Used for backwards compatibility
|
|
1094
|
+
*/
|
|
1095
|
+
getSystemPrompt() {
|
|
1096
|
+
return this.getStaticSystemPrompt() + "\n\n" + this.getDynamicContext();
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Override to return cached system prompt with proper structure
|
|
1100
|
+
* Static content is cached (50% cost reduction), dynamic content appended fresh
|
|
1101
|
+
*/
|
|
1102
|
+
getCachedSystemPrompt() {
|
|
1103
|
+
return [
|
|
1104
|
+
{
|
|
1105
|
+
type: "text",
|
|
1106
|
+
text: this.getStaticSystemPrompt(),
|
|
1107
|
+
cache_control: { type: "ephemeral" },
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
type: "text",
|
|
1111
|
+
text: this.getDynamicContext(),
|
|
1112
|
+
},
|
|
1113
|
+
];
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Override response handling to detect specialist invitations
|
|
1117
|
+
*/
|
|
1118
|
+
async handleLlmResponse(response, originalMessage) {
|
|
1119
|
+
// Get conversation for this discussion
|
|
1120
|
+
const conversation = this.conversationManager.getConversation(originalMessage.discussionId);
|
|
1121
|
+
// Add assistant response to conversation
|
|
1122
|
+
// Cast response content to MessageParam content type (ContentBlock[] → ContentBlockParam[])
|
|
1123
|
+
conversation.push({
|
|
1124
|
+
role: "assistant",
|
|
1125
|
+
content: response.content,
|
|
1126
|
+
});
|
|
1127
|
+
// Check for specialist invitation in text content
|
|
1128
|
+
const textBlocks = response.content.filter((block) => block.type === "text");
|
|
1129
|
+
const textContent = textBlocks.map((b) => b.text).join("\n");
|
|
1130
|
+
// Look for <invite specialist="...">...</invite> pattern
|
|
1131
|
+
const inviteMatch = textContent.match(/<invite specialist="(\w+)">([\s\S]*?)<\/invite>/);
|
|
1132
|
+
if (inviteMatch) {
|
|
1133
|
+
const [_fullMatch, specialistKey, handoffContext] = inviteMatch;
|
|
1134
|
+
const specialist = this.specialists.get(specialistKey);
|
|
1135
|
+
if (specialist && specialist.botUserId) {
|
|
1136
|
+
this.orchestratorLogger.info("LLM requested specialist invitation", {
|
|
1137
|
+
specialist: specialistKey,
|
|
1138
|
+
discussionId: originalMessage.discussionId,
|
|
1139
|
+
});
|
|
1140
|
+
// Extract any text before the invite tag to post as acknowledgment
|
|
1141
|
+
const preInviteText = textContent
|
|
1142
|
+
.substring(0, textContent.indexOf("<invite"))
|
|
1143
|
+
.trim();
|
|
1144
|
+
// Check for respond wrapper
|
|
1145
|
+
const respondMatch = preInviteText.match(/<respond discussion="([^"]+)">([\s\S]*)/);
|
|
1146
|
+
if (respondMatch) {
|
|
1147
|
+
const [, discussionId, content] = respondMatch;
|
|
1148
|
+
const cleanContent = content.replace(/<\/respond>.*$/s, "").trim();
|
|
1149
|
+
if (cleanContent) {
|
|
1150
|
+
await this.postResponse(discussionId, cleanContent);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
else if (preInviteText) {
|
|
1154
|
+
// No respond wrapper, but there's text - might be for high priority
|
|
1155
|
+
if (originalMessage.priority === "high") {
|
|
1156
|
+
await this.postResponse(originalMessage.discussionId, preInviteText);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
// Invite the specialist
|
|
1160
|
+
const invited = await this.inviteSpecialist(specialist, originalMessage.discussionId, handoffContext.trim());
|
|
1161
|
+
if (!invited) {
|
|
1162
|
+
// Failed to invite - let user know
|
|
1163
|
+
await this.postResponse(originalMessage.discussionId, `I tried to bring in ${specialist.name} but couldn't reach them. Let me try handling this myself...`);
|
|
1164
|
+
// Continue with normal handling
|
|
1165
|
+
}
|
|
1166
|
+
return; // Don't continue with normal response handling
|
|
1167
|
+
}
|
|
1168
|
+
else {
|
|
1169
|
+
// Specialist is disabled - feed back to LLM for natural response
|
|
1170
|
+
this.orchestratorLogger.info("Specialist disabled, asking LLM to respond naturally", {
|
|
1171
|
+
key: specialistKey,
|
|
1172
|
+
name: specialist?.name || specialistKey,
|
|
1173
|
+
});
|
|
1174
|
+
// Add system feedback to conversation so LLM knows the specialist is unavailable
|
|
1175
|
+
const conversation = this.conversationManager.getConversation(originalMessage.discussionId);
|
|
1176
|
+
conversation.push({
|
|
1177
|
+
role: 'user',
|
|
1178
|
+
content: `[SYSTEM: The specialist "${specialist?.name || specialistKey}" you tried to invite is currently disabled. Please inform the user naturally that this specialist is not available and they can enable it in the AI Hub settings if needed. Do NOT use XML tags in your response.]`,
|
|
1179
|
+
});
|
|
1180
|
+
// Get LLM to respond naturally about the unavailability (with caching enabled)
|
|
1181
|
+
const cachedConversation = this.conversationManager.prepareForCaching(conversation);
|
|
1182
|
+
const retryResponse = await this.client.messages.create({
|
|
1183
|
+
model: this.config.model || 'claude-haiku-4-5-20251001',
|
|
1184
|
+
max_tokens: 1000,
|
|
1185
|
+
system: this.getCachedSystemPrompt(),
|
|
1186
|
+
messages: cachedConversation,
|
|
1187
|
+
tools: this.getTools(),
|
|
1188
|
+
});
|
|
1189
|
+
// Track and burn tokens for specialist unavailable retry
|
|
1190
|
+
const sessionKey = this.currentLinkedActivityId || this.currentDiscussionId || "default";
|
|
1191
|
+
const retrySession = this.sessionLogger.getSession(sessionKey);
|
|
1192
|
+
if (retrySession && retryResponse.usage) {
|
|
1193
|
+
const inputTokens = retryResponse.usage.input_tokens;
|
|
1194
|
+
const outputTokens = retryResponse.usage.output_tokens;
|
|
1195
|
+
const cacheCreationTokens = retryResponse.usage.cache_creation_input_tokens || 0;
|
|
1196
|
+
const cacheReadTokens = retryResponse.usage.cache_read_input_tokens || 0;
|
|
1197
|
+
retrySession.metrics.inputTokens += inputTokens;
|
|
1198
|
+
retrySession.metrics.outputTokens += outputTokens;
|
|
1199
|
+
retrySession.metrics.cacheCreationTokens += cacheCreationTokens;
|
|
1200
|
+
retrySession.metrics.cacheReadTokens += cacheReadTokens;
|
|
1201
|
+
retrySession.metrics.apiCalls += 1;
|
|
1202
|
+
retrySession.lastActivityTime = Date.now();
|
|
1203
|
+
// Burn tokens real-time (fire-and-forget)
|
|
1204
|
+
if (this.tokenBilling && retrySession.workspaceId) {
|
|
1205
|
+
const cost = this.tokenBilling.calculateCost(inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens);
|
|
1206
|
+
this.tokenBilling.burnTokens({
|
|
1207
|
+
workspaceId: retrySession.workspaceId,
|
|
1208
|
+
inputTokens,
|
|
1209
|
+
outputTokens,
|
|
1210
|
+
cacheCreationTokens,
|
|
1211
|
+
cacheReadTokens,
|
|
1212
|
+
costUsd: cost,
|
|
1213
|
+
sessionId: retrySession.discussionId,
|
|
1214
|
+
activityId: retrySession.activityId,
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
// Process the retry response (should be a simple text response)
|
|
1219
|
+
await this.handleLlmResponse(retryResponse, originalMessage);
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
// Check for tool calls
|
|
1224
|
+
const toolUseBlocks = response.content.filter((block) => block.type === "tool_use");
|
|
1225
|
+
if (toolUseBlocks.length > 0) {
|
|
1226
|
+
// Mark that tools were used - subsequent responses should be posted
|
|
1227
|
+
this.toolsUsedInCurrentMessage = true;
|
|
1228
|
+
// Track which tools were used (for silent success detection)
|
|
1229
|
+
this.lastToolsUsed = toolUseBlocks.map(b => b.name);
|
|
1230
|
+
// Execute tools and continue conversation
|
|
1231
|
+
await this.executeToolsAndContinue(toolUseBlocks, originalMessage);
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
// Check for regular response (no invite, no tools)
|
|
1235
|
+
if (textBlocks.length > 0) {
|
|
1236
|
+
const responseText = textContent.trim();
|
|
1237
|
+
this.orchestratorLogger.info("LLM raw response", {
|
|
1238
|
+
discussion: originalMessage.discussionId,
|
|
1239
|
+
priority: originalMessage.priority,
|
|
1240
|
+
responseLength: responseText.length,
|
|
1241
|
+
fullResponse: responseText.substring(0, 500),
|
|
1242
|
+
hasIgnoreTag: responseText.includes("<ignore"),
|
|
1243
|
+
hasRespondTag: responseText.includes("<respond"),
|
|
1244
|
+
});
|
|
1245
|
+
// Check for IGNORE decision - remove from context to keep it clean
|
|
1246
|
+
if (responseText.includes("<decision>IGNORE</decision>") ||
|
|
1247
|
+
responseText.includes("<ignore")) {
|
|
1248
|
+
this.orchestratorLogger.debug("LLM decided to ignore - removing from context", {
|
|
1249
|
+
discussion: originalMessage.discussionId,
|
|
1250
|
+
});
|
|
1251
|
+
// Stop typing indicator
|
|
1252
|
+
this.typingIndicator?.stop();
|
|
1253
|
+
// Remove both the assistant's response AND the incoming message from context
|
|
1254
|
+
conversation.pop(); // Remove assistant response we just added
|
|
1255
|
+
conversation.pop(); // Remove the incoming message
|
|
1256
|
+
this.toolsUsedInCurrentMessage = false; // Reset for next message
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
// Check for explicit response directive
|
|
1260
|
+
const responseMatch = responseText.match(/<respond discussion="([^"]+)">([\s\S]*?)<\/respond>/);
|
|
1261
|
+
if (responseMatch) {
|
|
1262
|
+
const targetDiscussion = responseMatch[1];
|
|
1263
|
+
const content = responseMatch[2].trim();
|
|
1264
|
+
// SILENT SUCCESS: Skip confirmation if we just ran a silent tool successfully (not on error)
|
|
1265
|
+
const usedSilentTool = this.lastToolsUsed.some(t => OrchestratorDaemon.SILENT_SUCCESS_TOOLS.has(t));
|
|
1266
|
+
if (usedSilentTool && !this.lastToolsFailed) {
|
|
1267
|
+
this.orchestratorLogger.debug("Suppressing confirmation for silent success tool", {
|
|
1268
|
+
discussion: originalMessage.discussionId,
|
|
1269
|
+
tools: this.lastToolsUsed,
|
|
1270
|
+
});
|
|
1271
|
+
// Stop typing indicator
|
|
1272
|
+
this.typingIndicator?.stop();
|
|
1273
|
+
// NOTE: Don't pop from context - keep conversation valid for future messages
|
|
1274
|
+
this.toolsUsedInCurrentMessage = false;
|
|
1275
|
+
this.lastToolsUsed = [];
|
|
1276
|
+
this.lastToolsFailed = false;
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
await this.postResponse(targetDiscussion, content);
|
|
1280
|
+
this.toolsUsedInCurrentMessage = false; // Reset for next message
|
|
1281
|
+
this.lastToolsUsed = [];
|
|
1282
|
+
this.lastToolsFailed = false;
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
// For high priority messages, always send substantive responses
|
|
1286
|
+
// (unless we just ran a silent success tool)
|
|
1287
|
+
if (originalMessage.priority === "high" &&
|
|
1288
|
+
responseText &&
|
|
1289
|
+
!responseText.includes("<thinking>") &&
|
|
1290
|
+
!responseText.startsWith("I'll") &&
|
|
1291
|
+
responseText.length > 10) {
|
|
1292
|
+
// SILENT SUCCESS: Skip confirmation if we just ran a silent tool successfully (not on error)
|
|
1293
|
+
const usedSilentTool = this.lastToolsUsed.some(t => OrchestratorDaemon.SILENT_SUCCESS_TOOLS.has(t));
|
|
1294
|
+
if (usedSilentTool && !this.lastToolsFailed) {
|
|
1295
|
+
this.orchestratorLogger.debug("Suppressing high-priority confirmation for silent success tool", {
|
|
1296
|
+
discussion: originalMessage.discussionId,
|
|
1297
|
+
tools: this.lastToolsUsed,
|
|
1298
|
+
});
|
|
1299
|
+
// Stop typing indicator
|
|
1300
|
+
this.typingIndicator?.stop();
|
|
1301
|
+
// NOTE: Don't pop from context - keep conversation valid for future messages
|
|
1302
|
+
this.toolsUsedInCurrentMessage = false;
|
|
1303
|
+
this.lastToolsUsed = [];
|
|
1304
|
+
this.lastToolsFailed = false;
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
await this.postResponse(originalMessage.discussionId, responseText);
|
|
1308
|
+
this.toolsUsedInCurrentMessage = false; // Reset for next message
|
|
1309
|
+
this.lastToolsUsed = [];
|
|
1310
|
+
this.lastToolsFailed = false;
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
// For normal priority:
|
|
1314
|
+
// - If tools were used, post substantive responses (LLM was doing real work)
|
|
1315
|
+
// - Otherwise, require explicit <respond> tag
|
|
1316
|
+
if (originalMessage.priority === "normal") {
|
|
1317
|
+
// SILENT SUCCESS: Skip confirmation if we just ran a silent tool successfully (not on error)
|
|
1318
|
+
const usedSilentTool = this.lastToolsUsed.some(t => OrchestratorDaemon.SILENT_SUCCESS_TOOLS.has(t));
|
|
1319
|
+
const shouldSuppressSilent = usedSilentTool && !this.lastToolsFailed;
|
|
1320
|
+
if (this.toolsUsedInCurrentMessage && responseText.length > 50 && !responseText.includes("<ignore") && !shouldSuppressSilent) {
|
|
1321
|
+
// Tools were used and we have a substantive response - post it
|
|
1322
|
+
this.orchestratorLogger.info("Posting tool-assisted response", {
|
|
1323
|
+
discussion: originalMessage.discussionId,
|
|
1324
|
+
responseLength: responseText.length,
|
|
1325
|
+
});
|
|
1326
|
+
await this.postResponse(originalMessage.discussionId, responseText);
|
|
1327
|
+
this.toolsUsedInCurrentMessage = false; // Reset for next message
|
|
1328
|
+
this.lastToolsUsed = [];
|
|
1329
|
+
this.lastToolsFailed = false;
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1332
|
+
if (shouldSuppressSilent) {
|
|
1333
|
+
this.orchestratorLogger.debug("Suppressing normal-priority confirmation for silent success tool", {
|
|
1334
|
+
discussion: originalMessage.discussionId,
|
|
1335
|
+
tools: this.lastToolsUsed,
|
|
1336
|
+
});
|
|
1337
|
+
// Stop typing indicator
|
|
1338
|
+
this.typingIndicator?.stop();
|
|
1339
|
+
// NOTE: Don't pop from context when tools were used - keep conversation valid
|
|
1340
|
+
this.toolsUsedInCurrentMessage = false;
|
|
1341
|
+
this.lastToolsUsed = [];
|
|
1342
|
+
this.lastToolsFailed = false;
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1345
|
+
this.orchestratorLogger.debug("Normal priority without <respond> tag - removing from context", {
|
|
1346
|
+
discussion: originalMessage.discussionId,
|
|
1347
|
+
responsePreview: responseText.substring(0, 100),
|
|
1348
|
+
toolsUsed: this.toolsUsedInCurrentMessage,
|
|
1349
|
+
});
|
|
1350
|
+
// Stop typing indicator
|
|
1351
|
+
this.typingIndicator?.stop();
|
|
1352
|
+
// Remove from context - we didn't respond (only safe when no tools were used)
|
|
1353
|
+
if (!this.toolsUsedInCurrentMessage) {
|
|
1354
|
+
conversation.pop(); // Remove assistant response
|
|
1355
|
+
conversation.pop(); // Remove incoming message
|
|
1356
|
+
}
|
|
1357
|
+
this.toolsUsedInCurrentMessage = false; // Reset for next message
|
|
1358
|
+
this.lastToolsUsed = [];
|
|
1359
|
+
this.lastToolsFailed = false;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Get orchestrator status including specialist info
|
|
1365
|
+
*/
|
|
1366
|
+
getOrchestratorStatus() {
|
|
1367
|
+
const specialists = Array.from(this.specialists.entries()).map(([key, spec]) => ({
|
|
1368
|
+
key,
|
|
1369
|
+
name: spec.name,
|
|
1370
|
+
available: !!spec.botUserId,
|
|
1371
|
+
userId: spec.botUserId,
|
|
1372
|
+
}));
|
|
1373
|
+
const activeInDiscussions = {};
|
|
1374
|
+
for (const [discussionId, userIds] of this.activeSpecialistsInDiscussion) {
|
|
1375
|
+
activeInDiscussions[discussionId] = Array.from(userIds);
|
|
1376
|
+
}
|
|
1377
|
+
return {
|
|
1378
|
+
conversationState: this.getConversationState(),
|
|
1379
|
+
specialists,
|
|
1380
|
+
activeInDiscussions,
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
exports.OrchestratorDaemon = OrchestratorDaemon;
|
|
1385
|
+
//# sourceMappingURL=daemon.js.map
|