@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.
@@ -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