@hailer/mcp 0.1.15 → 0.1.17
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 +345 -0
- package/dist/mcp/workspace-cache.d.ts +5 -0
- package/dist/mcp/workspace-cache.js +11 -0
- package/dist/mcp-server.js +60 -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 +2 -2
- package/dist/modules/bug-reports/giuseppe-bot.js +66 -42
- 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 +84 -13
- package/dist/modules/bug-reports/giuseppe-lsp.js +403 -61
- package/dist/modules/bug-reports/index.d.ts +1 -0
- package/dist/modules/bug-reports/index.js +31 -29
- package/package.json +3 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Giuseppe MCP Tools
|
|
3
|
+
*
|
|
4
|
+
* Bug-fixing tools for Giuseppe specialist daemon.
|
|
5
|
+
* These tools handle file operations, git, and build commands.
|
|
6
|
+
*/
|
|
7
|
+
import { Tool } from "../tool-registry";
|
|
8
|
+
export declare const giuseppeFindAppTool: Tool;
|
|
9
|
+
export declare const giuseppeListFilesTool: Tool;
|
|
10
|
+
export declare const giuseppeReadFileTool: Tool;
|
|
11
|
+
export declare const giuseppeWriteFileTool: Tool;
|
|
12
|
+
export declare const giuseppeApplyFixTool: Tool;
|
|
13
|
+
export declare const giuseppeRunBuildTool: Tool;
|
|
14
|
+
export declare const giuseppeGitStatusTool: Tool;
|
|
15
|
+
export declare const giuseppeGitPullTool: Tool;
|
|
16
|
+
export declare const giuseppeGitCommitTool: Tool;
|
|
17
|
+
export declare const giuseppeGitPushTool: Tool;
|
|
18
|
+
export declare const giuseppeGitRevertTool: Tool;
|
|
19
|
+
export declare const giuseppePublishAppTool: Tool;
|
|
20
|
+
export declare const giuseppeTools: Tool[];
|
|
21
|
+
//# sourceMappingURL=giuseppe-tools.d.ts.map
|
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Giuseppe MCP Tools
|
|
4
|
+
*
|
|
5
|
+
* Bug-fixing tools for Giuseppe specialist daemon.
|
|
6
|
+
* These tools handle file operations, git, and build commands.
|
|
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.giuseppeTools = exports.giuseppePublishAppTool = exports.giuseppeGitRevertTool = exports.giuseppeGitPushTool = exports.giuseppeGitCommitTool = exports.giuseppeGitPullTool = exports.giuseppeGitStatusTool = exports.giuseppeRunBuildTool = exports.giuseppeApplyFixTool = exports.giuseppeWriteFileTool = exports.giuseppeReadFileTool = exports.giuseppeListFilesTool = exports.giuseppeFindAppTool = void 0;
|
|
43
|
+
const zod_1 = require("zod");
|
|
44
|
+
const child_process_1 = require("child_process");
|
|
45
|
+
const fs = __importStar(require("fs/promises"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const tool_registry_1 = require("../tool-registry");
|
|
48
|
+
const logger_1 = require("../../lib/logger");
|
|
49
|
+
const config_1 = require("../../config");
|
|
50
|
+
const logger = (0, logger_1.createLogger)({ component: "giuseppe-tools" });
|
|
51
|
+
const appsBasePath = config_1.environment.DEV_APPS_PATH || process.cwd();
|
|
52
|
+
// Helper to scan for apps
|
|
53
|
+
async function scanApps() {
|
|
54
|
+
const apps = [];
|
|
55
|
+
try {
|
|
56
|
+
const entries = await fs.readdir(appsBasePath, { withFileTypes: true });
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
if (entry.isDirectory() && !entry.name.startsWith(".") && !["node_modules", "dist"].includes(entry.name)) {
|
|
59
|
+
const appPath = path.join(appsBasePath, entry.name);
|
|
60
|
+
// Check for manifest.json (Hailer app indicator)
|
|
61
|
+
try {
|
|
62
|
+
await fs.access(path.join(appPath, "manifest.json"));
|
|
63
|
+
apps.push({ name: entry.name, path: appPath });
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
try {
|
|
67
|
+
await fs.access(path.join(appPath, "public", "manifest.json"));
|
|
68
|
+
apps.push({ name: entry.name, path: appPath });
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Not a Hailer app
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
logger.warn("Failed to scan apps", { error: e });
|
|
79
|
+
}
|
|
80
|
+
return apps;
|
|
81
|
+
}
|
|
82
|
+
// Find App Tool
|
|
83
|
+
exports.giuseppeFindAppTool = {
|
|
84
|
+
name: "giuseppe_find_app",
|
|
85
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
86
|
+
description: "Find a Hailer app project by name or from bug title",
|
|
87
|
+
schema: zod_1.z.object({
|
|
88
|
+
searchTerm: zod_1.z.string().describe("App name or bug title to search for").optional(),
|
|
89
|
+
name: zod_1.z.string().describe("Alias for searchTerm - app name to search for").optional()
|
|
90
|
+
}).refine(data => data.searchTerm || data.name, {
|
|
91
|
+
message: "Either searchTerm or name is required"
|
|
92
|
+
}),
|
|
93
|
+
async execute(args, _context) {
|
|
94
|
+
// Accept either searchTerm or name
|
|
95
|
+
const searchTerm = (args.searchTerm || args.name || '').toLowerCase();
|
|
96
|
+
const apps = await scanApps();
|
|
97
|
+
for (const app of apps) {
|
|
98
|
+
if (app.name.toLowerCase().includes(searchTerm) ||
|
|
99
|
+
searchTerm.includes(app.name.toLowerCase())) {
|
|
100
|
+
return {
|
|
101
|
+
content: [{ type: "text", text: JSON.stringify({ found: true, name: app.name, path: app.path }) }]
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
content: [{ type: "text", text: JSON.stringify({ found: false, availableApps: apps.map(a => a.name) }) }]
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
// List Files Tool
|
|
111
|
+
exports.giuseppeListFilesTool = {
|
|
112
|
+
name: "giuseppe_list_files",
|
|
113
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
114
|
+
description: "List source files in a Hailer app project",
|
|
115
|
+
schema: zod_1.z.object({
|
|
116
|
+
appPath: zod_1.z.string().describe("Path to the app project")
|
|
117
|
+
}),
|
|
118
|
+
async execute(args, _context) {
|
|
119
|
+
const files = [];
|
|
120
|
+
const extensions = [".tsx", ".ts", ".jsx", ".js"];
|
|
121
|
+
const ignoreDirs = ["node_modules", "dist", "build", ".git"];
|
|
122
|
+
const scan = async (dir, depth = 0) => {
|
|
123
|
+
if (depth > 5)
|
|
124
|
+
return;
|
|
125
|
+
try {
|
|
126
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
127
|
+
for (const entry of entries) {
|
|
128
|
+
const fullPath = path.join(dir, entry.name);
|
|
129
|
+
const relativePath = path.relative(args.appPath, fullPath);
|
|
130
|
+
if (entry.isDirectory()) {
|
|
131
|
+
if (!ignoreDirs.includes(entry.name) && !entry.name.startsWith(".")) {
|
|
132
|
+
await scan(fullPath, depth + 1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else if (extensions.some(ext => entry.name.endsWith(ext))) {
|
|
136
|
+
if (!entry.name.includes(".test.") && !entry.name.includes(".spec.")) {
|
|
137
|
+
files.push(relativePath);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch { /* skip */ }
|
|
143
|
+
};
|
|
144
|
+
await scan(args.appPath);
|
|
145
|
+
return {
|
|
146
|
+
content: [{ type: "text", text: JSON.stringify({ files: files.slice(0, 50), total: files.length }) }]
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
// Read File Tool
|
|
151
|
+
exports.giuseppeReadFileTool = {
|
|
152
|
+
name: "giuseppe_read_file",
|
|
153
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
154
|
+
description: "Read a source file from the app",
|
|
155
|
+
schema: zod_1.z.object({
|
|
156
|
+
appPath: zod_1.z.string().describe("Path to the app project"),
|
|
157
|
+
filePath: zod_1.z.string().describe("Relative path to the file")
|
|
158
|
+
}),
|
|
159
|
+
async execute(args, _context) {
|
|
160
|
+
try {
|
|
161
|
+
const fullPath = path.join(args.appPath, args.filePath);
|
|
162
|
+
const content = await fs.readFile(fullPath, "utf-8");
|
|
163
|
+
return {
|
|
164
|
+
content: [{ type: "text", text: JSON.stringify({ content }) }]
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
return {
|
|
169
|
+
content: [{ type: "text", text: JSON.stringify({ error: e.message }) }]
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
// Write File Tool
|
|
175
|
+
exports.giuseppeWriteFileTool = {
|
|
176
|
+
name: "giuseppe_write_file",
|
|
177
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
178
|
+
description: "Write/update a source file in the app",
|
|
179
|
+
schema: zod_1.z.object({
|
|
180
|
+
appPath: zod_1.z.string().describe("Path to the app project"),
|
|
181
|
+
filePath: zod_1.z.string().describe("Relative path to the file"),
|
|
182
|
+
content: zod_1.z.string().describe("New file content")
|
|
183
|
+
}),
|
|
184
|
+
async execute(args, _context) {
|
|
185
|
+
try {
|
|
186
|
+
const fullPath = path.join(args.appPath, args.filePath);
|
|
187
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
188
|
+
await fs.writeFile(fullPath, args.content, "utf-8");
|
|
189
|
+
logger.info("Giuseppe wrote file", { filePath: args.filePath });
|
|
190
|
+
return {
|
|
191
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, path: args.filePath }) }]
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
return {
|
|
196
|
+
content: [{ type: "text", text: JSON.stringify({ error: e.message }) }]
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
// Apply Fix Tool (search/replace pattern - calls existing bot logic)
|
|
202
|
+
const fixFileSchema = zod_1.z.object({
|
|
203
|
+
path: zod_1.z.string().describe("Relative file path (e.g., 'src/App.tsx')"),
|
|
204
|
+
action: zod_1.z.enum(["edit", "create", "delete"]).describe("Action: edit (search/replace), create (new file), delete"),
|
|
205
|
+
search: zod_1.z.string().optional().describe("For 'edit': the exact code snippet to find"),
|
|
206
|
+
replace: zod_1.z.string().optional().describe("For 'edit': the code to replace it with"),
|
|
207
|
+
content: zod_1.z.string().optional().describe("For 'create': the full file content")
|
|
208
|
+
});
|
|
209
|
+
exports.giuseppeApplyFixTool = {
|
|
210
|
+
name: "giuseppe_apply_fix",
|
|
211
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
212
|
+
description: `Apply code fixes using search/replace pattern. More token-efficient than rewriting entire files.
|
|
213
|
+
|
|
214
|
+
**For 'edit' action:** Provide search (code to find) and replace (code to replace with).
|
|
215
|
+
**For 'create' action:** Provide content (full file content).
|
|
216
|
+
**For 'delete' action:** Just provide path.
|
|
217
|
+
|
|
218
|
+
Example:
|
|
219
|
+
\`\`\`json
|
|
220
|
+
{
|
|
221
|
+
"appPath": "lineup-manager",
|
|
222
|
+
"fixes": [{
|
|
223
|
+
"path": "src/App.tsx",
|
|
224
|
+
"action": "edit",
|
|
225
|
+
"search": "const handleDragEnd = () => {\\n // old code\\n}",
|
|
226
|
+
"replace": "const handleDragEnd = () => {\\n // fixed code\\n}"
|
|
227
|
+
}]
|
|
228
|
+
}
|
|
229
|
+
\`\`\``,
|
|
230
|
+
schema: zod_1.z.object({
|
|
231
|
+
appPath: zod_1.z.string().describe("App folder name or path (e.g., 'lineup-manager')"),
|
|
232
|
+
fixes: zod_1.z.array(fixFileSchema).describe("Array of file operations to apply")
|
|
233
|
+
}),
|
|
234
|
+
async execute(args, _context) {
|
|
235
|
+
try {
|
|
236
|
+
// Resolve app path
|
|
237
|
+
let appFullPath = args.appPath;
|
|
238
|
+
if (!path.isAbsolute(args.appPath)) {
|
|
239
|
+
appFullPath = path.join(appsBasePath, args.appPath);
|
|
240
|
+
}
|
|
241
|
+
// Check app exists
|
|
242
|
+
try {
|
|
243
|
+
await fs.access(appFullPath);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return {
|
|
247
|
+
content: [{ type: "text", text: JSON.stringify({
|
|
248
|
+
success: false,
|
|
249
|
+
error: `App not found at: ${appFullPath}`
|
|
250
|
+
}) }]
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
const modifiedFiles = [];
|
|
254
|
+
const errors = [];
|
|
255
|
+
for (const fix of args.fixes) {
|
|
256
|
+
const filePath = path.join(appFullPath, fix.path);
|
|
257
|
+
try {
|
|
258
|
+
if (fix.action === 'edit' && fix.search && fix.replace !== undefined) {
|
|
259
|
+
// Read file
|
|
260
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
261
|
+
// Try exact match first
|
|
262
|
+
if (content.includes(fix.search)) {
|
|
263
|
+
const newContent = content.replace(fix.search, fix.replace);
|
|
264
|
+
await fs.writeFile(filePath, newContent, 'utf-8');
|
|
265
|
+
modifiedFiles.push(fix.path);
|
|
266
|
+
logger.info("Giuseppe applied fix (exact match)", { path: fix.path });
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// Try normalized whitespace match
|
|
270
|
+
const normalizeWs = (s) => s.replace(/\s+/g, ' ').trim();
|
|
271
|
+
const normalizedContent = normalizeWs(content);
|
|
272
|
+
const normalizedSearch = normalizeWs(fix.search);
|
|
273
|
+
if (normalizedContent.includes(normalizedSearch)) {
|
|
274
|
+
// Line-by-line search
|
|
275
|
+
const searchLines = fix.search.split('\n').map((l) => l.trim()).filter((l) => l);
|
|
276
|
+
const contentLines = content.split('\n');
|
|
277
|
+
let found = false;
|
|
278
|
+
for (let i = 0; i <= contentLines.length - searchLines.length; i++) {
|
|
279
|
+
const candidateLines = contentLines.slice(i, i + searchLines.length);
|
|
280
|
+
if (candidateLines.every((line, j) => line.trim() === searchLines[j])) {
|
|
281
|
+
const before = contentLines.slice(0, i);
|
|
282
|
+
const after = contentLines.slice(i + searchLines.length);
|
|
283
|
+
const replaceLines = fix.replace.split('\n');
|
|
284
|
+
const newContent = [...before, ...replaceLines, ...after].join('\n');
|
|
285
|
+
await fs.writeFile(filePath, newContent, 'utf-8');
|
|
286
|
+
modifiedFiles.push(fix.path);
|
|
287
|
+
found = true;
|
|
288
|
+
logger.info("Giuseppe applied fix (normalized match)", { path: fix.path });
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (!found) {
|
|
293
|
+
errors.push(`${fix.path}: Search string not found (whitespace mismatch)`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
errors.push(`${fix.path}: Search string not found`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else if (fix.action === 'create' && fix.content) {
|
|
302
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
303
|
+
await fs.writeFile(filePath, fix.content, 'utf-8');
|
|
304
|
+
modifiedFiles.push(fix.path);
|
|
305
|
+
logger.info("Giuseppe created file", { path: fix.path });
|
|
306
|
+
}
|
|
307
|
+
else if (fix.action === 'delete') {
|
|
308
|
+
await fs.unlink(filePath);
|
|
309
|
+
modifiedFiles.push(fix.path);
|
|
310
|
+
logger.info("Giuseppe deleted file", { path: fix.path });
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
errors.push(`${fix.path}: Invalid action or missing required fields`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch (e) {
|
|
317
|
+
errors.push(`${fix.path}: ${e.message}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (errors.length > 0) {
|
|
321
|
+
return {
|
|
322
|
+
content: [{ type: "text", text: JSON.stringify({
|
|
323
|
+
success: false,
|
|
324
|
+
modifiedFiles,
|
|
325
|
+
errors,
|
|
326
|
+
hint: "Check that 'search' exactly matches the code in the file (including whitespace)"
|
|
327
|
+
}) }]
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
content: [{ type: "text", text: JSON.stringify({
|
|
332
|
+
success: true,
|
|
333
|
+
modifiedFiles,
|
|
334
|
+
message: `Applied ${modifiedFiles.length} fix(es). Run giuseppe_run_build to verify.`
|
|
335
|
+
}) }]
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
catch (e) {
|
|
339
|
+
return {
|
|
340
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: e.message }) }]
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
// Run Build Tool
|
|
346
|
+
exports.giuseppeRunBuildTool = {
|
|
347
|
+
name: "giuseppe_run_build",
|
|
348
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
349
|
+
description: "Run TypeScript build to check for errors",
|
|
350
|
+
schema: zod_1.z.object({
|
|
351
|
+
appPath: zod_1.z.string().describe("Path to the app project")
|
|
352
|
+
}),
|
|
353
|
+
async execute(args, _context) {
|
|
354
|
+
try {
|
|
355
|
+
const output = (0, child_process_1.execSync)("npm run build 2>&1", { cwd: args.appPath, encoding: "utf-8", timeout: 60000 });
|
|
356
|
+
return {
|
|
357
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, output: output.slice(-2000) }) }]
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
catch (e) {
|
|
361
|
+
return {
|
|
362
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: (e.stdout || e.stderr || e.message).slice(-2000) }) }]
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
// Git Status Tool
|
|
368
|
+
exports.giuseppeGitStatusTool = {
|
|
369
|
+
name: "giuseppe_git_status",
|
|
370
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
371
|
+
description: "Check git status - branch, changes, sync with remote",
|
|
372
|
+
schema: zod_1.z.object({
|
|
373
|
+
appPath: zod_1.z.string().describe("Path to the app project")
|
|
374
|
+
}),
|
|
375
|
+
async execute(args, _context) {
|
|
376
|
+
try {
|
|
377
|
+
const status = (0, child_process_1.execSync)("git status --short", { cwd: args.appPath, encoding: "utf-8" });
|
|
378
|
+
const branch = (0, child_process_1.execSync)("git branch --show-current", { cwd: args.appPath, encoding: "utf-8" }).trim();
|
|
379
|
+
let behind = 0, ahead = 0;
|
|
380
|
+
try {
|
|
381
|
+
const revList = (0, child_process_1.execSync)("git rev-list --left-right --count HEAD...@{upstream} 2>/dev/null", { cwd: args.appPath, encoding: "utf-8" }).trim().split(/\s+/);
|
|
382
|
+
ahead = parseInt(revList[0]) || 0;
|
|
383
|
+
behind = parseInt(revList[1]) || 0;
|
|
384
|
+
}
|
|
385
|
+
catch { /* no upstream */ }
|
|
386
|
+
return {
|
|
387
|
+
content: [{ type: "text", text: JSON.stringify({ branch, status: status || "clean", ahead, behind }) }]
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
catch (e) {
|
|
391
|
+
return {
|
|
392
|
+
content: [{ type: "text", text: JSON.stringify({ error: e.message }) }]
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
// Git Pull Tool
|
|
398
|
+
exports.giuseppeGitPullTool = {
|
|
399
|
+
name: "giuseppe_git_pull",
|
|
400
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
401
|
+
description: "Pull latest changes from remote",
|
|
402
|
+
schema: zod_1.z.object({
|
|
403
|
+
appPath: zod_1.z.string().describe("Path to the app project")
|
|
404
|
+
}),
|
|
405
|
+
async execute(args, _context) {
|
|
406
|
+
try {
|
|
407
|
+
const output = (0, child_process_1.execSync)("git pull", { cwd: args.appPath, encoding: "utf-8" });
|
|
408
|
+
return {
|
|
409
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, output }) }]
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
catch (e) {
|
|
413
|
+
return {
|
|
414
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: e.stderr || e.message }) }]
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
// Git Commit Tool
|
|
420
|
+
exports.giuseppeGitCommitTool = {
|
|
421
|
+
name: "giuseppe_git_commit",
|
|
422
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
423
|
+
description: "Stage all changes and commit",
|
|
424
|
+
schema: zod_1.z.object({
|
|
425
|
+
appPath: zod_1.z.string().describe("Path to the app project"),
|
|
426
|
+
message: zod_1.z.string().describe("Commit message")
|
|
427
|
+
}),
|
|
428
|
+
async execute(args, _context) {
|
|
429
|
+
try {
|
|
430
|
+
(0, child_process_1.execSync)("git add -A", { cwd: args.appPath });
|
|
431
|
+
(0, child_process_1.execSync)(`git commit -m "${args.message.replace(/"/g, '\\"')}"`, { cwd: args.appPath });
|
|
432
|
+
const hash = (0, child_process_1.execSync)("git rev-parse --short HEAD", { cwd: args.appPath, encoding: "utf-8" }).trim();
|
|
433
|
+
logger.info("Giuseppe committed", { hash, message: args.message });
|
|
434
|
+
return {
|
|
435
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, hash }) }]
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
catch (e) {
|
|
439
|
+
return {
|
|
440
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: e.stderr || e.stdout || e.message }) }]
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
// Git Push Tool
|
|
446
|
+
exports.giuseppeGitPushTool = {
|
|
447
|
+
name: "giuseppe_git_push",
|
|
448
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
449
|
+
description: "Push commits to remote",
|
|
450
|
+
schema: zod_1.z.object({
|
|
451
|
+
appPath: zod_1.z.string().describe("Path to the app project")
|
|
452
|
+
}),
|
|
453
|
+
async execute(args, _context) {
|
|
454
|
+
try {
|
|
455
|
+
(0, child_process_1.execSync)("git push", { cwd: args.appPath, encoding: "utf-8", stdio: "pipe" });
|
|
456
|
+
return {
|
|
457
|
+
content: [{ type: "text", text: JSON.stringify({ success: true }) }]
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
catch (e) {
|
|
461
|
+
return {
|
|
462
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: e.stderr || e.message }) }]
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
// Git Revert Tool
|
|
468
|
+
exports.giuseppeGitRevertTool = {
|
|
469
|
+
name: "giuseppe_git_revert",
|
|
470
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
471
|
+
description: "Discard all uncommitted changes",
|
|
472
|
+
schema: zod_1.z.object({
|
|
473
|
+
appPath: zod_1.z.string().describe("Path to the app project")
|
|
474
|
+
}),
|
|
475
|
+
async execute(args, _context) {
|
|
476
|
+
try {
|
|
477
|
+
(0, child_process_1.execSync)("git checkout -- .", { cwd: args.appPath });
|
|
478
|
+
return {
|
|
479
|
+
content: [{ type: "text", text: JSON.stringify({ success: true }) }]
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
catch (e) {
|
|
483
|
+
return {
|
|
484
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: e.message }) }]
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
// Publish App Tool
|
|
490
|
+
exports.giuseppePublishAppTool = {
|
|
491
|
+
name: "giuseppe_publish_app",
|
|
492
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
493
|
+
description: "Publish app to Hailer production - ALWAYS ASK USER FIRST",
|
|
494
|
+
schema: zod_1.z.object({
|
|
495
|
+
appPath: zod_1.z.string().describe("Path to the app project")
|
|
496
|
+
}),
|
|
497
|
+
async execute(args, context) {
|
|
498
|
+
try {
|
|
499
|
+
const { publishHailerAppTool } = await Promise.resolve().then(() => __importStar(require("./app-scaffold")));
|
|
500
|
+
const result = await publishHailerAppTool.execute({ projectDirectory: args.appPath }, context);
|
|
501
|
+
return result;
|
|
502
|
+
}
|
|
503
|
+
catch (e) {
|
|
504
|
+
return {
|
|
505
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: e.message }) }]
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
// Export all tools
|
|
511
|
+
exports.giuseppeTools = [
|
|
512
|
+
exports.giuseppeFindAppTool,
|
|
513
|
+
exports.giuseppeListFilesTool,
|
|
514
|
+
exports.giuseppeReadFileTool,
|
|
515
|
+
exports.giuseppeWriteFileTool,
|
|
516
|
+
exports.giuseppeApplyFixTool, // New: search/replace (preferred)
|
|
517
|
+
exports.giuseppeRunBuildTool,
|
|
518
|
+
exports.giuseppeGitStatusTool,
|
|
519
|
+
exports.giuseppeGitPullTool,
|
|
520
|
+
exports.giuseppeGitCommitTool,
|
|
521
|
+
exports.giuseppeGitPushTool,
|
|
522
|
+
exports.giuseppeGitRevertTool,
|
|
523
|
+
exports.giuseppePublishAppTool,
|
|
524
|
+
];
|
|
525
|
+
//# sourceMappingURL=giuseppe-tools.js.map
|
|
@@ -17,6 +17,10 @@ export declare class HailerApiClient {
|
|
|
17
17
|
private clients;
|
|
18
18
|
private logger;
|
|
19
19
|
constructor(clients: HailerClient);
|
|
20
|
+
/**
|
|
21
|
+
* Get the underlying HailerClient for direct access (e.g., SignalHandler)
|
|
22
|
+
*/
|
|
23
|
+
getClient(): HailerClient;
|
|
20
24
|
/**
|
|
21
25
|
* Makes a socket API call - thin wrapper around clients.socket.request
|
|
22
26
|
*/
|
|
@@ -40,6 +44,7 @@ export declare class HailerApiClient {
|
|
|
40
44
|
includeStats?: boolean;
|
|
41
45
|
returnFlat?: boolean;
|
|
42
46
|
filters?: any;
|
|
47
|
+
fields?: string[];
|
|
43
48
|
}): Promise<any>;
|
|
44
49
|
/**
|
|
45
50
|
* Create activities - uses Socket API
|
|
@@ -63,8 +68,15 @@ export declare class HailerApiClient {
|
|
|
63
68
|
fetchPreviousDiscussionMessages(oldestMessageId: string, batches?: number): Promise<any>;
|
|
64
69
|
/**
|
|
65
70
|
* Fetch activity by ID - uses Socket API
|
|
71
|
+
* WARNING: This uses activities.load which evaluates function fields and may fail
|
|
72
|
+
* For bot config, prefer fetchActivityByIdSafe()
|
|
66
73
|
*/
|
|
67
74
|
fetchActivityById(activityId: string): Promise<any>;
|
|
75
|
+
/**
|
|
76
|
+
* Fetch activity by ID safely using v3.activity.list API
|
|
77
|
+
* This doesn't evaluate function fields so it works even when function fields are broken
|
|
78
|
+
*/
|
|
79
|
+
fetchActivityByIdSafe(activityId: string, workflowId?: string, phaseId?: string): Promise<any>;
|
|
68
80
|
/**
|
|
69
81
|
* Send discussion message - uses Socket API
|
|
70
82
|
*/
|
|
@@ -100,8 +112,37 @@ export declare class HailerApiClient {
|
|
|
100
112
|
}>;
|
|
101
113
|
/**
|
|
102
114
|
* Fetch workspace initialization data - uses Socket API
|
|
115
|
+
* @param include - What to include: 'users', 'network', 'networks', 'teams', etc.
|
|
116
|
+
*/
|
|
117
|
+
fetchInit(include?: string[]): Promise<any>;
|
|
118
|
+
/**
|
|
119
|
+
* Update current user's profile info (firstname, lastname, etc.)
|
|
120
|
+
* Only works for the currently authenticated user
|
|
121
|
+
* @param key - Field to update: firstname, lastname, email, status, etc.
|
|
122
|
+
* @param value - New value as string
|
|
123
|
+
*/
|
|
124
|
+
setUserInfo(key: 'firstname' | 'lastname' | 'email' | 'status' | 'default_company' | 'lastLocation' | 'preferredLanguages', value: string): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Update current user's display name (firstname + lastname)
|
|
127
|
+
* Parses a full name into first/last parts
|
|
128
|
+
* @param fullName - Full display name like "HAL 9000"
|
|
129
|
+
*/
|
|
130
|
+
setUserDisplayName(fullName: string): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Find user by name - searches init data for firstname/lastname match
|
|
133
|
+
* @param name - Full name to search for (firstname lastname)
|
|
134
|
+
* @returns User ID if found, null otherwise
|
|
135
|
+
*/
|
|
136
|
+
findUserByName(name: string): Promise<string | null>;
|
|
137
|
+
/**
|
|
138
|
+
* List all workflows in the workspace - extracts from init data
|
|
139
|
+
* @param workspaceId - Optional workspace ID to filter workflows (uses CID field)
|
|
140
|
+
*/
|
|
141
|
+
listWorkflows(workspaceId?: string): Promise<any[]>;
|
|
142
|
+
/**
|
|
143
|
+
* Get workflow details including phases and fields
|
|
103
144
|
*/
|
|
104
|
-
|
|
145
|
+
getWorkflow(workflowId: string): Promise<any>;
|
|
105
146
|
/**
|
|
106
147
|
* Global search across workspace - uses Socket API
|
|
107
148
|
*/
|