@vertesia/tools-sdk 0.24.0-dev.202601221707

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +122 -0
  3. package/lib/cjs/InteractionCollection.js +164 -0
  4. package/lib/cjs/InteractionCollection.js.map +1 -0
  5. package/lib/cjs/SkillCollection.js +376 -0
  6. package/lib/cjs/SkillCollection.js.map +1 -0
  7. package/lib/cjs/ToolCollection.js +228 -0
  8. package/lib/cjs/ToolCollection.js.map +1 -0
  9. package/lib/cjs/ToolRegistry.js +111 -0
  10. package/lib/cjs/ToolRegistry.js.map +1 -0
  11. package/lib/cjs/auth.js +104 -0
  12. package/lib/cjs/auth.js.map +1 -0
  13. package/lib/cjs/build/validate.js +7 -0
  14. package/lib/cjs/build/validate.js.map +1 -0
  15. package/lib/cjs/copy-assets.js +84 -0
  16. package/lib/cjs/copy-assets.js.map +1 -0
  17. package/lib/cjs/index.js +31 -0
  18. package/lib/cjs/index.js.map +1 -0
  19. package/lib/cjs/package.json +3 -0
  20. package/lib/cjs/server/interactions.js +66 -0
  21. package/lib/cjs/server/interactions.js.map +1 -0
  22. package/lib/cjs/server/mcp.js +45 -0
  23. package/lib/cjs/server/mcp.js.map +1 -0
  24. package/lib/cjs/server/site.js +30 -0
  25. package/lib/cjs/server/site.js.map +1 -0
  26. package/lib/cjs/server/skills.js +114 -0
  27. package/lib/cjs/server/skills.js.map +1 -0
  28. package/lib/cjs/server/tools.js +104 -0
  29. package/lib/cjs/server/tools.js.map +1 -0
  30. package/lib/cjs/server/types.js +3 -0
  31. package/lib/cjs/server/types.js.map +1 -0
  32. package/lib/cjs/server/widgets.js +27 -0
  33. package/lib/cjs/server/widgets.js.map +1 -0
  34. package/lib/cjs/server.js +132 -0
  35. package/lib/cjs/server.js.map +1 -0
  36. package/lib/cjs/site/styles.js +621 -0
  37. package/lib/cjs/site/styles.js.map +1 -0
  38. package/lib/cjs/site/templates.js +968 -0
  39. package/lib/cjs/site/templates.js.map +1 -0
  40. package/lib/cjs/types.js +3 -0
  41. package/lib/cjs/types.js.map +1 -0
  42. package/lib/cjs/utils.js +31 -0
  43. package/lib/cjs/utils.js.map +1 -0
  44. package/lib/esm/InteractionCollection.js +125 -0
  45. package/lib/esm/InteractionCollection.js.map +1 -0
  46. package/lib/esm/SkillCollection.js +369 -0
  47. package/lib/esm/SkillCollection.js.map +1 -0
  48. package/lib/esm/ToolCollection.js +190 -0
  49. package/lib/esm/ToolCollection.js.map +1 -0
  50. package/lib/esm/ToolRegistry.js +106 -0
  51. package/lib/esm/ToolRegistry.js.map +1 -0
  52. package/lib/esm/auth.js +97 -0
  53. package/lib/esm/auth.js.map +1 -0
  54. package/lib/esm/build/validate.js +4 -0
  55. package/lib/esm/build/validate.js.map +1 -0
  56. package/lib/esm/copy-assets.js +81 -0
  57. package/lib/esm/copy-assets.js.map +1 -0
  58. package/lib/esm/index.js +11 -0
  59. package/lib/esm/index.js.map +1 -0
  60. package/lib/esm/server/interactions.js +63 -0
  61. package/lib/esm/server/interactions.js.map +1 -0
  62. package/lib/esm/server/mcp.js +42 -0
  63. package/lib/esm/server/mcp.js.map +1 -0
  64. package/lib/esm/server/site.js +27 -0
  65. package/lib/esm/server/site.js.map +1 -0
  66. package/lib/esm/server/skills.js +111 -0
  67. package/lib/esm/server/skills.js.map +1 -0
  68. package/lib/esm/server/tools.js +101 -0
  69. package/lib/esm/server/tools.js.map +1 -0
  70. package/lib/esm/server/types.js +2 -0
  71. package/lib/esm/server/types.js.map +1 -0
  72. package/lib/esm/server/widgets.js +24 -0
  73. package/lib/esm/server/widgets.js.map +1 -0
  74. package/lib/esm/server.js +128 -0
  75. package/lib/esm/server.js.map +1 -0
  76. package/lib/esm/site/styles.js +618 -0
  77. package/lib/esm/site/styles.js.map +1 -0
  78. package/lib/esm/site/templates.js +956 -0
  79. package/lib/esm/site/templates.js.map +1 -0
  80. package/lib/esm/types.js +2 -0
  81. package/lib/esm/types.js.map +1 -0
  82. package/lib/esm/utils.js +26 -0
  83. package/lib/esm/utils.js.map +1 -0
  84. package/lib/types/InteractionCollection.d.ts +48 -0
  85. package/lib/types/InteractionCollection.d.ts.map +1 -0
  86. package/lib/types/SkillCollection.d.ts +118 -0
  87. package/lib/types/SkillCollection.d.ts.map +1 -0
  88. package/lib/types/ToolCollection.d.ts +72 -0
  89. package/lib/types/ToolCollection.d.ts.map +1 -0
  90. package/lib/types/ToolRegistry.d.ts +41 -0
  91. package/lib/types/ToolRegistry.d.ts.map +1 -0
  92. package/lib/types/auth.d.ts +32 -0
  93. package/lib/types/auth.d.ts.map +1 -0
  94. package/lib/types/build/validate.d.ts +2 -0
  95. package/lib/types/build/validate.d.ts.map +1 -0
  96. package/lib/types/copy-assets.d.ts +14 -0
  97. package/lib/types/copy-assets.d.ts.map +1 -0
  98. package/lib/types/index.d.ts +11 -0
  99. package/lib/types/index.d.ts.map +1 -0
  100. package/lib/types/server/interactions.d.ts +4 -0
  101. package/lib/types/server/interactions.d.ts.map +1 -0
  102. package/lib/types/server/mcp.d.ts +4 -0
  103. package/lib/types/server/mcp.d.ts.map +1 -0
  104. package/lib/types/server/site.d.ts +4 -0
  105. package/lib/types/server/site.d.ts.map +1 -0
  106. package/lib/types/server/skills.d.ts +4 -0
  107. package/lib/types/server/skills.d.ts.map +1 -0
  108. package/lib/types/server/tools.d.ts +4 -0
  109. package/lib/types/server/tools.d.ts.map +1 -0
  110. package/lib/types/server/types.d.ts +62 -0
  111. package/lib/types/server/types.d.ts.map +1 -0
  112. package/lib/types/server/widgets.d.ts +9 -0
  113. package/lib/types/server/widgets.d.ts.map +1 -0
  114. package/lib/types/server.d.ts +27 -0
  115. package/lib/types/server.d.ts.map +1 -0
  116. package/lib/types/site/styles.d.ts +5 -0
  117. package/lib/types/site/styles.d.ts.map +1 -0
  118. package/lib/types/site/templates.d.ts +54 -0
  119. package/lib/types/site/templates.d.ts.map +1 -0
  120. package/lib/types/types.d.ts +280 -0
  121. package/lib/types/types.d.ts.map +1 -0
  122. package/lib/types/utils.d.ts +4 -0
  123. package/lib/types/utils.d.ts.map +1 -0
  124. package/package.json +58 -0
  125. package/src/InteractionCollection.ts +143 -0
  126. package/src/SkillCollection.ts +461 -0
  127. package/src/ToolCollection.ts +223 -0
  128. package/src/ToolRegistry.ts +135 -0
  129. package/src/auth.ts +123 -0
  130. package/src/build/validate.ts +3 -0
  131. package/src/copy-assets.ts +104 -0
  132. package/src/index.ts +12 -0
  133. package/src/server/interactions.ts +79 -0
  134. package/src/server/mcp.ts +51 -0
  135. package/src/server/site.ts +46 -0
  136. package/src/server/skills.ts +133 -0
  137. package/src/server/tools.ts +128 -0
  138. package/src/server/types.ts +65 -0
  139. package/src/server/widgets.ts +38 -0
  140. package/src/server.ts +160 -0
  141. package/src/site/styles.ts +617 -0
  142. package/src/site/templates.ts +994 -0
  143. package/src/types.ts +303 -0
  144. package/src/utils.ts +23 -0
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared CSS styles for the tools server HTML pages
3
+ */
4
+ export declare const baseStyles = "\n:root {\n color-scheme: light dark;\n}\n\nbody {\n font-family: system-ui, -apple-system, sans-serif;\n margin: 0;\n padding: 2.5rem 1.75rem;\n background:\n radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.10), transparent 55%),\n radial-gradient(circle at 100% 0, rgba(129, 140, 248, 0.12), transparent 55%),\n #f9fafb;\n color: #0f172a;\n line-height: 1.5;\n}\n\n.page {\n max-width: 1120px;\n margin: 0 auto;\n}\n\n.hero {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 2.25rem;\n padding: 1.75rem 2rem;\n margin-bottom: 2.5rem;\n border-radius: 1.25rem;\n background: linear-gradient(135deg, #ffffff, #f3f4ff);\n border: 1px solid #e5e7eb;\n box-shadow:\n 0 18px 40px rgba(15, 23, 42, 0.08),\n 0 0 0 1px rgba(248, 250, 252, 0.8);\n}\n\n.hero-main {\n display: flex;\n gap: 1.5rem;\n align-items: center;\n}\n\n.hero-logo {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 56px;\n height: 56px;\n border-radius: 999px;\n background: radial-gradient(circle at 30% 0, #38bdf8, #6366f1);\n box-shadow:\n 0 0 0 1px rgba(15, 23, 42, 0.85),\n 0 12px 30px rgba(37, 99, 235, 0.6);\n}\n\n.hero-logo-initial {\n font-size: 1.1rem;\n font-weight: 650;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: #eff6ff;\n}\n\n.hero-logo img {\n display: block;\n max-width: 80%;\n max-height: 60%;\n}\n\n.logo-dark {\n display: none;\n}\n\n.hero-meta {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.hero-eyebrow {\n font-size: 0.75rem;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: #6b7280;\n}\n\n.hero-title {\n font-size: 1.9rem;\n font-weight: 650;\n letter-spacing: -0.03em;\n color: #0f172a;\n margin: 0;\n}\n\n.hero-tagline {\n font-size: 0.95rem;\n color: #4b5563;\n margin: 0.1rem 0 0 0;\n}\n\n.hero-summary {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-top: 0.75rem;\n font-size: 0.8rem;\n color: #6b7280;\n}\n\n.hero-summary span {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.15rem 0.55rem;\n border-radius: 999px;\n background: #f9fafb;\n border: 1px solid #e5e7eb;\n}\n\n.hero-summary dot {\n width: 6px;\n height: 6px;\n border-radius: 999px;\n display: inline-block;\n background: #22c55e;\n}\n\n.search-bar {\n display: flex;\n flex-direction: column;\n gap: 0.4rem;\n margin: 0 0 1.75rem 0;\n}\n\n.search-input {\n max-width: 360px;\n padding: 0.55rem 0.75rem;\n border-radius: 999px;\n border: 1px solid #e5e7eb;\n background: #ffffff;\n color: #111827;\n font-size: 0.9rem;\n font-family: inherit;\n box-shadow: 0 4px 10px rgba(15, 23, 42, 0.04);\n}\n\n.search-input::placeholder {\n color: #9ca3af;\n}\n\n.search-input:focus {\n outline: none;\n border-color: #60a5fa;\n box-shadow:\n 0 0 0 1px rgba(59, 130, 246, 0.4),\n 0 6px 18px rgba(37, 99, 235, 0.18);\n}\n\n.search-hint {\n font-size: 0.75rem;\n color: #9ca3af;\n}\n\n.search-empty {\n margin-top: 1rem;\n font-size: 0.85rem;\n color: #9ca3af;\n}\n\n.hero-panel {\n min-width: 220px;\n max-width: 260px;\n padding: 1.25rem 1.4rem;\n border-radius: 1rem;\n background: radial-gradient(circle at 0 0, rgba(59, 130, 246, 0.10), transparent 70%),\n #eff6ff;\n border: 1px solid #bfdbfe;\n box-shadow: 0 16px 34px rgba(15, 23, 42, 0.10);\n font-size: 0.8rem;\n}\n\n.hero-panel-label {\n font-size: 0.7rem;\n letter-spacing: 0.13em;\n text-transform: uppercase;\n color: #1d4ed8;\n margin-bottom: 0.5rem;\n}\n\n.hero-panel-endpoint {\n display: inline-flex;\n align-items: center;\n padding: 0.3rem 0.6rem;\n border-radius: 0.5rem;\n background: #f9fafb;\n border: 1px solid #e5e7eb;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 0.82rem;\n color: #111827;\n}\n\n.hero-panel-hint {\n margin-top: 0.6rem;\n color: #6b7280;\n line-height: 1.4;\n}\n\n.hero-panel-hint strong {\n color: #111827;\n}\n\nh1, h2 {\n margin: 0 0 1rem 0;\n color: #0f172a;\n}\n\nh1 { font-size: 1.875rem; }\nh2 {\n font-size: 1.4rem;\n margin-top: 2rem;\n letter-spacing: 0.03em;\n text-transform: uppercase;\n color: #6b7280;\n}\n\na {\n color: #2563eb;\n text-decoration: none;\n}\na:hover {\n text-decoration: underline;\n}\n\nhr {\n border: none;\n border-top: 1px solid #e5e7eb;\n margin: 2rem 0;\n}\n\n.card-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 1.5rem;\n}\n\n.card {\n background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.12), transparent 75%),\n #ffffff;\n padding: 1.25rem 1.35rem;\n border-radius: 14px;\n box-shadow:\n 0 14px 30px rgba(15, 23, 42, 0.06),\n 0 0 0 1px rgba(248, 250, 252, 0.9);\n border: 1px solid #e5e7eb;\n transition: transform 0.15s, box-shadow 0.15s;\n text-decoration: none;\n color: inherit;\n display: block;\n}\n\n.card:hover {\n transform: translateY(-3px);\n box-shadow:\n 0 18px 40px rgba(15, 23, 42, 0.10),\n 0 0 0 1px rgba(59, 130, 246, 0.6);\n}\n\n.card-icon {\n width: 48px;\n height: 48px;\n margin-bottom: 0.75rem;\n}\n\n.card-icon svg {\n width: 100%;\n height: 100%;\n}\n\n.card-title {\n font-weight: 600;\n font-size: 1.1rem;\n margin-bottom: 0.25rem;\n color: #0f172a;\n}\n\n.card-desc {\n font-size: 0.925rem;\n color: #6b7280;\n}\n\n.card-meta {\n margin-top: 0.45rem;\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: #9ca3af;\n}\n\n.item-list {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.item-card {\n background: #ffffff;\n padding: 1rem 1.25rem;\n border-radius: 10px;\n border-left: 4px solid #6366f1;\n box-shadow:\n 0 10px 24px rgba(15, 23, 42, 0.06),\n 0 0 0 1px rgba(248, 250, 252, 0.9);\n}\n\n.item-card.skill {\n border-left-color: #10b981;\n}\n\n.item-card.interaction {\n border-left-color: #f59e0b;\n}\n\n.item-name {\n font-weight: 600;\n font-size: 1.05rem;\n}\n\n.item-desc {\n font-size: 0.9rem;\n color: #6b7280;\n margin-top: 0.25rem;\n}\n\n.item-meta {\n font-size: 0.8rem;\n color: #9ca3af;\n margin-top: 0.5rem;\n}\n\n.item-schema {\n margin-top: 0.75rem;\n font-size: 0.8rem;\n font-family: ui-monospace, monospace;\n background: #f3f4f6;\n padding: 0.75rem;\n border-radius: 6px;\n overflow-x: auto;\n white-space: pre-wrap;\n color: #374151;\n}\n\n.header {\n display: flex;\n align-items: center;\n gap: 1rem;\n margin-bottom: 1.5rem;\n}\n\n.header-icon {\n width: 64px;\n height: 64px;\n}\n\n.header-icon svg {\n width: 100%;\n height: 100%;\n}\n\n.section-header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 1rem;\n margin-bottom: 0.75rem;\n}\n\n.section-subtitle {\n font-size: 0.8rem;\n color: #6b7280;\n}\n\n.endpoint-url {\n font-size: 0.85rem;\n color: #6b7280;\n margin-top: 0.25rem;\n}\n\n.endpoint-url code {\n background: #f3f4f6;\n padding: 0.125rem 0.375rem;\n border-radius: 4px;\n font-family: ui-monospace, monospace;\n}\n\n.badge {\n display: inline-block;\n font-size: 0.75rem;\n padding: 0.125rem 0.5rem;\n border-radius: 9999px;\n background: #f9fafb;\n color: #374151;\n border: 1px solid #e5e7eb;\n margin-right: 0.25rem;\n}\n\n.badge.python { background: #fef3c7; color: #92400e; border-color: #facc15; }\n.badge.typescript { background: #dbeafe; color: #1e40af; border-color: #60a5fa; }\n.badge.javascript { background: #fef9c3; color: #854d0e; border-color: #facc15; }\n\n@media (max-width: 768px) {\n body {\n padding: 1.75rem 1.25rem;\n }\n\n .hero {\n flex-direction: column;\n padding: 1.5rem 1.35rem;\n }\n\n .hero-panel {\n max-width: 100%;\n width: 100%;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n body {\n background:\n radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.18), transparent 55%),\n radial-gradient(circle at 100% 0, rgba(129, 140, 248, 0.25), transparent 55%),\n #020617;\n color: #e5e7eb;\n }\n\n .hero {\n background: linear-gradient(135deg, rgba(15, 23, 42, 0.98), rgba(15, 23, 42, 0.92));\n border: 1px solid rgba(148, 163, 184, 0.45);\n box-shadow:\n 0 24px 60px rgba(15, 23, 42, 0.85),\n 0 0 0 1px rgba(15, 23, 42, 0.75);\n }\n\n .hero-eyebrow {\n color: #9ca3af;\n }\n\n .hero-title {\n color: #f9fafb;\n }\n\n .hero-tagline {\n color: #cbd5f5;\n }\n\n .hero-summary {\n color: #9ca3af;\n }\n\n .hero-summary span {\n background: rgba(15, 23, 42, 0.95);\n border-color: rgba(148, 163, 184, 0.45);\n }\n\n .hero-panel {\n background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.16), transparent 70%),\n rgba(15, 23, 42, 0.96);\n border: 1px solid rgba(59, 130, 246, 0.6);\n box-shadow: 0 20px 40px rgba(15, 23, 42, 0.85);\n }\n\n .hero-panel-label {\n color: #93c5fd;\n }\n\n .hero-panel-endpoint {\n background: rgba(15, 23, 42, 0.98);\n border-color: rgba(148, 163, 184, 0.6);\n color: #e5e7eb;\n }\n\n .hero-panel-hint {\n color: #9ca3af;\n }\n\n .hero-panel-hint strong {\n color: #e5e7eb;\n }\n\n .search-input {\n background: rgba(15, 23, 42, 0.96);\n border-color: rgba(55, 65, 81, 0.9);\n color: #e5e7eb;\n box-shadow:\n 0 6px 16px rgba(15, 23, 42, 0.9),\n 0 0 0 1px rgba(15, 23, 42, 0.9);\n }\n\n .search-input::placeholder {\n color: #6b7280;\n }\n\n .search-input:focus {\n border-color: #60a5fa;\n box-shadow:\n 0 0 0 1px rgba(59, 130, 246, 0.7),\n 0 10px 26px rgba(30, 64, 175, 0.7);\n }\n\n .search-hint,\n .search-empty {\n color: #9ca3af;\n }\n\n h1, h2 {\n color: #e5e7eb;\n }\n\n h2 {\n color: #9ca3af;\n }\n\n a {\n color: #60a5fa;\n }\n\n hr {\n border-top-color: rgba(148, 163, 184, 0.4);\n }\n\n .card {\n background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.12), transparent 75%),\n rgba(15, 23, 42, 0.9);\n box-shadow:\n 0 14px 30px rgba(15, 23, 42, 0.8),\n 0 0 0 1px rgba(15, 23, 42, 0.85);\n border-color: rgba(148, 163, 184, 0.5);\n }\n\n .card:hover {\n box-shadow:\n 0 18px 40px rgba(15, 23, 42, 0.9),\n 0 0 0 1px rgba(59, 130, 246, 0.8);\n }\n\n .card-title {\n color: #e5e7eb;\n }\n\n .card-desc {\n color: #9ca3af;\n }\n\n .card-meta {\n color: #6b7280;\n }\n\n .item-card {\n background: rgba(15, 23, 42, 0.9);\n box-shadow:\n 0 10px 24px rgba(15, 23, 42, 0.9),\n 0 0 0 1px rgba(15, 23, 42, 0.9);\n }\n\n .item-desc,\n .item-meta {\n color: #9ca3af;\n }\n\n .item-schema {\n background: rgba(15, 23, 42, 0.95);\n color: #e5e7eb;\n }\n\n .endpoint-url {\n color: #9ca3af;\n }\n\n .endpoint-url code {\n background: rgba(15, 23, 42, 0.95);\n }\n\n .badge {\n background: rgba(15, 23, 42, 0.96);\n color: #e5e7eb;\n border-color: rgba(148, 163, 184, 0.6);\n }\n\n .badge.python {\n background: rgba(252, 211, 77, 0.12);\n color: #facc15;\n border-color: rgba(250, 204, 21, 0.5);\n }\n\n .badge.typescript {\n background: rgba(59, 130, 246, 0.12);\n color: #93c5fd;\n border-color: rgba(59, 130, 246, 0.7);\n }\n\n .badge.javascript {\n background: rgba(251, 191, 36, 0.12);\n color: #fbbf24;\n border-color: rgba(251, 191, 36, 0.55);\n }\n\n .logo-light {\n display: none;\n }\n .logo-dark {\n display: block;\n }\n}\n";
5
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/site/styles.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,UAAU,uuYAqmBtB,CAAC"}
@@ -0,0 +1,54 @@
1
+ import type { InteractionCollection } from "../InteractionCollection.js";
2
+ import type { SkillCollection } from "../SkillCollection.js";
3
+ import type { ToolCollection } from "../ToolCollection.js";
4
+ import type { ICollection, SkillDefinition, Tool } from "../types.js";
5
+ type MCPProviderMeta = {
6
+ name: string;
7
+ description?: string;
8
+ };
9
+ /**
10
+ * Render a collection card for the index page
11
+ */
12
+ export declare function collectionCard(collection: ICollection, pathPrefix: string, meta?: string): string;
13
+ /**
14
+ * Render a tool card (simple version for lists)
15
+ */
16
+ export declare function toolCard(tool: Tool<Record<string, unknown>>): string;
17
+ /**
18
+ * Render an MCP provider card
19
+ */
20
+ export declare function mcpProviderCard(provider: MCPProviderMeta): string;
21
+ /**
22
+ * Render a detailed tool card
23
+ */
24
+ export declare function toolDetailCard(tool: Tool<Record<string, unknown>>, collectionName: string): string;
25
+ /**
26
+ * Render a skill card (simple version for lists)
27
+ */
28
+ export declare function skillCard(skill: SkillDefinition): string;
29
+ /**
30
+ * Render a detailed skill card
31
+ */
32
+ export declare function skillDetailCard(skill: SkillDefinition, collection: SkillCollection): string;
33
+ /**
34
+ * Render the main index page
35
+ *
36
+ * Note: The fourth argument is backward compatible:
37
+ * - If a string is passed, it is treated as the title.
38
+ * - If an array is passed, it is treated as MCP providers and the fifth argument (if any) is the title.
39
+ */
40
+ export declare function indexPage(tools: ToolCollection[], skills: SkillCollection[], interactions: InteractionCollection[], mcpProvidersOrTitle?: MCPProviderMeta[] | string, titleParam?: string): string;
41
+ /**
42
+ * Render a tool collection detail page
43
+ */
44
+ export declare function toolCollectionPage(collection: ToolCollection): string;
45
+ /**
46
+ * Render a skill collection detail page
47
+ */
48
+ export declare function skillCollectionPage(collection: SkillCollection): string;
49
+ /**
50
+ * Render an interaction collection detail page
51
+ */
52
+ export declare function interactionCollectionPage(collection: InteractionCollection): string;
53
+ export {};
54
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/site/templates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAItE,KAAK,eAAe,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAiZF;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAQjG;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CASpE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAMjE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CA0DlG;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAWxD;AAsBD;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,eAAe,GAAG,MAAM,CAsF3F;AA2BD;;;;;;GAMG;AACH,wBAAgB,SAAS,CACrB,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,EAAE,eAAe,EAAE,EACzB,YAAY,EAAE,qBAAqB,EAAE,EACrC,mBAAmB,CAAC,EAAE,eAAe,EAAE,GAAG,MAAM,EAChD,UAAU,CAAC,EAAE,MAAM,GACpB,MAAM,CAiLR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,cAAc,GAAG,MAAM,CAsCrE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,eAAe,GAAG,MAAM,CAsCvE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,qBAAqB,GAAG,MAAM,CAgDnF"}
@@ -0,0 +1,280 @@
1
+ import type { ToolDefinition, ToolUse } from "@llumiverse/common";
2
+ import { VertesiaClient } from "@vertesia/client";
3
+ import { AuthTokenPayload, ToolExecutionMetadata, ToolResult, ToolResultContent } from "@vertesia/common";
4
+ export type { ToolExecutionMetadata };
5
+ export type ICollection<T = any> = CollectionProperties & Iterable<T>;
6
+ export interface CollectionProperties {
7
+ /**
8
+ * A kebab case collection name. Must only contains alphanumeric and dash characters,
9
+ * The name can be used to generate the path where the collection is exposed.
10
+ * Example: my-collection
11
+ */
12
+ name: string;
13
+ /**
14
+ * Optional title for UI display.
15
+ * If not provided the pascal case version of the name will be used
16
+ */
17
+ title?: string;
18
+ /**
19
+ * Optional icon for UI display
20
+ */
21
+ icon?: string;
22
+ /**
23
+ * A short description
24
+ */
25
+ description?: string;
26
+ }
27
+ export interface ToolExecutionContext {
28
+ /**
29
+ * The raw JWT token to the tool execution request
30
+ */
31
+ token: string;
32
+ /**
33
+ * The decoded JWT token
34
+ */
35
+ payload: AuthTokenPayload;
36
+ /**
37
+ * Vertesia client factory using the current auth token.
38
+ * @returns a vertesia client instance
39
+ */
40
+ getClient: () => Promise<VertesiaClient>;
41
+ }
42
+ export interface ToolExecutionResult extends ToolResultContent {
43
+ /**
44
+ * Medata can be used to return more info on the tool execution like stats or user messages.
45
+ */
46
+ meta?: Record<string, any>;
47
+ }
48
+ export interface ToolExecutionResponse extends ToolExecutionResult, ToolResult {
49
+ /**
50
+ * The tool use id of the tool use request. For traceability.
51
+ */
52
+ tool_use_id: string;
53
+ }
54
+ export interface ToolExecutionResponseError {
55
+ /**
56
+ * The tool use id of the tool use request. For traceability.
57
+ */
58
+ tool_use_id: string;
59
+ /**
60
+ * The http status code
61
+ */
62
+ status: number;
63
+ /**
64
+ * the error message
65
+ */
66
+ error: string;
67
+ /**
68
+ * Additional context information
69
+ */
70
+ data?: Record<string, any>;
71
+ }
72
+ export interface ToolExecutionPayload<ParamsT extends Record<string, any>> {
73
+ tool_use: ToolUse<ParamsT>;
74
+ /**
75
+ * Optional metadata related to the current execution request
76
+ */
77
+ metadata?: ToolExecutionMetadata;
78
+ }
79
+ export type ToolFn<ParamsT extends Record<string, any>> = (payload: ToolExecutionPayload<ParamsT>, context: ToolExecutionContext) => Promise<ToolExecutionResult>;
80
+ export interface Tool<ParamsT extends Record<string, any>> extends ToolDefinition {
81
+ run: ToolFn<ParamsT>;
82
+ /**
83
+ * Whether this tool is available by default.
84
+ * - true/undefined: Tool is always available to agents
85
+ * - false: Tool is only available when activated by a skill's related_tools
86
+ */
87
+ default?: boolean;
88
+ }
89
+ /**
90
+ * Tool definition with optional activation control for agent exposure.
91
+ */
92
+ export interface ToolDefinitionWithDefault extends ToolDefinition {
93
+ /**
94
+ * Whether this tool is available by default.
95
+ * - true/undefined: Tool is always available to agents
96
+ * - false: Tool is only available when activated by a skill's related_tools
97
+ */
98
+ default?: boolean;
99
+ /**
100
+ * For skill tools (learn_*): list of related tool names that become available
101
+ * when this skill is called. Used for dynamic tool discovery.
102
+ */
103
+ related_tools?: string[];
104
+ }
105
+ /**
106
+ * The interface that should be returned when requesting a collection endpoint using a GET
107
+ */
108
+ export interface ToolCollectionDefinition {
109
+ title: string;
110
+ description: string;
111
+ src: string;
112
+ tools: ToolDefinitionWithDefault[];
113
+ }
114
+ export type { ToolDefinition };
115
+ /**
116
+ * The details of a connection to a MCP server - including the server URL and an authentication token
117
+ */
118
+ export interface MCPConnectionDetails {
119
+ /**
120
+ * The mcp server name. It will be used to prefix tool names.
121
+ */
122
+ name: string;
123
+ /**
124
+ * The target mcp server URL
125
+ */
126
+ url: string;
127
+ /**
128
+ * The bearer authentication token to use when connecting to the mcp server.
129
+ * If an empty string no authentication will be done
130
+ */
131
+ token: string;
132
+ }
133
+ /**
134
+ * Content type for skill instructions
135
+ */
136
+ export type SkillContentType = 'md' | 'jst';
137
+ /**
138
+ * Context triggers for auto-injection of skills
139
+ */
140
+ export interface SkillContextTriggers {
141
+ /**
142
+ * Keywords in user input that should trigger this skill
143
+ */
144
+ keywords?: string[];
145
+ /**
146
+ * If these tools are being used, suggest this skill
147
+ */
148
+ tool_names?: string[];
149
+ /**
150
+ * Regex patterns to match against input data
151
+ */
152
+ data_patterns?: string[];
153
+ }
154
+ /**
155
+ * Execution configuration for skills that need code execution
156
+ */
157
+ export interface SkillExecution {
158
+ /**
159
+ * The programming language for execution
160
+ */
161
+ language: string;
162
+ /**
163
+ * Required packages to install
164
+ */
165
+ packages?: string[];
166
+ /**
167
+ * System-level packages to install (e.g., apt-get packages)
168
+ */
169
+ system_packages?: string[];
170
+ /**
171
+ * Code template to execute
172
+ */
173
+ template?: string;
174
+ }
175
+ /**
176
+ * Skill definition - parsed from SKILL.md or SKILL.jst
177
+ */
178
+ export interface SkillDefinition {
179
+ /**
180
+ * Unique skill name (kebab-case)
181
+ */
182
+ name: string;
183
+ /**
184
+ * Display title
185
+ */
186
+ title?: string;
187
+ /**
188
+ * Short description for discovery
189
+ */
190
+ description: string;
191
+ /**
192
+ * The skill instructions (markdown or JST template)
193
+ */
194
+ instructions: string;
195
+ /**
196
+ * Content type: 'md' for static markdown, 'jst' for dynamic templates
197
+ */
198
+ content_type: SkillContentType;
199
+ /**
200
+ * JSON Schema for skill input parameters.
201
+ * Used when skill is exposed as a tool.
202
+ */
203
+ input_schema?: {
204
+ type: 'object';
205
+ properties?: Record<string, any>;
206
+ required?: string[];
207
+ };
208
+ /**
209
+ * Context triggers for auto-injection
210
+ */
211
+ context_triggers?: SkillContextTriggers;
212
+ /**
213
+ * Execution configuration for code-based skills
214
+ */
215
+ execution?: SkillExecution;
216
+ /**
217
+ * Related tools that work well with this skill
218
+ */
219
+ related_tools?: string[];
220
+ /**
221
+ * Scripts bundled with this skill (synced to sandbox when skill is used)
222
+ */
223
+ scripts?: string[];
224
+ /**
225
+ * The name of the widgets provided by this skill (if any)
226
+ * The name will be used to load the widget dynamically from the agent chat
227
+ * and must match the code block language returned by the LLM (e.g., ```my-widget)
228
+ * which will be rendered using the widget.
229
+ * The widget file must be located in the skill directory under the name {{widget-name}}.tsx.
230
+ */
231
+ widgets?: string[];
232
+ }
233
+ /**
234
+ * Skill execution payload
235
+ */
236
+ export interface SkillExecutionPayload {
237
+ /**
238
+ * The skill name to execute
239
+ */
240
+ skill_name: string;
241
+ /**
242
+ * Data context for JST template rendering
243
+ */
244
+ data?: Record<string, any>;
245
+ /**
246
+ * Whether to execute the code template (if present)
247
+ */
248
+ execute?: boolean;
249
+ }
250
+ /**
251
+ * Skill execution result
252
+ */
253
+ export interface SkillExecutionResult {
254
+ /**
255
+ * The skill name
256
+ */
257
+ name: string;
258
+ /**
259
+ * Rendered instructions
260
+ */
261
+ instructions: string;
262
+ /**
263
+ * Execution output (if execute=true and skill has code template)
264
+ */
265
+ execution_result?: {
266
+ output: string;
267
+ files?: string[];
268
+ is_error: boolean;
269
+ };
270
+ }
271
+ /**
272
+ * Skill collection definition - returned by GET endpoint
273
+ */
274
+ export interface SkillCollectionDefinition {
275
+ name: string;
276
+ title: string;
277
+ description: string;
278
+ skills: SkillDefinition[];
279
+ }
280
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function kebabCaseToTitle(name: string): string;
2
+ export declare function makeScriptUrl(origin: string, script: string): string;
3
+ export declare function join(left: string, right: string): string;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,UAE5C;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAE3D;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAc/C"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@vertesia/tools-sdk",
3
+ "version": "0.24.0-dev.202601221707",
4
+ "description": "Tools SDK - utilities for building remote tools",
5
+ "type": "module",
6
+ "types": "./lib/types/index.d.ts",
7
+ "files": [
8
+ "lib",
9
+ "src"
10
+ ],
11
+ "license": "Apache-2.0",
12
+ "exports": {
13
+ "types": "./lib/types/index.d.ts",
14
+ "import": "./lib/esm/index.js",
15
+ "require": "./lib/cjs/index.js"
16
+ },
17
+ "bin": {
18
+ "tools-sdk-copy-assets": "./lib/esm/copy-assets.js"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^22.19.2",
22
+ "ts-dual-module": "^0.6.3",
23
+ "typescript": "^5.9.3",
24
+ "vitest": "^4.0.16"
25
+ },
26
+ "ts_dual_module": {
27
+ "outDir": "lib"
28
+ },
29
+ "peerDependencies": {
30
+ "hono": "^4.11.4"
31
+ },
32
+ "dependencies": {
33
+ "jose": "^6.0.11",
34
+ "zod": "^4.3.5",
35
+ "@llumiverse/common": "0.24.0-dev.202601221707",
36
+ "@vertesia/common": "0.24.0-dev.202601221707",
37
+ "@vertesia/client": "0.24.0-dev.202601221707"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/vertesia/composableai.git",
42
+ "directory": "packages/tools-sdk"
43
+ },
44
+ "keywords": [
45
+ "vertesia",
46
+ "tools",
47
+ "sdk",
48
+ "llm",
49
+ "ai",
50
+ "agents",
51
+ "typescript"
52
+ ],
53
+ "scripts": {
54
+ "test": "vitest run",
55
+ "build": "pnpm exec tsmod build",
56
+ "clean": "rimraf ./node_modules ./lib ./tsconfig.tsbuildinfo"
57
+ }
58
+ }
@@ -0,0 +1,143 @@
1
+ import { readdirSync, statSync, existsSync, readFileSync } from "fs";
2
+ import { join } from "path";
3
+ import { pathToFileURL } from "url";
4
+ import { InteractionSpec } from "@vertesia/common";
5
+ import { ICollection, CollectionProperties } from "./types.js";
6
+ import { kebabCaseToTitle } from "./utils.js";
7
+
8
+ export interface InteractionCollectionProps extends CollectionProperties {
9
+ interactions: InteractionSpec[];
10
+ }
11
+ export class InteractionCollection implements ICollection<InteractionSpec> {
12
+ interactions: InteractionSpec[];
13
+ name: string;
14
+ title?: string;
15
+ icon?: string;
16
+ description?: string;
17
+ constructor({
18
+ name, title, icon, description, interactions
19
+ }: InteractionCollectionProps) {
20
+ this.name = name;
21
+ this.title = title || kebabCaseToTitle(name);
22
+ this.icon = icon;
23
+ this.description = description;
24
+ this.interactions = interactions;
25
+ }
26
+ addInteraction(interaction: any) {
27
+ this.interactions.push(interaction);
28
+ }
29
+
30
+ getInteractions() {
31
+ return this.interactions;
32
+ }
33
+
34
+ [Symbol.iterator](): Iterator<InteractionSpec> {
35
+ let index = 0;
36
+ const interactions = this.interactions;
37
+
38
+ return {
39
+ next(): IteratorResult<InteractionSpec> {
40
+ if (index < interactions.length) {
41
+ return { value: interactions[index++], done: false };
42
+ } else {
43
+ return { done: true, value: undefined };
44
+ }
45
+ }
46
+ };
47
+ }
48
+
49
+ map<U>(callback: (interaction: InteractionSpec, index: number) => U): U[] {
50
+ return this.interactions.map(callback);
51
+ }
52
+
53
+ getInteractionByName(name: string): InteractionSpec | undefined {
54
+ return this.interactions.find(interaction => interaction.name === name);
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Load all interactions from a directory.
60
+ * Scans for subdirectories containing index.ts/index.js files.
61
+ *
62
+ * Directory structure:
63
+ * ```
64
+ * interactions/
65
+ * nagare/
66
+ * extract-fund-actuals/
67
+ * index.ts # exports default InteractionSpec
68
+ * prompt.jst # prompt template (read via readPromptFile helper)
69
+ * parse-fund-document/
70
+ * index.ts
71
+ * prompt.md
72
+ * ```
73
+ *
74
+ * @param interactionsDir - Path to the interactions collection directory
75
+ * @returns Promise resolving to array of InteractionSpec objects
76
+ */
77
+ export async function loadInteractionsFromDirectory(interactionsDir: string): Promise<InteractionSpec[]> {
78
+ const interactions: InteractionSpec[] = [];
79
+
80
+ if (!existsSync(interactionsDir)) {
81
+ console.warn(`Interactions directory not found: ${interactionsDir}`);
82
+ return interactions;
83
+ }
84
+
85
+ let entries: string[];
86
+ try {
87
+ entries = readdirSync(interactionsDir);
88
+ } catch {
89
+ console.warn(`Could not read interactions directory: ${interactionsDir}`);
90
+ return interactions;
91
+ }
92
+
93
+ for (const entry of entries) {
94
+ // Skip hidden files and index files
95
+ if (entry.startsWith('.')) continue;
96
+ if (entry === 'index.ts' || entry === 'index.js') continue;
97
+
98
+ const entryPath = join(interactionsDir, entry);
99
+
100
+ try {
101
+ const stat = statSync(entryPath);
102
+ if (!stat.isDirectory()) continue;
103
+
104
+ // Look for index.ts or index.js in the subdirectory
105
+ const indexTs = join(entryPath, 'index.ts');
106
+ const indexJs = join(entryPath, 'index.js');
107
+ const indexPath = existsSync(indexTs) ? indexTs : existsSync(indexJs) ? indexJs : null;
108
+
109
+ if (!indexPath) {
110
+ continue; // No index file, skip
111
+ }
112
+
113
+ // Dynamic import
114
+ const fileUrl = pathToFileURL(indexPath).href;
115
+ const module = await import(fileUrl);
116
+
117
+ const interaction = module.default || module.interaction;
118
+
119
+ if (interaction && typeof interaction.name === 'string') {
120
+ interactions.push(interaction);
121
+ } else {
122
+ console.warn(`No valid InteractionSpec export found in ${entry}/index`);
123
+ }
124
+ } catch (err) {
125
+ console.warn(`Error loading interaction from ${entry}:`, err);
126
+ }
127
+ }
128
+
129
+ return interactions;
130
+ }
131
+
132
+ /**
133
+ * Helper to read a prompt file from the same directory as the interaction.
134
+ * Use this in interaction index.ts files to load prompt templates.
135
+ *
136
+ * @param dirname - Pass __dirname or dirname(fileURLToPath(import.meta.url))
137
+ * @param filename - Prompt filename (e.g., 'prompt.jst' or 'prompt.md')
138
+ * @returns File contents as string
139
+ */
140
+ export function readPromptFile(dirname: string, filename: string): string {
141
+ const filePath = join(dirname, filename);
142
+ return readFileSync(filePath, 'utf-8');
143
+ }