digital-tools 2.1.3 → 2.3.0

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 (294) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +2 -0
  3. package/dist/client.d.ts +109 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +69 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/define.d.ts +2 -2
  8. package/dist/define.d.ts.map +1 -1
  9. package/dist/define.js +21 -11
  10. package/dist/define.js.map +1 -1
  11. package/dist/function-ref.d.ts +229 -0
  12. package/dist/function-ref.d.ts.map +1 -0
  13. package/dist/function-ref.js +28 -0
  14. package/dist/function-ref.js.map +1 -0
  15. package/dist/function-sugar.d.ts +57 -0
  16. package/dist/function-sugar.d.ts.map +1 -0
  17. package/dist/function-sugar.js +79 -0
  18. package/dist/function-sugar.js.map +1 -0
  19. package/dist/index.d.ts +10 -3
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +24 -4
  22. package/dist/index.js.map +1 -1
  23. package/dist/providers/analytics/mixpanel.d.ts.map +1 -1
  24. package/dist/providers/analytics/mixpanel.js +21 -18
  25. package/dist/providers/analytics/mixpanel.js.map +1 -1
  26. package/dist/providers/calendar/cal-com.d.ts.map +1 -1
  27. package/dist/providers/calendar/cal-com.js +10 -10
  28. package/dist/providers/calendar/cal-com.js.map +1 -1
  29. package/dist/providers/calendar/google-calendar.d.ts.map +1 -1
  30. package/dist/providers/calendar/google-calendar.js +4 -4
  31. package/dist/providers/calendar/google-calendar.js.map +1 -1
  32. package/dist/providers/crm/hubspot.d.ts.map +1 -1
  33. package/dist/providers/crm/hubspot.js +107 -85
  34. package/dist/providers/crm/hubspot.js.map +1 -1
  35. package/dist/providers/development/github.d.ts.map +1 -1
  36. package/dist/providers/development/github.js +40 -43
  37. package/dist/providers/development/github.js.map +1 -1
  38. package/dist/providers/ecommerce/shopify.d.ts.map +1 -1
  39. package/dist/providers/ecommerce/shopify.js +79 -62
  40. package/dist/providers/ecommerce/shopify.js.map +1 -1
  41. package/dist/providers/email/resend.d.ts.map +1 -1
  42. package/dist/providers/email/resend.js +20 -16
  43. package/dist/providers/email/resend.js.map +1 -1
  44. package/dist/providers/email/sendgrid.d.ts.map +1 -1
  45. package/dist/providers/email/sendgrid.js +12 -9
  46. package/dist/providers/email/sendgrid.js.map +1 -1
  47. package/dist/providers/finance/stripe.d.ts.map +1 -1
  48. package/dist/providers/finance/stripe.js +44 -42
  49. package/dist/providers/finance/stripe.js.map +1 -1
  50. package/dist/providers/forms/typeform.d.ts.map +1 -1
  51. package/dist/providers/forms/typeform.js +68 -58
  52. package/dist/providers/forms/typeform.js.map +1 -1
  53. package/dist/providers/knowledge/notion.d.ts.map +1 -1
  54. package/dist/providers/knowledge/notion.js +75 -41
  55. package/dist/providers/knowledge/notion.js.map +1 -1
  56. package/dist/providers/marketing/mailchimp.d.ts.map +1 -1
  57. package/dist/providers/marketing/mailchimp.js +74 -61
  58. package/dist/providers/marketing/mailchimp.js.map +1 -1
  59. package/dist/providers/media/cloudinary.d.ts.map +1 -1
  60. package/dist/providers/media/cloudinary.js +30 -28
  61. package/dist/providers/media/cloudinary.js.map +1 -1
  62. package/dist/providers/messaging/slack.d.ts.map +1 -1
  63. package/dist/providers/messaging/slack.js +75 -58
  64. package/dist/providers/messaging/slack.js.map +1 -1
  65. package/dist/providers/messaging/twilio-sms.d.ts.map +1 -1
  66. package/dist/providers/messaging/twilio-sms.js +33 -15
  67. package/dist/providers/messaging/twilio-sms.js.map +1 -1
  68. package/dist/providers/project-management/linear.d.ts.map +1 -1
  69. package/dist/providers/project-management/linear.js +31 -27
  70. package/dist/providers/project-management/linear.js.map +1 -1
  71. package/dist/providers/spreadsheet/google-sheets.d.ts.map +1 -1
  72. package/dist/providers/spreadsheet/google-sheets.js +21 -18
  73. package/dist/providers/spreadsheet/google-sheets.js.map +1 -1
  74. package/dist/providers/spreadsheet/xlsx.d.ts.map +1 -1
  75. package/dist/providers/spreadsheet/xlsx.js +4 -4
  76. package/dist/providers/spreadsheet/xlsx.js.map +1 -1
  77. package/dist/providers/storage/index.js +1 -0
  78. package/dist/providers/storage/index.js.map +1 -1
  79. package/dist/providers/storage/s3.d.ts.map +1 -1
  80. package/dist/providers/storage/s3.js +36 -27
  81. package/dist/providers/storage/s3.js.map +1 -1
  82. package/dist/providers/support/zendesk.d.ts.map +1 -1
  83. package/dist/providers/support/zendesk.js +24 -25
  84. package/dist/providers/support/zendesk.js.map +1 -1
  85. package/dist/providers/tasks/todoist.d.ts.map +1 -1
  86. package/dist/providers/tasks/todoist.js +18 -18
  87. package/dist/providers/tasks/todoist.js.map +1 -1
  88. package/dist/providers/video-conferencing/google-meet.d.ts.map +1 -1
  89. package/dist/providers/video-conferencing/google-meet.js +11 -11
  90. package/dist/providers/video-conferencing/google-meet.js.map +1 -1
  91. package/dist/providers/video-conferencing/jitsi.js +14 -14
  92. package/dist/providers/video-conferencing/jitsi.js.map +1 -1
  93. package/dist/providers/video-conferencing/teams.d.ts.map +1 -1
  94. package/dist/providers/video-conferencing/teams.js +9 -7
  95. package/dist/providers/video-conferencing/teams.js.map +1 -1
  96. package/dist/providers/video-conferencing/zoom.d.ts.map +1 -1
  97. package/dist/providers/video-conferencing/zoom.js +26 -24
  98. package/dist/providers/video-conferencing/zoom.js.map +1 -1
  99. package/dist/tools/data.d.ts.map +1 -1
  100. package/dist/tools/data.js +5 -12
  101. package/dist/tools/data.js.map +1 -1
  102. package/dist/tools/index.d.ts +1 -0
  103. package/dist/tools/index.d.ts.map +1 -1
  104. package/dist/tools/index.js +1 -0
  105. package/dist/tools/index.js.map +1 -1
  106. package/dist/tools/system.d.ts +289 -0
  107. package/dist/tools/system.d.ts.map +1 -0
  108. package/dist/tools/system.js +752 -0
  109. package/dist/tools/system.js.map +1 -0
  110. package/dist/tools/web.d.ts.map +1 -1
  111. package/dist/tools/web.js +22 -10
  112. package/dist/tools/web.js.map +1 -1
  113. package/dist/track-record.d.ts +101 -0
  114. package/dist/track-record.d.ts.map +1 -0
  115. package/dist/track-record.js +17 -0
  116. package/dist/track-record.js.map +1 -0
  117. package/dist/types.d.ts +210 -9
  118. package/dist/types.d.ts.map +1 -1
  119. package/dist/verb-registration.d.ts +122 -0
  120. package/dist/verb-registration.d.ts.map +1 -0
  121. package/dist/verb-registration.js +176 -0
  122. package/dist/verb-registration.js.map +1 -0
  123. package/dist/worker.d.ts +93 -0
  124. package/dist/worker.d.ts.map +1 -0
  125. package/dist/worker.js +315 -0
  126. package/dist/worker.js.map +1 -0
  127. package/dist/wrap.d.ts +89 -0
  128. package/dist/wrap.d.ts.map +1 -0
  129. package/dist/wrap.js +225 -0
  130. package/dist/wrap.js.map +1 -0
  131. package/package.json +31 -14
  132. package/src/client.ts +136 -0
  133. package/src/define.ts +30 -24
  134. package/src/function-ref.ts +264 -0
  135. package/src/function-sugar.ts +134 -0
  136. package/src/index.ts +132 -10
  137. package/src/providers/analytics/mixpanel.ts +19 -18
  138. package/src/providers/calendar/cal-com.ts +29 -18
  139. package/src/providers/calendar/google-calendar.ts +20 -14
  140. package/src/providers/crm/hubspot.ts +225 -99
  141. package/src/providers/development/github.ts +206 -135
  142. package/src/providers/ecommerce/shopify.ts +250 -89
  143. package/src/providers/email/resend.ts +101 -28
  144. package/src/providers/email/sendgrid.ts +12 -9
  145. package/src/providers/finance/stripe.ts +128 -49
  146. package/src/providers/forms/typeform.ts +74 -58
  147. package/src/providers/knowledge/notion.ts +340 -88
  148. package/src/providers/marketing/mailchimp.ts +86 -70
  149. package/src/providers/media/cloudinary.ts +99 -41
  150. package/src/providers/messaging/slack.ts +283 -85
  151. package/src/providers/messaging/twilio-sms.ts +35 -15
  152. package/src/providers/project-management/linear.ts +143 -55
  153. package/src/providers/spreadsheet/google-sheets.ts +222 -56
  154. package/src/providers/spreadsheet/xlsx.ts +47 -16
  155. package/src/providers/storage/s3.ts +119 -47
  156. package/src/providers/support/zendesk.ts +196 -46
  157. package/src/providers/tasks/todoist.ts +20 -26
  158. package/src/providers/video-conferencing/google-meet.ts +17 -20
  159. package/src/providers/video-conferencing/jitsi.ts +14 -14
  160. package/src/providers/video-conferencing/teams.ts +14 -13
  161. package/src/providers/video-conferencing/zoom.ts +54 -49
  162. package/src/tools/data.ts +6 -16
  163. package/src/tools/index.ts +1 -0
  164. package/src/tools/system.ts +887 -0
  165. package/src/tools/web.ts +22 -10
  166. package/src/track-record.ts +106 -0
  167. package/src/types.ts +241 -13
  168. package/src/verb-registration.ts +197 -0
  169. package/src/worker.ts +370 -0
  170. package/src/wrap.ts +260 -0
  171. package/test/client.test.ts +146 -0
  172. package/test/communication-tools-extended.test.ts +734 -0
  173. package/test/data-tools-extended.test.ts +743 -0
  174. package/test/define-extended.test.ts +819 -0
  175. package/test/define.test.ts +150 -41
  176. package/test/entities.test.ts +623 -0
  177. package/test/extended-entities.test.ts +1228 -0
  178. package/test/provider-implementations.test.ts +725 -0
  179. package/test/provider-registry-extended.test.ts +583 -0
  180. package/test/providers/google-sheets.test.ts +851 -0
  181. package/test/providers/helpers.ts +554 -0
  182. package/test/providers/hubspot.test.ts +576 -0
  183. package/test/providers/slack.test.ts +932 -0
  184. package/test/providers/stripe.test.ts +701 -0
  185. package/test/providers.test.ts +578 -0
  186. package/test/system-tools-extended.test.ts +632 -0
  187. package/test/system.test.ts +673 -0
  188. package/test/tools.test.ts +15 -11
  189. package/test/types.test.ts +402 -0
  190. package/test/verb-registration.test.ts +395 -0
  191. package/test/web-tools.test.ts +553 -0
  192. package/test/worker-extended.test.ts +699 -0
  193. package/test/worker.test.ts +576 -0
  194. package/test/wrap.test.ts +366 -0
  195. package/tsconfig.json +3 -13
  196. package/vitest.config.ts +37 -0
  197. package/wrangler.jsonc +9 -0
  198. package/.turbo/turbo-build.log +0 -4
  199. package/LICENSE +0 -21
  200. package/dist/providers/voice/vapi.d.ts +0 -27
  201. package/dist/providers/voice/vapi.d.ts.map +0 -1
  202. package/dist/providers/voice/vapi.js +0 -440
  203. package/dist/providers/voice/vapi.js.map +0 -1
  204. package/src/define.js +0 -259
  205. package/src/entities/advertising.js +0 -999
  206. package/src/entities/ai.js +0 -756
  207. package/src/entities/analytics.js +0 -1588
  208. package/src/entities/automation.js +0 -601
  209. package/src/entities/communication.js +0 -1150
  210. package/src/entities/crm.js +0 -1386
  211. package/src/entities/design.js +0 -546
  212. package/src/entities/development.js +0 -2212
  213. package/src/entities/document.js +0 -874
  214. package/src/entities/ecommerce.js +0 -1429
  215. package/src/entities/experiment.js +0 -1039
  216. package/src/entities/finance.js +0 -3478
  217. package/src/entities/forms.js +0 -1892
  218. package/src/entities/hr.js +0 -661
  219. package/src/entities/identity.js +0 -997
  220. package/src/entities/index.js +0 -282
  221. package/src/entities/infrastructure.js +0 -1153
  222. package/src/entities/knowledge.js +0 -1438
  223. package/src/entities/marketing.js +0 -1610
  224. package/src/entities/media.js +0 -1634
  225. package/src/entities/notification.js +0 -1199
  226. package/src/entities/presentation.js +0 -1274
  227. package/src/entities/productivity.js +0 -1317
  228. package/src/entities/project-management.js +0 -1136
  229. package/src/entities/recruiting.js +0 -736
  230. package/src/entities/shipping.js +0 -509
  231. package/src/entities/signature.js +0 -1102
  232. package/src/entities/site.js +0 -222
  233. package/src/entities/spreadsheet.js +0 -1341
  234. package/src/entities/storage.js +0 -1198
  235. package/src/entities/support.js +0 -1166
  236. package/src/entities/video-conferencing.js +0 -1750
  237. package/src/entities/video.js +0 -950
  238. package/src/entities.js +0 -1663
  239. package/src/index.js +0 -74
  240. package/src/providers/analytics/index.js +0 -17
  241. package/src/providers/analytics/mixpanel.js +0 -255
  242. package/src/providers/calendar/cal-com.js +0 -303
  243. package/src/providers/calendar/google-calendar.js +0 -335
  244. package/src/providers/calendar/index.js +0 -20
  245. package/src/providers/crm/hubspot.js +0 -566
  246. package/src/providers/crm/index.js +0 -17
  247. package/src/providers/development/github.js +0 -472
  248. package/src/providers/development/index.js +0 -17
  249. package/src/providers/ecommerce/index.js +0 -17
  250. package/src/providers/ecommerce/shopify.js +0 -378
  251. package/src/providers/email/index.js +0 -20
  252. package/src/providers/email/resend.js +0 -258
  253. package/src/providers/email/sendgrid.js +0 -161
  254. package/src/providers/finance/index.js +0 -17
  255. package/src/providers/finance/stripe.js +0 -549
  256. package/src/providers/forms/index.js +0 -17
  257. package/src/providers/forms/typeform.js +0 -500
  258. package/src/providers/index.js +0 -123
  259. package/src/providers/knowledge/index.js +0 -17
  260. package/src/providers/knowledge/notion.js +0 -389
  261. package/src/providers/marketing/index.js +0 -17
  262. package/src/providers/marketing/mailchimp.js +0 -443
  263. package/src/providers/media/cloudinary.js +0 -318
  264. package/src/providers/media/index.js +0 -17
  265. package/src/providers/messaging/index.js +0 -20
  266. package/src/providers/messaging/slack.js +0 -393
  267. package/src/providers/messaging/twilio-sms.js +0 -249
  268. package/src/providers/project-management/index.js +0 -17
  269. package/src/providers/project-management/linear.js +0 -575
  270. package/src/providers/registry.js +0 -86
  271. package/src/providers/spreadsheet/google-sheets.js +0 -375
  272. package/src/providers/spreadsheet/index.js +0 -20
  273. package/src/providers/spreadsheet/xlsx.js +0 -423
  274. package/src/providers/storage/index.js +0 -24
  275. package/src/providers/storage/s3.js +0 -419
  276. package/src/providers/support/index.js +0 -17
  277. package/src/providers/support/zendesk.js +0 -373
  278. package/src/providers/tasks/index.js +0 -17
  279. package/src/providers/tasks/todoist.js +0 -286
  280. package/src/providers/types.js +0 -9
  281. package/src/providers/video-conferencing/google-meet.js +0 -286
  282. package/src/providers/video-conferencing/index.js +0 -31
  283. package/src/providers/video-conferencing/jitsi.js +0 -254
  284. package/src/providers/video-conferencing/teams.js +0 -270
  285. package/src/providers/video-conferencing/zoom.js +0 -332
  286. package/src/registry.js +0 -128
  287. package/src/tools/communication.js +0 -184
  288. package/src/tools/data.js +0 -205
  289. package/src/tools/index.js +0 -11
  290. package/src/tools/web.js +0 -137
  291. package/src/types.js +0 -10
  292. package/test/define.test.js +0 -306
  293. package/test/registry.test.js +0 -357
  294. package/test/tools.test.js +0 -363
@@ -43,13 +43,13 @@ describe('Web Tools', () => {
43
43
  })
44
44
 
45
45
  it('has required parameters', () => {
46
- const urlParam = fetchUrl.parameters.find(p => p.name === 'url')
46
+ const urlParam = fetchUrl.parameters.find((p) => p.name === 'url')
47
47
  expect(urlParam).toBeDefined()
48
48
  expect(urlParam?.required).toBe(true)
49
49
  })
50
50
 
51
51
  it('has optional parameters', () => {
52
- const methodParam = fetchUrl.parameters.find(p => p.name === 'method')
52
+ const methodParam = fetchUrl.parameters.find((p) => p.name === 'method')
53
53
  expect(methodParam).toBeDefined()
54
54
  expect(methodParam?.required).toBe(false)
55
55
  })
@@ -103,9 +103,9 @@ describe('Web Tools', () => {
103
103
  describe('webTools array', () => {
104
104
  it('contains all web tools', () => {
105
105
  expect(webTools).toHaveLength(3)
106
- expect(webTools.map(t => t.id)).toContain('web.fetch')
107
- expect(webTools.map(t => t.id)).toContain('web.parse-html')
108
- expect(webTools.map(t => t.id)).toContain('web.read')
106
+ expect(webTools.map((t) => t.id)).toContain('web.fetch')
107
+ expect(webTools.map((t) => t.id)).toContain('web.parse-html')
108
+ expect(webTools.map((t) => t.id)).toContain('web.read')
109
109
  })
110
110
  })
111
111
  })
@@ -304,7 +304,7 @@ describe('Data Tools', () => {
304
304
  describe('dataTools array', () => {
305
305
  it('contains all data tools', () => {
306
306
  expect(dataTools).toHaveLength(5)
307
- const ids = dataTools.map(t => t.id)
307
+ const ids = dataTools.map((t) => t.id)
308
308
  expect(ids).toContain('data.json.parse')
309
309
  expect(ids).toContain('data.json.stringify')
310
310
  expect(ids).toContain('data.csv.parse')
@@ -323,9 +323,9 @@ describe('Communication Tools', () => {
323
323
  })
324
324
 
325
325
  it('has required parameters', () => {
326
- const toParam = sendEmail.parameters.find(p => p.name === 'to')
327
- const subjectParam = sendEmail.parameters.find(p => p.name === 'subject')
328
- const bodyParam = sendEmail.parameters.find(p => p.name === 'body')
326
+ const toParam = sendEmail.parameters.find((p) => p.name === 'to')
327
+ const subjectParam = sendEmail.parameters.find((p) => p.name === 'subject')
328
+ const bodyParam = sendEmail.parameters.find((p) => p.name === 'body')
329
329
 
330
330
  expect(toParam?.required).toBe(true)
331
331
  expect(subjectParam?.required).toBe(true)
@@ -419,7 +419,7 @@ describe('Communication Tools', () => {
419
419
  describe('communicationTools array', () => {
420
420
  it('contains all communication tools', () => {
421
421
  expect(communicationTools).toHaveLength(4)
422
- const ids = communicationTools.map(t => t.id)
422
+ const ids = communicationTools.map((t) => t.id)
423
423
  expect(ids).toContain('communication.email.send')
424
424
  expect(ids).toContain('communication.slack.send')
425
425
  expect(ids).toContain('communication.notify')
@@ -437,7 +437,11 @@ describe('Builtin Tools Utilities', () => {
437
437
  it('returns all builtin tools', () => {
438
438
  const tools = getBuiltinTools()
439
439
 
440
- expect(tools.length).toBe(webTools.length + dataTools.length + communicationTools.length)
440
+ // Note: systemTools are included as of fsx/gitx/bashx integration (aip-3749.3)
441
+ // Use >= to allow for future additions while ensuring the core tools are present
442
+ expect(tools.length).toBeGreaterThanOrEqual(
443
+ webTools.length + dataTools.length + communicationTools.length
444
+ )
441
445
  })
442
446
  })
443
447
 
@@ -0,0 +1,402 @@
1
+ /**
2
+ * Tests for Type Definitions
3
+ *
4
+ * Covers tool categories, subcategories, and type structures.
5
+ * Note: We primarily test via runtime behavior since TypeScript types
6
+ * are compile-time only.
7
+ */
8
+
9
+ import { describe, it, expect } from 'vitest'
10
+ import { defineTool, registry } from '../src/index.js'
11
+
12
+ describe('Tool Category Type System', () => {
13
+ describe('ToolCategory', () => {
14
+ it('accepts valid categories via defineTool', () => {
15
+ const categories = [
16
+ 'communication',
17
+ 'data',
18
+ 'development',
19
+ 'documents',
20
+ 'finance',
21
+ 'integration',
22
+ 'knowledge',
23
+ 'media',
24
+ 'productivity',
25
+ 'security',
26
+ 'system',
27
+ 'web',
28
+ ]
29
+
30
+ // Each category should work in defineTool
31
+ for (const category of categories) {
32
+ const tool = defineTool({
33
+ id: `cat.${category}`,
34
+ name: `${category} Test`,
35
+ description: 'Test',
36
+ category: category as any,
37
+ input: { type: 'object', properties: {} },
38
+ handler: async () => ({}),
39
+ })
40
+
41
+ expect(tool.category).toBe(category)
42
+ }
43
+ })
44
+ })
45
+
46
+ describe('ToolSubcategory', () => {
47
+ it('accepts valid subcategory values', () => {
48
+ const tool = defineTool({
49
+ id: 'sub.test',
50
+ name: 'Subcategory Test',
51
+ description: 'Test',
52
+ category: 'data',
53
+ subcategory: 'transform',
54
+ input: { type: 'object', properties: {} },
55
+ handler: async () => ({}),
56
+ })
57
+
58
+ expect(tool.subcategory).toBe('transform')
59
+ })
60
+ })
61
+ })
62
+
63
+ describe('Tool Access Types', () => {
64
+ describe('ToolAudience', () => {
65
+ it('accepts agent audience', () => {
66
+ const tool = defineTool({
67
+ id: 'audience.agent',
68
+ name: 'Agent Only',
69
+ description: 'Only for agents',
70
+ category: 'data',
71
+ input: { type: 'object', properties: {} },
72
+ handler: async () => ({}),
73
+ options: { audience: 'agent' },
74
+ })
75
+
76
+ expect(tool.audience).toBe('agent')
77
+ })
78
+
79
+ it('accepts human audience', () => {
80
+ const tool = defineTool({
81
+ id: 'audience.human',
82
+ name: 'Human Only',
83
+ description: 'Only for humans',
84
+ category: 'data',
85
+ input: { type: 'object', properties: {} },
86
+ handler: async () => ({}),
87
+ options: { audience: 'human' },
88
+ })
89
+
90
+ expect(tool.audience).toBe('human')
91
+ })
92
+
93
+ it('accepts both audience', () => {
94
+ const tool = defineTool({
95
+ id: 'audience.both',
96
+ name: 'Both',
97
+ description: 'For both',
98
+ category: 'data',
99
+ input: { type: 'object', properties: {} },
100
+ handler: async () => ({}),
101
+ options: { audience: 'both' },
102
+ })
103
+
104
+ expect(tool.audience).toBe('both')
105
+ })
106
+ })
107
+
108
+ describe('ToolPermission', () => {
109
+ it('can be used in tool definition', () => {
110
+ const tool = defineTool({
111
+ id: 'perm.test',
112
+ name: 'Permission Test',
113
+ description: 'Test',
114
+ category: 'communication',
115
+ input: { type: 'object', properties: {} },
116
+ handler: async () => ({}),
117
+ options: {
118
+ permissions: [
119
+ { type: 'write', resource: 'email' },
120
+ { type: 'read', resource: 'contacts' },
121
+ ],
122
+ },
123
+ })
124
+
125
+ expect(tool.permissions).toHaveLength(2)
126
+ expect(tool.permissions?.[0].type).toBe('write')
127
+ expect(tool.permissions?.[0].resource).toBe('email')
128
+ expect(tool.permissions?.[1].type).toBe('read')
129
+ })
130
+ })
131
+
132
+ describe('RateLimit', () => {
133
+ it('can be used in tool definition', () => {
134
+ const tool = defineTool({
135
+ id: 'rate.test',
136
+ name: 'Rate Test',
137
+ description: 'Test',
138
+ category: 'web',
139
+ input: { type: 'object', properties: {} },
140
+ handler: async () => ({}),
141
+ options: {
142
+ rateLimit: {
143
+ maxCalls: 100,
144
+ periodSeconds: 60,
145
+ scope: 'user',
146
+ },
147
+ },
148
+ })
149
+
150
+ expect(tool.rateLimit?.maxCalls).toBe(100)
151
+ expect(tool.rateLimit?.periodSeconds).toBe(60)
152
+ expect(tool.rateLimit?.scope).toBe('user')
153
+ })
154
+ })
155
+ })
156
+
157
+ describe('Tool Interface', () => {
158
+ describe('Tool definition structure', () => {
159
+ it('has all required fields', () => {
160
+ const tool = defineTool({
161
+ id: 'structure.test',
162
+ name: 'Structure Test',
163
+ description: 'Tests structure',
164
+ category: 'data',
165
+ input: {
166
+ type: 'object',
167
+ properties: {
168
+ value: { type: 'string' },
169
+ },
170
+ required: ['value'],
171
+ },
172
+ handler: async (input) => ({ result: input }),
173
+ })
174
+
175
+ expect(tool.id).toBeDefined()
176
+ expect(tool.name).toBeDefined()
177
+ expect(tool.description).toBeDefined()
178
+ expect(tool.category).toBeDefined()
179
+ expect(tool.parameters).toBeDefined()
180
+ expect(tool.handler).toBeDefined()
181
+ })
182
+
183
+ it('supports optional metadata fields', () => {
184
+ const tool = defineTool({
185
+ id: 'metadata.test',
186
+ name: 'Metadata Test',
187
+ description: 'Tests metadata',
188
+ category: 'web',
189
+ subcategory: 'fetch',
190
+ input: { type: 'object', properties: {} },
191
+ handler: async () => ({}),
192
+ options: {
193
+ version: '1.0.0',
194
+ author: 'Test Author',
195
+ docsUrl: 'https://docs.example.com',
196
+ requiresConfirmation: true,
197
+ idempotent: false,
198
+ estimatedDuration: 1000,
199
+ costPerExecution: 0.01,
200
+ },
201
+ })
202
+
203
+ expect(tool.version).toBe('1.0.0')
204
+ expect(tool.author).toBe('Test Author')
205
+ expect(tool.docsUrl).toBe('https://docs.example.com')
206
+ expect(tool.requiresConfirmation).toBe(true)
207
+ expect(tool.idempotent).toBe(false)
208
+ expect(tool.estimatedDuration).toBe(1000)
209
+ expect(tool.costPerExecution).toBe(0.01)
210
+ })
211
+ })
212
+
213
+ describe('Tool with tags', () => {
214
+ it('supports tags for classification', () => {
215
+ const tool = defineTool({
216
+ id: 'tags.test',
217
+ name: 'Tags Test',
218
+ description: 'Test',
219
+ category: 'data',
220
+ input: { type: 'object', properties: {} },
221
+ handler: async () => ({}),
222
+ options: {
223
+ tags: ['json', 'parse', 'transform'],
224
+ },
225
+ })
226
+
227
+ expect(tool.tags).toHaveLength(3)
228
+ expect(tool.tags).toContain('json')
229
+ expect(tool.tags).toContain('parse')
230
+ })
231
+ })
232
+
233
+ describe('Tool with security level', () => {
234
+ it('supports security classification', () => {
235
+ const tool = defineTool({
236
+ id: 'security.test',
237
+ name: 'Security Test',
238
+ description: 'Test',
239
+ category: 'security',
240
+ input: { type: 'object', properties: {} },
241
+ handler: async () => ({}),
242
+ options: {
243
+ securityLevel: 'confidential',
244
+ },
245
+ })
246
+
247
+ expect(tool.securityLevel).toBe('confidential')
248
+ })
249
+ })
250
+ })
251
+
252
+ describe('Registry Types', () => {
253
+ describe('ToolRegistry interface', () => {
254
+ it('has all required methods', () => {
255
+ expect(typeof registry.register).toBe('function')
256
+ expect(typeof registry.unregister).toBe('function')
257
+ expect(typeof registry.get).toBe('function')
258
+ expect(typeof registry.has).toBe('function')
259
+ expect(typeof registry.list).toBe('function')
260
+ expect(typeof registry.query).toBe('function')
261
+ expect(typeof registry.byCategory).toBe('function')
262
+ expect(typeof registry.clear).toBe('function')
263
+ })
264
+
265
+ it('registers and retrieves tools', () => {
266
+ const tool = defineTool({
267
+ id: 'registry.integration.test',
268
+ name: 'Registry Test',
269
+ description: 'Test',
270
+ category: 'data',
271
+ input: { type: 'object', properties: {} },
272
+ handler: async () => ({}),
273
+ })
274
+
275
+ registry.register(tool)
276
+
277
+ expect(registry.has('registry.integration.test')).toBe(true)
278
+ expect(registry.get('registry.integration.test')).toBe(tool)
279
+
280
+ // Cleanup
281
+ registry.unregister('registry.integration.test')
282
+ })
283
+
284
+ it('queries tools by category', () => {
285
+ const dataTool = defineTool({
286
+ id: 'query.data.test',
287
+ name: 'Data Tool',
288
+ description: 'Test',
289
+ category: 'data',
290
+ input: { type: 'object', properties: {} },
291
+ handler: async () => ({}),
292
+ })
293
+
294
+ registry.register(dataTool)
295
+
296
+ const dataTools = registry.byCategory('data')
297
+ expect(dataTools.some((t) => t.id === 'query.data.test')).toBe(true)
298
+
299
+ // Cleanup
300
+ registry.unregister('query.data.test')
301
+ })
302
+
303
+ it('queries tools with filters', () => {
304
+ const tool = defineTool({
305
+ id: 'query.filter.test',
306
+ name: 'Filter Test',
307
+ description: 'A test tool for filtering',
308
+ category: 'web',
309
+ subcategory: 'fetch',
310
+ input: { type: 'object', properties: {} },
311
+ handler: async () => ({}),
312
+ options: {
313
+ tags: ['http', 'network'],
314
+ audience: 'both',
315
+ },
316
+ })
317
+
318
+ registry.register(tool)
319
+
320
+ const results = registry.query({
321
+ category: 'web',
322
+ subcategory: 'fetch',
323
+ })
324
+
325
+ expect(results.some((t) => t.id === 'query.filter.test')).toBe(true)
326
+
327
+ // Cleanup
328
+ registry.unregister('query.filter.test')
329
+ })
330
+ })
331
+ })
332
+
333
+ describe('Tool Execution', () => {
334
+ it('executes handler with input', async () => {
335
+ const tool = defineTool<{ a: number; b: number }, { sum: number }>({
336
+ id: 'exec.test',
337
+ name: 'Add',
338
+ description: 'Add two numbers',
339
+ category: 'data',
340
+ input: {
341
+ type: 'object',
342
+ properties: {
343
+ a: { type: 'number' },
344
+ b: { type: 'number' },
345
+ },
346
+ required: ['a', 'b'],
347
+ },
348
+ handler: async (input) => ({ sum: input.a + input.b }),
349
+ })
350
+
351
+ const result = await tool.handler({ a: 2, b: 3 })
352
+
353
+ expect(result.sum).toBe(5)
354
+ })
355
+
356
+ it('handles async operations', async () => {
357
+ const tool = defineTool<{ delay: number }, { completed: boolean }>({
358
+ id: 'exec.async.test',
359
+ name: 'Async Test',
360
+ description: 'Test async',
361
+ category: 'system',
362
+ input: {
363
+ type: 'object',
364
+ properties: {
365
+ delay: { type: 'number' },
366
+ },
367
+ },
368
+ handler: async (input) => {
369
+ await new Promise((resolve) => setTimeout(resolve, input.delay))
370
+ return { completed: true }
371
+ },
372
+ })
373
+
374
+ const result = await tool.handler({ delay: 10 })
375
+
376
+ expect(result.completed).toBe(true)
377
+ })
378
+
379
+ it('handles errors in handler', async () => {
380
+ const tool = defineTool<{ shouldError: boolean }, { success: boolean }>({
381
+ id: 'exec.error.test',
382
+ name: 'Error Test',
383
+ description: 'Test error',
384
+ category: 'system',
385
+ input: {
386
+ type: 'object',
387
+ properties: {
388
+ shouldError: { type: 'boolean' },
389
+ },
390
+ },
391
+ handler: async (input) => {
392
+ if (input.shouldError) {
393
+ throw new Error('Intentional error')
394
+ }
395
+ return { success: true }
396
+ },
397
+ })
398
+
399
+ await expect(tool.handler({ shouldError: true })).rejects.toThrow('Intentional error')
400
+ await expect(tool.handler({ shouldError: false })).resolves.toEqual({ success: true })
401
+ })
402
+ })