@hailer/mcp 0.0.4 → 0.0.5
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/hooks/post-scaffold-hook.cjs +125 -0
- package/.claude/hooks/prompt-skill-loader.cjs +106 -5
- package/.claude/hooks/publish-template-guard.cjs +123 -0
- package/.claude/hooks/skill-loader.cjs +1 -1
- package/.claude/settings.json +22 -0
- package/.claude/skills/MCP-build-data-app-skill/SKILL.md +372 -0
- package/.claude/skills/MCP-publish-template-skill/SKILL.md +278 -0
- package/.claude/skills/MCP-scaffold-hailer-app-skill/SKILL.md +250 -47
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +274 -9
- package/.claude/skills/hailer-app-builder/SKILL.md +340 -0
- package/.claude/skills/spawn-app-builder/SKILL.md +366 -0
- package/CHANGELOG.md +24 -0
- package/dist/app.js +8 -0
- package/dist/mcp/tools/app.d.ts +7 -0
- package/dist/mcp/tools/app.js +997 -1
- package/package.json +1 -1
package/dist/mcp/tools/app.js
CHANGED
|
@@ -43,7 +43,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
43
43
|
};
|
|
44
44
|
})();
|
|
45
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.publishHailerAppTool = exports.scaffoldHailerAppTool = exports.removeAppMemberTool = exports.addAppMemberTool = exports.removeAppTool = exports.updateAppTool = exports.listAppsTool = exports.createAppTool = void 0;
|
|
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
47
|
const zod_1 = require("zod");
|
|
48
48
|
const tool_registry_1 = require("../tool-registry");
|
|
49
49
|
const workspace_cache_1 = require("../workspace-cache");
|
|
@@ -1485,4 +1485,1000 @@ exports.publishHailerAppTool = {
|
|
|
1485
1485
|
}
|
|
1486
1486
|
}
|
|
1487
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
|
+
}
|
|
2483
|
+
};
|
|
1488
2484
|
//# sourceMappingURL=app.js.map
|