digital-tools 2.1.1 → 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 (293) hide show
  1. package/CHANGELOG.md +17 -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 +22 -20
  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 +21 -4
  132. package/src/client.ts +136 -0
  133. package/src/define.ts +31 -37
  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 -5
  199. package/dist/providers/voice/vapi.d.ts +0 -27
  200. package/dist/providers/voice/vapi.d.ts.map +0 -1
  201. package/dist/providers/voice/vapi.js +0 -440
  202. package/dist/providers/voice/vapi.js.map +0 -1
  203. package/src/define.js +0 -267
  204. package/src/entities/advertising.js +0 -999
  205. package/src/entities/ai.js +0 -756
  206. package/src/entities/analytics.js +0 -1588
  207. package/src/entities/automation.js +0 -601
  208. package/src/entities/communication.js +0 -1150
  209. package/src/entities/crm.js +0 -1386
  210. package/src/entities/design.js +0 -546
  211. package/src/entities/development.js +0 -2212
  212. package/src/entities/document.js +0 -874
  213. package/src/entities/ecommerce.js +0 -1429
  214. package/src/entities/experiment.js +0 -1039
  215. package/src/entities/finance.js +0 -3478
  216. package/src/entities/forms.js +0 -1892
  217. package/src/entities/hr.js +0 -661
  218. package/src/entities/identity.js +0 -997
  219. package/src/entities/index.js +0 -282
  220. package/src/entities/infrastructure.js +0 -1153
  221. package/src/entities/knowledge.js +0 -1438
  222. package/src/entities/marketing.js +0 -1610
  223. package/src/entities/media.js +0 -1634
  224. package/src/entities/notification.js +0 -1199
  225. package/src/entities/presentation.js +0 -1274
  226. package/src/entities/productivity.js +0 -1317
  227. package/src/entities/project-management.js +0 -1136
  228. package/src/entities/recruiting.js +0 -736
  229. package/src/entities/shipping.js +0 -509
  230. package/src/entities/signature.js +0 -1102
  231. package/src/entities/site.js +0 -222
  232. package/src/entities/spreadsheet.js +0 -1341
  233. package/src/entities/storage.js +0 -1198
  234. package/src/entities/support.js +0 -1166
  235. package/src/entities/video-conferencing.js +0 -1750
  236. package/src/entities/video.js +0 -950
  237. package/src/entities.js +0 -1663
  238. package/src/index.js +0 -74
  239. package/src/providers/analytics/index.js +0 -17
  240. package/src/providers/analytics/mixpanel.js +0 -255
  241. package/src/providers/calendar/cal-com.js +0 -303
  242. package/src/providers/calendar/google-calendar.js +0 -335
  243. package/src/providers/calendar/index.js +0 -20
  244. package/src/providers/crm/hubspot.js +0 -566
  245. package/src/providers/crm/index.js +0 -17
  246. package/src/providers/development/github.js +0 -472
  247. package/src/providers/development/index.js +0 -17
  248. package/src/providers/ecommerce/index.js +0 -17
  249. package/src/providers/ecommerce/shopify.js +0 -378
  250. package/src/providers/email/index.js +0 -20
  251. package/src/providers/email/resend.js +0 -258
  252. package/src/providers/email/sendgrid.js +0 -161
  253. package/src/providers/finance/index.js +0 -17
  254. package/src/providers/finance/stripe.js +0 -549
  255. package/src/providers/forms/index.js +0 -17
  256. package/src/providers/forms/typeform.js +0 -500
  257. package/src/providers/index.js +0 -123
  258. package/src/providers/knowledge/index.js +0 -17
  259. package/src/providers/knowledge/notion.js +0 -389
  260. package/src/providers/marketing/index.js +0 -17
  261. package/src/providers/marketing/mailchimp.js +0 -443
  262. package/src/providers/media/cloudinary.js +0 -318
  263. package/src/providers/media/index.js +0 -17
  264. package/src/providers/messaging/index.js +0 -20
  265. package/src/providers/messaging/slack.js +0 -393
  266. package/src/providers/messaging/twilio-sms.js +0 -249
  267. package/src/providers/project-management/index.js +0 -17
  268. package/src/providers/project-management/linear.js +0 -575
  269. package/src/providers/registry.js +0 -86
  270. package/src/providers/spreadsheet/google-sheets.js +0 -375
  271. package/src/providers/spreadsheet/index.js +0 -20
  272. package/src/providers/spreadsheet/xlsx.js +0 -423
  273. package/src/providers/storage/index.js +0 -24
  274. package/src/providers/storage/s3.js +0 -419
  275. package/src/providers/support/index.js +0 -17
  276. package/src/providers/support/zendesk.js +0 -373
  277. package/src/providers/tasks/index.js +0 -17
  278. package/src/providers/tasks/todoist.js +0 -286
  279. package/src/providers/types.js +0 -9
  280. package/src/providers/video-conferencing/google-meet.js +0 -286
  281. package/src/providers/video-conferencing/index.js +0 -31
  282. package/src/providers/video-conferencing/jitsi.js +0 -254
  283. package/src/providers/video-conferencing/teams.js +0 -270
  284. package/src/providers/video-conferencing/zoom.js +0 -332
  285. package/src/registry.js +0 -128
  286. package/src/tools/communication.js +0 -184
  287. package/src/tools/data.js +0 -205
  288. package/src/tools/index.js +0 -11
  289. package/src/tools/web.js +0 -137
  290. package/src/types.js +0 -10
  291. package/test/define.test.js +0 -306
  292. package/test/registry.test.js +0 -357
  293. 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
+ })