@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.
- package/.claude/agents/agent-giuseppe-app-builder.md +7 -6
- package/.claude/agents/agent-lars-code-inspector.md +26 -14
- package/dist/agents/bot-manager.d.ts +48 -0
- package/dist/agents/bot-manager.js +254 -0
- package/dist/agents/factory.d.ts +150 -0
- package/dist/agents/factory.js +650 -0
- package/dist/agents/giuseppe/ai.d.ts +83 -0
- package/dist/agents/giuseppe/ai.js +466 -0
- package/dist/agents/giuseppe/bot.d.ts +110 -0
- package/dist/agents/giuseppe/bot.js +780 -0
- package/dist/agents/giuseppe/config.d.ts +25 -0
- package/dist/agents/giuseppe/config.js +227 -0
- package/dist/agents/giuseppe/files.d.ts +52 -0
- package/dist/agents/giuseppe/files.js +338 -0
- package/dist/agents/giuseppe/git.d.ts +48 -0
- package/dist/agents/giuseppe/git.js +298 -0
- package/dist/agents/giuseppe/index.d.ts +97 -0
- package/dist/agents/giuseppe/index.js +258 -0
- package/dist/agents/giuseppe/lsp.d.ts +113 -0
- package/dist/agents/giuseppe/lsp.js +485 -0
- package/dist/agents/giuseppe/monitor.d.ts +118 -0
- package/dist/agents/giuseppe/monitor.js +621 -0
- package/dist/agents/giuseppe/prompt.d.ts +5 -0
- package/dist/agents/giuseppe/prompt.js +94 -0
- package/dist/agents/giuseppe/registries/pending-classification.d.ts +28 -0
- package/dist/agents/giuseppe/registries/pending-classification.js +50 -0
- package/dist/agents/giuseppe/registries/pending-fix.d.ts +30 -0
- package/dist/agents/giuseppe/registries/pending-fix.js +42 -0
- package/dist/agents/giuseppe/registries/pending.d.ts +27 -0
- package/dist/agents/giuseppe/registries/pending.js +49 -0
- package/dist/agents/giuseppe/specialist.d.ts +47 -0
- package/dist/agents/giuseppe/specialist.js +237 -0
- package/dist/agents/giuseppe/types.d.ts +123 -0
- package/dist/agents/giuseppe/types.js +9 -0
- package/dist/agents/hailer-expert/index.d.ts +8 -0
- package/dist/agents/hailer-expert/index.js +14 -0
- package/dist/agents/hal/daemon.d.ts +142 -0
- package/dist/agents/hal/daemon.js +1103 -0
- package/dist/agents/hal/definitions.d.ts +55 -0
- package/dist/agents/hal/definitions.js +263 -0
- package/dist/agents/hal/index.d.ts +3 -0
- package/dist/agents/hal/index.js +8 -0
- package/dist/agents/index.d.ts +18 -0
- package/dist/agents/index.js +48 -0
- package/dist/agents/shared/base.d.ts +216 -0
- package/dist/agents/shared/base.js +846 -0
- package/dist/agents/shared/services/agent-registry.d.ts +107 -0
- package/dist/agents/shared/services/agent-registry.js +629 -0
- package/dist/agents/shared/services/conversation-manager.d.ts +50 -0
- package/dist/agents/shared/services/conversation-manager.js +136 -0
- package/dist/agents/shared/services/mcp-client.d.ts +56 -0
- package/dist/agents/shared/services/mcp-client.js +124 -0
- package/dist/agents/shared/services/message-classifier.d.ts +37 -0
- package/dist/agents/shared/services/message-classifier.js +187 -0
- package/dist/agents/shared/services/message-formatter.d.ts +89 -0
- package/dist/agents/shared/services/message-formatter.js +371 -0
- package/dist/agents/shared/services/session-logger.d.ts +106 -0
- package/dist/agents/shared/services/session-logger.js +446 -0
- package/dist/agents/shared/services/tool-executor.d.ts +41 -0
- package/dist/agents/shared/services/tool-executor.js +169 -0
- package/dist/agents/shared/services/workspace-schema-cache.d.ts +125 -0
- package/dist/agents/shared/services/workspace-schema-cache.js +578 -0
- package/dist/agents/shared/specialist.d.ts +91 -0
- package/dist/agents/shared/specialist.js +399 -0
- package/dist/agents/shared/tool-schema-loader.d.ts +62 -0
- package/dist/agents/shared/tool-schema-loader.js +232 -0
- package/dist/agents/shared/types.d.ts +327 -0
- package/dist/agents/shared/types.js +121 -0
- package/dist/app.js +21 -4
- package/dist/cli.js +0 -0
- package/dist/client/agents/orchestrator.d.ts +1 -0
- package/dist/client/agents/orchestrator.js +12 -1
- package/dist/commands/seed-config.d.ts +9 -0
- package/dist/commands/seed-config.js +372 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.js +61 -1
- package/dist/core.d.ts +8 -0
- package/dist/core.js +137 -6
- package/dist/lib/discussion-lock.d.ts +42 -0
- package/dist/lib/discussion-lock.js +110 -0
- package/dist/mcp/UserContextCache.js +2 -2
- package/dist/mcp/hailer-clients.d.ts +15 -0
- package/dist/mcp/hailer-clients.js +100 -6
- package/dist/mcp/signal-handler.d.ts +16 -5
- package/dist/mcp/signal-handler.js +173 -122
- package/dist/mcp/tools/activity.js +9 -1
- package/dist/mcp/tools/bot-config.d.ts +184 -9
- package/dist/mcp/tools/bot-config.js +2177 -163
- package/dist/mcp/tools/giuseppe-tools.d.ts +21 -0
- package/dist/mcp/tools/giuseppe-tools.js +525 -0
- package/dist/mcp/utils/hailer-api-client.d.ts +42 -1
- package/dist/mcp/utils/hailer-api-client.js +128 -2
- package/dist/mcp/webhook-handler.d.ts +87 -0
- package/dist/mcp/webhook-handler.js +343 -0
- package/dist/mcp/workspace-cache.d.ts +5 -0
- package/dist/mcp/workspace-cache.js +11 -0
- package/dist/mcp-server.js +55 -5
- package/dist/modules/bug-reports/giuseppe-agent.d.ts +58 -0
- package/dist/modules/bug-reports/giuseppe-agent.js +467 -0
- package/dist/modules/bug-reports/giuseppe-ai.d.ts +25 -1
- package/dist/modules/bug-reports/giuseppe-ai.js +133 -2
- package/dist/modules/bug-reports/giuseppe-bot.d.ts +3 -2
- package/dist/modules/bug-reports/giuseppe-bot.js +75 -36
- package/dist/modules/bug-reports/giuseppe-daemon.d.ts +80 -0
- package/dist/modules/bug-reports/giuseppe-daemon.js +617 -0
- package/dist/modules/bug-reports/giuseppe-files.d.ts +12 -0
- package/dist/modules/bug-reports/giuseppe-files.js +37 -0
- package/dist/modules/bug-reports/giuseppe-lsp.d.ts +113 -0
- package/dist/modules/bug-reports/giuseppe-lsp.js +485 -0
- package/dist/modules/bug-reports/index.d.ts +1 -0
- package/dist/modules/bug-reports/index.js +31 -29
- 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
|