@vertesia/tools-sdk 1.0.0-dev.20260128.144200 → 1.0.0-dev.20260225.024852Z

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 (113) hide show
  1. package/lib/cjs/ContentTypesCollection.js +43 -0
  2. package/lib/cjs/ContentTypesCollection.js.map +1 -0
  3. package/lib/cjs/InteractionCollection.js +0 -121
  4. package/lib/cjs/InteractionCollection.js.map +1 -1
  5. package/lib/cjs/SkillCollection.js +10 -2
  6. package/lib/cjs/SkillCollection.js.map +1 -1
  7. package/lib/cjs/ToolCollection.js +6 -13
  8. package/lib/cjs/ToolCollection.js.map +1 -1
  9. package/lib/cjs/ToolRegistry.js +16 -32
  10. package/lib/cjs/ToolRegistry.js.map +1 -1
  11. package/lib/cjs/index.js +1 -0
  12. package/lib/cjs/index.js.map +1 -1
  13. package/lib/cjs/server/app-package.js +130 -0
  14. package/lib/cjs/server/app-package.js.map +1 -0
  15. package/lib/cjs/server/content-types.js +73 -0
  16. package/lib/cjs/server/content-types.js.map +1 -0
  17. package/lib/cjs/server/interactions.js +26 -3
  18. package/lib/cjs/server/interactions.js.map +1 -1
  19. package/lib/cjs/server/site.js +7 -1
  20. package/lib/cjs/server/site.js.map +1 -1
  21. package/lib/cjs/server/tools.js +2 -19
  22. package/lib/cjs/server/tools.js.map +1 -1
  23. package/lib/cjs/server/widgets.js.map +1 -1
  24. package/lib/cjs/server.js +4 -0
  25. package/lib/cjs/server.js.map +1 -1
  26. package/lib/cjs/site/styles.js +55 -0
  27. package/lib/cjs/site/styles.js.map +1 -1
  28. package/lib/cjs/site/templates.js +104 -85
  29. package/lib/cjs/site/templates.js.map +1 -1
  30. package/lib/cjs/utils.js +13 -0
  31. package/lib/cjs/utils.js.map +1 -1
  32. package/lib/esm/ContentTypesCollection.js +39 -0
  33. package/lib/esm/ContentTypesCollection.js.map +1 -0
  34. package/lib/esm/InteractionCollection.js +0 -86
  35. package/lib/esm/InteractionCollection.js.map +1 -1
  36. package/lib/esm/SkillCollection.js +10 -2
  37. package/lib/esm/SkillCollection.js.map +1 -1
  38. package/lib/esm/ToolCollection.js +7 -14
  39. package/lib/esm/ToolCollection.js.map +1 -1
  40. package/lib/esm/ToolRegistry.js +16 -32
  41. package/lib/esm/ToolRegistry.js.map +1 -1
  42. package/lib/esm/index.js +1 -0
  43. package/lib/esm/index.js.map +1 -1
  44. package/lib/esm/server/app-package.js +127 -0
  45. package/lib/esm/server/app-package.js.map +1 -0
  46. package/lib/esm/server/content-types.js +70 -0
  47. package/lib/esm/server/content-types.js.map +1 -0
  48. package/lib/esm/server/interactions.js +26 -3
  49. package/lib/esm/server/interactions.js.map +1 -1
  50. package/lib/esm/server/site.js +8 -2
  51. package/lib/esm/server/site.js.map +1 -1
  52. package/lib/esm/server/tools.js +2 -19
  53. package/lib/esm/server/tools.js.map +1 -1
  54. package/lib/esm/server/widgets.js.map +1 -1
  55. package/lib/esm/server.js +4 -0
  56. package/lib/esm/server.js.map +1 -1
  57. package/lib/esm/site/styles.js +55 -0
  58. package/lib/esm/site/styles.js.map +1 -1
  59. package/lib/esm/site/templates.js +103 -85
  60. package/lib/esm/site/templates.js.map +1 -1
  61. package/lib/esm/utils.js +12 -0
  62. package/lib/esm/utils.js.map +1 -1
  63. package/lib/types/ContentTypesCollection.d.ts +18 -0
  64. package/lib/types/ContentTypesCollection.d.ts.map +1 -0
  65. package/lib/types/InteractionCollection.d.ts +1 -31
  66. package/lib/types/InteractionCollection.d.ts.map +1 -1
  67. package/lib/types/SkillCollection.d.ts +3 -2
  68. package/lib/types/SkillCollection.d.ts.map +1 -1
  69. package/lib/types/ToolCollection.d.ts +5 -10
  70. package/lib/types/ToolCollection.d.ts.map +1 -1
  71. package/lib/types/ToolRegistry.d.ts +5 -24
  72. package/lib/types/ToolRegistry.d.ts.map +1 -1
  73. package/lib/types/index.d.ts +1 -0
  74. package/lib/types/index.d.ts.map +1 -1
  75. package/lib/types/server/app-package.d.ts +4 -0
  76. package/lib/types/server/app-package.d.ts.map +1 -0
  77. package/lib/types/server/content-types.d.ts +4 -0
  78. package/lib/types/server/content-types.d.ts.map +1 -0
  79. package/lib/types/server/interactions.d.ts.map +1 -1
  80. package/lib/types/server/site.d.ts.map +1 -1
  81. package/lib/types/server/tools.d.ts.map +1 -1
  82. package/lib/types/server/types.d.ts +22 -0
  83. package/lib/types/server/types.d.ts.map +1 -1
  84. package/lib/types/server/widgets.d.ts +0 -5
  85. package/lib/types/server/widgets.d.ts.map +1 -1
  86. package/lib/types/server.d.ts.map +1 -1
  87. package/lib/types/site/styles.d.ts +1 -1
  88. package/lib/types/site/styles.d.ts.map +1 -1
  89. package/lib/types/site/templates.d.ts +5 -0
  90. package/lib/types/site/templates.d.ts.map +1 -1
  91. package/lib/types/types.d.ts +29 -16
  92. package/lib/types/types.d.ts.map +1 -1
  93. package/lib/types/utils.d.ts +6 -0
  94. package/lib/types/utils.d.ts.map +1 -1
  95. package/package.json +5 -5
  96. package/src/ContentTypesCollection.ts +51 -0
  97. package/src/InteractionCollection.ts +1 -94
  98. package/src/SkillCollection.ts +13 -3
  99. package/src/ToolCollection.ts +11 -18
  100. package/src/ToolRegistry.ts +22 -55
  101. package/src/index.ts +1 -0
  102. package/src/server/app-package.ts +147 -0
  103. package/src/server/content-types.ts +89 -0
  104. package/src/server/interactions.ts +29 -3
  105. package/src/server/site.ts +9 -0
  106. package/src/server/tools.ts +3 -22
  107. package/src/server/types.ts +26 -0
  108. package/src/server/widgets.ts +2 -6
  109. package/src/server.ts +5 -0
  110. package/src/site/styles.ts +55 -0
  111. package/src/site/templates.ts +107 -84
  112. package/src/types.ts +33 -16
  113. package/src/utils.ts +15 -1
@@ -2,6 +2,7 @@ import type { InteractionCollection } from "../InteractionCollection.js";
2
2
  import { ToolServerConfig } from "../server/types.js";
3
3
  import type { SkillCollection } from "../SkillCollection.js";
4
4
  import type { ToolCollection } from "../ToolCollection.js";
5
+ import type { ContentTypesCollection } from "../ContentTypesCollection.js";
5
6
  import type { ICollection, SkillDefinition, Tool } from "../types.js";
6
7
  import { join } from "../utils.js";
7
8
  import { baseStyles } from "./styles.js";
@@ -230,43 +231,6 @@ ${baseStyles}
230
231
  white-space: pre-wrap;
231
232
  }
232
233
 
233
- .endpoint-box {
234
- display: flex;
235
- align-items: center;
236
- gap: 0.75rem;
237
- background: #f3f4f6;
238
- padding: 0.75rem 1rem;
239
- border-radius: 8px;
240
- margin-top: 0.5rem;
241
- }
242
-
243
- .endpoint-box code {
244
- flex: 1;
245
- font-family: ui-monospace, monospace;
246
- font-size: 0.875rem;
247
- color: #1f2937;
248
- }
249
-
250
- .copy-btn {
251
- background: #e5e7eb;
252
- border: none;
253
- padding: 0.5rem;
254
- border-radius: 6px;
255
- cursor: pointer;
256
- color: #6b7280;
257
- transition: all 0.15s;
258
- }
259
-
260
- .copy-btn:hover {
261
- background: #d1d5db;
262
- color: #374151;
263
- }
264
-
265
- .copy-btn svg {
266
- width: 16px;
267
- height: 16px;
268
- }
269
-
270
234
  .empty-state {
271
235
  text-align: center;
272
236
  padding: 3rem;
@@ -347,24 +311,6 @@ ${baseStyles}
347
311
  color: #e5e7eb;
348
312
  }
349
313
 
350
- .endpoint-box {
351
- background: rgba(31, 41, 55, 0.95);
352
- }
353
-
354
- .endpoint-box code {
355
- color: #e5e7eb;
356
- }
357
-
358
- .copy-btn {
359
- background: rgba(55, 65, 81, 0.95);
360
- color: #e5e7eb;
361
- }
362
-
363
- .copy-btn:hover {
364
- background: rgba(75, 85, 99, 0.98);
365
- color: #f9fafb;
366
- }
367
-
368
314
  .empty-state {
369
315
  color: #9ca3af;
370
316
  }
@@ -719,6 +665,7 @@ export function indexPage(
719
665
  tools = [],
720
666
  interactions = [],
721
667
  skills = [],
668
+ types = [],
722
669
  mcpProviders = [],
723
670
  hideUILinks = false,
724
671
  } = config;
@@ -744,12 +691,13 @@ export function indexPage(
744
691
  <p class="hero-eyebrow">Tools Server</p>
745
692
  <h1 class="hero-title">${title}</h1>
746
693
  <p class="hero-tagline">
747
- Discover the tools, skills, and interactions exposed by this server.
694
+ Discover the tools, skills, interactions, and content types exposed by this server.
748
695
  </p>
749
696
  <div class="hero-summary">
750
697
  ${tools.length ? /*html*/`<span><dot></dot> ${tools.length} tool collection${tools.length !== 1 ? 's' : ''}</span>` : ''}
751
698
  ${skills.length ? /*html*/`<span><dot></dot> ${skills.length} skill collection${skills.length !== 1 ? 's' : ''}</span>` : ''}
752
699
  ${interactions.length ? /*html*/`<span><dot></dot> ${interactions.length} interaction collection${interactions.length !== 1 ? 's' : ''}</span>` : ''}
700
+ ${types.length ? /*html*/`<span><dot></dot> ${types.length} content type collection${types.length !== 1 ? 's' : ''}</span>` : ''}
753
701
  ${mcpProviders.length ? /*html*/`<span><dot></dot> ${mcpProviders.length} MCP provider${mcpProviders.length !== 1 ? 's' : ''}</span>` : ''}
754
702
  </div>
755
703
  ${hideUILinks ? '' : renderUILinks()}
@@ -758,6 +706,13 @@ export function indexPage(
758
706
  <aside class="hero-panel">
759
707
  <div class="hero-panel-label">Base endpoint</div>
760
708
  <div class="hero-panel-endpoint"><code>/api</code></div>
709
+ <div class="hero-panel-label" style="margin-top: 1rem;">Package endpoint</div>
710
+ <div class="endpoint-box" style="margin-top: 0.5rem;">
711
+ <code id="package-endpoint-url">/api/package</code>
712
+ <button class="copy-btn" onclick="copyPackageUrl(this)" title="Copy package endpoint URL">
713
+ ${copyIcon}
714
+ </button>
715
+ </div>
761
716
  <p class="hero-panel-hint">
762
717
  Use <strong>POST /api/tools/&lt;collection&gt;</strong> or
763
718
  <strong>POST /api/skills/&lt;collection&gt;</strong> to call these from your apps or agents.
@@ -770,7 +725,7 @@ export function indexPage(
770
725
  type="search"
771
726
  id="collection-search"
772
727
  class="search-input"
773
- placeholder="Search tools, skills, interactions..."
728
+ placeholder="Search tools, skills, interactions, types..."
774
729
  aria-label="Search collections"
775
730
  autocomplete="off"
776
731
  />
@@ -823,6 +778,22 @@ export function indexPage(
823
778
  </section>
824
779
  ` : ''}
825
780
 
781
+ ${types.length > 0 ? /*html*/`
782
+ <section data-section="types">
783
+ <hr>
784
+ <div class="section-header">
785
+ <h2>Content Type Collections</h2>
786
+ <p class="section-subtitle">Schema definitions for structured content in the data store.</p>
787
+ </div>
788
+ <div class="card-grid">
789
+ ${types.map((t: ContentTypesCollection) => {
790
+ const count = t.getContentTypes().length;
791
+ return collectionCard(t, 'types', `${count} type${count !== 1 ? 's' : ''}`);
792
+ }).join('')}
793
+ </div>
794
+ </section>
795
+ ` : ''}
796
+
826
797
  ${mcpProviders.length > 0 ? /*html*/`
827
798
  <section data-section="mcp">
828
799
  <hr>
@@ -884,6 +855,18 @@ export function indexPage(
884
855
  update(input.value);
885
856
  });
886
857
  }());
858
+
859
+ function copyPackageUrl(btn) {
860
+ var url = window.location.origin + '/api/package';
861
+ navigator.clipboard.writeText(url);
862
+ var originalHtml = btn.innerHTML;
863
+ btn.innerHTML = '✓';
864
+ btn.style.color = '#10b981';
865
+ setTimeout(function() {
866
+ btn.innerHTML = originalHtml;
867
+ btn.style.color = '#6b7280';
868
+ }, 1500);
869
+ }
887
870
  </script>
888
871
  </body>
889
872
  </html>`;
@@ -976,19 +959,10 @@ export function skillCollectionPage(collection: SkillCollection): string {
976
959
  }
977
960
 
978
961
  /**
979
- * Render an interaction collection detail page
962
+ * Render a collection header with icon, title, description, and endpoint
980
963
  */
981
- export function interactionCollectionPage(collection: InteractionCollection): string {
964
+ function collectionDetailHeader(collection: ICollection, pathPrefix: string): string {
982
965
  return /*html*/`
983
- <!DOCTYPE html>
984
- <html lang="en">
985
- <head>
986
- <meta charset="UTF-8">
987
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
988
- <title>${collection.title || collection.name} - Interactions</title>
989
- <style>${detailStyles}</style>
990
- </head>
991
- <body>
992
966
  <nav class="nav">
993
967
  <a href="/">${backArrow} Back to all collections</a>
994
968
  </nav>
@@ -999,30 +973,79 @@ export function interactionCollectionPage(collection: InteractionCollection): st
999
973
  <h1>${collection.title || collection.name}</h1>
1000
974
  <p style="color: #6b7280; margin: 0.25rem 0 0 0;">${collection.description || ''}</p>
1001
975
  <div class="endpoint-box">
1002
- <code>/api/interactions/${collection.name}</code>
1003
- <button class="copy-btn" onclick="navigator.clipboard.writeText(window.location.origin + '/api/interactions/${collection.name}')" title="Copy endpoint URL">
976
+ <code>/api/${pathPrefix}/${collection.name}</code>
977
+ <button class="copy-btn" onclick="navigator.clipboard.writeText(window.location.origin + '/api/${pathPrefix}/${collection.name}')" title="Copy endpoint URL">
1004
978
  ${copyIcon}
1005
979
  </button>
1006
980
  </div>
1007
981
  </div>
1008
- </div>
982
+ </div>`;
983
+ }
984
+
985
+ /**
986
+ * Render a simple item card with name, description, and tags
987
+ */
988
+ function simpleItemCard(item: { name: string; description?: string; tags?: string[] }): string {
989
+ return /*html*/`
990
+ <div class="detail-card">
991
+ <div class="detail-header">
992
+ <div>
993
+ <h3 class="detail-title">${item.name}</h3>
994
+ <p class="detail-desc">${item.description || 'No description'}</p>
995
+ </div>
996
+ <div class="detail-badges">
997
+ ${item.tags?.map(tag => `<span class="badge">${tag}</span>`).join('') || ''}
998
+ </div>
999
+ </div>
1000
+ </div>`;
1001
+ }
1002
+
1003
+ /**
1004
+ * Render an interaction collection detail page
1005
+ */
1006
+ export function interactionCollectionPage(collection: InteractionCollection): string {
1007
+ return /*html*/`
1008
+ <!DOCTYPE html>
1009
+ <html lang="en">
1010
+ <head>
1011
+ <meta charset="UTF-8">
1012
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
1013
+ <title>${collection.title || collection.name} - Interactions</title>
1014
+ <style>${detailStyles}</style>
1015
+ </head>
1016
+ <body>
1017
+ ${collectionDetailHeader(collection, 'interactions')}
1009
1018
 
1010
1019
  <h2>${collection.interactions.length} Interaction${collection.interactions.length !== 1 ? 's' : ''}</h2>
1011
1020
 
1012
1021
  <div class="item-list">
1013
- ${collection.interactions.map(inter => /*html*/`
1014
- <div class="detail-card">
1015
- <div class="detail-header">
1016
- <div>
1017
- <h3 class="detail-title">${inter.name}</h3>
1018
- <p class="detail-desc">${inter.description || 'No description'}</p>
1019
- </div>
1020
- <div class="detail-badges">
1021
- ${inter.tags?.map(tag => `<span class="badge">${tag}</span>`).join('') || ''}
1022
- </div>
1023
- </div>
1024
- </div>
1025
- `).join('')}
1022
+ ${collection.interactions.map(inter => simpleItemCard(inter)).join('')}
1023
+ </div>
1024
+ </body>
1025
+ </html>`;
1026
+ }
1027
+
1028
+ /**
1029
+ * Render a content type collection detail page
1030
+ */
1031
+ export function contentTypeCollectionPage(collection: ContentTypesCollection): string {
1032
+ const typesArray = collection.getContentTypes();
1033
+ return /*html*/`
1034
+ <!DOCTYPE html>
1035
+ <html lang="en">
1036
+ <head>
1037
+ <meta charset="UTF-8">
1038
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
1039
+ <title>${collection.title || collection.name} - Content Types</title>
1040
+ <style>${detailStyles}</style>
1041
+ </head>
1042
+ <body>
1043
+ ${collectionDetailHeader(collection, 'types')}
1044
+
1045
+ <h2>${typesArray.length} Content Type${typesArray.length !== 1 ? 's' : ''}</h2>
1046
+
1047
+ <div class="item-list">
1048
+ ${typesArray.map(type => simpleItemCard(type)).join('')}
1026
1049
  </div>
1027
1050
  </body>
1028
1051
  </html>`;
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ToolDefinition, ToolUse } from "@llumiverse/common";
2
2
  import { VertesiaClient } from "@vertesia/client";
3
- import { AuthTokenPayload, ToolExecutionMetadata, ToolResult, ToolResultContent } from "@vertesia/common";
3
+ import { AgentToolDefinition, AuthTokenPayload, ProjectConfiguration, ToolExecutionMetadata, ToolResult, ToolResultContent } from "@vertesia/common";
4
4
 
5
5
  export type { ToolExecutionMetadata };
6
6
 
@@ -87,6 +87,15 @@ export interface ToolExecutionPayload<ParamsT extends Record<string, any>> {
87
87
 
88
88
  export type ToolFn<ParamsT extends Record<string, any>> = (payload: ToolExecutionPayload<ParamsT>, context: ToolExecutionContext) => Promise<ToolExecutionResult>;
89
89
 
90
+ export interface ToolUseContext {
91
+ project_id?: string,
92
+ account_id?: string,
93
+ project_name?: string,
94
+ project_ns?: string,
95
+ configuration?: ProjectConfiguration;
96
+ vars?: Record<string, any>;
97
+ }
98
+
90
99
  export interface Tool<ParamsT extends Record<string, any>> extends ToolDefinition {
91
100
  run: ToolFn<ParamsT>;
92
101
  /**
@@ -95,25 +104,18 @@ export interface Tool<ParamsT extends Record<string, any>> extends ToolDefinitio
95
104
  * - false: Tool is only available when activated by a skill's related_tools
96
105
  */
97
106
  default?: boolean;
98
- }
99
107
 
100
- /**
101
- * Tool definition with optional activation control for agent exposure.
102
- */
103
- export interface ToolDefinitionWithDefault extends ToolDefinition {
104
108
  /**
105
- * Whether this tool is available by default.
106
- * - true/undefined: Tool is always available to agents
107
- * - false: Tool is only available when activated by a skill's related_tools
109
+ * Optional filter to check if the tool is enabled for the given project configuration.
110
+ * This can be used to dynamically enable/disable tools based on project settings, environment variables, or any other logic.
111
+ * If no filter is provided, the tool will be enabled by default.
112
+ * @param payload
113
+ * @returns
108
114
  */
109
- default?: boolean;
110
- /**
111
- * For skill tools (learn_*): list of related tool names that become available
112
- * when this skill is called. Used for dynamic tool discovery.
113
- */
114
- related_tools?: string[];
115
+ isEnabled?: (payload: ToolUseContext) => boolean;
115
116
  }
116
117
 
118
+
117
119
  /**
118
120
  * The interface that should be returned when requesting a collection endpoint using a GET
119
121
  */
@@ -121,7 +123,7 @@ export interface ToolCollectionDefinition {
121
123
  title: string;
122
124
  description: string;
123
125
  src: string;
124
- tools: ToolDefinitionWithDefault[];
126
+ tools: AgentToolDefinition[];
125
127
  }
126
128
 
127
129
  export type { ToolDefinition };
@@ -143,6 +145,11 @@ export interface MCPConnectionDetails {
143
145
  * If an empty string no authentication will be done
144
146
  */
145
147
  token: string;
148
+ /**
149
+ * Optional additional HTTP headers to include with requests to the MCP server.
150
+ * Merged with the Authorization header derived from the token.
151
+ */
152
+ headers?: Record<string, string>;
146
153
  }
147
154
 
148
155
  // ================== Skill Types ==================
@@ -250,6 +257,16 @@ export interface SkillDefinition {
250
257
  * The widget file must be located in the skill directory under the name {{widget-name}}.tsx.
251
258
  */
252
259
  widgets?: string[];
260
+
261
+ /**
262
+ * Optional filter to check if the tool is enabled for the given project configuration.
263
+ * This can be used to dynamically enable/disable tools based on project settings, environment variables, or any other logic.
264
+ * If no filter is provided, the tool will be enabled by default.
265
+ * @param payload
266
+ * @returns
267
+ */
268
+ isEnabled?: (payload: ToolUseContext) => boolean;
269
+
253
270
  }
254
271
 
255
272
  /**
package/src/utils.ts CHANGED
@@ -1,3 +1,16 @@
1
+ /**
2
+ * Convert a name to a URL-safe path segment.
3
+ * If the name contains spaces or underscores, convert to PascalCase.
4
+ * Otherwise return as-is. Any characters not in [a-zA-Z0-9$_\-@] are replaced with '-'.
5
+ */
6
+ export function toPathName(name: string): string {
7
+ let result = name;
8
+ if (result.includes(' ') || result.includes('_')) {
9
+ result = result.split(/[\s_]+/).map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('');
10
+ }
11
+ return result.replace(/[^a-zA-Z0-9$_\-@]/g, '-');
12
+ }
13
+
1
14
  export function kebabCaseToTitle(name: string) {
2
15
  return name.split('-').map(p => p[0].toUpperCase() + p.substring(1)).join(' ');
3
16
  }
@@ -20,4 +33,5 @@ export function join(left: string, right: string) {
20
33
  } else {
21
34
  return left + '/' + right;
22
35
  }
23
- }
36
+ }
37
+