@hailer/mcp 1.0.29 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/.claude/.session-checked +1 -0
  2. package/.claude/agents/agent-ada-skill-builder.md +10 -2
  3. package/.claude/agents/agent-alejandro-function-fields.md +104 -37
  4. package/.claude/agents/agent-bjorn-config-audit.md +41 -21
  5. package/.claude/agents/agent-builder-agent-creator.md +13 -3
  6. package/.claude/agents/agent-code-simplifier.md +53 -0
  7. package/.claude/agents/agent-dmitri-activity-crud.md +126 -11
  8. package/.claude/agents/agent-giuseppe-app-builder.md +212 -22
  9. package/.claude/agents/agent-gunther-mcp-tools.md +7 -36
  10. package/.claude/agents/agent-helga-workflow-config.md +75 -10
  11. package/.claude/agents/agent-igor-activity-mover-automation.md +125 -0
  12. package/.claude/agents/agent-ingrid-doc-templates.md +164 -36
  13. package/.claude/agents/agent-ivan-monolith.md +154 -0
  14. package/.claude/agents/agent-kenji-data-reader.md +15 -8
  15. package/.claude/agents/agent-lars-code-inspector.md +56 -8
  16. package/.claude/agents/agent-marco-mockup-builder.md +110 -0
  17. package/.claude/agents/agent-marcus-api-documenter.md +323 -0
  18. package/.claude/agents/agent-marketplace-publisher.md +232 -72
  19. package/.claude/agents/agent-marketplace-reviewer.md +255 -79
  20. package/.claude/agents/agent-permissions-handler.md +208 -0
  21. package/.claude/agents/agent-simple-writer.md +48 -0
  22. package/.claude/agents/agent-svetlana-code-review.md +127 -14
  23. package/.claude/agents/agent-tanya-test-runner.md +333 -0
  24. package/.claude/agents/agent-ui-designer.md +100 -0
  25. package/.claude/agents/agent-viktor-sql-insights.md +19 -6
  26. package/.claude/agents/agent-web-search.md +55 -0
  27. package/.claude/agents/agent-yevgeni-discussions.md +7 -1
  28. package/.claude/agents/agent-zara-zapier.md +159 -0
  29. package/.claude/commands/app-squad.md +135 -0
  30. package/.claude/commands/audit-squad.md +158 -0
  31. package/.claude/commands/autoplan.md +563 -0
  32. package/.claude/commands/cleanup-squad.md +98 -0
  33. package/.claude/commands/config-squad.md +106 -0
  34. package/.claude/commands/crud-squad.md +87 -0
  35. package/.claude/commands/data-squad.md +97 -0
  36. package/.claude/commands/debug-squad.md +303 -0
  37. package/.claude/commands/doc-squad.md +65 -0
  38. package/.claude/commands/handoff.md +137 -0
  39. package/.claude/commands/health.md +49 -0
  40. package/.claude/commands/help.md +2 -1
  41. package/.claude/commands/help:agents.md +96 -16
  42. package/.claude/commands/help:commands.md +55 -11
  43. package/.claude/commands/help:faq.md +16 -1
  44. package/.claude/commands/help:skills.md +93 -0
  45. package/.claude/commands/hotfix-squad.md +112 -0
  46. package/.claude/commands/integration-squad.md +82 -0
  47. package/.claude/commands/janitor-squad.md +167 -0
  48. package/.claude/commands/learn-auto.md +120 -0
  49. package/.claude/commands/learn.md +120 -0
  50. package/.claude/commands/mcp-list.md +27 -0
  51. package/.claude/commands/onboard-squad.md +140 -0
  52. package/.claude/commands/plan-workspace.md +732 -0
  53. package/.claude/commands/prd.md +131 -0
  54. package/.claude/commands/project-status.md +82 -0
  55. package/.claude/commands/publish.md +138 -0
  56. package/.claude/commands/recap.md +69 -0
  57. package/.claude/commands/restore.md +64 -0
  58. package/.claude/commands/review-squad.md +152 -0
  59. package/.claude/commands/save.md +24 -0
  60. package/.claude/commands/stats.md +19 -0
  61. package/.claude/commands/swarm.md +210 -0
  62. package/.claude/commands/tool-builder.md +3 -1
  63. package/.claude/commands/ws-pull.md +1 -1
  64. package/.claude/commands/yolo-off.md +17 -0
  65. package/.claude/commands/yolo.md +82 -0
  66. package/.claude/hooks/_shared-memory.cjs +305 -0
  67. package/.claude/hooks/_utils.cjs +134 -0
  68. package/.claude/hooks/agent-failure-detector.cjs +164 -79
  69. package/.claude/hooks/agent-usage-logger.cjs +204 -0
  70. package/.claude/hooks/app-edit-guard.cjs +20 -4
  71. package/.claude/hooks/auto-learn.cjs +316 -0
  72. package/.claude/hooks/bash-guard.cjs +282 -0
  73. package/.claude/hooks/builder-mode-manager.cjs +183 -54
  74. package/.claude/hooks/bulk-activity-guard.cjs +283 -0
  75. package/.claude/hooks/context-watchdog.cjs +292 -0
  76. package/.claude/hooks/delegation-reminder.cjs +478 -0
  77. package/.claude/hooks/design-system-lint.cjs +283 -0
  78. package/.claude/hooks/post-scaffold-hook.cjs +16 -3
  79. package/.claude/hooks/prompt-guard.cjs +366 -0
  80. package/.claude/hooks/publish-template-guard.cjs +16 -0
  81. package/.claude/hooks/session-start.cjs +35 -0
  82. package/.claude/hooks/shared-memory-writer.cjs +147 -0
  83. package/.claude/hooks/skill-injector.cjs +140 -0
  84. package/.claude/hooks/skill-usage-logger.cjs +258 -0
  85. package/.claude/hooks/src-edit-guard.cjs +16 -1
  86. package/.claude/hooks/sync-marketplace-agents.cjs +53 -8
  87. package/.claude/scripts/yolo-toggle.cjs +142 -0
  88. package/.claude/settings.json +141 -14
  89. package/.claude/skills/SDK-activity-patterns/SKILL.md +428 -0
  90. package/.claude/skills/SDK-document-templates/SKILL.md +1033 -0
  91. package/.claude/skills/SDK-function-fields/SKILL.md +542 -0
  92. package/.claude/skills/SDK-generate-skill/SKILL.md +92 -0
  93. package/.claude/skills/SDK-init-skill/SKILL.md +127 -0
  94. package/.claude/skills/SDK-insight-queries/SKILL.md +787 -0
  95. package/.claude/skills/SDK-ws-config-skill/SKILL.md +1139 -0
  96. package/.claude/skills/agent-structure/SKILL.md +98 -0
  97. package/.claude/skills/api-documentation-patterns/SKILL.md +474 -0
  98. package/.claude/skills/chrome-mcp-reference/SKILL.md +370 -0
  99. package/.claude/skills/delegation-routing/SKILL.md +202 -0
  100. package/.claude/skills/frontend-design/SKILL.md +254 -0
  101. package/.claude/skills/hailer-activity-mover/SKILL.md +213 -0
  102. package/.claude/skills/hailer-api-client/SKILL.md +518 -0
  103. package/.claude/skills/hailer-app-builder/SKILL.md +939 -11
  104. package/.claude/skills/hailer-apps-pictures/SKILL.md +269 -0
  105. package/.claude/skills/hailer-design-system/SKILL.md +235 -0
  106. package/.claude/skills/hailer-monolith-automations/SKILL.md +686 -0
  107. package/.claude/skills/hailer-permissions-system/SKILL.md +121 -0
  108. package/.claude/skills/hailer-project-protocol/SKILL.md +488 -0
  109. package/.claude/skills/hailer-rest-api/SKILL.md +61 -0
  110. package/.claude/skills/hailer-rest-api/hailer-activities.md +184 -0
  111. package/.claude/skills/hailer-rest-api/hailer-admin.md +473 -0
  112. package/.claude/skills/hailer-rest-api/hailer-calendar.md +256 -0
  113. package/.claude/skills/hailer-rest-api/hailer-feed.md +249 -0
  114. package/.claude/skills/hailer-rest-api/hailer-insights.md +195 -0
  115. package/.claude/skills/hailer-rest-api/hailer-messaging.md +276 -0
  116. package/.claude/skills/hailer-rest-api/hailer-workflows.md +283 -0
  117. package/.claude/skills/insight-join-patterns/SKILL.md +3 -0
  118. package/.claude/skills/integration-patterns/SKILL.md +421 -0
  119. package/.claude/skills/json-only-output/SKILL.md +52 -12
  120. package/.claude/skills/lsp-setup/SKILL.md +160 -0
  121. package/.claude/skills/mcp-direct-tools/SKILL.md +153 -0
  122. package/.claude/skills/optional-parameters/SKILL.md +32 -23
  123. package/.claude/skills/publish-hailer-app/SKILL.md +76 -12
  124. package/.claude/skills/testing-patterns/SKILL.md +630 -0
  125. package/.claude/skills/tool-builder/SKILL.md +250 -0
  126. package/.claude/skills/tool-parameter-usage/SKILL.md +59 -45
  127. package/.claude/skills/tool-response-verification/SKILL.md +82 -48
  128. package/.claude/skills/zapier-hailer-patterns/SKILL.md +581 -0
  129. package/.env.example +26 -7
  130. package/CLAUDE.md +290 -224
  131. package/dist/CLAUDE.md +370 -0
  132. package/dist/app.d.ts +1 -1
  133. package/dist/app.js +101 -101
  134. package/dist/bot/bot-config.d.ts +26 -0
  135. package/dist/bot/bot-config.js +135 -0
  136. package/dist/bot/bot-manager.d.ts +40 -0
  137. package/dist/bot/bot-manager.js +137 -0
  138. package/dist/bot/bot.d.ts +127 -0
  139. package/dist/bot/bot.js +1328 -0
  140. package/dist/bot/operation-logger.d.ts +28 -0
  141. package/dist/bot/operation-logger.js +132 -0
  142. package/dist/bot/services/conversation-manager.d.ts +60 -0
  143. package/dist/bot/services/conversation-manager.js +246 -0
  144. package/dist/bot/services/index.d.ts +9 -0
  145. package/dist/bot/services/index.js +18 -0
  146. package/dist/bot/services/message-classifier.d.ts +42 -0
  147. package/dist/bot/services/message-classifier.js +228 -0
  148. package/dist/bot/services/message-formatter.d.ts +88 -0
  149. package/dist/bot/services/message-formatter.js +411 -0
  150. package/dist/bot/services/session-logger.d.ts +162 -0
  151. package/dist/bot/services/session-logger.js +724 -0
  152. package/dist/bot/services/token-billing.d.ts +78 -0
  153. package/dist/bot/services/token-billing.js +233 -0
  154. package/dist/bot/services/types.d.ts +169 -0
  155. package/dist/bot/services/types.js +12 -0
  156. package/dist/bot/services/typing-indicator.d.ts +23 -0
  157. package/dist/bot/services/typing-indicator.js +60 -0
  158. package/dist/bot/services/workspace-schema-cache.d.ts +122 -0
  159. package/dist/bot/services/workspace-schema-cache.js +506 -0
  160. package/dist/bot/tool-executor.d.ts +28 -0
  161. package/dist/bot/tool-executor.js +48 -0
  162. package/dist/bot/workspace-overview.d.ts +12 -0
  163. package/dist/bot/workspace-overview.js +94 -0
  164. package/dist/cli.d.ts +1 -8
  165. package/dist/cli.js +1 -253
  166. package/dist/config.d.ts +96 -3
  167. package/dist/config.js +148 -37
  168. package/dist/core.d.ts +5 -0
  169. package/dist/core.js +61 -8
  170. package/dist/lib/discussion-lock.d.ts +42 -0
  171. package/dist/lib/discussion-lock.js +110 -0
  172. package/dist/lib/logger.d.ts +0 -1
  173. package/dist/lib/logger.js +39 -23
  174. package/dist/lib/request-logger.d.ts +77 -0
  175. package/dist/lib/request-logger.js +147 -0
  176. package/dist/mcp/UserContextCache.js +16 -13
  177. package/dist/mcp/hailer-clients.js +18 -17
  178. package/dist/mcp/signal-handler.js +43 -13
  179. package/dist/mcp/tool-registry.d.ts +4 -15
  180. package/dist/mcp/tool-registry.js +94 -32
  181. package/dist/mcp/tools/activity.js +28 -69
  182. package/dist/mcp/tools/app-core.js +9 -4
  183. package/dist/mcp/tools/app-marketplace.js +22 -12
  184. package/dist/mcp/tools/app-member.js +5 -2
  185. package/dist/mcp/tools/app-scaffold.js +32 -18
  186. package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
  187. package/dist/mcp/tools/bot-config/constants.js +94 -0
  188. package/dist/mcp/tools/bot-config/core.d.ts +253 -0
  189. package/dist/mcp/tools/bot-config/core.js +2456 -0
  190. package/dist/mcp/tools/bot-config/index.d.ts +10 -0
  191. package/dist/mcp/tools/bot-config/index.js +59 -0
  192. package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
  193. package/dist/mcp/tools/bot-config/tools.js +15 -0
  194. package/dist/mcp/tools/bot-config/types.d.ts +50 -0
  195. package/dist/mcp/tools/bot-config/types.js +6 -0
  196. package/dist/mcp/tools/discussion.js +107 -77
  197. package/dist/mcp/tools/document.d.ts +11 -0
  198. package/dist/mcp/tools/document.js +741 -0
  199. package/dist/mcp/tools/file.js +5 -2
  200. package/dist/mcp/tools/insight.js +36 -12
  201. package/dist/mcp/tools/investigate.d.ts +9 -0
  202. package/dist/mcp/tools/investigate.js +254 -0
  203. package/dist/mcp/tools/user.d.ts +2 -4
  204. package/dist/mcp/tools/user.js +9 -50
  205. package/dist/mcp/tools/workflow.d.ts +1 -0
  206. package/dist/mcp/tools/workflow.js +164 -52
  207. package/dist/mcp/utils/hailer-api-client.js +26 -17
  208. package/dist/mcp/webhook-handler.d.ts +64 -3
  209. package/dist/mcp/webhook-handler.js +227 -9
  210. package/dist/mcp-server.d.ts +4 -0
  211. package/dist/mcp-server.js +237 -25
  212. package/dist/plugins/bug-fixer/index.d.ts +2 -0
  213. package/dist/plugins/bug-fixer/index.js +18 -0
  214. package/dist/plugins/bug-fixer/tools.d.ts +45 -0
  215. package/dist/plugins/bug-fixer/tools.js +1096 -0
  216. package/package.json +10 -10
  217. package/scripts/test-hal-tools.ts +154 -0
  218. package/.claude/agents/agent-nora-name-functions.md +0 -123
  219. package/.claude/assistant-knowledge.md +0 -23
  220. package/.claude/commands/install-plugin.md +0 -261
  221. package/.claude/commands/list-plugins.md +0 -42
  222. package/.claude/commands/marketplace-setup.md +0 -33
  223. package/.claude/commands/publish-plugin.md +0 -55
  224. package/.claude/commands/uninstall-plugin.md +0 -87
  225. package/.claude/hooks/interactive-mode.cjs +0 -87
  226. package/.claude/hooks/mcp-server-guard.cjs +0 -108
  227. package/.claude/skills/marketplace-publishing.md +0 -155
  228. package/dist/bot/chat-bot.d.ts +0 -31
  229. package/dist/bot/chat-bot.js +0 -357
  230. package/dist/mcp/tools/metrics.d.ts +0 -13
  231. package/dist/mcp/tools/metrics.js +0 -546
  232. package/dist/stdio-server.d.ts +0 -14
  233. package/dist/stdio-server.js +0 -114
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ /**
3
+ * Bot Config Reader
4
+ *
5
+ * Simple config reader for .bot-config/*.json files.
6
+ * Extracts orchestrator credentials into a flat BotConfig interface.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.loadBotConfigs = loadBotConfigs;
43
+ exports.saveBotConfig = saveBotConfig;
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const logger_1 = require("../lib/logger");
47
+ const logger = (0, logger_1.createLogger)({ component: 'BotConfig' });
48
+ const DEFAULT_API_HOST = 'https://api.hailer.com';
49
+ function getApiHost() {
50
+ return process.env.BOT_API_BASE_URL || DEFAULT_API_HOST;
51
+ }
52
+ function getConfigDir() {
53
+ return path.join(process.cwd(), '.bot-config');
54
+ }
55
+ /**
56
+ * Load all bot configs from .bot-config/*.json files.
57
+ * Extracts orchestrator credentials into flat BotConfig objects.
58
+ */
59
+ function loadBotConfigs() {
60
+ const configDir = getConfigDir();
61
+ if (!fs.existsSync(configDir)) {
62
+ logger.warn('No .bot-config directory found');
63
+ return [];
64
+ }
65
+ const files = fs.readdirSync(configDir).filter(f => f.endsWith('.json'));
66
+ const configs = [];
67
+ for (const file of files) {
68
+ try {
69
+ const filePath = path.join(configDir, file);
70
+ const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
71
+ const orch = raw.orchestrator;
72
+ const hasCredentials = !!orch?.email && !!orch?.password;
73
+ configs.push({
74
+ workspaceId: raw.workspaceId,
75
+ workspaceName: raw.workspaceName,
76
+ email: orch?.email ?? '',
77
+ password: orch?.password ?? '',
78
+ displayName: orch?.displayName,
79
+ enabled: hasCredentials,
80
+ apiHost: getApiHost(),
81
+ });
82
+ logger.debug('Loaded bot config', {
83
+ workspaceId: raw.workspaceId,
84
+ workspaceName: raw.workspaceName,
85
+ enabled: hasCredentials,
86
+ });
87
+ }
88
+ catch (error) {
89
+ logger.warn('Failed to load bot config file', {
90
+ file,
91
+ error: error instanceof Error ? error.message : String(error),
92
+ });
93
+ }
94
+ }
95
+ logger.debug('Bot configs loaded', { total: configs.length });
96
+ return configs;
97
+ }
98
+ /**
99
+ * Save a BotConfig to .bot-config/{workspaceId}.json.
100
+ * Preserves the existing file structure, updating orchestrator credentials.
101
+ */
102
+ function saveBotConfig(config) {
103
+ const configDir = getConfigDir();
104
+ if (!fs.existsSync(configDir)) {
105
+ fs.mkdirSync(configDir, { recursive: true });
106
+ }
107
+ const filePath = path.join(configDir, `${config.workspaceId}.json`);
108
+ // Load existing file to preserve specialists/schema if present
109
+ let existing = {};
110
+ try {
111
+ if (fs.existsSync(filePath)) {
112
+ existing = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
113
+ }
114
+ }
115
+ catch {
116
+ // Start fresh if existing file is corrupt
117
+ }
118
+ const output = {
119
+ workspaceId: config.workspaceId,
120
+ workspaceName: config.workspaceName,
121
+ orchestrator: config.enabled ? {
122
+ activityId: existing.orchestrator?.activityId ?? '',
123
+ userId: existing.orchestrator?.userId ?? null,
124
+ email: config.email,
125
+ password: config.password,
126
+ displayName: config.displayName,
127
+ } : null,
128
+ specialists: existing.specialists ?? [],
129
+ lastSynced: new Date().toISOString(),
130
+ schema: existing.schema,
131
+ };
132
+ fs.writeFileSync(filePath, JSON.stringify(output, null, 2));
133
+ logger.debug('Saved bot config', { workspaceId: config.workspaceId, filePath });
134
+ }
135
+ //# sourceMappingURL=bot-config.js.map
@@ -0,0 +1,40 @@
1
+ /**
2
+ * BotManager - Manages lifecycle of Bot instances across workspaces.
3
+ *
4
+ * Loads configs from .bot-config/, starts one Bot per enabled workspace,
5
+ * and provides start/stop/status operations.
6
+ */
7
+ import { ToolRegistry } from '../mcp/tool-registry';
8
+ import { BotConfig } from './bot-config';
9
+ interface BotUpdateEntry {
10
+ email: string;
11
+ password: string;
12
+ botType: string;
13
+ enabled: boolean;
14
+ displayName?: string;
15
+ }
16
+ export declare class BotManager {
17
+ private toolRegistry;
18
+ private anthropicApiKey;
19
+ private bots;
20
+ private apiHost;
21
+ constructor(toolRegistry: ToolRegistry, anthropicApiKey: string);
22
+ startAll(): Promise<void>;
23
+ startBot(config: BotConfig): Promise<void>;
24
+ stopBot(workspaceId: string): Promise<void>;
25
+ stopAll(): Promise<void>;
26
+ getStatus(): Array<{
27
+ workspaceId: string;
28
+ connected: boolean;
29
+ displayName: string;
30
+ }>;
31
+ getBotCount(): number;
32
+ /**
33
+ * Handle hot reload from webhook updates.
34
+ * Only processes orchestrator bots. Workspace-isolated — only touches
35
+ * the bot for the specified workspaceId, never affects other workspaces.
36
+ */
37
+ handleBotUpdate(workspaceId: string, bot: BotUpdateEntry, action: 'add' | 'update' | 'remove'): Promise<void>;
38
+ }
39
+ export {};
40
+ //# sourceMappingURL=bot-manager.d.ts.map
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ /**
3
+ * BotManager - Manages lifecycle of Bot instances across workspaces.
4
+ *
5
+ * Loads configs from .bot-config/, starts one Bot per enabled workspace,
6
+ * and provides start/stop/status operations.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.BotManager = void 0;
10
+ const bot_1 = require("./bot");
11
+ const bot_config_1 = require("./bot-config");
12
+ const logger_1 = require("../lib/logger");
13
+ const logger = (0, logger_1.createLogger)({ component: 'bot-manager' });
14
+ class BotManager {
15
+ toolRegistry;
16
+ anthropicApiKey;
17
+ bots = new Map();
18
+ apiHost;
19
+ constructor(toolRegistry, anthropicApiKey) {
20
+ this.toolRegistry = toolRegistry;
21
+ this.anthropicApiKey = anthropicApiKey;
22
+ this.apiHost = process.env.BOT_API_BASE_URL || 'https://api.hailer.com';
23
+ }
24
+ async startAll() {
25
+ const configs = (0, bot_config_1.loadBotConfigs)();
26
+ const enabled = configs.filter(c => c.enabled);
27
+ logger.debug('Starting bots', { total: configs.length, enabled: enabled.length });
28
+ const results = await Promise.allSettled(enabled.map(config => this.startBot(config)));
29
+ const succeeded = results.filter(r => r.status === 'fulfilled').length;
30
+ const failed = results.filter(r => r.status === 'rejected').length;
31
+ if (failed > 0) {
32
+ const errors = results
33
+ .filter((r) => r.status === 'rejected')
34
+ .map(r => r.reason);
35
+ logger.error('Some bots failed to start', { failed, errors });
36
+ }
37
+ logger.debug('Bot startup complete', { succeeded, failed });
38
+ }
39
+ async startBot(config) {
40
+ if (this.bots.has(config.workspaceId)) {
41
+ logger.warn('Bot already running', { workspaceId: config.workspaceId });
42
+ return;
43
+ }
44
+ logger.debug('Starting bot', {
45
+ workspaceId: config.workspaceId,
46
+ workspace: config.workspaceName,
47
+ });
48
+ const bot = new bot_1.Bot({
49
+ email: config.email,
50
+ password: config.password,
51
+ apiHost: config.apiHost,
52
+ anthropicApiKey: this.anthropicApiKey,
53
+ toolRegistry: this.toolRegistry,
54
+ workspaceId: config.workspaceId,
55
+ });
56
+ await bot.start();
57
+ this.bots.set(config.workspaceId, bot);
58
+ logger.debug('Bot started', { workspaceId: config.workspaceId });
59
+ }
60
+ async stopBot(workspaceId) {
61
+ const bot = this.bots.get(workspaceId);
62
+ if (!bot)
63
+ return;
64
+ await bot.stop();
65
+ this.bots.delete(workspaceId);
66
+ logger.debug('Bot stopped', { workspaceId });
67
+ }
68
+ async stopAll() {
69
+ logger.debug('Stopping all bots', { count: this.bots.size });
70
+ await Promise.allSettled(Array.from(this.bots.entries()).map(async ([wsId, bot]) => {
71
+ await bot.stop();
72
+ logger.debug('Bot stopped', { workspaceId: wsId });
73
+ }));
74
+ this.bots.clear();
75
+ }
76
+ getStatus() {
77
+ return Array.from(this.bots.entries()).map(([wsId, bot]) => ({
78
+ workspaceId: wsId,
79
+ connected: bot.connected,
80
+ displayName: wsId,
81
+ }));
82
+ }
83
+ getBotCount() {
84
+ return this.bots.size;
85
+ }
86
+ /**
87
+ * Handle hot reload from webhook updates.
88
+ * Only processes orchestrator bots. Workspace-isolated — only touches
89
+ * the bot for the specified workspaceId, never affects other workspaces.
90
+ */
91
+ async handleBotUpdate(workspaceId, bot, action) {
92
+ if (bot.botType !== 'orchestrator') {
93
+ logger.debug('Ignoring non-orchestrator bot update', { workspaceId, botType: bot.botType });
94
+ return;
95
+ }
96
+ const running = this.bots.has(workspaceId);
97
+ if (action === 'remove' || !bot.enabled) {
98
+ if (running) {
99
+ logger.info('Stopping bot (disabled via webhook)', { workspaceId });
100
+ await this.stopBot(workspaceId);
101
+ }
102
+ return;
103
+ }
104
+ // Validate credentials before proceeding
105
+ if (!/.+@.+\..+/.test(bot.email) || !bot.password || bot.password.length < 6) {
106
+ logger.warn('Invalid bot credentials, skipping', { workspaceId });
107
+ return;
108
+ }
109
+ // action is 'add' or 'update' with enabled=true
110
+ if (running) {
111
+ // Restart — credentials or config may have changed
112
+ logger.info('Restarting bot (updated via webhook)', { workspaceId });
113
+ await this.stopBot(workspaceId);
114
+ }
115
+ const config = {
116
+ workspaceId,
117
+ workspaceName: workspaceId,
118
+ email: bot.email,
119
+ password: bot.password,
120
+ displayName: bot.displayName,
121
+ enabled: true,
122
+ apiHost: this.apiHost,
123
+ };
124
+ try {
125
+ await this.startBot(config);
126
+ logger.info('Bot started via webhook', { workspaceId, displayName: bot.displayName });
127
+ }
128
+ catch (error) {
129
+ logger.error('Failed to start bot via webhook', {
130
+ workspaceId,
131
+ error: error instanceof Error ? error.message : String(error),
132
+ });
133
+ }
134
+ }
135
+ }
136
+ exports.BotManager = BotManager;
137
+ //# sourceMappingURL=bot-manager.js.map
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Bot - Single class replacing the agents/ hierarchy.
3
+ *
4
+ * Connects to Hailer, subscribes to messenger signals,
5
+ * processes messages through the Anthropic API with tool use,
6
+ * and posts responses back to discussions.
7
+ */
8
+ import { ToolRegistry } from '../mcp/tool-registry';
9
+ export declare class Bot {
10
+ private logger;
11
+ private clientManager;
12
+ private client;
13
+ private anthropic;
14
+ private toolExecutor;
15
+ private userContext;
16
+ private init;
17
+ private workspaceCache;
18
+ private workspaceOverview;
19
+ private userId;
20
+ private _workspaceId;
21
+ private conversationManager;
22
+ private messageClassifier;
23
+ private messageFormatter;
24
+ private typingIndicator;
25
+ private tokenBilling;
26
+ private sessionLogger;
27
+ private opLogger;
28
+ private discussionStates;
29
+ private processingDiscussions;
30
+ private static DISENGAGE_THRESHOLD;
31
+ private processedMessageIds;
32
+ private signalTimestampsPerDiscussion;
33
+ private globalSignalTimestamps;
34
+ private signalHandler;
35
+ private processUpdatedHandler;
36
+ private workspaceUpdatedHandler;
37
+ private cacheInvalidateHandler;
38
+ private _connected;
39
+ private refreshTimer;
40
+ private refreshDirty;
41
+ private refreshScope;
42
+ private isRefreshing;
43
+ private refreshQueued;
44
+ private permissionIndex;
45
+ private adminUserIds;
46
+ private ownerUserIds;
47
+ private config;
48
+ constructor(config: {
49
+ email: string;
50
+ password: string;
51
+ apiHost: string;
52
+ anthropicApiKey: string;
53
+ model?: string;
54
+ toolRegistry: ToolRegistry;
55
+ workspaceId?: string;
56
+ });
57
+ get connected(): boolean;
58
+ get workspaceId(): string | undefined;
59
+ start(): Promise<void>;
60
+ stop(): Promise<void>;
61
+ private handleSignal;
62
+ private processDiscussion;
63
+ /**
64
+ * Classify message complexity using a lightweight Haiku call.
65
+ * Returns model + max_tokens to use for the main LLM loop.
66
+ * Falls back to Haiku on any error.
67
+ */
68
+ private routeMessage;
69
+ /**
70
+ * Extract recent conversation text for the router prompt.
71
+ * Walks backwards, extracts only text blocks (no tool calls/results),
72
+ * truncates each to 200 chars. Returns up to 3 recent exchanges.
73
+ */
74
+ private getRecentContext;
75
+ /**
76
+ * Bill the router classification call the same way as main LLM calls.
77
+ */
78
+ private trackRouterTokenUsage;
79
+ private processMessage;
80
+ private runLlmLoop;
81
+ private executeTools;
82
+ /**
83
+ * Inject pending messages from the context buffer into the conversation
84
+ * between LLM iterations. Merges into the existing user message to preserve
85
+ * Anthropic's alternation rule (user/assistant/user/assistant).
86
+ */
87
+ private injectPendingContext;
88
+ /**
89
+ * Remove orphaned tool_use/tool_result pairs from conversation after abort.
90
+ * Walks backwards and removes incomplete exchanges to keep conversation valid.
91
+ */
92
+ private cleanupIncompleteExchange;
93
+ private formatIncomingMessage;
94
+ private formatOutgoingMessage;
95
+ /**
96
+ * Find bare 24-char hex IDs in text that aren't already inside hailerTags
97
+ * and try to resolve them to clickable hailerTags.
98
+ */
99
+ private resolveBareIds;
100
+ private getBotDisplayName;
101
+ private buildSystemPrompt;
102
+ private getAnthropicTools;
103
+ private sendMessage;
104
+ /**
105
+ * Schedule a workspace data refresh with debounce.
106
+ * Signals can fire in bursts (e.g., bulk field edits), so we debounce
107
+ * to avoid hammering the API. 2-second delay is effectively instant
108
+ * from a user perspective but handles bursts.
109
+ */
110
+ private scheduleRefresh;
111
+ /**
112
+ * Re-fetch workspace data and rebuild the overview.
113
+ * Called when process.updated, workspace.updated, or cache.invalidate signals fire.
114
+ */
115
+ private refreshWorkspaceData;
116
+ private buildPermissionIndex;
117
+ private getOrCreateDiscussionState;
118
+ private getUserContext;
119
+ private getDefaultTeamId;
120
+ /**
121
+ * Extract workflow ID from tool result for post-execution permission checks.
122
+ * Returns the workflow ID if found, or undefined if extraction fails.
123
+ */
124
+ private extractWorkflowIdFromResult;
125
+ private trackTokenUsage;
126
+ }
127
+ //# sourceMappingURL=bot.d.ts.map