@hailer/mcp 0.0.6 → 0.1.1
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/ada.md +127 -0
- package/.claude/agents/agent-builder.md +151 -0
- package/.claude/agents/alejandro.md +66 -0
- package/.claude/agents/bjorn.md +305 -0
- package/.claude/agents/dmitri.md +61 -0
- package/.claude/agents/giuseppe.md +66 -0
- package/.claude/agents/gunther.md +355 -0
- package/.claude/agents/helga.md +68 -0
- package/.claude/agents/ingrid.md +108 -0
- package/.claude/agents/kenji.md +58 -0
- package/.claude/agents/svetlana.md +394 -0
- package/.claude/agents/viktor.md +63 -0
- package/.claude/agents/yevgeni.md +60 -0
- package/.claude/hooks/agent-failure-detector.cjs +286 -0
- package/.claude/hooks/app-edit-guard.cjs +462 -0
- package/.claude/hooks/interactive-mode.cjs +59 -0
- package/.claude/hooks/mcp-server-guard.cjs +92 -0
- package/.claude/hooks/post-scaffold-hook.cjs +31 -0
- package/.claude/hooks/sdk-delete-guard.cjs +2 -0
- package/.claude/hooks/src-edit-guard.cjs +208 -0
- package/.claude/settings.json +47 -2
- package/.claude/skills/insight-join-patterns/SKILL.md +209 -0
- package/.env.example +13 -1
- package/CLAUDE.md +135 -0
- package/dist/app.js +4 -3
- package/dist/cli.js +0 -0
- package/dist/client/adaptive-documentation-bot.d.ts +0 -2
- package/dist/client/adaptive-documentation-bot.js +5 -16
- package/dist/client/message-processor.js +5 -0
- package/dist/client/providers/anthropic-provider.js +21 -7
- package/dist/mcp/UserContextCache.d.ts +14 -0
- package/dist/mcp/UserContextCache.js +49 -24
- package/dist/mcp/auth.d.ts +7 -0
- package/dist/mcp/auth.js +13 -5
- package/dist/mcp/hailer-clients.d.ts +5 -2
- package/dist/mcp/signal-handler.d.ts +28 -2
- package/dist/mcp/signal-handler.js +4 -2
- package/dist/mcp/tool-registry.d.ts +55 -2
- package/dist/mcp/tool-registry.js +197 -2
- package/dist/mcp/tools/app-core.d.ts +15 -0
- package/dist/mcp/tools/app-core.js +609 -0
- package/dist/mcp/tools/app-marketplace.d.ts +21 -0
- package/dist/mcp/tools/app-marketplace.js +1284 -0
- package/dist/mcp/tools/app-member.d.ts +11 -0
- package/dist/mcp/tools/app-member.js +258 -0
- package/dist/mcp/tools/app-scaffold.d.ts +11 -0
- package/dist/mcp/tools/app-scaffold.js +743 -0
- package/dist/mcp/tools/app.d.ts +13 -22
- package/dist/mcp/tools/app.js +17 -2466
- package/dist/mcp/tools/file.js +6 -6
- package/dist/mcp/tools/insight.d.ts +1 -0
- package/dist/mcp/tools/insight.js +203 -64
- package/dist/mcp/tools/user.js +3 -9
- package/dist/mcp/tools/workflow.js +49 -38
- package/dist/mcp/utils/hailer-api-client.js +4 -13
- package/dist/mcp/utils/tool-helpers.d.ts +102 -0
- package/dist/mcp/utils/tool-helpers.js +179 -0
- package/dist/mcp/utils/types.d.ts +6 -0
- package/dist/mcp/workspace-cache.d.ts +5 -5
- package/dist/mcp/workspace-cache.js +4 -3
- package/package.json +1 -1
- package/.claude/hooks/PreToolUse.sh +0 -52
- package/.claude/hooks/prompt-skill-loader.cjs +0 -553
- package/.claude/hooks/skill-loader.cjs +0 -142
- package/.claude/settings.local.json +0 -49
- package/.claude/skills/MCP-add-app-member-skill/SKILL.md +0 -977
- package/.claude/skills/MCP-build-data-app-skill/SKILL.md +0 -372
- package/.claude/skills/MCP-create-app-skill/SKILL.md +0 -1101
- package/.claude/skills/MCP-create-insight-skill/SKILL.md +0 -1317
- package/.claude/skills/MCP-get-insight-data-skill/SKILL.md +0 -1053
- package/.claude/skills/MCP-insight-api/SKILL.md +0 -185
- package/.claude/skills/MCP-insight-api/references/insight-endpoints.md +0 -514
- package/.claude/skills/MCP-install-workflow-skill/SKILL.md +0 -1056
- package/.claude/skills/MCP-list-apps-skill/SKILL.md +0 -1010
- package/.claude/skills/MCP-list-workflows-minimal-skill/SKILL.md +0 -992
- package/.claude/skills/MCP-local-first-skill/SKILL.md +0 -570
- package/.claude/skills/MCP-populate-workflow-data-skill/SKILL.md +0 -395
- package/.claude/skills/MCP-preview-insight-skill/SKILL.md +0 -1290
- package/.claude/skills/MCP-publish-hailer-app-skill/SKILL.md +0 -453
- package/.claude/skills/MCP-publish-template-skill/SKILL.md +0 -278
- package/.claude/skills/MCP-remove-app-member-skill/SKILL.md +0 -671
- package/.claude/skills/MCP-remove-app-skill/SKILL.md +0 -985
- package/.claude/skills/MCP-remove-insight-skill/SKILL.md +0 -1011
- package/.claude/skills/MCP-remove-workflow-skill/SKILL.md +0 -920
- package/.claude/skills/MCP-scaffold-hailer-app-skill/SKILL.md +0 -1314
- package/.claude/skills/MCP-update-app-skill/SKILL.md +0 -970
- package/.claude/skills/MCP-update-workflow-field-skill/SKILL.md +0 -1098
- package/.claude/skills/SDK-create-function-field-skill/SKILL.md +0 -313
- package/.claude/skills/SDK-generate-skill/SKILL.md +0 -223
- package/.claude/skills/SDK-init-skill/SKILL.md +0 -177
- package/.claude/skills/SDK-workspace-setup-skill/SKILL.md +0 -605
- package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -435
- package/.claude/skills/activity-api/SKILL.md +0 -96
- package/.claude/skills/activity-api/references/activity-endpoints.md +0 -845
- package/.claude/skills/agent-building/SKILL.md +0 -243
- package/.claude/skills/agent-building/references/architecture-patterns.md +0 -446
- package/.claude/skills/agent-building/references/code-examples.md +0 -587
- package/.claude/skills/agent-building/references/implementation-guide.md +0 -619
- package/.claude/skills/app-api/SKILL.md +0 -219
- package/.claude/skills/app-api/references/app-endpoints.md +0 -759
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +0 -813
- package/.claude/skills/hailer-api/SKILL.md +0 -283
- package/.claude/skills/hailer-api/references/activities.md +0 -620
- package/.claude/skills/hailer-api/references/authentication.md +0 -216
- package/.claude/skills/hailer-api/references/datasets.md +0 -437
- package/.claude/skills/hailer-api/references/files.md +0 -301
- package/.claude/skills/hailer-api/references/insights.md +0 -469
- package/.claude/skills/hailer-api/references/workflows.md +0 -720
- package/.claude/skills/hailer-api/references/workspaces-users.md +0 -445
- package/.claude/skills/hailer-app-builder/SKILL.md +0 -340
- package/.claude/skills/mcp-tools/SKILL.md +0 -419
- package/.claude/skills/mcp-tools/references/api-endpoints.md +0 -499
- package/.claude/skills/mcp-tools/references/data-structures.md +0 -554
- package/.claude/skills/mcp-tools/references/implementation-patterns.md +0 -717
- package/.claude/skills/skill-testing/README.md +0 -137
- package/.claude/skills/skill-testing/SKILL.md +0 -348
- package/.claude/skills/skill-testing/references/test-patterns.md +0 -705
- package/.claude/skills/skill-testing/references/testing-guide.md +0 -603
- package/.claude/skills/skill-testing/references/validation-checklist.md +0 -537
- package/.claude/skills/spawn-app-builder/SKILL.md +0 -366
- package/.claude/skills/tool-builder/SKILL.md +0 -328
- package/tsconfig.json +0 -23
package/dist/mcp/tools/app.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* App Tools -
|
|
3
|
+
* App Tools - Re-exports
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* - Apps extend workspace functionality
|
|
7
|
-
* - Development apps (localhost URLs)
|
|
8
|
-
* - Published apps (auto-generated URLs)
|
|
5
|
+
* This file re-exports all app tools from the split modules for backwards compatibility.
|
|
9
6
|
*
|
|
10
|
-
*
|
|
7
|
+
* Tool Distribution:
|
|
8
|
+
* - app-core.ts: Create, List, Update, Remove apps (4 tools)
|
|
9
|
+
* - app-member.ts: Add/Remove app members (2 tools)
|
|
10
|
+
* - app-scaffold.ts: Scaffold apps, Publish builds (2 tools)
|
|
11
|
+
* - app-marketplace.ts: Templates & marketplace (9 tools)
|
|
12
|
+
*
|
|
13
|
+
* Total: 17 app management tools
|
|
11
14
|
*/
|
|
12
15
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
16
|
if (k2 === undefined) k2 = k;
|
|
@@ -20,2465 +23,13 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
20
23
|
if (k2 === undefined) k2 = k;
|
|
21
24
|
o[k2] = m[k];
|
|
22
25
|
}));
|
|
23
|
-
var
|
|
24
|
-
|
|
25
|
-
}) : function(o, v) {
|
|
26
|
-
o["default"] = v;
|
|
27
|
-
});
|
|
28
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
-
var ownKeys = function(o) {
|
|
30
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
-
var ar = [];
|
|
32
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
-
return ar;
|
|
34
|
-
};
|
|
35
|
-
return ownKeys(o);
|
|
36
|
-
};
|
|
37
|
-
return function (mod) {
|
|
38
|
-
if (mod && mod.__esModule) return mod;
|
|
39
|
-
var result = {};
|
|
40
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
-
__setModuleDefault(result, mod);
|
|
42
|
-
return result;
|
|
43
|
-
};
|
|
44
|
-
})();
|
|
45
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.getProductManifestTool = exports.getProductTool = exports.publishTemplateTool = exports.getTemplateTool = exports.installTemplateTool = exports.createTemplateTool = exports.listTemplatesTool = exports.publishHailerAppTool = exports.scaffoldHailerAppTool = exports.removeAppMemberTool = exports.addAppMemberTool = exports.removeAppTool = exports.updateAppTool = exports.listAppsTool = exports.createAppTool = void 0;
|
|
47
|
-
const zod_1 = require("zod");
|
|
48
|
-
const tool_registry_1 = require("../tool-registry");
|
|
49
|
-
const workspace_cache_1 = require("../workspace-cache");
|
|
50
|
-
const logger_1 = require("../../lib/logger");
|
|
51
|
-
const config_1 = require("../../config");
|
|
52
|
-
const logger = (0, logger_1.createLogger)({ component: 'app-tools' });
|
|
53
|
-
// ============================================================================
|
|
54
|
-
// CREATE APP TOOL
|
|
55
|
-
// ============================================================================
|
|
56
|
-
const createAppDescription = `🧪 [PLAYGROUND] Create App - Create Hailer app entry in workspace
|
|
57
|
-
|
|
58
|
-
**What are Apps?**
|
|
59
|
-
Apps are custom web applications that extend Hailer workspace functionality. Think React/vanilla JS apps running within Hailer.
|
|
60
|
-
|
|
61
|
-
**App Types**:
|
|
62
|
-
- **Development Apps**: URL points to localhost (e.g., http://localhost:3000)
|
|
63
|
-
- **Published Apps**: URL empty or points to production
|
|
64
|
-
|
|
65
|
-
**Example 1 - Development App**:
|
|
66
|
-
\`\`\`javascript
|
|
67
|
-
create_app({
|
|
68
|
-
name: 'Local Development',
|
|
69
|
-
description: 'App pointing to local server',
|
|
70
|
-
url: 'http://localhost:3000'
|
|
71
|
-
})
|
|
72
|
-
\`\`\`
|
|
73
|
-
|
|
74
|
-
**Example 2 - Published App**:
|
|
75
|
-
\`\`\`javascript
|
|
76
|
-
create_app({
|
|
77
|
-
name: 'Task Manager',
|
|
78
|
-
description: 'Production task management app',
|
|
79
|
-
url: '' // Empty for auto URL
|
|
80
|
-
})
|
|
81
|
-
\`\`\`
|
|
82
|
-
|
|
83
|
-
**Properties**:
|
|
84
|
-
- \`name\` (required) - App display name
|
|
85
|
-
- \`description\` (optional) - App description
|
|
86
|
-
- \`url\` (optional) - App URL or empty for auto-generated
|
|
87
|
-
- \`image\` (optional) - Image/icon ID
|
|
88
|
-
|
|
89
|
-
**Requirements**:
|
|
90
|
-
- User must be workspace administrator
|
|
91
|
-
- For published apps, leave URL empty
|
|
92
|
-
|
|
93
|
-
**Tips**:
|
|
94
|
-
- Use development apps for local testing
|
|
95
|
-
- Published apps get automatic URLs from Hailer
|
|
96
|
-
- Use \`add_app_member\` to share with others`;
|
|
97
|
-
exports.createAppTool = {
|
|
98
|
-
name: 'create_app',
|
|
99
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
100
|
-
description: createAppDescription,
|
|
101
|
-
schema: zod_1.z.object({
|
|
102
|
-
workspaceId: zod_1.z
|
|
103
|
-
.string()
|
|
104
|
-
.optional()
|
|
105
|
-
.describe("Optional workspace ID - defaults to current workspace"),
|
|
106
|
-
name: zod_1.z
|
|
107
|
-
.string()
|
|
108
|
-
.min(1)
|
|
109
|
-
.describe("App name (required)"),
|
|
110
|
-
description: zod_1.z
|
|
111
|
-
.string()
|
|
112
|
-
.optional()
|
|
113
|
-
.describe("App description"),
|
|
114
|
-
url: zod_1.z
|
|
115
|
-
.string()
|
|
116
|
-
.optional()
|
|
117
|
-
.describe("App URL (empty for published apps, localhost for dev)"),
|
|
118
|
-
image: zod_1.z
|
|
119
|
-
.string()
|
|
120
|
-
.optional()
|
|
121
|
-
.describe("Image/icon ID (24 characters)"),
|
|
122
|
-
config: zod_1.z
|
|
123
|
-
.record(zod_1.z.unknown())
|
|
124
|
-
.optional()
|
|
125
|
-
.describe("Optional app configuration"),
|
|
126
|
-
}),
|
|
127
|
-
async execute(args, context) {
|
|
128
|
-
logger.debug('Creating app', {
|
|
129
|
-
name: args.name,
|
|
130
|
-
workspaceId: args.workspaceId,
|
|
131
|
-
hasUrl: !!args.url,
|
|
132
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
133
|
-
});
|
|
134
|
-
try {
|
|
135
|
-
if (!context.workspaceCache) {
|
|
136
|
-
return {
|
|
137
|
-
content: [{
|
|
138
|
-
type: "text",
|
|
139
|
-
text: "❌ Workspace cache not available",
|
|
140
|
-
}],
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
const workspaceId = args.workspaceId
|
|
144
|
-
? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
|
|
145
|
-
: context.workspaceCache.currentWorkspace._id;
|
|
146
|
-
if (!workspaceId) {
|
|
147
|
-
return {
|
|
148
|
-
content: [{
|
|
149
|
-
type: "text",
|
|
150
|
-
text: `❌ Could not resolve workspace: ${args.workspaceId}`,
|
|
151
|
-
}],
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
logger.debug('Calling v3.app.create', {
|
|
155
|
-
workspaceId,
|
|
156
|
-
name: args.name
|
|
157
|
-
});
|
|
158
|
-
const appData = {
|
|
159
|
-
cid: workspaceId,
|
|
160
|
-
name: args.name
|
|
161
|
-
};
|
|
162
|
-
if (args.description)
|
|
163
|
-
appData.description = args.description;
|
|
164
|
-
if (args.url !== undefined)
|
|
165
|
-
appData.url = args.url;
|
|
166
|
-
if (args.image)
|
|
167
|
-
appData.image = args.image;
|
|
168
|
-
if (args.config)
|
|
169
|
-
appData.config = args.config;
|
|
170
|
-
const result = await context.hailer.request('v3.app.create', [appData]);
|
|
171
|
-
logger.debug('App creation successful', {
|
|
172
|
-
appId: result.appId || result._id
|
|
173
|
-
});
|
|
174
|
-
const appId = result.appId || result._id;
|
|
175
|
-
let responseText = `✅ **App Created Successfully**\n\n`;
|
|
176
|
-
responseText += `**App Name:** ${args.name}\n`;
|
|
177
|
-
responseText += `**App ID:** \`${appId}\`\n`;
|
|
178
|
-
responseText += `**Workspace:** ${workspaceId}\n`;
|
|
179
|
-
if (args.description) {
|
|
180
|
-
responseText += `**Description:** ${args.description}\n`;
|
|
181
|
-
}
|
|
182
|
-
if (args.url) {
|
|
183
|
-
responseText += `**URL:** ${args.url}\n`;
|
|
184
|
-
responseText += `**Type:** Development App (points to ${args.url})\n`;
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
responseText += `**URL:** Auto-generated by Hailer\n`;
|
|
188
|
-
responseText += `**Type:** Published App\n`;
|
|
189
|
-
}
|
|
190
|
-
responseText += `\n💡 **Next Steps:**\n`;
|
|
191
|
-
responseText += `- Use \`list_apps\` to see all apps\n`;
|
|
192
|
-
responseText += `- Use \`add_app_member\` to share with users/teams\n`;
|
|
193
|
-
responseText += `- Use \`update_app\` to modify properties\n`;
|
|
194
|
-
if (!args.url) {
|
|
195
|
-
responseText += `\n📦 **Publishing:**\n`;
|
|
196
|
-
responseText += `1. Configure manifest.json with this appId: \`${appId}\`\n`;
|
|
197
|
-
responseText += `2. Run: \`EMAIL=your@email.com npm run publish-production\`\n`;
|
|
198
|
-
}
|
|
199
|
-
return {
|
|
200
|
-
content: [{
|
|
201
|
-
type: "text",
|
|
202
|
-
text: responseText,
|
|
203
|
-
}],
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
catch (error) {
|
|
207
|
-
logger.error("Error creating app", error);
|
|
208
|
-
let errorMessage = 'Unknown error occurred';
|
|
209
|
-
if (error instanceof Error) {
|
|
210
|
-
errorMessage = error.message;
|
|
211
|
-
}
|
|
212
|
-
else if (typeof error === 'object' && error !== null) {
|
|
213
|
-
try {
|
|
214
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
215
|
-
}
|
|
216
|
-
catch {
|
|
217
|
-
errorMessage = String(error);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
errorMessage = String(error);
|
|
222
|
-
}
|
|
223
|
-
if (errorMessage.toLowerCase().includes('permission')) {
|
|
224
|
-
return {
|
|
225
|
-
content: [{
|
|
226
|
-
type: "text",
|
|
227
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to create apps. Only workspace administrators can create apps.\n\n**Error:** ${errorMessage}`,
|
|
228
|
-
}],
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
return {
|
|
232
|
-
content: [{
|
|
233
|
-
type: "text",
|
|
234
|
-
text: `❌ **Error creating app**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- User must be workspace administrator\n- Invalid workspace ID\n- Image ID must be 24 characters if provided`,
|
|
235
|
-
}],
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
// ============================================================================
|
|
241
|
-
// LIST APPS TOOL
|
|
242
|
-
// ============================================================================
|
|
243
|
-
const listAppsDescription = `🧪 [PLAYGROUND] List Apps - View all apps in workspace
|
|
244
|
-
|
|
245
|
-
**What it does**:
|
|
246
|
-
Lists all Hailer apps in the current workspace that you have access to.
|
|
247
|
-
|
|
248
|
-
**Example**:
|
|
249
|
-
\`\`\`javascript
|
|
250
|
-
list_apps()
|
|
251
|
-
\`\`\`
|
|
252
|
-
|
|
253
|
-
**Shows**:
|
|
254
|
-
- App name and description
|
|
255
|
-
- App ID
|
|
256
|
-
- URL (localhost for dev, auto for published)
|
|
257
|
-
- Creator and timestamps
|
|
258
|
-
- Configuration
|
|
259
|
-
|
|
260
|
-
**Use Cases**:
|
|
261
|
-
- See all workspace apps
|
|
262
|
-
- Find app IDs for updates
|
|
263
|
-
- Check which apps are development vs published
|
|
264
|
-
- Audit app configuration`;
|
|
265
|
-
exports.listAppsTool = {
|
|
266
|
-
name: 'list_apps',
|
|
267
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
268
|
-
description: listAppsDescription,
|
|
269
|
-
schema: zod_1.z.object({
|
|
270
|
-
workspaceId: zod_1.z
|
|
271
|
-
.string()
|
|
272
|
-
.optional()
|
|
273
|
-
.describe("Optional workspace ID - defaults to current workspace"),
|
|
274
|
-
}),
|
|
275
|
-
async execute(args, context) {
|
|
276
|
-
logger.debug('Listing apps', {
|
|
277
|
-
workspaceId: args.workspaceId,
|
|
278
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
279
|
-
});
|
|
280
|
-
try {
|
|
281
|
-
if (!context.workspaceCache) {
|
|
282
|
-
return {
|
|
283
|
-
content: [{
|
|
284
|
-
type: "text",
|
|
285
|
-
text: "❌ Workspace cache not available",
|
|
286
|
-
}],
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
const workspaceId = args.workspaceId
|
|
290
|
-
? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
|
|
291
|
-
: context.workspaceCache.currentWorkspace._id;
|
|
292
|
-
if (!workspaceId) {
|
|
293
|
-
return {
|
|
294
|
-
content: [{
|
|
295
|
-
type: "text",
|
|
296
|
-
text: `❌ Could not resolve workspace: ${args.workspaceId}`,
|
|
297
|
-
}],
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
logger.debug('Calling v3.app.list');
|
|
301
|
-
const result = await context.hailer.request('v3.app.list', [{}]);
|
|
302
|
-
logger.debug('List apps successful', {
|
|
303
|
-
appCount: result.apps?.length || 0
|
|
304
|
-
});
|
|
305
|
-
let responseText = `✅ **Apps Retrieved**\n\n`;
|
|
306
|
-
responseText += `**Workspace:** ${workspaceId}\n\n`;
|
|
307
|
-
if (!result.apps || result.apps.length === 0) {
|
|
308
|
-
responseText += `**No apps found** in this workspace.\n\n`;
|
|
309
|
-
responseText += `💡 Use \`create_app\` to create your first app.`;
|
|
310
|
-
return {
|
|
311
|
-
content: [{
|
|
312
|
-
type: "text",
|
|
313
|
-
text: responseText,
|
|
314
|
-
}],
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
const apps = result.apps;
|
|
318
|
-
responseText += `**Total Apps:** ${apps.length}\n\n`;
|
|
319
|
-
apps.forEach((app) => {
|
|
320
|
-
responseText += `### ${app.name || 'Unnamed App'}\n`;
|
|
321
|
-
responseText += `- **App ID:** \`${app._id}\`\n`;
|
|
322
|
-
if (app.description) {
|
|
323
|
-
responseText += `- **Description:** ${app.description}\n`;
|
|
324
|
-
}
|
|
325
|
-
if (app.url) {
|
|
326
|
-
responseText += `- **URL:** ${app.url}\n`;
|
|
327
|
-
responseText += `- **Type:** ${app.url.includes('localhost') ? 'Development' : 'Custom URL'}\n`;
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
responseText += `- **URL:** Auto-generated (Published App)\n`;
|
|
331
|
-
responseText += `- **Type:** Published\n`;
|
|
332
|
-
}
|
|
333
|
-
if (app.created) {
|
|
334
|
-
responseText += `- **Created:** ${new Date(app.created * 1000).toLocaleString()}\n`;
|
|
335
|
-
}
|
|
336
|
-
if (app.config && Object.keys(app.config).length > 0) {
|
|
337
|
-
responseText += `- **Config:** Present\n`;
|
|
338
|
-
}
|
|
339
|
-
responseText += `\n`;
|
|
340
|
-
});
|
|
341
|
-
responseText += `💡 **Next Steps:**\n`;
|
|
342
|
-
responseText += `- Use \`update_app\` to modify an app\n`;
|
|
343
|
-
responseText += `- Use \`add_app_member\` to share apps\n`;
|
|
344
|
-
responseText += `- Use \`remove_app\` to delete apps`;
|
|
345
|
-
return {
|
|
346
|
-
content: [{
|
|
347
|
-
type: "text",
|
|
348
|
-
text: responseText,
|
|
349
|
-
}],
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
catch (error) {
|
|
353
|
-
logger.error("Error listing apps", error);
|
|
354
|
-
let errorMessage = 'Unknown error occurred';
|
|
355
|
-
if (error instanceof Error) {
|
|
356
|
-
errorMessage = error.message;
|
|
357
|
-
}
|
|
358
|
-
else if (typeof error === 'object' && error !== null) {
|
|
359
|
-
try {
|
|
360
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
361
|
-
}
|
|
362
|
-
catch {
|
|
363
|
-
errorMessage = String(error);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
errorMessage = String(error);
|
|
368
|
-
}
|
|
369
|
-
return {
|
|
370
|
-
content: [{
|
|
371
|
-
type: "text",
|
|
372
|
-
text: `❌ **Error listing apps**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- Workspace not accessible\n- Permission issues`,
|
|
373
|
-
}],
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
// ============================================================================
|
|
379
|
-
// UPDATE APP TOOL
|
|
380
|
-
// ============================================================================
|
|
381
|
-
const updateAppDescription = `🧪 [PLAYGROUND] Update App - Modify app properties
|
|
382
|
-
|
|
383
|
-
**What it does**:
|
|
384
|
-
Updates an existing app's properties (name, description, URL, etc.).
|
|
385
|
-
|
|
386
|
-
**Example - Update name and description**:
|
|
387
|
-
\`\`\`javascript
|
|
388
|
-
update_app({
|
|
389
|
-
appId: '<app-id>',
|
|
390
|
-
name: 'Updated App Name',
|
|
391
|
-
description: 'New description'
|
|
392
|
-
})
|
|
393
|
-
\`\`\`
|
|
394
|
-
|
|
395
|
-
**Example - Change URL (dev to prod)**:
|
|
396
|
-
\`\`\`javascript
|
|
397
|
-
update_app({
|
|
398
|
-
appId: '<app-id>',
|
|
399
|
-
url: '' // Empty for published
|
|
400
|
-
})
|
|
401
|
-
\`\`\`
|
|
402
|
-
|
|
403
|
-
**Updatable Properties**:
|
|
404
|
-
- \`name\` - App display name
|
|
405
|
-
- \`description\` - App description
|
|
406
|
-
- \`url\` - App URL
|
|
407
|
-
- \`image\` - App icon ID
|
|
408
|
-
- \`config\` - App configuration
|
|
409
|
-
|
|
410
|
-
**Requirements**:
|
|
411
|
-
- User must be app creator or workspace admin
|
|
412
|
-
|
|
413
|
-
**Tips**:
|
|
414
|
-
- Only specified properties are updated
|
|
415
|
-
- Use \`list_apps\` to get app IDs`;
|
|
416
|
-
exports.updateAppTool = {
|
|
417
|
-
name: 'update_app',
|
|
418
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
419
|
-
description: updateAppDescription,
|
|
420
|
-
schema: zod_1.z.object({
|
|
421
|
-
appId: zod_1.z
|
|
422
|
-
.string()
|
|
423
|
-
.min(1)
|
|
424
|
-
.describe("App ID to update"),
|
|
425
|
-
name: zod_1.z
|
|
426
|
-
.string()
|
|
427
|
-
.optional()
|
|
428
|
-
.describe("New app name"),
|
|
429
|
-
description: zod_1.z
|
|
430
|
-
.string()
|
|
431
|
-
.optional()
|
|
432
|
-
.describe("New description"),
|
|
433
|
-
url: zod_1.z
|
|
434
|
-
.string()
|
|
435
|
-
.optional()
|
|
436
|
-
.describe("New URL"),
|
|
437
|
-
image: zod_1.z
|
|
438
|
-
.string()
|
|
439
|
-
.optional()
|
|
440
|
-
.describe("New image ID"),
|
|
441
|
-
config: zod_1.z
|
|
442
|
-
.record(zod_1.z.unknown())
|
|
443
|
-
.optional()
|
|
444
|
-
.describe("New configuration"),
|
|
445
|
-
}),
|
|
446
|
-
async execute(args, context) {
|
|
447
|
-
logger.debug('Updating app', {
|
|
448
|
-
appId: args.appId,
|
|
449
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
450
|
-
});
|
|
451
|
-
try {
|
|
452
|
-
const updateData = {};
|
|
453
|
-
if (args.name !== undefined)
|
|
454
|
-
updateData.name = args.name;
|
|
455
|
-
if (args.description !== undefined)
|
|
456
|
-
updateData.description = args.description;
|
|
457
|
-
if (args.url !== undefined)
|
|
458
|
-
updateData.url = args.url;
|
|
459
|
-
if (args.image !== undefined)
|
|
460
|
-
updateData.image = args.image;
|
|
461
|
-
if (args.config !== undefined)
|
|
462
|
-
updateData.config = args.config;
|
|
463
|
-
logger.debug('Calling v3.app.update', {
|
|
464
|
-
appId: args.appId,
|
|
465
|
-
updates: Object.keys(updateData)
|
|
466
|
-
});
|
|
467
|
-
await context.hailer.request('v3.app.update', [
|
|
468
|
-
args.appId,
|
|
469
|
-
updateData
|
|
470
|
-
]);
|
|
471
|
-
logger.debug('App update successful');
|
|
472
|
-
let responseText = `✅ **App Updated Successfully**\n\n`;
|
|
473
|
-
responseText += `**App ID:** \`${args.appId}\`\n\n`;
|
|
474
|
-
responseText += `**Updated Properties:**\n`;
|
|
475
|
-
const updatedFields = [];
|
|
476
|
-
if (args.name)
|
|
477
|
-
updatedFields.push(`name → "${args.name}"`);
|
|
478
|
-
if (args.description)
|
|
479
|
-
updatedFields.push(`description → "${args.description}"`);
|
|
480
|
-
if (args.url !== undefined)
|
|
481
|
-
updatedFields.push(`url → "${args.url || 'auto-generated'}"`);
|
|
482
|
-
if (args.image)
|
|
483
|
-
updatedFields.push(`image → "${args.image}"`);
|
|
484
|
-
if (args.config)
|
|
485
|
-
updatedFields.push(`config (updated)`);
|
|
486
|
-
updatedFields.forEach(field => {
|
|
487
|
-
responseText += `- ${field}\n`;
|
|
488
|
-
});
|
|
489
|
-
responseText += `\n💡 Use \`list_apps\` to verify changes.`;
|
|
490
|
-
return {
|
|
491
|
-
content: [{
|
|
492
|
-
type: "text",
|
|
493
|
-
text: responseText,
|
|
494
|
-
}],
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
catch (error) {
|
|
498
|
-
logger.error("Error updating app", error);
|
|
499
|
-
let errorMessage = 'Unknown error occurred';
|
|
500
|
-
if (error instanceof Error) {
|
|
501
|
-
errorMessage = error.message;
|
|
502
|
-
}
|
|
503
|
-
else if (typeof error === 'object' && error !== null) {
|
|
504
|
-
try {
|
|
505
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
506
|
-
}
|
|
507
|
-
catch {
|
|
508
|
-
errorMessage = String(error);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
else {
|
|
512
|
-
errorMessage = String(error);
|
|
513
|
-
}
|
|
514
|
-
if (errorMessage.toLowerCase().includes('not found')) {
|
|
515
|
-
return {
|
|
516
|
-
content: [{
|
|
517
|
-
type: "text",
|
|
518
|
-
text: `❌ **App Not Found**\n\nThe specified app doesn't exist.\n\n**App ID:** \`${args.appId}\`\n\n💡 Use \`list_apps\` to see available apps.`,
|
|
519
|
-
}],
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
if (errorMessage.toLowerCase().includes('permission')) {
|
|
523
|
-
return {
|
|
524
|
-
content: [{
|
|
525
|
-
type: "text",
|
|
526
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to update this app. Only app creator or workspace admin can update apps.\n\n**Error:** ${errorMessage}`,
|
|
527
|
-
}],
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
return {
|
|
531
|
-
content: [{
|
|
532
|
-
type: "text",
|
|
533
|
-
text: `❌ **Error updating app**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- App ID invalid\n- Not app creator or admin\n- Invalid property values`,
|
|
534
|
-
}],
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
};
|
|
539
|
-
// ============================================================================
|
|
540
|
-
// REMOVE APP TOOL
|
|
541
|
-
// ============================================================================
|
|
542
|
-
const removeAppDescription = `🧪 [PLAYGROUND] Remove App - ⚠️ DANGER: Permanently deletes app entry from Hailer
|
|
543
|
-
|
|
544
|
-
⚠️ **MANDATORY: GATHER COMPLETE CONTEXT BEFORE CALLING THIS TOOL**
|
|
545
|
-
**BEFORE calling this tool, you are REQUIRED to:**
|
|
546
|
-
1. Load the skill: \`get_skill({ skillName: "remove-app-skill" })\`
|
|
547
|
-
2. Fetch app details with \`list_apps\` to get:
|
|
548
|
-
- App name and ID
|
|
549
|
-
- Workspace ID and name
|
|
550
|
-
- App type (development/published)
|
|
551
|
-
- App configuration
|
|
552
|
-
3. Show comprehensive confirmation message including:
|
|
553
|
-
- Workspace ID and name
|
|
554
|
-
- App ID and name
|
|
555
|
-
- What will be deleted (entry, permissions, configuration)
|
|
556
|
-
- What won't be deleted (published code remains)
|
|
557
|
-
- Clear irreversibility warning
|
|
558
|
-
4. Wait for explicit user confirmation
|
|
559
|
-
**FAILURE TO GATHER AND SHOW THIS CONTEXT IS AN ERROR**
|
|
560
|
-
|
|
561
|
-
**Required**: appId
|
|
562
|
-
**Permission**: App creator or workspace administrator
|
|
563
|
-
|
|
564
|
-
**What gets deleted**:
|
|
565
|
-
- App entry (name, description, URL, metadata)
|
|
566
|
-
- App permissions
|
|
567
|
-
- App configuration
|
|
568
|
-
|
|
569
|
-
**What doesn't get deleted**:
|
|
570
|
-
- Published app code (remains on server)
|
|
571
|
-
- App data (if any)
|
|
572
|
-
|
|
573
|
-
**Example**:
|
|
574
|
-
\`\`\`javascript
|
|
575
|
-
remove_app({
|
|
576
|
-
appId: '<app-id>'
|
|
577
|
-
})
|
|
578
|
-
\`\`\`
|
|
579
|
-
|
|
580
|
-
**Tips**:
|
|
581
|
-
- Use \`list_apps\` to get app IDs
|
|
582
|
-
- Published app code must be removed separately
|
|
583
|
-
- Operation cannot be undone`;
|
|
584
|
-
exports.removeAppTool = {
|
|
585
|
-
name: 'remove_app',
|
|
586
|
-
group: tool_registry_1.ToolGroup.NUCLEAR,
|
|
587
|
-
description: removeAppDescription,
|
|
588
|
-
schema: zod_1.z.object({
|
|
589
|
-
appId: zod_1.z
|
|
590
|
-
.string()
|
|
591
|
-
.min(1)
|
|
592
|
-
.describe("App ID to remove"),
|
|
593
|
-
confirmed: zod_1.z
|
|
594
|
-
.boolean()
|
|
595
|
-
.optional()
|
|
596
|
-
.describe("First confirmation - must be true to proceed"),
|
|
597
|
-
secondConfirmed: zod_1.z
|
|
598
|
-
.boolean()
|
|
599
|
-
.optional()
|
|
600
|
-
.describe("Second confirmation - must be true to proceed (required for double-check safety)"),
|
|
601
|
-
}),
|
|
602
|
-
async execute(args, context) {
|
|
603
|
-
logger.debug('Removing app', {
|
|
604
|
-
appId: args.appId,
|
|
605
|
-
confirmed: args.confirmed,
|
|
606
|
-
secondConfirmed: args.secondConfirmed,
|
|
607
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
608
|
-
});
|
|
609
|
-
try {
|
|
610
|
-
// Fetch app info and workspace info
|
|
611
|
-
const [appListResult, initData] = await Promise.all([
|
|
612
|
-
context.hailer.request('v3.app.list', [{}]),
|
|
613
|
-
context.hailer.request('v2.core.init', [["network"]])
|
|
614
|
-
]);
|
|
615
|
-
const app = appListResult.apps?.find(a => a._id === args.appId);
|
|
616
|
-
const appName = app?.name || 'Unknown';
|
|
617
|
-
const workspaceId = initData.network?._id || 'Unknown';
|
|
618
|
-
const workspaceName = initData.network?.name || 'Unknown';
|
|
619
|
-
// SAFETY CHECK: Require double confirmation
|
|
620
|
-
if (!args.confirmed || !args.secondConfirmed) {
|
|
621
|
-
let warningText = `⚠️ **DESTRUCTIVE OPERATION - CONFIRMATION REQUIRED**\n\n`;
|
|
622
|
-
warningText += `You are about to **permanently delete** the following:\n\n`;
|
|
623
|
-
warningText += `**App:** ${appName}\n`;
|
|
624
|
-
warningText += `**App ID:** \`${args.appId}\`\n`;
|
|
625
|
-
warningText += `**Workspace:** ${workspaceName} (\`${workspaceId}\`)\n\n`;
|
|
626
|
-
warningText += `**⚠️ This will permanently delete:**\n`;
|
|
627
|
-
warningText += `- App entry (name, description, URL)\n`;
|
|
628
|
-
warningText += `- App permissions\n`;
|
|
629
|
-
warningText += `- App configuration\n\n`;
|
|
630
|
-
warningText += `**🚨 THIS CANNOT BE UNDONE! 🚨**\n\n`;
|
|
631
|
-
warningText += `**To proceed, you must:**\n`;
|
|
632
|
-
warningText += `1. Review the \`remove-app-skill\` (REQUIRED)\n`;
|
|
633
|
-
warningText += `2. Call this tool again with BOTH confirmations:\n\n`;
|
|
634
|
-
warningText += `\`\`\`javascript\n`;
|
|
635
|
-
warningText += `remove_app({\n`;
|
|
636
|
-
warningText += ` appId: "${args.appId}",\n`;
|
|
637
|
-
warningText += ` confirmed: true,\n`;
|
|
638
|
-
warningText += ` secondConfirmed: true\n`;
|
|
639
|
-
warningText += `})\n`;
|
|
640
|
-
warningText += `\`\`\`\n\n`;
|
|
641
|
-
warningText += `💡 **Before proceeding:**\n`;
|
|
642
|
-
warningText += `- Load \`remove-app-skill\` to review safety checklist\n`;
|
|
643
|
-
warningText += `- Verify with user that this is intentional\n`;
|
|
644
|
-
warningText += `- Note: Published app code remains on server`;
|
|
645
|
-
return {
|
|
646
|
-
content: [{
|
|
647
|
-
type: "text",
|
|
648
|
-
text: warningText,
|
|
649
|
-
}],
|
|
650
|
-
};
|
|
651
|
-
}
|
|
652
|
-
logger.debug('Calling v3.app.remove', {
|
|
653
|
-
appId: args.appId,
|
|
654
|
-
appName,
|
|
655
|
-
workspaceId,
|
|
656
|
-
workspaceName
|
|
657
|
-
});
|
|
658
|
-
await context.hailer.request('v3.app.remove', [args.appId]);
|
|
659
|
-
logger.debug('App removal successful', {
|
|
660
|
-
appId: args.appId,
|
|
661
|
-
appName
|
|
662
|
-
});
|
|
663
|
-
let responseText = `✅ **App Removed Successfully**\n\n`;
|
|
664
|
-
responseText += `**App:** ${appName}\n`;
|
|
665
|
-
responseText += `**App ID:** \`${args.appId}\`\n`;
|
|
666
|
-
responseText += `**Workspace:** ${workspaceName} (\`${workspaceId}\`)\n\n`;
|
|
667
|
-
responseText += `⚠️ **The app entry has been permanently deleted.**\n\n`;
|
|
668
|
-
responseText += `**What was deleted:**\n`;
|
|
669
|
-
responseText += `- App entry (name, description, URL)\n`;
|
|
670
|
-
responseText += `- App permissions\n`;
|
|
671
|
-
responseText += `- App configuration\n\n`;
|
|
672
|
-
responseText += `**Note:** Published app code remains on server (if applicable).\n\n`;
|
|
673
|
-
responseText += `💡 Use \`list_apps\` to see remaining apps.`;
|
|
674
|
-
return {
|
|
675
|
-
content: [{
|
|
676
|
-
type: "text",
|
|
677
|
-
text: responseText,
|
|
678
|
-
}],
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
catch (error) {
|
|
682
|
-
logger.error("Error removing app", error);
|
|
683
|
-
let errorMessage = 'Unknown error occurred';
|
|
684
|
-
if (error instanceof Error) {
|
|
685
|
-
errorMessage = error.message;
|
|
686
|
-
}
|
|
687
|
-
else if (typeof error === 'object' && error !== null) {
|
|
688
|
-
try {
|
|
689
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
690
|
-
}
|
|
691
|
-
catch {
|
|
692
|
-
errorMessage = String(error);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
else {
|
|
696
|
-
errorMessage = String(error);
|
|
697
|
-
}
|
|
698
|
-
if (errorMessage.toLowerCase().includes('not found')) {
|
|
699
|
-
return {
|
|
700
|
-
content: [{
|
|
701
|
-
type: "text",
|
|
702
|
-
text: `❌ **App Not Found**\n\nThe specified app doesn't exist or has already been deleted.\n\n**App ID:** \`${args.appId}\`\n\n💡 Use \`list_apps\` to see available apps.`,
|
|
703
|
-
}],
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
if (errorMessage.toLowerCase().includes('permission')) {
|
|
707
|
-
return {
|
|
708
|
-
content: [{
|
|
709
|
-
type: "text",
|
|
710
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to remove this app. Only app creator or workspace admin can delete apps.\n\n**Error:** ${errorMessage}`,
|
|
711
|
-
}],
|
|
712
|
-
};
|
|
713
|
-
}
|
|
714
|
-
return {
|
|
715
|
-
content: [{
|
|
716
|
-
type: "text",
|
|
717
|
-
text: `❌ **Error removing app**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- App ID invalid\n- App already deleted\n- Not app creator or admin`,
|
|
718
|
-
}],
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
};
|
|
723
|
-
// ============================================================================
|
|
724
|
-
// ADD APP MEMBER TOOL
|
|
725
|
-
// ============================================================================
|
|
726
|
-
const addAppMemberDescription = `🧪 [PLAYGROUND] Add App Member - Share app with users/teams
|
|
727
|
-
|
|
728
|
-
**What it does**:
|
|
729
|
-
Grants permission for users, teams, or entire workspace to access an app.
|
|
730
|
-
|
|
731
|
-
**Member Formats**:
|
|
732
|
-
- \`network_<workspaceId>\` - Entire workspace
|
|
733
|
-
- \`team_<teamId>\` - Specific team
|
|
734
|
-
- \`user_<userId>\` - Individual user
|
|
735
|
-
- \`group_<groupId>\` - Custom group
|
|
736
|
-
|
|
737
|
-
**Example - Share with workspace**:
|
|
738
|
-
\`\`\`javascript
|
|
739
|
-
add_app_member({
|
|
740
|
-
appId: '<app-id>',
|
|
741
|
-
member: 'network_68446c045b30685f67c6fc8c'
|
|
742
|
-
})
|
|
743
|
-
\`\`\`
|
|
744
|
-
|
|
745
|
-
**Example - Share with team**:
|
|
746
|
-
\`\`\`javascript
|
|
747
|
-
add_app_member({
|
|
748
|
-
appId: '<app-id>',
|
|
749
|
-
member: 'team_<team-id>'
|
|
750
|
-
})
|
|
751
|
-
\`\`\`
|
|
752
|
-
|
|
753
|
-
**Example - Share with user**:
|
|
754
|
-
\`\`\`javascript
|
|
755
|
-
add_app_member({
|
|
756
|
-
appId: '<app-id>',
|
|
757
|
-
member: 'user_<user-id>'
|
|
758
|
-
})
|
|
759
|
-
\`\`\`
|
|
760
|
-
|
|
761
|
-
**Requirements**:
|
|
762
|
-
- User must be app creator or workspace admin
|
|
763
|
-
|
|
764
|
-
**Tips**:
|
|
765
|
-
- Default: Only creator and admins see app
|
|
766
|
-
- Use network_ to make app available to everyone
|
|
767
|
-
- Use team_ for team-specific apps`;
|
|
768
|
-
exports.addAppMemberTool = {
|
|
769
|
-
name: 'add_app_member',
|
|
770
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
771
|
-
description: addAppMemberDescription,
|
|
772
|
-
schema: zod_1.z.object({
|
|
773
|
-
appId: zod_1.z
|
|
774
|
-
.string()
|
|
775
|
-
.min(1)
|
|
776
|
-
.describe("App ID"),
|
|
777
|
-
member: zod_1.z
|
|
778
|
-
.string()
|
|
779
|
-
.regex(/^(network_|team_|user_|group_)[a-zA-Z0-9]+$/, "Member must be network_*, team_*, user_*, or group_*")
|
|
780
|
-
.describe("Member identifier (network_<id>, team_<id>, user_<id>, or group_<id>)"),
|
|
781
|
-
}),
|
|
782
|
-
async execute(args, context) {
|
|
783
|
-
logger.debug('Adding app member', {
|
|
784
|
-
appId: args.appId,
|
|
785
|
-
member: args.member,
|
|
786
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
787
|
-
});
|
|
788
|
-
try {
|
|
789
|
-
logger.debug('Calling v3.app.member.add', {
|
|
790
|
-
appId: args.appId,
|
|
791
|
-
member: args.member
|
|
792
|
-
});
|
|
793
|
-
await context.hailer.request('v3.app.member.add', [
|
|
794
|
-
args.appId,
|
|
795
|
-
args.member
|
|
796
|
-
]);
|
|
797
|
-
logger.debug('App member added successfully');
|
|
798
|
-
const memberType = args.member.split('_')[0];
|
|
799
|
-
const memberTypeLabel = {
|
|
800
|
-
'network': 'Workspace',
|
|
801
|
-
'team': 'Team',
|
|
802
|
-
'user': 'User',
|
|
803
|
-
'group': 'Group'
|
|
804
|
-
};
|
|
805
|
-
let responseText = `✅ **App Member Added Successfully**\n\n`;
|
|
806
|
-
responseText += `**App ID:** \`${args.appId}\`\n`;
|
|
807
|
-
responseText += `**Member Type:** ${memberTypeLabel[memberType] || 'Member'}\n`;
|
|
808
|
-
responseText += `**Member ID:** \`${args.member}\`\n\n`;
|
|
809
|
-
if (memberType === 'network') {
|
|
810
|
-
responseText += `🌐 **App is now accessible to entire workspace!**\n`;
|
|
811
|
-
}
|
|
812
|
-
else if (memberType === 'team') {
|
|
813
|
-
responseText += `👥 **App is now accessible to all team members.**\n`;
|
|
814
|
-
}
|
|
815
|
-
else if (memberType === 'user') {
|
|
816
|
-
responseText += `👤 **App is now accessible to this user.**\n`;
|
|
817
|
-
}
|
|
818
|
-
else {
|
|
819
|
-
responseText += `🔑 **App is now accessible to this group.**\n`;
|
|
820
|
-
}
|
|
821
|
-
return {
|
|
822
|
-
content: [{
|
|
823
|
-
type: "text",
|
|
824
|
-
text: responseText,
|
|
825
|
-
}],
|
|
826
|
-
};
|
|
827
|
-
}
|
|
828
|
-
catch (error) {
|
|
829
|
-
logger.error("Error adding app member", error);
|
|
830
|
-
let errorMessage = 'Unknown error occurred';
|
|
831
|
-
if (error instanceof Error) {
|
|
832
|
-
errorMessage = error.message;
|
|
833
|
-
}
|
|
834
|
-
else if (typeof error === 'object' && error !== null) {
|
|
835
|
-
try {
|
|
836
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
837
|
-
}
|
|
838
|
-
catch {
|
|
839
|
-
errorMessage = String(error);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
else {
|
|
843
|
-
errorMessage = String(error);
|
|
844
|
-
}
|
|
845
|
-
if (errorMessage.toLowerCase().includes('not found')) {
|
|
846
|
-
return {
|
|
847
|
-
content: [{
|
|
848
|
-
type: "text",
|
|
849
|
-
text: `❌ **App Not Found**\n\nThe specified app doesn't exist.\n\n**App ID:** \`${args.appId}\`\n\n💡 Use \`list_apps\` to see available apps.`,
|
|
850
|
-
}],
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
if (errorMessage.toLowerCase().includes('permission')) {
|
|
854
|
-
return {
|
|
855
|
-
content: [{
|
|
856
|
-
type: "text",
|
|
857
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to manage this app's members. Only app creator or workspace admin can add members.\n\n**Error:** ${errorMessage}`,
|
|
858
|
-
}],
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
|
-
return {
|
|
862
|
-
content: [{
|
|
863
|
-
type: "text",
|
|
864
|
-
text: `❌ **Error adding app member**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- App ID invalid\n- Member ID invalid\n- Not app creator or admin\n- Member format must be network_*, team_*, user_*, or group_*`,
|
|
865
|
-
}],
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
// ============================================================================
|
|
871
|
-
// REMOVE APP MEMBER TOOL
|
|
872
|
-
// ============================================================================
|
|
873
|
-
const removeAppMemberDescription = `🧪 [PLAYGROUND] Remove App Member - Revoke app access
|
|
874
|
-
|
|
875
|
-
**What it does**:
|
|
876
|
-
Revokes permission for users, teams, or workspace to access an app.
|
|
877
|
-
|
|
878
|
-
**Example - Remove workspace access**:
|
|
879
|
-
\`\`\`javascript
|
|
880
|
-
remove_app_member({
|
|
881
|
-
appId: '<app-id>',
|
|
882
|
-
member: 'network_68446c045b30685f67c6fc8c'
|
|
883
|
-
})
|
|
884
|
-
\`\`\`
|
|
885
|
-
|
|
886
|
-
**Example - Remove team access**:
|
|
887
|
-
\`\`\`javascript
|
|
888
|
-
remove_app_member({
|
|
889
|
-
appId: '<app-id>',
|
|
890
|
-
member: 'team_<team-id>'
|
|
891
|
-
})
|
|
892
|
-
\`\`\`
|
|
893
|
-
|
|
894
|
-
**Requirements**:
|
|
895
|
-
- User must be app creator or workspace admin
|
|
896
|
-
|
|
897
|
-
**Notes**:
|
|
898
|
-
- Creator and admins always retain access
|
|
899
|
-
- Removing workspace revokes access from all members
|
|
900
|
-
|
|
901
|
-
**Tips**:
|
|
902
|
-
- Use \`list_apps\` to get app IDs
|
|
903
|
-
- Member format same as add_app_member`;
|
|
904
|
-
exports.removeAppMemberTool = {
|
|
905
|
-
name: 'remove_app_member',
|
|
906
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
907
|
-
description: removeAppMemberDescription,
|
|
908
|
-
schema: zod_1.z.object({
|
|
909
|
-
appId: zod_1.z
|
|
910
|
-
.string()
|
|
911
|
-
.min(1)
|
|
912
|
-
.describe("App ID"),
|
|
913
|
-
member: zod_1.z
|
|
914
|
-
.string()
|
|
915
|
-
.regex(/^(network_|team_|user_|group_)[a-zA-Z0-9]+$/, "Member must be network_*, team_*, user_*, or group_*")
|
|
916
|
-
.describe("Member identifier to remove"),
|
|
917
|
-
}),
|
|
918
|
-
async execute(args, context) {
|
|
919
|
-
logger.debug('Removing app member', {
|
|
920
|
-
appId: args.appId,
|
|
921
|
-
member: args.member,
|
|
922
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
923
|
-
});
|
|
924
|
-
try {
|
|
925
|
-
logger.debug('Calling v3.app.member.remove', {
|
|
926
|
-
appId: args.appId,
|
|
927
|
-
member: args.member
|
|
928
|
-
});
|
|
929
|
-
await context.hailer.request('v3.app.member.remove', [
|
|
930
|
-
args.appId,
|
|
931
|
-
args.member
|
|
932
|
-
]);
|
|
933
|
-
logger.debug('App member removed successfully');
|
|
934
|
-
const memberType = args.member.split('_')[0];
|
|
935
|
-
const memberTypeLabel = {
|
|
936
|
-
'network': 'Workspace',
|
|
937
|
-
'team': 'Team',
|
|
938
|
-
'user': 'User',
|
|
939
|
-
'group': 'Group'
|
|
940
|
-
};
|
|
941
|
-
let responseText = `✅ **App Member Removed Successfully**\n\n`;
|
|
942
|
-
responseText += `**App ID:** \`${args.appId}\`\n`;
|
|
943
|
-
responseText += `**Member Type:** ${memberTypeLabel[memberType] || 'Member'}\n`;
|
|
944
|
-
responseText += `**Member ID:** \`${args.member}\`\n\n`;
|
|
945
|
-
responseText += `🔒 **Access revoked for this ${(memberTypeLabel[memberType] || 'Member').toLowerCase()}.**\n\n`;
|
|
946
|
-
responseText += `**Note:** Creator and admins always retain access.`;
|
|
947
|
-
return {
|
|
948
|
-
content: [{
|
|
949
|
-
type: "text",
|
|
950
|
-
text: responseText,
|
|
951
|
-
}],
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
|
-
catch (error) {
|
|
955
|
-
logger.error("Error removing app member", error);
|
|
956
|
-
let errorMessage = 'Unknown error occurred';
|
|
957
|
-
if (error instanceof Error) {
|
|
958
|
-
errorMessage = error.message;
|
|
959
|
-
}
|
|
960
|
-
else if (typeof error === 'object' && error !== null) {
|
|
961
|
-
try {
|
|
962
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
963
|
-
}
|
|
964
|
-
catch {
|
|
965
|
-
errorMessage = String(error);
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
else {
|
|
969
|
-
errorMessage = String(error);
|
|
970
|
-
}
|
|
971
|
-
if (errorMessage.toLowerCase().includes('not found')) {
|
|
972
|
-
return {
|
|
973
|
-
content: [{
|
|
974
|
-
type: "text",
|
|
975
|
-
text: `❌ **App or Member Not Found**\n\nThe specified app or member doesn't exist.\n\n**App ID:** \`${args.appId}\`\n**Member:** \`${args.member}\`\n\n💡 Use \`list_apps\` to see available apps.`,
|
|
976
|
-
}],
|
|
977
|
-
};
|
|
978
|
-
}
|
|
979
|
-
if (errorMessage.toLowerCase().includes('permission')) {
|
|
980
|
-
return {
|
|
981
|
-
content: [{
|
|
982
|
-
type: "text",
|
|
983
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to manage this app's members. Only app creator or workspace admin can remove members.\n\n**Error:** ${errorMessage}`,
|
|
984
|
-
}],
|
|
985
|
-
};
|
|
986
|
-
}
|
|
987
|
-
return {
|
|
988
|
-
content: [{
|
|
989
|
-
type: "text",
|
|
990
|
-
text: `❌ **Error removing app member**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- App ID invalid\n- Member doesn't have access\n- Not app creator or admin`,
|
|
991
|
-
}],
|
|
992
|
-
};
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
};
|
|
996
|
-
// ============================================================================
|
|
997
|
-
// SCAFFOLD HAILER APP TOOL
|
|
998
|
-
// ============================================================================
|
|
999
|
-
const scaffoldHailerAppDescription = `Scaffold new Hailer app from template - ONE SHOT SETUP
|
|
1000
|
-
|
|
1001
|
-
⚠️ **MANDATORY: YOU MUST LOAD SKILL FIRST**
|
|
1002
|
-
**BEFORE calling this tool, you are REQUIRED to:**
|
|
1003
|
-
1. Load the skill: \`get_skill({ skillName: "scaffold-hailer-app-skill" })\`
|
|
1004
|
-
2. Read the setup guide and understand the process
|
|
1005
|
-
3. Review template options and troubleshooting tips
|
|
1006
|
-
**FAILURE TO LOAD THE SKILL FIRST IS AN ERROR**
|
|
1007
|
-
|
|
1008
|
-
**Required Parameters**:
|
|
1009
|
-
- projectName: Project folder name
|
|
1010
|
-
- template: react-ts (recommended), react-swc-ts, or vanilla
|
|
1011
|
-
|
|
1012
|
-
**Optional Parameters**:
|
|
1013
|
-
- description: App description for Hailer
|
|
1014
|
-
- autoCreateDevApp: (default: true) Automatically create dev app entry in Hailer
|
|
1015
|
-
- autoShareWithWorkspace: (default: true) Share app with entire workspace
|
|
1016
|
-
- autoStartDevServer: (default: true) Start dev server in background
|
|
1017
|
-
|
|
1018
|
-
**What This Does (One Shot)**:
|
|
1019
|
-
1. ✅ Scaffolds project from template
|
|
1020
|
-
2. ✅ Installs dependencies
|
|
1021
|
-
3. ✅ Creates dev app entry in Hailer with correct URL
|
|
1022
|
-
4. ✅ Shares app with workspace
|
|
1023
|
-
5. ✅ Updates manifest.json with app ID
|
|
1024
|
-
6. ✅ Starts dev server on port 3000
|
|
1025
|
-
7. ✅ App ready to open in Hailer!
|
|
1026
|
-
|
|
1027
|
-
**Target Directory**:
|
|
1028
|
-
- Uses DEV_APPS_PATH from .env.local if set
|
|
1029
|
-
- Falls back to targetDirectory parameter
|
|
1030
|
-
- Falls back to current directory if neither set`;
|
|
1031
|
-
exports.scaffoldHailerAppTool = {
|
|
1032
|
-
name: 'scaffold_hailer_app',
|
|
1033
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
1034
|
-
description: scaffoldHailerAppDescription,
|
|
1035
|
-
schema: zod_1.z.object({
|
|
1036
|
-
projectName: zod_1.z.string().min(1).describe("Project folder name"),
|
|
1037
|
-
template: zod_1.z.enum(['react-ts', 'react-swc-ts', 'vanilla']).describe("Template to use"),
|
|
1038
|
-
description: zod_1.z.string().optional().describe("App description for Hailer"),
|
|
1039
|
-
targetDirectory: zod_1.z.string().optional().describe("Target directory (defaults to DEV_APPS_PATH or current)"),
|
|
1040
|
-
installDependencies: zod_1.z.coerce.boolean().optional().default(true).describe("Run npm install after scaffolding"),
|
|
1041
|
-
autoCreateDevApp: zod_1.z.coerce.boolean().optional().default(true).describe("Automatically create dev app entry in Hailer"),
|
|
1042
|
-
autoShareWithWorkspace: zod_1.z.coerce.boolean().optional().default(true).describe("Share app with entire workspace"),
|
|
1043
|
-
autoStartDevServer: zod_1.z.coerce.boolean().optional().default(true).describe("Start dev server in background on port 3000")
|
|
1044
|
-
}),
|
|
1045
|
-
async execute(args, context) {
|
|
1046
|
-
const { execSync, spawn } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
1047
|
-
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
1048
|
-
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
1049
|
-
try {
|
|
1050
|
-
const targetDir = args.targetDirectory || config_1.environment.DEV_APPS_PATH || process.cwd();
|
|
1051
|
-
const projectPath = path.join(targetDir, args.projectName);
|
|
1052
|
-
// Check if directory already exists
|
|
1053
|
-
if (fs.existsSync(projectPath)) {
|
|
1054
|
-
return {
|
|
1055
|
-
content: [{
|
|
1056
|
-
type: "text",
|
|
1057
|
-
text: `❌ **Directory Already Exists**\n\nThe directory \`${projectPath}\` already exists.\n\n**Options:**\n- Choose a different project name\n- Remove the existing directory\n- Use a different target directory`,
|
|
1058
|
-
}],
|
|
1059
|
-
};
|
|
1060
|
-
}
|
|
1061
|
-
let responseText = `🚀 **ONE-SHOT HAILER APP SETUP**\n\n`;
|
|
1062
|
-
responseText += `**Project:** ${args.projectName}\n`;
|
|
1063
|
-
responseText += `**Template:** ${args.template}\n`;
|
|
1064
|
-
responseText += `**Location:** ${projectPath}\n\n`;
|
|
1065
|
-
// Step 1: Scaffold project
|
|
1066
|
-
responseText += `⏳ Step 1/8: Creating project from template...\n`;
|
|
1067
|
-
try {
|
|
1068
|
-
const createCmd = `npm create @hailer/app@latest ${args.projectName} -- --template ${args.template}`;
|
|
1069
|
-
execSync(createCmd, {
|
|
1070
|
-
cwd: targetDir,
|
|
1071
|
-
stdio: 'pipe',
|
|
1072
|
-
encoding: 'utf-8',
|
|
1073
|
-
shell: '/bin/bash'
|
|
1074
|
-
});
|
|
1075
|
-
responseText += `✅ Project scaffolded\n\n`;
|
|
1076
|
-
}
|
|
1077
|
-
catch (error) {
|
|
1078
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1079
|
-
return {
|
|
1080
|
-
content: [{
|
|
1081
|
-
type: "text",
|
|
1082
|
-
text: `❌ **Error scaffolding project**\n\n**Error:** ${errorMessage}\n\n**Possible Issues:**\n- npm not available\n- Network issues\n- Insufficient permissions`,
|
|
1083
|
-
}],
|
|
1084
|
-
};
|
|
1085
|
-
}
|
|
1086
|
-
// Step 2: Install dependencies
|
|
1087
|
-
if (args.installDependencies !== false) {
|
|
1088
|
-
responseText += `⏳ Step 2/8: Installing dependencies...\n`;
|
|
1089
|
-
try {
|
|
1090
|
-
execSync('npm install', {
|
|
1091
|
-
cwd: projectPath,
|
|
1092
|
-
stdio: 'pipe',
|
|
1093
|
-
encoding: 'utf-8',
|
|
1094
|
-
shell: '/bin/bash'
|
|
1095
|
-
});
|
|
1096
|
-
responseText += `✅ Dependencies installed\n\n`;
|
|
1097
|
-
}
|
|
1098
|
-
catch (error) {
|
|
1099
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1100
|
-
responseText += `⚠️ Failed to install dependencies: ${errorMessage}\n\n`;
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
else {
|
|
1104
|
-
responseText += `⏭️ Step 2/8: Skipped (installDependencies = false)\n\n`;
|
|
1105
|
-
}
|
|
1106
|
-
// Step 3: Configure CORS in vite.config.ts
|
|
1107
|
-
responseText += `⏳ Step 3/8: Configuring CORS for Hailer access...\n`;
|
|
1108
|
-
try {
|
|
1109
|
-
const viteConfigPath = path.join(projectPath, 'vite.config.ts');
|
|
1110
|
-
if (fs.existsSync(viteConfigPath)) {
|
|
1111
|
-
let viteConfig = fs.readFileSync(viteConfigPath, 'utf-8');
|
|
1112
|
-
// Check if CORS is already configured
|
|
1113
|
-
if (!viteConfig.includes('cors:')) {
|
|
1114
|
-
// Add CORS configuration to the server block
|
|
1115
|
-
// Matches: server: { port: 3000 } or server: { port: 3000, } with optional whitespace
|
|
1116
|
-
viteConfig = viteConfig.replace(/server:\s*{\s*port:\s*3000\s*,?\s*}/, `server: {
|
|
1117
|
-
port: 3000,
|
|
1118
|
-
cors: {
|
|
1119
|
-
origin: '*',
|
|
1120
|
-
credentials: true
|
|
1121
|
-
}
|
|
1122
|
-
}`);
|
|
1123
|
-
fs.writeFileSync(viteConfigPath, viteConfig);
|
|
1124
|
-
responseText += `✅ CORS configured in vite.config.ts\n\n`;
|
|
1125
|
-
}
|
|
1126
|
-
else {
|
|
1127
|
-
responseText += `✅ CORS already configured\n\n`;
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
else {
|
|
1131
|
-
responseText += `⚠️ vite.config.ts not found, skipping CORS configuration\n\n`;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
catch (error) {
|
|
1135
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1136
|
-
responseText += `⚠️ Failed to configure CORS: ${errorMessage}\n\n`;
|
|
1137
|
-
}
|
|
1138
|
-
let appId;
|
|
1139
|
-
let workspaceId;
|
|
1140
|
-
// Step 4: Create dev app in Hailer
|
|
1141
|
-
if (args.autoCreateDevApp !== false) {
|
|
1142
|
-
responseText += `⏳ Step 4/8: Creating dev app entry in Hailer...\n`;
|
|
1143
|
-
try {
|
|
1144
|
-
if (!context.workspaceCache) {
|
|
1145
|
-
responseText += `⚠️ Workspace cache not available, skipping app creation\n\n`;
|
|
1146
|
-
}
|
|
1147
|
-
else {
|
|
1148
|
-
workspaceId = context.workspaceCache.currentWorkspace._id;
|
|
1149
|
-
const appData = {
|
|
1150
|
-
cid: workspaceId,
|
|
1151
|
-
name: args.projectName,
|
|
1152
|
-
url: 'http://localhost:3000'
|
|
1153
|
-
};
|
|
1154
|
-
if (args.description) {
|
|
1155
|
-
appData.description = args.description;
|
|
1156
|
-
}
|
|
1157
|
-
const result = await context.hailer.request('v3.app.create', [appData]);
|
|
1158
|
-
appId = result.appId || result._id;
|
|
1159
|
-
responseText += `✅ App created: ${appId}\n`;
|
|
1160
|
-
responseText += ` URL: http://localhost:3000\n\n`;
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
catch (error) {
|
|
1164
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1165
|
-
responseText += `⚠️ Failed to create app in Hailer: ${errorMessage}\n\n`;
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
else {
|
|
1169
|
-
responseText += `⏭️ Step 4/8: Skipped (autoCreateDevApp = false)\n\n`;
|
|
1170
|
-
}
|
|
1171
|
-
// Step 5: Share with workspace
|
|
1172
|
-
if (args.autoShareWithWorkspace !== false && appId && workspaceId) {
|
|
1173
|
-
responseText += `⏳ Step 5/8: Sharing app with workspace...\n`;
|
|
1174
|
-
try {
|
|
1175
|
-
await context.hailer.request('v3.app.member.add', [
|
|
1176
|
-
appId,
|
|
1177
|
-
`network_${workspaceId}`
|
|
1178
|
-
]);
|
|
1179
|
-
responseText += `✅ App shared with entire workspace\n\n`;
|
|
1180
|
-
}
|
|
1181
|
-
catch (error) {
|
|
1182
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1183
|
-
responseText += `⚠️ Failed to share app: ${errorMessage}\n\n`;
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
else {
|
|
1187
|
-
responseText += `⏭️ Step 5/8: Skipped (no app ID or autoShareWithWorkspace = false)\n\n`;
|
|
1188
|
-
}
|
|
1189
|
-
// Step 6: Update manifest.json with app ID
|
|
1190
|
-
if (appId) {
|
|
1191
|
-
responseText += `⏳ Step 6/8: Updating manifest.json with app ID...\n`;
|
|
1192
|
-
try {
|
|
1193
|
-
const manifestPath = path.join(projectPath, 'public', 'manifest.json');
|
|
1194
|
-
if (fs.existsSync(manifestPath)) {
|
|
1195
|
-
const manifestContent = fs.readFileSync(manifestPath, 'utf-8');
|
|
1196
|
-
const manifest = JSON.parse(manifestContent);
|
|
1197
|
-
manifest.appId = appId;
|
|
1198
|
-
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
1199
|
-
responseText += `✅ manifest.json updated with appId\n\n`;
|
|
1200
|
-
}
|
|
1201
|
-
else {
|
|
1202
|
-
responseText += `⚠️ manifest.json not found at ${manifestPath}\n\n`;
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
catch (error) {
|
|
1206
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1207
|
-
responseText += `⚠️ Failed to update manifest: ${errorMessage}\n\n`;
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
else {
|
|
1211
|
-
responseText += `⏭️ Step 6/8: Skipped (no app ID)\n\n`;
|
|
1212
|
-
}
|
|
1213
|
-
// Step 7: Start dev server
|
|
1214
|
-
if (args.autoStartDevServer !== false) {
|
|
1215
|
-
responseText += `⏳ Step 7/8: Starting dev server on port 3000...\n`;
|
|
1216
|
-
try {
|
|
1217
|
-
// Start dev server in background
|
|
1218
|
-
const devServer = spawn('npm', ['run', 'dev'], {
|
|
1219
|
-
cwd: projectPath,
|
|
1220
|
-
detached: true,
|
|
1221
|
-
stdio: 'ignore',
|
|
1222
|
-
shell: true
|
|
1223
|
-
});
|
|
1224
|
-
devServer.unref();
|
|
1225
|
-
responseText += `✅ Dev server started in background\n`;
|
|
1226
|
-
responseText += ` PID: ${devServer.pid}\n`;
|
|
1227
|
-
responseText += ` URL: http://localhost:3000\n\n`;
|
|
1228
|
-
}
|
|
1229
|
-
catch (error) {
|
|
1230
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1231
|
-
responseText += `⚠️ Failed to start dev server: ${errorMessage}\n`;
|
|
1232
|
-
responseText += ` Start manually: cd ${args.projectName} && npm run dev\n\n`;
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
else {
|
|
1236
|
-
responseText += `⏭️ Step 7/8: Skipped (autoStartDevServer = false)\n\n`;
|
|
1237
|
-
}
|
|
1238
|
-
// Step 8: Complete
|
|
1239
|
-
responseText += `✅ **Step 8/8: Setup Complete!**\n\n`;
|
|
1240
|
-
// Final summary
|
|
1241
|
-
responseText += `## 🎉 Your Hailer App is Ready!\n\n`;
|
|
1242
|
-
responseText += `**What was done:**\n`;
|
|
1243
|
-
responseText += `- ✅ Project scaffolded from ${args.template} template\n`;
|
|
1244
|
-
if (args.installDependencies !== false)
|
|
1245
|
-
responseText += `- ✅ Dependencies installed\n`;
|
|
1246
|
-
responseText += `- ✅ CORS configured for Hailer access\n`;
|
|
1247
|
-
if (appId)
|
|
1248
|
-
responseText += `- ✅ Dev app entry created in Hailer (ID: \`${appId}\`)\n`;
|
|
1249
|
-
if (args.autoShareWithWorkspace !== false && appId)
|
|
1250
|
-
responseText += `- ✅ App shared with entire workspace\n`;
|
|
1251
|
-
if (appId)
|
|
1252
|
-
responseText += `- ✅ manifest.json configured with app ID\n`;
|
|
1253
|
-
if (args.autoStartDevServer !== false)
|
|
1254
|
-
responseText += `- ✅ Dev server started on http://localhost:3000\n`;
|
|
1255
|
-
responseText += `\n## 🚀 Next Steps\n\n`;
|
|
1256
|
-
responseText += `1. **Open the app in Hailer** - Look for "${args.projectName}" in your apps menu\n`;
|
|
1257
|
-
responseText += `2. **Start coding** - Files in \`${projectPath}/src\` will hot-reload\n`;
|
|
1258
|
-
responseText += `3. **View logs** - Check dev server output if needed\n\n`;
|
|
1259
|
-
responseText += `## 📂 Project Location\n\n`;
|
|
1260
|
-
responseText += `\`\`\`\n${projectPath}\n\`\`\`\n\n`;
|
|
1261
|
-
if (appId) {
|
|
1262
|
-
responseText += `## 🔗 App Info\n\n`;
|
|
1263
|
-
responseText += `- **App ID:** \`${appId}\`\n`;
|
|
1264
|
-
responseText += `- **Dev URL:** http://localhost:3000\n`;
|
|
1265
|
-
responseText += `- **Shared with:** Entire workspace\n`;
|
|
1266
|
-
}
|
|
1267
|
-
return {
|
|
1268
|
-
content: [{
|
|
1269
|
-
type: "text",
|
|
1270
|
-
text: responseText,
|
|
1271
|
-
}],
|
|
1272
|
-
};
|
|
1273
|
-
}
|
|
1274
|
-
catch (error) {
|
|
1275
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1276
|
-
return {
|
|
1277
|
-
content: [{
|
|
1278
|
-
type: "text",
|
|
1279
|
-
text: `❌ **Error in one-shot setup**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- Node.js not installed or version < 18\n- npm not available\n- Insufficient permissions\n- Hailer API connection issues`,
|
|
1280
|
-
}],
|
|
1281
|
-
};
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
};
|
|
1285
|
-
// ============================================================================
|
|
1286
|
-
// PUBLISH HAILER APP TOOL
|
|
1287
|
-
// ============================================================================
|
|
1288
|
-
const publishHailerAppDescription = `Publish Hailer app to production - Builds and uploads to Hailer hosting
|
|
1289
|
-
|
|
1290
|
-
⚠️ **MANDATORY: YOU MUST LOAD SKILL FIRST**
|
|
1291
|
-
**BEFORE calling this tool, you are REQUIRED to:**
|
|
1292
|
-
1. Load the skill: \`get_skill({ skillName: "publish-hailer-app-skill" })\`
|
|
1293
|
-
2. Read the complete workflow and prerequisites
|
|
1294
|
-
3. Review troubleshooting tips and common issues
|
|
1295
|
-
**FAILURE TO LOAD THE SKILL FIRST IS AN ERROR**
|
|
1296
|
-
|
|
1297
|
-
**Required Parameters**:
|
|
1298
|
-
- email: Hailer user email
|
|
1299
|
-
- password: User password
|
|
1300
|
-
|
|
1301
|
-
**Project Directory**:
|
|
1302
|
-
- Uses DEV_APPS_PATH from .env.local if set
|
|
1303
|
-
- Falls back to projectDirectory parameter
|
|
1304
|
-
- Falls back to current directory if neither set
|
|
1305
|
-
|
|
1306
|
-
**Prerequisites**: Published app entry exists (create_app with empty URL), manifest.json has appId
|
|
1307
|
-
**Process**: Builds bundle → authenticates → uploads files`;
|
|
1308
|
-
exports.publishHailerAppTool = {
|
|
1309
|
-
name: 'publish_hailer_app',
|
|
1310
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
1311
|
-
description: publishHailerAppDescription,
|
|
1312
|
-
schema: zod_1.z.object({
|
|
1313
|
-
email: zod_1.z.string().email().describe("Hailer user email for authentication"),
|
|
1314
|
-
password: zod_1.z.string().min(1).describe("Hailer user password"),
|
|
1315
|
-
projectDirectory: zod_1.z.string().optional().describe("Path to app project (defaults to current directory)"),
|
|
1316
|
-
appId: zod_1.z.string().optional().describe("App ID to publish to (reads from manifest.json if not provided)")
|
|
1317
|
-
}),
|
|
1318
|
-
async execute(args, _context) {
|
|
1319
|
-
const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
1320
|
-
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
1321
|
-
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
1322
|
-
try {
|
|
1323
|
-
const projectDir = args.projectDirectory || config_1.environment.DEV_APPS_PATH || process.cwd();
|
|
1324
|
-
// Check if directory exists
|
|
1325
|
-
if (!fs.existsSync(projectDir)) {
|
|
1326
|
-
return {
|
|
1327
|
-
content: [{
|
|
1328
|
-
type: "text",
|
|
1329
|
-
text: `❌ **Directory Not Found**\n\nThe directory \`${projectDir}\` does not exist.\n\n**Check:**\n- Project directory path is correct\n- You're in the right location`,
|
|
1330
|
-
}],
|
|
1331
|
-
};
|
|
1332
|
-
}
|
|
1333
|
-
// Check if package.json exists
|
|
1334
|
-
const packageJsonPath = path.join(projectDir, 'package.json');
|
|
1335
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
1336
|
-
return {
|
|
1337
|
-
content: [{
|
|
1338
|
-
type: "text",
|
|
1339
|
-
text: `❌ **Not a Hailer App Project**\n\nNo package.json found in \`${projectDir}\`\n\n**This doesn't appear to be a Hailer app project.**\n\nMake sure you're in the correct directory.`,
|
|
1340
|
-
}],
|
|
1341
|
-
};
|
|
1342
|
-
}
|
|
1343
|
-
// Read manifest.json to get/verify appId
|
|
1344
|
-
const manifestPath = path.join(projectDir, 'public', 'manifest.json');
|
|
1345
|
-
let appId = args.appId;
|
|
1346
|
-
let appName = 'Unknown';
|
|
1347
|
-
if (fs.existsSync(manifestPath)) {
|
|
1348
|
-
try {
|
|
1349
|
-
const manifestContent = fs.readFileSync(manifestPath, 'utf-8');
|
|
1350
|
-
const manifest = JSON.parse(manifestContent);
|
|
1351
|
-
if (!appId) {
|
|
1352
|
-
appId = manifest.appId;
|
|
1353
|
-
}
|
|
1354
|
-
appName = manifest.name || appName;
|
|
1355
|
-
if (!appId) {
|
|
1356
|
-
return {
|
|
1357
|
-
content: [{
|
|
1358
|
-
type: "text",
|
|
1359
|
-
text: `❌ **App ID Not Configured**\n\nNo appId found in \`manifest.json\` and none provided.\n\n**Steps to fix:**\n1. Get your published app ID from Hailer\n2. Edit \`public/manifest.json\`\n3. Set \`"appId": "your-app-id-here"\`\n\nOr provide appId parameter when calling this tool.`,
|
|
1360
|
-
}],
|
|
1361
|
-
};
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
catch (error) {
|
|
1365
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1366
|
-
return {
|
|
1367
|
-
content: [{
|
|
1368
|
-
type: "text",
|
|
1369
|
-
text: `❌ **Invalid manifest.json**\n\nFailed to parse \`public/manifest.json\`: ${errorMessage}\n\n**Check:**\n- manifest.json is valid JSON\n- appId field is set correctly`,
|
|
1370
|
-
}],
|
|
1371
|
-
};
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
else if (!appId) {
|
|
1375
|
-
return {
|
|
1376
|
-
content: [{
|
|
1377
|
-
type: "text",
|
|
1378
|
-
text: `❌ **Manifest Not Found**\n\nNo \`public/manifest.json\` found and no appId provided.\n\n**Steps to fix:**\n1. Ensure \`public/manifest.json\` exists\n2. Set appId in manifest\n\nOr provide appId parameter when calling this tool.`,
|
|
1379
|
-
}],
|
|
1380
|
-
};
|
|
1381
|
-
}
|
|
1382
|
-
let responseText = `🚀 **Publishing Hailer App**\n\n`;
|
|
1383
|
-
responseText += `**App Name:** ${appName}\n`;
|
|
1384
|
-
responseText += `**App ID:** \`${appId}\`\n`;
|
|
1385
|
-
responseText += `**Project:** ${projectDir}\n\n`;
|
|
1386
|
-
// Check if publish-production script exists
|
|
1387
|
-
try {
|
|
1388
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
1389
|
-
if (!packageJson.scripts?.['publish-production']) {
|
|
1390
|
-
return {
|
|
1391
|
-
content: [{
|
|
1392
|
-
type: "text",
|
|
1393
|
-
text: `❌ **Publish Script Not Found**\n\nNo \`publish-production\` script found in package.json.\n\n**This may not be a Hailer app created with @hailer/create-app.**\n\nHailer apps should have:\n\`\`\`json\n"scripts": {\n "publish-production": "...",\n ...\n}\n\`\`\``,
|
|
1394
|
-
}],
|
|
1395
|
-
};
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
catch (error) {
|
|
1399
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1400
|
-
return {
|
|
1401
|
-
content: [{
|
|
1402
|
-
type: "text",
|
|
1403
|
-
text: `❌ **Invalid package.json**\n\n${errorMessage}`,
|
|
1404
|
-
}],
|
|
1405
|
-
};
|
|
1406
|
-
}
|
|
1407
|
-
// Run publish command with email and password
|
|
1408
|
-
responseText += `⏳ Building and publishing app...\n\n`;
|
|
1409
|
-
try {
|
|
1410
|
-
const publishCmd = `EMAIL=${args.email} npm run publish-production`;
|
|
1411
|
-
// Execute with password via stdin
|
|
1412
|
-
const result = execSync(publishCmd, {
|
|
1413
|
-
cwd: projectDir,
|
|
1414
|
-
input: args.password + '\n',
|
|
1415
|
-
encoding: 'utf-8',
|
|
1416
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
1417
|
-
});
|
|
1418
|
-
responseText += `✅ **App Published Successfully!**\n\n`;
|
|
1419
|
-
// Try to parse output for useful info
|
|
1420
|
-
if (result) {
|
|
1421
|
-
responseText += `\`\`\`\n${result.trim()}\n\`\`\`\n\n`;
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
catch (error) {
|
|
1425
|
-
const err = error;
|
|
1426
|
-
const errorOutput = err.stderr || err.stdout || err.message || String(error);
|
|
1427
|
-
// Check for common errors
|
|
1428
|
-
if (errorOutput.includes('Authentication failed') || errorOutput.includes('Invalid credentials')) {
|
|
1429
|
-
return {
|
|
1430
|
-
content: [{
|
|
1431
|
-
type: "text",
|
|
1432
|
-
text: `❌ **Authentication Failed**\n\nInvalid email or password.\n\n**Check:**\n- Email is correct\n- Password is correct\n- Account has access to this workspace`,
|
|
1433
|
-
}],
|
|
1434
|
-
};
|
|
1435
|
-
}
|
|
1436
|
-
if (errorOutput.includes('Permission denied') || errorOutput.includes('not authorized')) {
|
|
1437
|
-
return {
|
|
1438
|
-
content: [{
|
|
1439
|
-
type: "text",
|
|
1440
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to publish this app.\n\n**Requirements:**\n- Must be app creator or workspace admin\n- Must have access to the workspace`,
|
|
1441
|
-
}],
|
|
1442
|
-
};
|
|
1443
|
-
}
|
|
1444
|
-
if (errorOutput.includes('App not found') || errorOutput.includes('Invalid app')) {
|
|
1445
|
-
return {
|
|
1446
|
-
content: [{
|
|
1447
|
-
type: "text",
|
|
1448
|
-
text: `❌ **App Not Found**\n\nApp ID \`${appId}\` not found in Hailer.\n\n**Steps to fix:**\n1. Verify app exists: use \`list_apps\` tool\n2. Check appId in manifest.json is correct\n3. Ensure you created a published app entry (with empty URL)`,
|
|
1449
|
-
}],
|
|
1450
|
-
};
|
|
1451
|
-
}
|
|
1452
|
-
return {
|
|
1453
|
-
content: [{
|
|
1454
|
-
type: "text",
|
|
1455
|
-
text: `❌ **Publish Failed**\n\n\`\`\`\n${errorOutput}\n\`\`\`\n\n**Common Issues:**\n- Build errors (check app code)\n- Network connectivity issues\n- Invalid appId in manifest.json\n- Missing dependencies (run npm install)`,
|
|
1456
|
-
}],
|
|
1457
|
-
};
|
|
1458
|
-
}
|
|
1459
|
-
responseText += `## 📋 Next Steps\n\n`;
|
|
1460
|
-
responseText += `1. **Open published app in Hailer** (not the dev version)\n`;
|
|
1461
|
-
responseText += `2. **Verify functionality** - test all features work\n`;
|
|
1462
|
-
responseText += `3. **Share with users** - use \`add_app_member\` tool:\n`;
|
|
1463
|
-
responseText += ` \`\`\`javascript\n`;
|
|
1464
|
-
responseText += ` add_app_member({\n`;
|
|
1465
|
-
responseText += ` appId: "${appId}",\n`;
|
|
1466
|
-
responseText += ` member: "network_<workspace-id>" // or team_*, user_*\n`;
|
|
1467
|
-
responseText += ` })\n`;
|
|
1468
|
-
responseText += ` \`\`\`\n\n`;
|
|
1469
|
-
responseText += `**Note:** Published files have replaced the previous version of this app.`;
|
|
1470
|
-
return {
|
|
1471
|
-
content: [{
|
|
1472
|
-
type: "text",
|
|
1473
|
-
text: responseText,
|
|
1474
|
-
}],
|
|
1475
|
-
};
|
|
1476
|
-
}
|
|
1477
|
-
catch (error) {
|
|
1478
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1479
|
-
return {
|
|
1480
|
-
content: [{
|
|
1481
|
-
type: "text",
|
|
1482
|
-
text: `❌ **Error publishing Hailer app**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- Not in a Hailer app directory\n- Missing package.json or manifest.json\n- Network connectivity issues\n- Build failures`,
|
|
1483
|
-
}],
|
|
1484
|
-
};
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
};
|
|
1488
|
-
// ============================================================================
|
|
1489
|
-
// LIST TEMPLATES TOOL (MARKETPLACE)
|
|
1490
|
-
// ============================================================================
|
|
1491
|
-
const listTemplatesDescription = `🏪 [PLAYGROUND] List Templates - View marketplace templates available
|
|
1492
|
-
|
|
1493
|
-
**What it does**:
|
|
1494
|
-
Lists all workflow templates available in the Hailer marketplace.
|
|
1495
|
-
|
|
1496
|
-
**Example**:
|
|
1497
|
-
\`\`\`javascript
|
|
1498
|
-
list_templates()
|
|
1499
|
-
\`\`\`
|
|
1500
|
-
|
|
1501
|
-
**Shows**:
|
|
1502
|
-
- Template name and description
|
|
1503
|
-
- Template ID
|
|
1504
|
-
- Creator info
|
|
1505
|
-
- Installation status
|
|
1506
|
-
|
|
1507
|
-
**Use Cases**:
|
|
1508
|
-
- Discover available templates
|
|
1509
|
-
- Find template IDs for installation
|
|
1510
|
-
- Browse marketplace offerings
|
|
1511
|
-
|
|
1512
|
-
**Note**: Products created with \`create_template\` are workspace-specific and won't appear here until published to the public marketplace.`;
|
|
1513
|
-
exports.listTemplatesTool = {
|
|
1514
|
-
name: 'list_templates',
|
|
1515
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
1516
|
-
description: listTemplatesDescription,
|
|
1517
|
-
schema: zod_1.z.object({
|
|
1518
|
-
workspaceId: zod_1.z
|
|
1519
|
-
.string()
|
|
1520
|
-
.optional()
|
|
1521
|
-
.describe("Optional workspace ID - defaults to current workspace"),
|
|
1522
|
-
publicOnly: zod_1.z
|
|
1523
|
-
.boolean()
|
|
1524
|
-
.optional()
|
|
1525
|
-
.default(false)
|
|
1526
|
-
.describe("If true, show only public marketplace templates. If false (default), show private/workspace templates."),
|
|
1527
|
-
}),
|
|
1528
|
-
async execute(args, context) {
|
|
1529
|
-
const showPublic = args.publicOnly ?? false;
|
|
1530
|
-
logger.debug('Listing marketplace templates', {
|
|
1531
|
-
workspaceId: args.workspaceId,
|
|
1532
|
-
publicOnly: showPublic,
|
|
1533
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
1534
|
-
});
|
|
1535
|
-
try {
|
|
1536
|
-
if (!context.workspaceCache) {
|
|
1537
|
-
return {
|
|
1538
|
-
content: [{
|
|
1539
|
-
type: "text",
|
|
1540
|
-
text: "❌ Workspace cache not available",
|
|
1541
|
-
}],
|
|
1542
|
-
};
|
|
1543
|
-
}
|
|
1544
|
-
const workspaceId = args.workspaceId
|
|
1545
|
-
? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
|
|
1546
|
-
: context.workspaceCache.currentWorkspace._id;
|
|
1547
|
-
logger.debug('Calling v3.product.list', { workspaceId, public: showPublic });
|
|
1548
|
-
// v3.product.list endpoint with public flag
|
|
1549
|
-
const result = await context.hailer.request('v3.product.list', [
|
|
1550
|
-
{ cid: workspaceId, public: showPublic },
|
|
1551
|
-
{} // pagination options
|
|
1552
|
-
]);
|
|
1553
|
-
logger.debug('Template list response', {
|
|
1554
|
-
result: JSON.stringify(result)
|
|
1555
|
-
});
|
|
1556
|
-
const templateType = showPublic ? 'Public Marketplace' : 'Private/Workspace';
|
|
1557
|
-
let responseText = `✅ **${templateType} Templates**\n\n`;
|
|
1558
|
-
responseText += `**Workspace:** ${workspaceId}\n`;
|
|
1559
|
-
responseText += `**Filter:** ${showPublic ? 'Public only' : 'Private/workspace'}\n\n`;
|
|
1560
|
-
// Handle response: {products: [], totalCount: 0}
|
|
1561
|
-
const products = result?.products || [];
|
|
1562
|
-
const totalCount = result?.totalCount || 0;
|
|
1563
|
-
if (products.length === 0) {
|
|
1564
|
-
responseText += `**No ${showPublic ? 'public' : 'private'} templates found.**\n\n`;
|
|
1565
|
-
if (showPublic) {
|
|
1566
|
-
responseText += `💡 Try \`list_templates()\` without \`publicOnly: true\` to see private workspace templates.\n`;
|
|
1567
|
-
}
|
|
1568
|
-
else {
|
|
1569
|
-
responseText += `💡 Use \`create_template\` to create a new template.\n`;
|
|
1570
|
-
}
|
|
1571
|
-
return {
|
|
1572
|
-
content: [{
|
|
1573
|
-
type: "text",
|
|
1574
|
-
text: responseText,
|
|
1575
|
-
}],
|
|
1576
|
-
};
|
|
1577
|
-
}
|
|
1578
|
-
const templates = products;
|
|
1579
|
-
responseText += `**Total Templates:** ${templates.length}\n\n`;
|
|
1580
|
-
templates.forEach((template, index) => {
|
|
1581
|
-
responseText += `### ${index + 1}. ${template.name || 'Unnamed Template'}\n`;
|
|
1582
|
-
responseText += `- **ID:** \`${template._id || template.id || 'N/A'}\`\n`;
|
|
1583
|
-
if (template.description) {
|
|
1584
|
-
responseText += `- **Description:** ${template.description}\n`;
|
|
1585
|
-
}
|
|
1586
|
-
if (template.creator) {
|
|
1587
|
-
responseText += `- **Creator:** ${template.creator}\n`;
|
|
1588
|
-
}
|
|
1589
|
-
if (template.version) {
|
|
1590
|
-
responseText += `- **Version:** ${template.version}\n`;
|
|
1591
|
-
}
|
|
1592
|
-
if (template.icon) {
|
|
1593
|
-
responseText += `- **Icon:** \`${template.icon}\`\n`;
|
|
1594
|
-
}
|
|
1595
|
-
if (template.images && template.images.length > 0) {
|
|
1596
|
-
responseText += `- **Images:** ${template.images.map((img) => `\`${img}\``).join(', ')}\n`;
|
|
1597
|
-
}
|
|
1598
|
-
responseText += `\n`;
|
|
1599
|
-
});
|
|
1600
|
-
responseText += `💡 **Next Steps:**\n`;
|
|
1601
|
-
responseText += `- Use \`install_template\` to install a template\n`;
|
|
1602
|
-
responseText += `- Use \`get_template\` to see template details`;
|
|
1603
|
-
return {
|
|
1604
|
-
content: [{
|
|
1605
|
-
type: "text",
|
|
1606
|
-
text: responseText,
|
|
1607
|
-
}],
|
|
1608
|
-
};
|
|
1609
|
-
}
|
|
1610
|
-
catch (error) {
|
|
1611
|
-
logger.error("Error listing templates", error);
|
|
1612
|
-
let errorMessage = 'Unknown error occurred';
|
|
1613
|
-
if (error instanceof Error) {
|
|
1614
|
-
errorMessage = error.message;
|
|
1615
|
-
}
|
|
1616
|
-
else if (typeof error === 'object' && error !== null) {
|
|
1617
|
-
try {
|
|
1618
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
1619
|
-
}
|
|
1620
|
-
catch {
|
|
1621
|
-
errorMessage = String(error);
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
else {
|
|
1625
|
-
errorMessage = String(error);
|
|
1626
|
-
}
|
|
1627
|
-
return {
|
|
1628
|
-
content: [{
|
|
1629
|
-
type: "text",
|
|
1630
|
-
text: `❌ **Error listing templates**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- API endpoint not available\n- Permission issues`,
|
|
1631
|
-
}],
|
|
1632
|
-
};
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
};
|
|
1636
|
-
// ============================================================================
|
|
1637
|
-
// CREATE TEMPLATE TOOL (MARKETPLACE)
|
|
1638
|
-
// ============================================================================
|
|
1639
|
-
const createTemplateDescription = `🏪 [PLAYGROUND] Create Template - Add template to marketplace
|
|
1640
|
-
|
|
1641
|
-
**What it does**:
|
|
1642
|
-
Creates a new workflow template in the Hailer marketplace.
|
|
1643
|
-
|
|
1644
|
-
**Example**:
|
|
1645
|
-
\`\`\`javascript
|
|
1646
|
-
create_template({
|
|
1647
|
-
name: 'Project Management',
|
|
1648
|
-
description: 'Template for managing projects',
|
|
1649
|
-
workflowId: '<source-workflow-id>'
|
|
1650
|
-
})
|
|
1651
|
-
\`\`\`
|
|
1652
|
-
|
|
1653
|
-
**Parameters**:
|
|
1654
|
-
- \`name\` (required) - Template name
|
|
1655
|
-
- \`description\` (optional) - Template description
|
|
1656
|
-
- \`workflowId\` (optional) - Source workflow to create template from
|
|
1657
|
-
|
|
1658
|
-
**Requirements**:
|
|
1659
|
-
- User must be workspace administrator
|
|
1660
|
-
|
|
1661
|
-
**Tips**:
|
|
1662
|
-
- Create template from existing workflow
|
|
1663
|
-
- Use descriptive names for discoverability`;
|
|
1664
|
-
exports.createTemplateTool = {
|
|
1665
|
-
name: 'create_template',
|
|
1666
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
1667
|
-
description: createTemplateDescription,
|
|
1668
|
-
schema: zod_1.z.object({
|
|
1669
|
-
name: zod_1.z
|
|
1670
|
-
.string()
|
|
1671
|
-
.min(1)
|
|
1672
|
-
.describe("Template name (required)"),
|
|
1673
|
-
description: zod_1.z
|
|
1674
|
-
.string()
|
|
1675
|
-
.optional()
|
|
1676
|
-
.describe("Template description"),
|
|
1677
|
-
workflowId: zod_1.z
|
|
1678
|
-
.string()
|
|
1679
|
-
.optional()
|
|
1680
|
-
.describe("Source workflow ID to create template from"),
|
|
1681
|
-
}),
|
|
1682
|
-
async execute(args, context) {
|
|
1683
|
-
logger.debug('Creating marketplace template', {
|
|
1684
|
-
name: args.name,
|
|
1685
|
-
hasWorkflowId: !!args.workflowId,
|
|
1686
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
1687
|
-
});
|
|
1688
|
-
try {
|
|
1689
|
-
if (!context.workspaceCache) {
|
|
1690
|
-
return {
|
|
1691
|
-
content: [{
|
|
1692
|
-
type: "text",
|
|
1693
|
-
text: "❌ Workspace cache not available",
|
|
1694
|
-
}],
|
|
1695
|
-
};
|
|
1696
|
-
}
|
|
1697
|
-
const workspaceId = context.workspaceCache.currentWorkspace._id;
|
|
1698
|
-
// v2.network.product.create - creates a product entry (only accepts name)
|
|
1699
|
-
const templateData = {
|
|
1700
|
-
name: args.name
|
|
1701
|
-
};
|
|
1702
|
-
logger.debug('Calling v2.network.product.create', {
|
|
1703
|
-
workspaceId,
|
|
1704
|
-
templateData
|
|
1705
|
-
});
|
|
1706
|
-
const result = await context.hailer.request('v2.network.product.create', [templateData]);
|
|
1707
|
-
logger.debug('Template creation response', {
|
|
1708
|
-
result: JSON.stringify(result)
|
|
1709
|
-
});
|
|
1710
|
-
const templateId = result?.productId || result?._id || result?.id;
|
|
1711
|
-
let responseText = `✅ **Template Created Successfully**\n\n`;
|
|
1712
|
-
responseText += `**Template Name:** ${args.name}\n`;
|
|
1713
|
-
responseText += `**Template ID:** \`${templateId || 'See response'}\`\n`;
|
|
1714
|
-
responseText += `**Workspace:** ${workspaceId}\n`;
|
|
1715
|
-
responseText += `\n💡 **Next Steps:**\n`;
|
|
1716
|
-
responseText += `- Use Hailer marketplace UI to add workflows and description\n`;
|
|
1717
|
-
responseText += `- Share the template ID with others to install\n`;
|
|
1718
|
-
if (args.description || args.workflowId) {
|
|
1719
|
-
responseText += `\n⚠️ **Note:** The \`v3.app.product.create\` API only accepts \`name\`.\n`;
|
|
1720
|
-
responseText += `Description and workflow attachment must be done via Hailer UI.\n`;
|
|
1721
|
-
}
|
|
1722
|
-
return {
|
|
1723
|
-
content: [{
|
|
1724
|
-
type: "text",
|
|
1725
|
-
text: responseText,
|
|
1726
|
-
}],
|
|
1727
|
-
};
|
|
1728
|
-
}
|
|
1729
|
-
catch (error) {
|
|
1730
|
-
logger.error("Error creating template", error);
|
|
1731
|
-
let errorMessage = 'Unknown error occurred';
|
|
1732
|
-
if (error instanceof Error) {
|
|
1733
|
-
errorMessage = error.message;
|
|
1734
|
-
}
|
|
1735
|
-
else if (typeof error === 'object' && error !== null) {
|
|
1736
|
-
try {
|
|
1737
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
1738
|
-
}
|
|
1739
|
-
catch {
|
|
1740
|
-
errorMessage = String(error);
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1743
|
-
else {
|
|
1744
|
-
errorMessage = String(error);
|
|
1745
|
-
}
|
|
1746
|
-
if (errorMessage.toLowerCase().includes('permission')) {
|
|
1747
|
-
return {
|
|
1748
|
-
content: [{
|
|
1749
|
-
type: "text",
|
|
1750
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to create templates. Only workspace administrators can create templates.\n\n**Error:** ${errorMessage}`,
|
|
1751
|
-
}],
|
|
1752
|
-
};
|
|
1753
|
-
}
|
|
1754
|
-
return {
|
|
1755
|
-
content: [{
|
|
1756
|
-
type: "text",
|
|
1757
|
-
text: `❌ **Error creating template**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- User must be workspace administrator\n- Invalid workflow ID`,
|
|
1758
|
-
}],
|
|
1759
|
-
};
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
};
|
|
1763
|
-
// ============================================================================
|
|
1764
|
-
// INSTALL TEMPLATE TOOL (MARKETPLACE)
|
|
1765
|
-
// ============================================================================
|
|
1766
|
-
const installTemplateDescription = `🏪 [PLAYGROUND] Install Template - Install marketplace template to workspace
|
|
1767
|
-
|
|
1768
|
-
**What it does**:
|
|
1769
|
-
Installs a template from the Hailer marketplace into your workspace.
|
|
1770
|
-
|
|
1771
|
-
**Example**:
|
|
1772
|
-
\`\`\`javascript
|
|
1773
|
-
install_template({
|
|
1774
|
-
templateId: '<template-id>'
|
|
1775
|
-
})
|
|
1776
|
-
\`\`\`
|
|
1777
|
-
|
|
1778
|
-
**Parameters**:
|
|
1779
|
-
- \`templateId\` (required) - Template/Product ID from marketplace
|
|
1780
|
-
|
|
1781
|
-
**Requirements**:
|
|
1782
|
-
- User must be workspace administrator
|
|
1783
|
-
|
|
1784
|
-
**Tips**:
|
|
1785
|
-
- Use \`list_templates\` to find template IDs
|
|
1786
|
-
- Template creates new workflow(s) in workspace`;
|
|
1787
|
-
exports.installTemplateTool = {
|
|
1788
|
-
name: 'install_template',
|
|
1789
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
1790
|
-
description: installTemplateDescription,
|
|
1791
|
-
schema: zod_1.z.object({
|
|
1792
|
-
templateId: zod_1.z
|
|
1793
|
-
.string()
|
|
1794
|
-
.min(1)
|
|
1795
|
-
.describe("Template/Product ID to install"),
|
|
1796
|
-
workspaceId: zod_1.z
|
|
1797
|
-
.string()
|
|
1798
|
-
.optional()
|
|
1799
|
-
.describe("Target workspace ID (defaults to current)"),
|
|
1800
|
-
}),
|
|
1801
|
-
async execute(args, context) {
|
|
1802
|
-
logger.debug('Installing marketplace template', {
|
|
1803
|
-
templateId: args.templateId,
|
|
1804
|
-
workspaceId: args.workspaceId,
|
|
1805
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
1806
|
-
});
|
|
1807
|
-
try {
|
|
1808
|
-
if (!context.workspaceCache) {
|
|
1809
|
-
return {
|
|
1810
|
-
content: [{
|
|
1811
|
-
type: "text",
|
|
1812
|
-
text: "❌ Workspace cache not available",
|
|
1813
|
-
}],
|
|
1814
|
-
};
|
|
1815
|
-
}
|
|
1816
|
-
const workspaceId = args.workspaceId
|
|
1817
|
-
? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
|
|
1818
|
-
: context.workspaceCache.currentWorkspace._id;
|
|
1819
|
-
if (!workspaceId) {
|
|
1820
|
-
return {
|
|
1821
|
-
content: [{
|
|
1822
|
-
type: "text",
|
|
1823
|
-
text: `❌ Could not resolve workspace: ${args.workspaceId}`,
|
|
1824
|
-
}],
|
|
1825
|
-
};
|
|
1826
|
-
}
|
|
1827
|
-
logger.debug('Calling v2.network.product.install', {
|
|
1828
|
-
templateId: args.templateId,
|
|
1829
|
-
workspaceId
|
|
1830
|
-
});
|
|
1831
|
-
const result = await context.hailer.request('v2.network.product.install', [
|
|
1832
|
-
args.templateId,
|
|
1833
|
-
workspaceId
|
|
1834
|
-
]);
|
|
1835
|
-
logger.debug('Template installation response', {
|
|
1836
|
-
result: JSON.stringify(result)
|
|
1837
|
-
});
|
|
1838
|
-
const appId = result?.appId || result?._id;
|
|
1839
|
-
let responseText = `✅ **Template Installed Successfully**\n\n`;
|
|
1840
|
-
responseText += `**Template ID:** \`${args.templateId}\`\n`;
|
|
1841
|
-
responseText += `**Workspace:** ${workspaceId}\n`;
|
|
1842
|
-
if (appId) {
|
|
1843
|
-
responseText += `**App ID:** \`${appId}\`\n`;
|
|
1844
|
-
}
|
|
1845
|
-
responseText += `\n💡 **Next Steps:**\n`;
|
|
1846
|
-
responseText += `- Use \`list_workflows\` to see new workflow(s)\n`;
|
|
1847
|
-
responseText += `- Use \`list_apps\` to see new app(s)\n`;
|
|
1848
|
-
return {
|
|
1849
|
-
content: [{
|
|
1850
|
-
type: "text",
|
|
1851
|
-
text: responseText,
|
|
1852
|
-
}],
|
|
1853
|
-
};
|
|
1854
|
-
}
|
|
1855
|
-
catch (error) {
|
|
1856
|
-
logger.error("Error installing template", error);
|
|
1857
|
-
let errorMessage = 'Unknown error occurred';
|
|
1858
|
-
if (error instanceof Error) {
|
|
1859
|
-
errorMessage = error.message;
|
|
1860
|
-
}
|
|
1861
|
-
else if (typeof error === 'object' && error !== null) {
|
|
1862
|
-
try {
|
|
1863
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
1864
|
-
}
|
|
1865
|
-
catch {
|
|
1866
|
-
errorMessage = String(error);
|
|
1867
|
-
}
|
|
1868
|
-
}
|
|
1869
|
-
else {
|
|
1870
|
-
errorMessage = String(error);
|
|
1871
|
-
}
|
|
1872
|
-
if (errorMessage.toLowerCase().includes('not found')) {
|
|
1873
|
-
return {
|
|
1874
|
-
content: [{
|
|
1875
|
-
type: "text",
|
|
1876
|
-
text: `❌ **Template Not Found**\n\nTemplate ID \`${args.templateId}\` not found in marketplace.\n\n**Check:**\n- Template ID is correct\n- Template is published and available\n\n💡 Use \`list_templates\` to see available templates.`,
|
|
1877
|
-
}],
|
|
1878
|
-
};
|
|
1879
|
-
}
|
|
1880
|
-
if (errorMessage.toLowerCase().includes('permission')) {
|
|
1881
|
-
return {
|
|
1882
|
-
content: [{
|
|
1883
|
-
type: "text",
|
|
1884
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to install templates. Only workspace administrators can install templates.\n\n**Error:** ${errorMessage}`,
|
|
1885
|
-
}],
|
|
1886
|
-
};
|
|
1887
|
-
}
|
|
1888
|
-
if (errorMessage.toLowerCase().includes('already installed')) {
|
|
1889
|
-
return {
|
|
1890
|
-
content: [{
|
|
1891
|
-
type: "text",
|
|
1892
|
-
text: `⚠️ **Template Already Installed**\n\nThis template is already installed in the workspace.\n\n**Template ID:** \`${args.templateId}\`\n\n💡 Use \`list_apps\` to see installed apps.`,
|
|
1893
|
-
}],
|
|
1894
|
-
};
|
|
1895
|
-
}
|
|
1896
|
-
// Include debug info for troubleshooting
|
|
1897
|
-
const debugInfo = {
|
|
1898
|
-
endpoint: 'v2.network.product.install',
|
|
1899
|
-
requestData: [args.templateId, args.workspaceId || 'current-workspace']
|
|
1900
|
-
};
|
|
1901
|
-
return {
|
|
1902
|
-
content: [{
|
|
1903
|
-
type: "text",
|
|
1904
|
-
text: `❌ **Error installing template**\n\n**Error:** ${errorMessage}\n\n**Debug Info:**\n\`\`\`json\n${JSON.stringify(debugInfo, null, 2)}\n\`\`\`\n\n**Common Issues:**\n- Invalid template ID\n- Template not found\n- Permission denied\n- Already installed`,
|
|
1905
|
-
}],
|
|
1906
|
-
};
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
};
|
|
1910
|
-
// ============================================================================
|
|
1911
|
-
// GET TEMPLATE TOOL (MARKETPLACE)
|
|
1912
|
-
// ============================================================================
|
|
1913
|
-
const getTemplateDescription = `🏪 [PLAYGROUND] Get Template - View template details from marketplace
|
|
1914
|
-
|
|
1915
|
-
**What it does**:
|
|
1916
|
-
Retrieves detailed information about a specific marketplace template.
|
|
1917
|
-
|
|
1918
|
-
**Example**:
|
|
1919
|
-
\`\`\`javascript
|
|
1920
|
-
get_template({
|
|
1921
|
-
templateId: '<template-id>'
|
|
1922
|
-
})
|
|
1923
|
-
\`\`\`
|
|
1924
|
-
|
|
1925
|
-
**Shows**:
|
|
1926
|
-
- Template name and description
|
|
1927
|
-
- Template version
|
|
1928
|
-
- Included workflows
|
|
1929
|
-
- Manifest information
|
|
1930
|
-
|
|
1931
|
-
**Use Cases**:
|
|
1932
|
-
- Preview template before installing
|
|
1933
|
-
- Check template version
|
|
1934
|
-
- View template structure`;
|
|
1935
|
-
exports.getTemplateTool = {
|
|
1936
|
-
name: 'get_template',
|
|
1937
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
1938
|
-
description: getTemplateDescription,
|
|
1939
|
-
schema: zod_1.z.object({
|
|
1940
|
-
templateId: zod_1.z
|
|
1941
|
-
.string()
|
|
1942
|
-
.min(1)
|
|
1943
|
-
.describe("Template/Product ID to get details for"),
|
|
1944
|
-
}),
|
|
1945
|
-
async execute(args, context) {
|
|
1946
|
-
logger.debug('Getting marketplace template', {
|
|
1947
|
-
templateId: args.templateId,
|
|
1948
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
1949
|
-
});
|
|
1950
|
-
try {
|
|
1951
|
-
logger.debug('Calling v2.network.product.get', {
|
|
1952
|
-
templateId: args.templateId
|
|
1953
|
-
});
|
|
1954
|
-
const result = await context.hailer.request('v2.network.product.get', [args.templateId]);
|
|
1955
|
-
logger.debug('Template get response', {
|
|
1956
|
-
result: JSON.stringify(result)
|
|
1957
|
-
});
|
|
1958
|
-
const product = result?.product || result;
|
|
1959
|
-
let responseText = `✅ **Template Details**\n\n`;
|
|
1960
|
-
responseText += `**Template ID:** \`${args.templateId}\`\n`;
|
|
1961
|
-
if (product?.name) {
|
|
1962
|
-
responseText += `**Name:** ${product.name}\n`;
|
|
1963
|
-
}
|
|
1964
|
-
if (product?.description) {
|
|
1965
|
-
responseText += `**Description:** ${product.description}\n`;
|
|
1966
|
-
}
|
|
1967
|
-
if (product?.version) {
|
|
1968
|
-
responseText += `**Version:** ${product.version}\n`;
|
|
1969
|
-
}
|
|
1970
|
-
// Also try to get manifest
|
|
1971
|
-
try {
|
|
1972
|
-
const manifest = await context.hailer.request('v2.network.product.getManifest', [args.templateId]);
|
|
1973
|
-
logger.debug('Template manifest response', {
|
|
1974
|
-
manifest: JSON.stringify(manifest)
|
|
1975
|
-
});
|
|
1976
|
-
if (manifest) {
|
|
1977
|
-
responseText += `\n**Manifest:**\n\`\`\`json\n${JSON.stringify(manifest, null, 2)}\n\`\`\`\n`;
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
catch (manifestError) {
|
|
1981
|
-
logger.debug('Could not fetch manifest', { error: manifestError });
|
|
1982
|
-
}
|
|
1983
|
-
// Check if installed (needs productId and workspaceId)
|
|
1984
|
-
try {
|
|
1985
|
-
if (context.workspaceCache) {
|
|
1986
|
-
const workspaceId = context.workspaceCache.currentWorkspace._id;
|
|
1987
|
-
const installed = await context.hailer.request('v2.network.product.isProductInstalled', [
|
|
1988
|
-
args.templateId,
|
|
1989
|
-
workspaceId
|
|
1990
|
-
]);
|
|
1991
|
-
logger.debug('Template installation check', {
|
|
1992
|
-
installed: JSON.stringify(installed)
|
|
1993
|
-
});
|
|
1994
|
-
if (installed?.installed) {
|
|
1995
|
-
responseText += `\n✅ **Status:** Installed in current workspace\n`;
|
|
1996
|
-
if (installed.appId) {
|
|
1997
|
-
responseText += `**App ID:** \`${installed.appId}\`\n`;
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
else {
|
|
2001
|
-
responseText += `\n⚪ **Status:** Not installed in current workspace\n`;
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
catch (installCheckError) {
|
|
2006
|
-
logger.debug('Could not check installation status', { error: installCheckError });
|
|
2007
|
-
}
|
|
2008
|
-
responseText += `\n💡 **Next Steps:**\n`;
|
|
2009
|
-
responseText += `- Use \`install_template\` to install this template\n`;
|
|
2010
|
-
responseText += `- Use \`list_templates\` to see other templates`;
|
|
2011
|
-
return {
|
|
2012
|
-
content: [{
|
|
2013
|
-
type: "text",
|
|
2014
|
-
text: responseText,
|
|
2015
|
-
}],
|
|
2016
|
-
};
|
|
2017
|
-
}
|
|
2018
|
-
catch (error) {
|
|
2019
|
-
logger.error("Error getting template", error);
|
|
2020
|
-
let errorMessage = 'Unknown error occurred';
|
|
2021
|
-
if (error instanceof Error) {
|
|
2022
|
-
errorMessage = error.message;
|
|
2023
|
-
}
|
|
2024
|
-
else if (typeof error === 'object' && error !== null) {
|
|
2025
|
-
try {
|
|
2026
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
2027
|
-
}
|
|
2028
|
-
catch {
|
|
2029
|
-
errorMessage = String(error);
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
|
-
else {
|
|
2033
|
-
errorMessage = String(error);
|
|
2034
|
-
}
|
|
2035
|
-
if (errorMessage.toLowerCase().includes('not found')) {
|
|
2036
|
-
return {
|
|
2037
|
-
content: [{
|
|
2038
|
-
type: "text",
|
|
2039
|
-
text: `❌ **Template Not Found**\n\nTemplate ID \`${args.templateId}\` not found in marketplace.\n\n**Check:**\n- Template ID is correct\n- Template exists and is published\n\n💡 Use \`list_templates\` to see available templates.`,
|
|
2040
|
-
}],
|
|
2041
|
-
};
|
|
2042
|
-
}
|
|
2043
|
-
return {
|
|
2044
|
-
content: [{
|
|
2045
|
-
type: "text",
|
|
2046
|
-
text: `❌ **Error getting template**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- Invalid template ID\n- Template not found`,
|
|
2047
|
-
}],
|
|
2048
|
-
};
|
|
2049
|
-
}
|
|
2050
|
-
}
|
|
2051
|
-
};
|
|
2052
|
-
// ============================================================================
|
|
2053
|
-
// PUBLISH TEMPLATE TOOL (MARKETPLACE)
|
|
2054
|
-
// ============================================================================
|
|
2055
|
-
const publishTemplateDescription = `🏪 [PLAYGROUND] Publish Template - Publish workspace to marketplace
|
|
2056
|
-
|
|
2057
|
-
**What it does**:
|
|
2058
|
-
Publishes the current workspace as a template to the Hailer marketplace, making it installable by other workspaces.
|
|
2059
|
-
|
|
2060
|
-
**Example - New Template**:
|
|
2061
|
-
\`\`\`javascript
|
|
2062
|
-
publish_template({
|
|
2063
|
-
title: 'Football Manager',
|
|
2064
|
-
description: 'Complete football club management workspace',
|
|
2065
|
-
version: '1.0.0',
|
|
2066
|
-
versionDescription: 'Initial release with Players, Matches, Training workflows',
|
|
2067
|
-
publisher: 'Hailer Oy',
|
|
2068
|
-
iconFileId: '692d3e66e98c7bab4af7f0a1'
|
|
2069
|
-
})
|
|
2070
|
-
\`\`\`
|
|
2071
|
-
|
|
2072
|
-
**Example - Update Existing Template**:
|
|
2073
|
-
\`\`\`javascript
|
|
2074
|
-
publish_template({
|
|
2075
|
-
productId: '692d46bfca77093f10b0c09a', // Existing product ID
|
|
2076
|
-
title: 'Football Manager',
|
|
2077
|
-
description: 'Updated description',
|
|
2078
|
-
version: '1.1.0',
|
|
2079
|
-
versionDescription: 'Fixed icon and added new features',
|
|
2080
|
-
publisher: 'Hailer Oy',
|
|
2081
|
-
iconFileId: '692d47adf9383bd1a9e26d78'
|
|
2082
|
-
})
|
|
2083
|
-
\`\`\`
|
|
2084
|
-
|
|
2085
|
-
**Required Parameters** (gather ALL before calling):
|
|
2086
|
-
- \`title\` - Template name (max 64 chars)
|
|
2087
|
-
- \`description\` - Template description (max 4096 chars)
|
|
2088
|
-
- \`version\` - Version string (e.g. "1.0.0")
|
|
2089
|
-
- \`versionDescription\` - Release notes for this version
|
|
2090
|
-
- \`publisher\` - Publishing company/person name
|
|
2091
|
-
- \`iconFileId\` - Icon file ID (upload with \`upload_files\` first)
|
|
2092
|
-
|
|
2093
|
-
**Optional Parameters**:
|
|
2094
|
-
- \`productId\` - Existing product ID to UPDATE (omit to create new)
|
|
2095
|
-
- \`imageFileIds\` - Array of preview image file IDs
|
|
2096
|
-
- \`externalUrl\` - External website URL
|
|
2097
|
-
|
|
2098
|
-
**IMPORTANT**: A PreToolUse hook will BLOCK this call if required fields are missing.
|
|
2099
|
-
Gather ALL information from user BEFORE calling this tool.
|
|
2100
|
-
|
|
2101
|
-
**Workflow**:
|
|
2102
|
-
1. Ask user for template details (name, description, version, etc.)
|
|
2103
|
-
2. Ask user for icon (URL, path, or existing fileId)
|
|
2104
|
-
3. Upload icon with \`upload_files\`
|
|
2105
|
-
4. Call \`publish_template\` with ALL fields
|
|
2106
|
-
5. To UPDATE: include \`productId\` from previous publish
|
|
2107
|
-
|
|
2108
|
-
**What Gets Published**:
|
|
2109
|
-
- The ENTIRE current workspace is published as a template
|
|
2110
|
-
- All workflows, fields, phases are included
|
|
2111
|
-
|
|
2112
|
-
**After Publishing**:
|
|
2113
|
-
- Template appears in \`list_templates()\`
|
|
2114
|
-
- Other workspaces can install with \`install_template()\``;
|
|
2115
|
-
exports.publishTemplateTool = {
|
|
2116
|
-
name: 'publish_template',
|
|
2117
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
2118
|
-
description: publishTemplateDescription,
|
|
2119
|
-
schema: zod_1.z.object({
|
|
2120
|
-
productId: zod_1.z
|
|
2121
|
-
.string()
|
|
2122
|
-
.length(24)
|
|
2123
|
-
.optional()
|
|
2124
|
-
.describe("Existing product ID to UPDATE (omit to create new template)"),
|
|
2125
|
-
title: zod_1.z
|
|
2126
|
-
.string()
|
|
2127
|
-
.min(1)
|
|
2128
|
-
.max(64)
|
|
2129
|
-
.describe("Template name (max 64 chars)"),
|
|
2130
|
-
description: zod_1.z
|
|
2131
|
-
.string()
|
|
2132
|
-
.min(1)
|
|
2133
|
-
.max(4096)
|
|
2134
|
-
.describe("Template description (max 4096 chars)"),
|
|
2135
|
-
version: zod_1.z
|
|
2136
|
-
.string()
|
|
2137
|
-
.min(1)
|
|
2138
|
-
.describe("Version string (e.g. '1.0.0')"),
|
|
2139
|
-
versionDescription: zod_1.z
|
|
2140
|
-
.string()
|
|
2141
|
-
.min(1)
|
|
2142
|
-
.describe("Release notes for this version"),
|
|
2143
|
-
publisher: zod_1.z
|
|
2144
|
-
.string()
|
|
2145
|
-
.min(1)
|
|
2146
|
-
.describe("Publishing company or person name"),
|
|
2147
|
-
iconFileId: zod_1.z
|
|
2148
|
-
.string()
|
|
2149
|
-
.length(24)
|
|
2150
|
-
.describe("Icon file ID (24 chars). Upload with upload_files first"),
|
|
2151
|
-
imageFileIds: zod_1.z
|
|
2152
|
-
.array(zod_1.z.string().length(24))
|
|
2153
|
-
.optional()
|
|
2154
|
-
.describe("Optional array of preview image file IDs"),
|
|
2155
|
-
externalUrl: zod_1.z
|
|
2156
|
-
.string()
|
|
2157
|
-
.url()
|
|
2158
|
-
.optional()
|
|
2159
|
-
.describe("Optional external website URL"),
|
|
2160
|
-
}),
|
|
2161
|
-
async execute(args, context) {
|
|
2162
|
-
const isUpdate = !!args.productId;
|
|
2163
|
-
logger.debug(`${isUpdate ? 'Updating' : 'Publishing'} template to marketplace`, {
|
|
2164
|
-
title: args.title,
|
|
2165
|
-
version: args.version,
|
|
2166
|
-
productId: args.productId,
|
|
2167
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
2168
|
-
});
|
|
2169
|
-
try {
|
|
2170
|
-
if (!context.workspaceCache) {
|
|
2171
|
-
return {
|
|
2172
|
-
content: [{
|
|
2173
|
-
type: "text",
|
|
2174
|
-
text: "❌ Workspace cache not available",
|
|
2175
|
-
}],
|
|
2176
|
-
};
|
|
2177
|
-
}
|
|
2178
|
-
const workspaceId = context.workspaceCache.currentWorkspace._id;
|
|
2179
|
-
let productId = args.productId;
|
|
2180
|
-
// Only create new manifest if not updating existing template
|
|
2181
|
-
if (!isUpdate) {
|
|
2182
|
-
// Note: versionDescription is required and cannot be empty
|
|
2183
|
-
const publishData = {
|
|
2184
|
-
workspaceId,
|
|
2185
|
-
version: args.version,
|
|
2186
|
-
versionDescription: args.versionDescription,
|
|
2187
|
-
title: args.title,
|
|
2188
|
-
description: args.description
|
|
2189
|
-
};
|
|
2190
|
-
logger.debug('Calling v2.network.product.publishTemplate', {
|
|
2191
|
-
publishData
|
|
2192
|
-
});
|
|
2193
|
-
// Step 1: Create the template manifest
|
|
2194
|
-
const publishResult = await context.hailer.request('v2.network.product.publishTemplate', [publishData]);
|
|
2195
|
-
logger.debug('Publish template response', {
|
|
2196
|
-
result: JSON.stringify(publishResult)
|
|
2197
|
-
});
|
|
2198
|
-
productId = publishResult?.productId || publishResult?._id || publishResult?.id;
|
|
2199
|
-
if (!productId) {
|
|
2200
|
-
return {
|
|
2201
|
-
content: [{
|
|
2202
|
-
type: "text",
|
|
2203
|
-
text: `❌ **Error**: publishTemplate succeeded but no product ID returned.\n\n**Response:**\n\`\`\`json\n${JSON.stringify(publishResult, null, 2)}\n\`\`\``,
|
|
2204
|
-
}],
|
|
2205
|
-
};
|
|
2206
|
-
}
|
|
2207
|
-
}
|
|
2208
|
-
// Step 2: Create or Update the product in marketplace
|
|
2209
|
-
let productData;
|
|
2210
|
-
let apiMethod;
|
|
2211
|
-
let apiArgs;
|
|
2212
|
-
if (isUpdate) {
|
|
2213
|
-
// Update only allows specific fields
|
|
2214
|
-
productData = {
|
|
2215
|
-
name: args.title,
|
|
2216
|
-
description: args.description,
|
|
2217
|
-
publisher: args.publisher,
|
|
2218
|
-
icon: args.iconFileId,
|
|
2219
|
-
images: args.imageFileIds || [args.iconFileId]
|
|
2220
|
-
};
|
|
2221
|
-
if (args.externalUrl) {
|
|
2222
|
-
productData.externalUrl = args.externalUrl;
|
|
2223
|
-
}
|
|
2224
|
-
apiMethod = 'v3.product.update';
|
|
2225
|
-
apiArgs = [productId, productData];
|
|
2226
|
-
}
|
|
2227
|
-
else {
|
|
2228
|
-
// Create requires full data
|
|
2229
|
-
productData = {
|
|
2230
|
-
cid: workspaceId,
|
|
2231
|
-
targetId: productId,
|
|
2232
|
-
name: args.title,
|
|
2233
|
-
description: args.description,
|
|
2234
|
-
type: 'template',
|
|
2235
|
-
publisher: args.publisher,
|
|
2236
|
-
icon: args.iconFileId,
|
|
2237
|
-
images: args.imageFileIds || [args.iconFileId]
|
|
2238
|
-
};
|
|
2239
|
-
if (args.externalUrl) {
|
|
2240
|
-
productData.externalUrl = args.externalUrl;
|
|
2241
|
-
}
|
|
2242
|
-
apiMethod = 'v3.product.create';
|
|
2243
|
-
apiArgs = [productData];
|
|
2244
|
-
}
|
|
2245
|
-
logger.debug(`Calling ${apiMethod}`, { productId, workspaceId, iconFileId: args.iconFileId });
|
|
2246
|
-
const apiResult = await context.hailer.request(apiMethod, apiArgs);
|
|
2247
|
-
logger.debug(`${apiMethod} response`, {
|
|
2248
|
-
result: JSON.stringify(apiResult)
|
|
2249
|
-
});
|
|
2250
|
-
// Get the final product ID from the v3 API response (this is the correct marketplace ID)
|
|
2251
|
-
const finalProductId = apiResult?._id || apiResult?.id || productId;
|
|
2252
|
-
let responseText = `✅ **Template ${isUpdate ? 'Updated' : 'Published'} Successfully**\n\n`;
|
|
2253
|
-
responseText += `**Title:** ${args.title}\n`;
|
|
2254
|
-
responseText += `**Publisher:** ${args.publisher}\n`;
|
|
2255
|
-
responseText += `**Version:** ${args.version}\n`;
|
|
2256
|
-
responseText += `**Workspace:** ${workspaceId}\n`;
|
|
2257
|
-
responseText += `**Product ID:** \`${finalProductId}\`\n`;
|
|
2258
|
-
responseText += `**Release Notes:** ${args.versionDescription}\n`;
|
|
2259
|
-
responseText += `\n💡 **Next Steps:**\n`;
|
|
2260
|
-
responseText += `- Use \`list_templates()\` to see it in the marketplace\n`;
|
|
2261
|
-
responseText += `- Share the product ID with other workspaces\n`;
|
|
2262
|
-
responseText += `- They can install with \`install_template({ templateId: "${finalProductId}" })\`\n`;
|
|
2263
|
-
return {
|
|
2264
|
-
content: [{
|
|
2265
|
-
type: "text",
|
|
2266
|
-
text: responseText,
|
|
2267
|
-
}],
|
|
2268
|
-
};
|
|
2269
|
-
}
|
|
2270
|
-
catch (error) {
|
|
2271
|
-
logger.error("Error publishing template", error);
|
|
2272
|
-
let errorMessage = 'Unknown error occurred';
|
|
2273
|
-
if (error instanceof Error) {
|
|
2274
|
-
errorMessage = error.message;
|
|
2275
|
-
}
|
|
2276
|
-
else if (typeof error === 'object' && error !== null) {
|
|
2277
|
-
try {
|
|
2278
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
2279
|
-
}
|
|
2280
|
-
catch {
|
|
2281
|
-
errorMessage = String(error);
|
|
2282
|
-
}
|
|
2283
|
-
}
|
|
2284
|
-
else {
|
|
2285
|
-
errorMessage = String(error);
|
|
2286
|
-
}
|
|
2287
|
-
if (errorMessage.toLowerCase().includes('permission')) {
|
|
2288
|
-
return {
|
|
2289
|
-
content: [{
|
|
2290
|
-
type: "text",
|
|
2291
|
-
text: `❌ **Permission Denied**\n\nYou don't have permission to publish templates. Only workspace administrators can publish.\n\n**Error:** ${errorMessage}`,
|
|
2292
|
-
}],
|
|
2293
|
-
};
|
|
2294
|
-
}
|
|
2295
|
-
// Always include debug info for troubleshooting
|
|
2296
|
-
const debugWorkspaceId = context.workspaceCache?.currentWorkspace._id || 'unknown';
|
|
2297
|
-
const debugInfo = {
|
|
2298
|
-
endpoint: 'v2.network.product.publishTemplate',
|
|
2299
|
-
requestData: {
|
|
2300
|
-
workspaceId: debugWorkspaceId,
|
|
2301
|
-
version: args.version,
|
|
2302
|
-
versionDescription: args.versionDescription,
|
|
2303
|
-
title: args.title,
|
|
2304
|
-
description: args.description
|
|
2305
|
-
}
|
|
2306
|
-
};
|
|
2307
|
-
return {
|
|
2308
|
-
content: [{
|
|
2309
|
-
type: "text",
|
|
2310
|
-
text: `❌ **Error publishing template**\n\n**Error:** ${errorMessage}\n\n**Debug Info:**\n\`\`\`json\n${JSON.stringify(debugInfo, null, 2)}\n\`\`\`\n\n**Common Issues:**\n- Product may need to exist first (use create_template)\n- Version format may be incorrect\n- Workflow may not be attached to product`,
|
|
2311
|
-
}],
|
|
2312
|
-
};
|
|
2313
|
-
}
|
|
2314
|
-
}
|
|
2315
|
-
};
|
|
2316
|
-
// =============================================================================
|
|
2317
|
-
// GET PRODUCT (v3) TOOL
|
|
2318
|
-
// =============================================================================
|
|
2319
|
-
const getProductDescription = `🏪 [PLAYGROUND] Get Product - Get detailed product info from marketplace (v3 API)
|
|
2320
|
-
|
|
2321
|
-
**What it does**:
|
|
2322
|
-
Retrieves detailed information about a marketplace product using v3 API.
|
|
2323
|
-
|
|
2324
|
-
**Example**:
|
|
2325
|
-
\`\`\`javascript
|
|
2326
|
-
get_product({
|
|
2327
|
-
productId: '692994df55996e1201963cd7'
|
|
2328
|
-
})
|
|
2329
|
-
\`\`\`
|
|
2330
|
-
|
|
2331
|
-
**Returns**: Product details including versions, workflows, and configuration`;
|
|
2332
|
-
exports.getProductTool = {
|
|
2333
|
-
name: 'get_product',
|
|
2334
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
2335
|
-
description: getProductDescription,
|
|
2336
|
-
schema: zod_1.z.object({
|
|
2337
|
-
productId: zod_1.z
|
|
2338
|
-
.string()
|
|
2339
|
-
.length(24)
|
|
2340
|
-
.describe("Product ID to get details for (24 characters)"),
|
|
2341
|
-
}),
|
|
2342
|
-
async execute(args, context) {
|
|
2343
|
-
logger.debug('Getting product details (v3)', {
|
|
2344
|
-
productId: args.productId,
|
|
2345
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
2346
|
-
});
|
|
2347
|
-
try {
|
|
2348
|
-
logger.debug('Calling v3.app.product.get', {
|
|
2349
|
-
productId: args.productId
|
|
2350
|
-
});
|
|
2351
|
-
const result = await context.hailer.request('v3.app.product.get', [args.productId]);
|
|
2352
|
-
logger.debug('Product get response', {
|
|
2353
|
-
result: JSON.stringify(result)
|
|
2354
|
-
});
|
|
2355
|
-
const product = result;
|
|
2356
|
-
let responseText = `✅ **Product Details (v3)**\n\n`;
|
|
2357
|
-
responseText += `**Product ID:** \`${args.productId}\`\n`;
|
|
2358
|
-
if (product?.name) {
|
|
2359
|
-
responseText += `**Name:** ${product.name}\n`;
|
|
2360
|
-
}
|
|
2361
|
-
if (product?.description) {
|
|
2362
|
-
responseText += `**Description:** ${product.description}\n`;
|
|
2363
|
-
}
|
|
2364
|
-
if (product?.type) {
|
|
2365
|
-
responseText += `**Type:** ${product.type}\n`;
|
|
2366
|
-
}
|
|
2367
|
-
if (product?.versions?.length) {
|
|
2368
|
-
responseText += `**Versions:** ${product.versions.length}\n`;
|
|
2369
|
-
}
|
|
2370
|
-
return {
|
|
2371
|
-
content: [{
|
|
2372
|
-
type: "text",
|
|
2373
|
-
text: responseText,
|
|
2374
|
-
}],
|
|
2375
|
-
};
|
|
2376
|
-
}
|
|
2377
|
-
catch (error) {
|
|
2378
|
-
logger.error("Error getting product", error);
|
|
2379
|
-
let errorMessage = 'Unknown error occurred';
|
|
2380
|
-
if (error instanceof Error) {
|
|
2381
|
-
errorMessage = error.message;
|
|
2382
|
-
}
|
|
2383
|
-
else if (typeof error === 'object' && error !== null) {
|
|
2384
|
-
try {
|
|
2385
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
2386
|
-
}
|
|
2387
|
-
catch {
|
|
2388
|
-
errorMessage = String(error);
|
|
2389
|
-
}
|
|
2390
|
-
}
|
|
2391
|
-
else {
|
|
2392
|
-
errorMessage = String(error);
|
|
2393
|
-
}
|
|
2394
|
-
return {
|
|
2395
|
-
content: [{
|
|
2396
|
-
type: "text",
|
|
2397
|
-
text: `❌ **Error getting product**\n\n**Error:** ${errorMessage}`,
|
|
2398
|
-
}],
|
|
2399
|
-
};
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2402
|
-
};
|
|
2403
|
-
// =============================================================================
|
|
2404
|
-
// GET PRODUCT MANIFEST (v3) TOOL
|
|
2405
|
-
// =============================================================================
|
|
2406
|
-
const getProductManifestDescription = `🏪 [PLAYGROUND] Get Product Manifest - Get manifest/version info from marketplace product
|
|
2407
|
-
|
|
2408
|
-
**What it does**:
|
|
2409
|
-
Retrieves the manifest for a marketplace product, which may include version and workflow information.
|
|
2410
|
-
|
|
2411
|
-
**Example**:
|
|
2412
|
-
\`\`\`javascript
|
|
2413
|
-
get_product_manifest({
|
|
2414
|
-
productId: '692994df55996e1201963cd7'
|
|
2415
|
-
})
|
|
2416
|
-
\`\`\`
|
|
2417
|
-
|
|
2418
|
-
**Returns**: Product manifest with version details`;
|
|
2419
|
-
exports.getProductManifestTool = {
|
|
2420
|
-
name: 'get_product_manifest',
|
|
2421
|
-
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
2422
|
-
description: getProductManifestDescription,
|
|
2423
|
-
schema: zod_1.z.object({
|
|
2424
|
-
productId: zod_1.z
|
|
2425
|
-
.string()
|
|
2426
|
-
.length(24)
|
|
2427
|
-
.describe("Product ID to get manifest for (24 characters)"),
|
|
2428
|
-
}),
|
|
2429
|
-
async execute(args, context) {
|
|
2430
|
-
logger.debug('Getting product manifest (v3)', {
|
|
2431
|
-
productId: args.productId,
|
|
2432
|
-
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
2433
|
-
});
|
|
2434
|
-
try {
|
|
2435
|
-
logger.debug('Calling v3.app.product.getManifest', {
|
|
2436
|
-
productId: args.productId
|
|
2437
|
-
});
|
|
2438
|
-
const result = await context.hailer.request('v3.app.product.getManifest', [args.productId]);
|
|
2439
|
-
logger.debug('Product manifest response', {
|
|
2440
|
-
result: JSON.stringify(result)
|
|
2441
|
-
});
|
|
2442
|
-
const manifest = result;
|
|
2443
|
-
let responseText = `✅ **Product Manifest (v3)**\n\n`;
|
|
2444
|
-
responseText += `**Product ID:** \`${args.productId}\`\n`;
|
|
2445
|
-
if (manifest?.version) {
|
|
2446
|
-
responseText += `**Version:** ${manifest.version}\n`;
|
|
2447
|
-
}
|
|
2448
|
-
if (manifest?.workflows?.length) {
|
|
2449
|
-
responseText += `**Workflows:** ${manifest.workflows.length}\n`;
|
|
2450
|
-
}
|
|
2451
|
-
return {
|
|
2452
|
-
content: [{
|
|
2453
|
-
type: "text",
|
|
2454
|
-
text: responseText,
|
|
2455
|
-
}],
|
|
2456
|
-
};
|
|
2457
|
-
}
|
|
2458
|
-
catch (error) {
|
|
2459
|
-
logger.error("Error getting product manifest", error);
|
|
2460
|
-
let errorMessage = 'Unknown error occurred';
|
|
2461
|
-
if (error instanceof Error) {
|
|
2462
|
-
errorMessage = error.message;
|
|
2463
|
-
}
|
|
2464
|
-
else if (typeof error === 'object' && error !== null) {
|
|
2465
|
-
try {
|
|
2466
|
-
errorMessage = JSON.stringify(error, null, 2);
|
|
2467
|
-
}
|
|
2468
|
-
catch {
|
|
2469
|
-
errorMessage = String(error);
|
|
2470
|
-
}
|
|
2471
|
-
}
|
|
2472
|
-
else {
|
|
2473
|
-
errorMessage = String(error);
|
|
2474
|
-
}
|
|
2475
|
-
return {
|
|
2476
|
-
content: [{
|
|
2477
|
-
type: "text",
|
|
2478
|
-
text: `❌ **Error getting product manifest**\n\n**Error:** ${errorMessage}`,
|
|
2479
|
-
}],
|
|
2480
|
-
};
|
|
2481
|
-
}
|
|
2482
|
-
}
|
|
26
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
27
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
2483
28
|
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
// Re-export all tools for backwards compatibility
|
|
31
|
+
__exportStar(require("./app-core"), exports);
|
|
32
|
+
__exportStar(require("./app-member"), exports);
|
|
33
|
+
__exportStar(require("./app-scaffold"), exports);
|
|
34
|
+
__exportStar(require("./app-marketplace"), exports);
|
|
2484
35
|
//# sourceMappingURL=app.js.map
|