@hailer/mcp 0.1.14 → 0.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.
Files changed (112) hide show
  1. package/.claude/agents/agent-giuseppe-app-builder.md +7 -6
  2. package/.claude/agents/agent-lars-code-inspector.md +26 -14
  3. package/dist/agents/bot-manager.d.ts +48 -0
  4. package/dist/agents/bot-manager.js +254 -0
  5. package/dist/agents/factory.d.ts +150 -0
  6. package/dist/agents/factory.js +650 -0
  7. package/dist/agents/giuseppe/ai.d.ts +83 -0
  8. package/dist/agents/giuseppe/ai.js +466 -0
  9. package/dist/agents/giuseppe/bot.d.ts +110 -0
  10. package/dist/agents/giuseppe/bot.js +780 -0
  11. package/dist/agents/giuseppe/config.d.ts +25 -0
  12. package/dist/agents/giuseppe/config.js +227 -0
  13. package/dist/agents/giuseppe/files.d.ts +52 -0
  14. package/dist/agents/giuseppe/files.js +338 -0
  15. package/dist/agents/giuseppe/git.d.ts +48 -0
  16. package/dist/agents/giuseppe/git.js +298 -0
  17. package/dist/agents/giuseppe/index.d.ts +97 -0
  18. package/dist/agents/giuseppe/index.js +258 -0
  19. package/dist/agents/giuseppe/lsp.d.ts +113 -0
  20. package/dist/agents/giuseppe/lsp.js +485 -0
  21. package/dist/agents/giuseppe/monitor.d.ts +118 -0
  22. package/dist/agents/giuseppe/monitor.js +621 -0
  23. package/dist/agents/giuseppe/prompt.d.ts +5 -0
  24. package/dist/agents/giuseppe/prompt.js +94 -0
  25. package/dist/agents/giuseppe/registries/pending-classification.d.ts +28 -0
  26. package/dist/agents/giuseppe/registries/pending-classification.js +50 -0
  27. package/dist/agents/giuseppe/registries/pending-fix.d.ts +30 -0
  28. package/dist/agents/giuseppe/registries/pending-fix.js +42 -0
  29. package/dist/agents/giuseppe/registries/pending.d.ts +27 -0
  30. package/dist/agents/giuseppe/registries/pending.js +49 -0
  31. package/dist/agents/giuseppe/specialist.d.ts +47 -0
  32. package/dist/agents/giuseppe/specialist.js +237 -0
  33. package/dist/agents/giuseppe/types.d.ts +123 -0
  34. package/dist/agents/giuseppe/types.js +9 -0
  35. package/dist/agents/hailer-expert/index.d.ts +8 -0
  36. package/dist/agents/hailer-expert/index.js +14 -0
  37. package/dist/agents/hal/daemon.d.ts +142 -0
  38. package/dist/agents/hal/daemon.js +1103 -0
  39. package/dist/agents/hal/definitions.d.ts +55 -0
  40. package/dist/agents/hal/definitions.js +263 -0
  41. package/dist/agents/hal/index.d.ts +3 -0
  42. package/dist/agents/hal/index.js +8 -0
  43. package/dist/agents/index.d.ts +18 -0
  44. package/dist/agents/index.js +48 -0
  45. package/dist/agents/shared/base.d.ts +216 -0
  46. package/dist/agents/shared/base.js +846 -0
  47. package/dist/agents/shared/services/agent-registry.d.ts +107 -0
  48. package/dist/agents/shared/services/agent-registry.js +629 -0
  49. package/dist/agents/shared/services/conversation-manager.d.ts +50 -0
  50. package/dist/agents/shared/services/conversation-manager.js +136 -0
  51. package/dist/agents/shared/services/mcp-client.d.ts +56 -0
  52. package/dist/agents/shared/services/mcp-client.js +124 -0
  53. package/dist/agents/shared/services/message-classifier.d.ts +37 -0
  54. package/dist/agents/shared/services/message-classifier.js +187 -0
  55. package/dist/agents/shared/services/message-formatter.d.ts +89 -0
  56. package/dist/agents/shared/services/message-formatter.js +371 -0
  57. package/dist/agents/shared/services/session-logger.d.ts +106 -0
  58. package/dist/agents/shared/services/session-logger.js +446 -0
  59. package/dist/agents/shared/services/tool-executor.d.ts +41 -0
  60. package/dist/agents/shared/services/tool-executor.js +169 -0
  61. package/dist/agents/shared/services/workspace-schema-cache.d.ts +125 -0
  62. package/dist/agents/shared/services/workspace-schema-cache.js +578 -0
  63. package/dist/agents/shared/specialist.d.ts +91 -0
  64. package/dist/agents/shared/specialist.js +399 -0
  65. package/dist/agents/shared/tool-schema-loader.d.ts +62 -0
  66. package/dist/agents/shared/tool-schema-loader.js +232 -0
  67. package/dist/agents/shared/types.d.ts +327 -0
  68. package/dist/agents/shared/types.js +121 -0
  69. package/dist/app.js +21 -4
  70. package/dist/cli.js +0 -0
  71. package/dist/client/agents/orchestrator.d.ts +1 -0
  72. package/dist/client/agents/orchestrator.js +12 -1
  73. package/dist/commands/seed-config.d.ts +9 -0
  74. package/dist/commands/seed-config.js +372 -0
  75. package/dist/config.d.ts +10 -0
  76. package/dist/config.js +61 -1
  77. package/dist/core.d.ts +8 -0
  78. package/dist/core.js +137 -6
  79. package/dist/lib/discussion-lock.d.ts +42 -0
  80. package/dist/lib/discussion-lock.js +110 -0
  81. package/dist/mcp/UserContextCache.js +2 -2
  82. package/dist/mcp/hailer-clients.d.ts +15 -0
  83. package/dist/mcp/hailer-clients.js +100 -6
  84. package/dist/mcp/signal-handler.d.ts +16 -5
  85. package/dist/mcp/signal-handler.js +173 -122
  86. package/dist/mcp/tools/activity.js +9 -1
  87. package/dist/mcp/tools/bot-config.d.ts +184 -9
  88. package/dist/mcp/tools/bot-config.js +2177 -163
  89. package/dist/mcp/tools/giuseppe-tools.d.ts +21 -0
  90. package/dist/mcp/tools/giuseppe-tools.js +525 -0
  91. package/dist/mcp/utils/hailer-api-client.d.ts +42 -1
  92. package/dist/mcp/utils/hailer-api-client.js +128 -2
  93. package/dist/mcp/webhook-handler.d.ts +87 -0
  94. package/dist/mcp/webhook-handler.js +343 -0
  95. package/dist/mcp/workspace-cache.d.ts +5 -0
  96. package/dist/mcp/workspace-cache.js +11 -0
  97. package/dist/mcp-server.js +55 -5
  98. package/dist/modules/bug-reports/giuseppe-agent.d.ts +58 -0
  99. package/dist/modules/bug-reports/giuseppe-agent.js +467 -0
  100. package/dist/modules/bug-reports/giuseppe-ai.d.ts +25 -1
  101. package/dist/modules/bug-reports/giuseppe-ai.js +133 -2
  102. package/dist/modules/bug-reports/giuseppe-bot.d.ts +3 -2
  103. package/dist/modules/bug-reports/giuseppe-bot.js +75 -36
  104. package/dist/modules/bug-reports/giuseppe-daemon.d.ts +80 -0
  105. package/dist/modules/bug-reports/giuseppe-daemon.js +617 -0
  106. package/dist/modules/bug-reports/giuseppe-files.d.ts +12 -0
  107. package/dist/modules/bug-reports/giuseppe-files.js +37 -0
  108. package/dist/modules/bug-reports/giuseppe-lsp.d.ts +113 -0
  109. package/dist/modules/bug-reports/giuseppe-lsp.js +485 -0
  110. package/dist/modules/bug-reports/index.d.ts +1 -0
  111. package/dist/modules/bug-reports/index.js +31 -29
  112. package/package.json +5 -4
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ /**
3
+ * Giuseppe System Prompt - Expert TypeScript/React debugger prompt
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.GIUSEPPE_SYSTEM_PROMPT = void 0;
7
+ exports.GIUSEPPE_SYSTEM_PROMPT = `<identity>
8
+ You are Giuseppe, an expert TypeScript/React debugger for Hailer apps.
9
+ You fix bugs by TRACING code paths, not by guessing.
10
+ </identity>
11
+
12
+ <expertise>
13
+ TYPESCRIPT: Strict types, interfaces, generics, type guards
14
+ REACT: Hooks, state, effects, memoization, dependency arrays
15
+ CHAKRA UI: Box, Flex, useColorModeValue, responsive props
16
+ HAILER SDK: useHailerContext, useActivity, useWorkflows, activity fields
17
+ CANVAS: 2D context, drawing, hit detection, coordinate systems
18
+ </expertise>
19
+
20
+ <debugging-process>
21
+ STEP 1: TRACE THE CODE PATH
22
+ - What function handles the user action? (onClick, onMouseMove, etc.)
23
+ - What state/props does it use?
24
+ - What conditions might fail?
25
+
26
+ STEP 2: CHECK REACT REACTIVITY
27
+ - Is state being SET? (setState called)
28
+ - Is component RE-RENDERING? (check useCallback/useMemo deps)
29
+ - Are closures STALE? (missing deps = old values)
30
+
31
+ STEP 3: IDENTIFY EXACT FAILURE POINT
32
+ GOOD: "handleClick uses selectedId but renderList deps array is missing selectedId"
33
+ BAD: "Something might be wrong with the click handler"
34
+
35
+ STEP 4: MINIMAL FIX
36
+ - Add missing dependency to array
37
+ - Add missing prop to component
38
+ - Fix the one broken thing - don't refactor
39
+ </debugging-process>
40
+
41
+ <react-patterns>
42
+ DEPENDENCY ARRAY BUGS (most common!):
43
+ - useCallback/useMemo/useEffect use state but deps array missing it
44
+ - Symptom: UI doesn't update when state changes
45
+ - Fix: Add ALL used state variables to deps array
46
+
47
+ STATE UPDATE BUGS:
48
+ - setState called but component doesn't re-render
49
+ - Check if state is used in memoized callback with stale closure
50
+
51
+ PROP DRILLING BUGS:
52
+ - Prop passed but not used in child
53
+ - Prop used but not passed from parent
54
+
55
+ EVENT HANDLER BUGS:
56
+ - Handler defined but not connected to element
57
+ - Handler connected but wrong event type
58
+ </react-patterns>
59
+
60
+ <hailer-sdk>
61
+ useHailerContext() - workspace, user, permissions
62
+ useActivity(id) - load single activity by ID
63
+ useWorkflows() - list available workflows
64
+ Activity fields keyed by FIELD ID not label
65
+ Always handle loading states
66
+ useToast() for notifications
67
+ </hailer-sdk>
68
+
69
+ <output-format>
70
+ {
71
+ "debugTrace": "Step-by-step: function X calls Y, which uses state Z, but useCallback deps missing Z",
72
+ "failurePoint": "File.tsx line N - deps array missing stateVariable",
73
+ "rootCause": "Stale closure - useCallback keeps old value of stateVariable",
74
+ "fix": {
75
+ "files": [{
76
+ "path": "src/components/File.tsx",
77
+ "action": "edit",
78
+ "search": "exact code to find",
79
+ "replace": "fixed code"
80
+ }]
81
+ },
82
+ "explanation": "Added stateVariable to deps array so callback updates when state changes",
83
+ "testSuggestions": ["How to verify the fix works"]
84
+ }
85
+ </output-format>
86
+
87
+ <rules>
88
+ 1. TRACE before fixing - follow the code path
89
+ 2. CHECK DEPS ARRAYS - most common React bug
90
+ 3. Fix ONE thing - minimal change
91
+ 4. Use EXACT file paths from provided code
92
+ 5. Search string must EXACTLY match file content
93
+ </rules>`;
94
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Pending Classification Registry - Tracks bug classifications awaiting confirmation
3
+ */
4
+ import { PendingRegistry, PendingItem } from './pending';
5
+ import type { BugReport } from '../types';
6
+ export interface PendingClassificationInfo extends PendingItem {
7
+ bugId: string;
8
+ bugName: string;
9
+ appId?: string;
10
+ appName?: string;
11
+ classification: 'bug' | 'feature_request' | 'unclear';
12
+ reason: string;
13
+ bug: BugReport;
14
+ }
15
+ declare class PendingClassificationRegistry extends PendingRegistry<PendingClassificationInfo> {
16
+ private fixItCallback?;
17
+ private notABugCallback?;
18
+ constructor();
19
+ setCallbacks(fixItCallback: (discussionId: string) => Promise<void>, notABugCallback: (discussionId: string) => Promise<void>): void;
20
+ triggerFixIt(discussionId: string): Promise<boolean>;
21
+ triggerNotABug(discussionId: string): Promise<boolean>;
22
+ hasPendingClassification(discussionId: string): boolean;
23
+ getPendingClassification(discussionId: string): PendingClassificationInfo | undefined;
24
+ getAllPendingClassifications(): PendingClassificationInfo[];
25
+ }
26
+ export declare const pendingClassificationRegistry: PendingClassificationRegistry;
27
+ export {};
28
+ //# sourceMappingURL=pending-classification.d.ts.map
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /**
3
+ * Pending Classification Registry - Tracks bug classifications awaiting confirmation
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pendingClassificationRegistry = void 0;
7
+ const pending_1 = require("./pending");
8
+ class PendingClassificationRegistry extends pending_1.PendingRegistry {
9
+ fixItCallback;
10
+ notABugCallback;
11
+ constructor() {
12
+ super('pending-classification-registry');
13
+ }
14
+ setCallbacks(fixItCallback, notABugCallback) {
15
+ this.fixItCallback = fixItCallback;
16
+ this.notABugCallback = notABugCallback;
17
+ }
18
+ async triggerFixIt(discussionId) {
19
+ if (!this.fixItCallback) {
20
+ this.logger.warn('No fixIt callback registered', { discussionId });
21
+ return false;
22
+ }
23
+ if (!this.has(discussionId)) {
24
+ this.logger.warn('No pending classification to fix', { discussionId });
25
+ return false;
26
+ }
27
+ this.logger.info('Triggering fix it', { discussionId });
28
+ await this.fixItCallback(discussionId);
29
+ return true;
30
+ }
31
+ async triggerNotABug(discussionId) {
32
+ if (!this.notABugCallback) {
33
+ this.logger.warn('No notABug callback registered', { discussionId });
34
+ return false;
35
+ }
36
+ if (!this.has(discussionId)) {
37
+ this.logger.warn('No pending classification to decline', { discussionId });
38
+ return false;
39
+ }
40
+ this.logger.info('Triggering not a bug', { discussionId });
41
+ await this.notABugCallback(discussionId);
42
+ return true;
43
+ }
44
+ // Backward-compatible aliases
45
+ hasPendingClassification(discussionId) { return this.has(discussionId); }
46
+ getPendingClassification(discussionId) { return this.get(discussionId); }
47
+ getAllPendingClassifications() { return this.getAll(); }
48
+ }
49
+ exports.pendingClassificationRegistry = new PendingClassificationRegistry();
50
+ //# sourceMappingURL=pending-classification.js.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Pending Fix Registry - Tracks bug fixes awaiting approval
3
+ */
4
+ import { PendingRegistry, PendingItem } from './pending';
5
+ import type { BugReport, AppRegistryEntry } from '../types';
6
+ import type { FixPlan } from '../ai';
7
+ export interface PendingFixInfo extends PendingItem {
8
+ bugId: string;
9
+ appId: string;
10
+ state: 'awaiting_test' | 'awaiting_explanation';
11
+ fixSummary: string;
12
+ bug: BugReport;
13
+ app: AppRegistryEntry;
14
+ fixPlan: FixPlan;
15
+ filesModified: string[];
16
+ commitHash?: string;
17
+ }
18
+ declare class PendingFixRegistry extends PendingRegistry<PendingFixInfo> {
19
+ private retryCallback?;
20
+ constructor();
21
+ updateState(discussionId: string, state: PendingFixInfo['state']): void;
22
+ setRetryCallback(callback: (discussionId: string, explanation: string) => Promise<void>): void;
23
+ triggerRetry(discussionId: string, explanation: string): Promise<boolean>;
24
+ hasPendingFix(discussionId: string): boolean;
25
+ getPendingFix(discussionId: string): PendingFixInfo | undefined;
26
+ getAllPendingFixes(): PendingFixInfo[];
27
+ }
28
+ export declare const pendingFixRegistry: PendingFixRegistry;
29
+ export {};
30
+ //# sourceMappingURL=pending-fix.d.ts.map
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /**
3
+ * Pending Fix Registry - Tracks bug fixes awaiting approval
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pendingFixRegistry = void 0;
7
+ const pending_1 = require("./pending");
8
+ class PendingFixRegistry extends pending_1.PendingRegistry {
9
+ retryCallback;
10
+ constructor() {
11
+ super('pending-fix-registry');
12
+ }
13
+ updateState(discussionId, state) {
14
+ const fix = this.get(discussionId);
15
+ if (fix) {
16
+ fix.state = state;
17
+ this.logger.debug('Updated pending fix state', { discussionId, state });
18
+ }
19
+ }
20
+ setRetryCallback(callback) {
21
+ this.retryCallback = callback;
22
+ }
23
+ async triggerRetry(discussionId, explanation) {
24
+ if (!this.retryCallback) {
25
+ this.logger.warn('No retry callback registered', { discussionId });
26
+ return false;
27
+ }
28
+ if (!this.has(discussionId)) {
29
+ this.logger.warn('No pending fix to retry', { discussionId });
30
+ return false;
31
+ }
32
+ this.logger.info('Triggering retry with explanation', { discussionId, explanationLength: explanation.length });
33
+ await this.retryCallback(discussionId, explanation);
34
+ return true;
35
+ }
36
+ // Backward-compatible aliases
37
+ hasPendingFix(discussionId) { return this.has(discussionId); }
38
+ getPendingFix(discussionId) { return this.get(discussionId); }
39
+ getAllPendingFixes() { return this.getAll(); }
40
+ }
41
+ exports.pendingFixRegistry = new PendingFixRegistry();
42
+ //# sourceMappingURL=pending-fix.js.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Generic Pending Registry Base Class
3
+ *
4
+ * Shared foundation for PendingFixRegistry and PendingClassificationRegistry.
5
+ * Provides Map-based storage with register/unregister/has/get/getAll methods.
6
+ */
7
+ import { Logger } from '../../../lib/logger';
8
+ export interface PendingItem {
9
+ discussionId: string;
10
+ timestamp: number;
11
+ }
12
+ /**
13
+ * Generic registry for pending items keyed by discussionId
14
+ */
15
+ export declare class PendingRegistry<T extends PendingItem> {
16
+ protected items: Map<string, T>;
17
+ protected logger: Logger;
18
+ constructor(component: string);
19
+ register(item: T): void;
20
+ unregister(discussionId: string): void;
21
+ has(discussionId: string): boolean;
22
+ get(discussionId: string): T | undefined;
23
+ getAll(): T[];
24
+ get size(): number;
25
+ clear(): void;
26
+ }
27
+ //# sourceMappingURL=pending.d.ts.map
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /**
3
+ * Generic Pending Registry Base Class
4
+ *
5
+ * Shared foundation for PendingFixRegistry and PendingClassificationRegistry.
6
+ * Provides Map-based storage with register/unregister/has/get/getAll methods.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.PendingRegistry = void 0;
10
+ const logger_1 = require("../../../lib/logger");
11
+ /**
12
+ * Generic registry for pending items keyed by discussionId
13
+ */
14
+ class PendingRegistry {
15
+ items = new Map();
16
+ logger;
17
+ constructor(component) {
18
+ this.logger = (0, logger_1.createLogger)({ component });
19
+ }
20
+ register(item) {
21
+ this.items.set(item.discussionId, item);
22
+ this.logger.debug('Registered pending item', {
23
+ discussionId: item.discussionId,
24
+ timestamp: item.timestamp
25
+ });
26
+ }
27
+ unregister(discussionId) {
28
+ this.items.delete(discussionId);
29
+ this.logger.debug('Unregistered pending item', { discussionId });
30
+ }
31
+ has(discussionId) {
32
+ return this.items.has(discussionId);
33
+ }
34
+ get(discussionId) {
35
+ return this.items.get(discussionId);
36
+ }
37
+ getAll() {
38
+ return Array.from(this.items.values());
39
+ }
40
+ get size() {
41
+ return this.items.size;
42
+ }
43
+ clear() {
44
+ this.items.clear();
45
+ this.logger.debug('Cleared all pending items');
46
+ }
47
+ }
48
+ exports.PendingRegistry = PendingRegistry;
49
+ //# sourceMappingURL=pending.js.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Giuseppe Specialist Daemon
3
+ *
4
+ * A specialist daemon for bug fixing that extends SpecialistDaemon.
5
+ * Giuseppe handles bug discussions naturally - responds to all messages
6
+ * in bug discussions (not just @mentions).
7
+ *
8
+ * Tools: Uses MCP tools registered in the tool registry.
9
+ */
10
+ import { SpecialistDaemon, SpecialistDaemonConfig } from "../shared/specialist";
11
+ import { IncomingMessage } from "../shared/base";
12
+ import { HailerSignal } from "../../mcp/signal-handler";
13
+ export interface GiuseppeSpecialistConfig extends SpecialistDaemonConfig {
14
+ /** Base path for app projects */
15
+ appsBasePath?: string;
16
+ }
17
+ export declare class GiuseppeSpecialist extends SpecialistDaemon {
18
+ private giuseppeLogger;
19
+ private bugDiscussions;
20
+ constructor(config: GiuseppeSpecialistConfig);
21
+ /**
22
+ * Register a bug discussion for Giuseppe to handle
23
+ * Call this when a new bug is detected
24
+ */
25
+ registerBugDiscussion(discussionId: string, bugId: string, bugName: string, appPath?: string): void;
26
+ /**
27
+ * Unregister a bug discussion (bug resolved)
28
+ */
29
+ unregisterBugDiscussion(discussionId: string): void;
30
+ /**
31
+ * Check if Giuseppe is handling a discussion
32
+ */
33
+ isHandlingDiscussion(discussionId: string): boolean;
34
+ /**
35
+ * Override to respond to ALL messages in bug discussions (not just @mentions)
36
+ */
37
+ protected extractIncomingMessage(signal: HailerSignal): Promise<IncomingMessage | null>;
38
+ /**
39
+ * Giuseppe's tool whitelist - bug fixing tools
40
+ */
41
+ protected getToolWhitelist(): string[];
42
+ /**
43
+ * Override system prompt to add Giuseppe-specific instructions
44
+ */
45
+ protected getSystemPrompt(): string;
46
+ }
47
+ //# sourceMappingURL=specialist.d.ts.map
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ /**
3
+ * Giuseppe Specialist Daemon
4
+ *
5
+ * A specialist daemon for bug fixing that extends SpecialistDaemon.
6
+ * Giuseppe handles bug discussions naturally - responds to all messages
7
+ * in bug discussions (not just @mentions).
8
+ *
9
+ * Tools: Uses MCP tools registered in the tool registry.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.GiuseppeSpecialist = void 0;
13
+ const specialist_1 = require("../shared/specialist");
14
+ const logger_1 = require("../../lib/logger");
15
+ class GiuseppeSpecialist extends specialist_1.SpecialistDaemon {
16
+ giuseppeLogger;
17
+ // Track bug discussions Giuseppe is handling
18
+ bugDiscussions = new Map();
19
+ constructor(config) {
20
+ super(config);
21
+ this.giuseppeLogger = (0, logger_1.createLogger)({
22
+ component: "GiuseppeSpecialist",
23
+ botId: config.botClient.userId,
24
+ });
25
+ }
26
+ /**
27
+ * Register a bug discussion for Giuseppe to handle
28
+ * Call this when a new bug is detected
29
+ */
30
+ registerBugDiscussion(discussionId, bugId, bugName, appPath) {
31
+ this.bugDiscussions.set(discussionId, { bugId, bugName, appPath });
32
+ this.giuseppeLogger.info("Registered bug discussion", { discussionId, bugId, bugName });
33
+ }
34
+ /**
35
+ * Unregister a bug discussion (bug resolved)
36
+ */
37
+ unregisterBugDiscussion(discussionId) {
38
+ this.bugDiscussions.delete(discussionId);
39
+ }
40
+ /**
41
+ * Check if Giuseppe is handling a discussion
42
+ */
43
+ isHandlingDiscussion(discussionId) {
44
+ return this.bugDiscussions.has(discussionId);
45
+ }
46
+ /**
47
+ * Override to respond to ALL messages in bug discussions (not just @mentions)
48
+ */
49
+ async extractIncomingMessage(signal) {
50
+ // FIRST: Check if this is a bug discussion we're handling (before @mention check)
51
+ const discussionId = signal.data?.discussion;
52
+ this.giuseppeLogger.debug("Checking signal for bug discussion", {
53
+ discussionId,
54
+ registeredDiscussions: Array.from(this.bugDiscussions.keys()),
55
+ signalType: signal.type,
56
+ });
57
+ // Check if this is a registered bug discussion
58
+ const bugInfo = discussionId ? this.bugDiscussions.get(discussionId) : null;
59
+ if (!bugInfo) {
60
+ // Not a bug discussion - fall back to @mention check (parent behavior)
61
+ return super.extractIncomingMessage(signal);
62
+ }
63
+ this.giuseppeLogger.info("Processing message in registered bug discussion", {
64
+ discussionId,
65
+ bugName: bugInfo.bugName,
66
+ });
67
+ // Get the message content
68
+ const senderId = signal.data?.uid;
69
+ if (!senderId)
70
+ return null;
71
+ // Skip our own messages
72
+ if (senderId === this.botClient.userId)
73
+ return null;
74
+ // Fetch the message content using the Hailer API
75
+ try {
76
+ const msgId = signal.data?.msg_id;
77
+ this.giuseppeLogger.info("Processing bug discussion message", {
78
+ discussionId,
79
+ bugName: bugInfo.bugName,
80
+ msgId,
81
+ });
82
+ // Fetch actual message content from API
83
+ const response = await this.botClient.client.socket.request("v3.discussion.message.latest", [discussionId]);
84
+ const messages = response?.messages || [];
85
+ const targetMessage = messages.find((msg) => msg._id === msgId);
86
+ if (!targetMessage) {
87
+ this.giuseppeLogger.warn("Message not found in discussion", { discussionId, msgId });
88
+ return null;
89
+ }
90
+ // Extract content - try both field names
91
+ const messageContent = targetMessage.msg || targetMessage.content || "";
92
+ if (!messageContent) {
93
+ this.giuseppeLogger.warn("Message has no content", { discussionId, msgId, targetMessage });
94
+ return null;
95
+ }
96
+ // Get sender name from cache or message
97
+ const cachedUser = this.botClient.workspaceCache?.usersById[senderId];
98
+ const senderName = cachedUser?.fullName
99
+ || `${cachedUser?.firstname || ''} ${cachedUser?.lastname || ''}`.trim()
100
+ || targetMessage.userName
101
+ || "User";
102
+ this.giuseppeLogger.debug("Extracted message content", {
103
+ discussionId,
104
+ msgId,
105
+ contentPreview: messageContent.substring(0, 50),
106
+ senderName,
107
+ });
108
+ // Return a properly structured IncomingMessage with actual content
109
+ return {
110
+ id: msgId,
111
+ discussionId,
112
+ senderId,
113
+ senderName,
114
+ content: messageContent,
115
+ timestamp: Date.now(),
116
+ priority: "high",
117
+ priorityReason: `Bug discussion: ${bugInfo.bugName}`,
118
+ workspaceId: signal.workspaceId || '',
119
+ linkedActivityId: bugInfo.bugId,
120
+ linkedActivityName: bugInfo.bugName,
121
+ isMention: false,
122
+ isReplyToBot: false,
123
+ isDirectMessage: true,
124
+ };
125
+ }
126
+ catch (error) {
127
+ this.giuseppeLogger.warn("Failed to process bug discussion message", { discussionId, error });
128
+ return null;
129
+ }
130
+ }
131
+ /**
132
+ * Giuseppe's tool whitelist - bug fixing tools
133
+ */
134
+ getToolWhitelist() {
135
+ return [
136
+ // Standard Hailer tools
137
+ "list_workflows",
138
+ "list_workflow_phases",
139
+ "get_workflow_schema",
140
+ "list_activities",
141
+ "show_activity_by_id",
142
+ "update_activity",
143
+ "add_discussion_message",
144
+ "fetch_discussion_messages",
145
+ "get_activity_from_discussion",
146
+ "search_workspace_users",
147
+ // Giuseppe's bug-fixing tools (registered as MCP tools)
148
+ "giuseppe_find_app",
149
+ "giuseppe_list_files",
150
+ "giuseppe_read_file",
151
+ // "giuseppe_write_file", // Disabled - use giuseppe_apply_fix instead
152
+ "giuseppe_apply_fix", // search/replace pattern (token-efficient)
153
+ "giuseppe_run_build",
154
+ "giuseppe_git_status",
155
+ "giuseppe_git_pull",
156
+ "giuseppe_git_commit",
157
+ "giuseppe_git_push",
158
+ "giuseppe_git_revert",
159
+ "giuseppe_publish_app",
160
+ ];
161
+ }
162
+ /**
163
+ * Override system prompt to add Giuseppe-specific instructions
164
+ */
165
+ getSystemPrompt() {
166
+ const basePrompt = super.getSystemPrompt();
167
+ const giuseppeAddition = `
168
+
169
+ <giuseppe_mode>
170
+ You are Giuseppe, the bug-fixing specialist. You handle bug reports through natural conversation.
171
+
172
+ **WORKFLOW - Follow this order:**
173
+
174
+ 1. **ANALYZE** - When you see a new bug:
175
+ - Greet the user and acknowledge the bug
176
+ - Use giuseppe_find_app to locate the app project
177
+ - Read the bug description carefully
178
+ - Ask clarifying questions if needed
179
+
180
+ 2. **INVESTIGATE** - Understand the code:
181
+ - Use giuseppe_git_status to check repo state
182
+ - Use giuseppe_git_pull if behind remote
183
+ - Use giuseppe_list_files to see project structure
184
+ - Use giuseppe_read_file to examine relevant code
185
+ - Use giuseppe_run_build to check current state
186
+
187
+ 3. **PROPOSE FIX** - Present your plan:
188
+ - Explain what you found (root cause)
189
+ - Describe your proposed fix clearly
190
+ - List the files you'll modify
191
+ - **ASK: "Does this fix plan look good? Reply 'approved' to proceed."**
192
+
193
+ 4. **EXECUTE** (only after user says "approved"):
194
+ - Use giuseppe_apply_fix with search/replace pattern (more efficient than rewriting entire files)
195
+ - Example:
196
+ giuseppe_apply_fix({
197
+ appPath: "my-app",
198
+ fixes: [{
199
+ path: "src/App.tsx",
200
+ action: "edit",
201
+ search: "const oldCode = () => {\\n // buggy code\\n}",
202
+ replace: "const oldCode = () => {\\n // fixed code\\n}"
203
+ }]
204
+ })
205
+ - The 'search' must EXACTLY match the code in the file
206
+ - Use giuseppe_run_build to verify fix works
207
+ - If build fails, adjust the fix and try again
208
+ - Use giuseppe_git_commit with clear message
209
+
210
+ 5. **PUBLISH** (only after asking):
211
+ - **ASK: "Fix is ready. Should I publish to production?"**
212
+ - If user confirms, use giuseppe_publish_app
213
+ - Report success with version number
214
+
215
+ **BUG STATUS - Update phases:**
216
+ 1. First call list_workflow_phases(workflowId) to get available phases and their IDs
217
+ 2. Find the phase you need (e.g., "Fixed", "In Progress", "Declined")
218
+ 3. Use the hex ID in update_activity: update_activity(activityId, { phaseId: "actual-hex-id-here" })
219
+ - FIXED: move to "Fixed" phase
220
+ - DECLINED: move to "Declined" phase
221
+ - WORKING: move to "In Progress" phase
222
+
223
+ **RULES:**
224
+ - NEVER execute fixes without user approval
225
+ - NEVER publish without explicit confirmation
226
+ - Be conversational and explain in plain language
227
+ - If something fails, explain the error and ask how to proceed
228
+ - ALWAYS update bug phase when status changes (look up phase ID first with list_workflow_phases)
229
+ - You can add notes to the bug by updating its description field
230
+
231
+ **You're responding to messages in a bug discussion - no need for @mentions.**
232
+ </giuseppe_mode>`;
233
+ return basePrompt + giuseppeAddition;
234
+ }
235
+ }
236
+ exports.GiuseppeSpecialist = GiuseppeSpecialist;
237
+ //# sourceMappingURL=specialist.js.map