@hailer/mcp 0.1.15 → 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 +2 -2
  103. package/dist/modules/bug-reports/giuseppe-bot.js +66 -42
  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 +84 -13
  109. package/dist/modules/bug-reports/giuseppe-lsp.js +403 -61
  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 +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
- fetchInit(): Promise<any>;
145
+ getWorkflow(workflowId: string): Promise<any>;
105
146
  /**
106
147
  * Global search across workspace - uses Socket API
107
148
  */