autonomous-agents 0.1.0 → 2.0.1

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 (51) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/CHANGELOG.md +9 -0
  3. package/README.md +260 -96
  4. package/dist/actions.d.ts +136 -0
  5. package/dist/actions.d.ts.map +1 -0
  6. package/dist/actions.js +303 -0
  7. package/dist/actions.js.map +1 -0
  8. package/dist/agent.d.ts +49 -0
  9. package/dist/agent.d.ts.map +1 -0
  10. package/dist/agent.js +452 -0
  11. package/dist/agent.js.map +1 -0
  12. package/dist/goals.d.ts +138 -0
  13. package/dist/goals.d.ts.map +1 -0
  14. package/dist/goals.js +342 -0
  15. package/dist/goals.js.map +1 -0
  16. package/dist/index.d.ts +55 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +60 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/metrics.d.ts +245 -0
  21. package/dist/metrics.d.ts.map +1 -0
  22. package/dist/metrics.js +436 -0
  23. package/dist/metrics.js.map +1 -0
  24. package/dist/role.d.ts +122 -0
  25. package/dist/role.d.ts.map +1 -0
  26. package/dist/role.js +393 -0
  27. package/dist/role.js.map +1 -0
  28. package/dist/team.d.ts +152 -0
  29. package/dist/team.d.ts.map +1 -0
  30. package/dist/team.js +347 -0
  31. package/dist/team.js.map +1 -0
  32. package/dist/types.d.ts +327 -0
  33. package/dist/types.d.ts.map +1 -0
  34. package/dist/types.js +8 -0
  35. package/dist/types.js.map +1 -0
  36. package/package.json +27 -36
  37. package/src/actions.ts +366 -0
  38. package/src/agent.ts +548 -0
  39. package/src/goals.ts +435 -0
  40. package/src/index.ts +135 -0
  41. package/src/metrics.ts +591 -0
  42. package/src/role.ts +422 -0
  43. package/src/team.ts +466 -0
  44. package/src/types.ts +356 -0
  45. package/test/actions.test.ts +522 -0
  46. package/test/agent.test.ts +490 -0
  47. package/test/goals.test.ts +570 -0
  48. package/test/metrics.test.ts +707 -0
  49. package/test/role.test.ts +423 -0
  50. package/test/team.test.ts +708 -0
  51. package/tsconfig.json +9 -0
@@ -0,0 +1,423 @@
1
+ /**
2
+ * Tests for Role functionality
3
+ *
4
+ * Covers role creation, predefined roles, and helper functions.
5
+ */
6
+
7
+ import { describe, it, expect } from 'vitest'
8
+ import {
9
+ Role,
10
+ Roles,
11
+ hasPermission,
12
+ hasSkill,
13
+ getPermissions,
14
+ getSkills,
15
+ mergeRoles,
16
+ } from '../src/index.js'
17
+
18
+ describe('Role', () => {
19
+ describe('Role creation', () => {
20
+ it('creates a role with basic config', () => {
21
+ const role = Role({
22
+ name: 'Developer',
23
+ description: 'Software developer',
24
+ skills: ['typescript', 'javascript'],
25
+ permissions: ['code.write', 'code.read'],
26
+ })
27
+
28
+ expect(role.name).toBe('Developer')
29
+ expect(role.description).toBe('Software developer')
30
+ expect(role.permissions).toEqual(['code.write', 'code.read'])
31
+ expect(role.skills).toEqual(['typescript', 'javascript'])
32
+ })
33
+
34
+ it('generates id from name', () => {
35
+ const role = Role({
36
+ name: 'Product Manager',
37
+ description: 'Manages products',
38
+ skills: ['strategy'],
39
+ })
40
+
41
+ expect(role.id).toBe('product-manager')
42
+ })
43
+
44
+ it('creates a role with minimal config (skills required)', () => {
45
+ const role = Role({
46
+ name: 'Simple',
47
+ description: 'A simple role',
48
+ skills: ['general'],
49
+ })
50
+
51
+ expect(role.name).toBe('Simple')
52
+ expect(role.description).toBe('A simple role')
53
+ expect(role.permissions).toBeUndefined()
54
+ })
55
+
56
+ it('creates a role with outputs', () => {
57
+ const role = Role({
58
+ name: 'Writer',
59
+ description: 'Content writer',
60
+ skills: ['writing'],
61
+ outputs: ['blog posts', 'documentation'],
62
+ })
63
+
64
+ expect(role.outputs).toEqual(['blog posts', 'documentation'])
65
+ })
66
+
67
+ it('creates a role with tools', () => {
68
+ const role = Role({
69
+ name: 'Developer',
70
+ description: 'Software developer',
71
+ skills: ['coding'],
72
+ tools: [
73
+ { name: 'runTests', description: 'Run tests', parameters: {}, handler: async () => {} },
74
+ ],
75
+ })
76
+
77
+ expect(role.tools).toHaveLength(1)
78
+ expect(role.tools?.[0]?.name).toBe('runTests')
79
+ })
80
+ })
81
+
82
+ describe('Predefined Roles', () => {
83
+ it('has ProductManager role', () => {
84
+ const pm = Roles.ProductManager
85
+
86
+ expect(pm.name).toBe('Product Manager')
87
+ expect(pm.permissions).toContain('create:feature')
88
+ expect(pm.skills).toContain('product strategy')
89
+ })
90
+
91
+ it('has SoftwareEngineer role', () => {
92
+ const engineer = Roles.SoftwareEngineer
93
+
94
+ expect(engineer.name).toBe('Software Engineer')
95
+ expect(engineer.permissions).toContain('write:code')
96
+ expect(engineer.skills).toContain('programming')
97
+ })
98
+
99
+ it('has Designer role', () => {
100
+ const designer = Roles.Designer
101
+
102
+ expect(designer.name).toBe('Designer')
103
+ expect(designer.permissions).toContain('create:design')
104
+ expect(designer.skills).toContain('UI design')
105
+ })
106
+
107
+ it('has DataAnalyst role', () => {
108
+ const analyst = Roles.DataAnalyst
109
+
110
+ expect(analyst.name).toBe('Data Analyst')
111
+ expect(analyst.permissions).toContain('read:analytics')
112
+ expect(analyst.skills).toContain('data analysis')
113
+ })
114
+
115
+ it('has ContentWriter role', () => {
116
+ const writer = Roles.ContentWriter
117
+
118
+ expect(writer.name).toBe('Content Writer')
119
+ expect(writer.permissions).toContain('create:content')
120
+ expect(writer.skills).toContain('writing')
121
+ })
122
+
123
+ it('has CustomerSupport role', () => {
124
+ const support = Roles.CustomerSupport
125
+
126
+ expect(support.name).toBe('Customer Support')
127
+ expect(support.permissions).toContain('read:tickets')
128
+ expect(support.skills).toContain('customer service')
129
+ })
130
+
131
+ it('has ProjectManager role', () => {
132
+ const manager = Roles.ProjectManager
133
+
134
+ expect(manager.name).toBe('Project Manager')
135
+ expect(manager.permissions).toContain('create:project')
136
+ expect(manager.skills).toContain('project planning')
137
+ })
138
+
139
+ it('has QAEngineer role', () => {
140
+ const qa = Roles.QAEngineer
141
+
142
+ expect(qa.name).toBe('QA Engineer')
143
+ expect(qa.permissions).toContain('run:tests')
144
+ expect(qa.skills).toContain('manual testing')
145
+ })
146
+
147
+ it('has MarketingManager role', () => {
148
+ const marketing = Roles.MarketingManager
149
+
150
+ expect(marketing.name).toBe('Marketing Manager')
151
+ expect(marketing.permissions).toContain('create:campaign')
152
+ expect(marketing.skills).toContain('marketing strategy')
153
+ })
154
+
155
+ it('has DevOpsEngineer role', () => {
156
+ const devops = Roles.DevOpsEngineer
157
+
158
+ expect(devops.name).toBe('DevOps Engineer')
159
+ expect(devops.permissions).toContain('deploy:production')
160
+ expect(devops.skills).toContain('infrastructure management')
161
+ })
162
+ })
163
+
164
+ describe('hasPermission', () => {
165
+ it('returns true when role has permission', () => {
166
+ const role = Role({
167
+ name: 'Test',
168
+ description: 'Test role',
169
+ skills: ['testing'],
170
+ permissions: ['read', 'write', 'admin'],
171
+ })
172
+
173
+ expect(hasPermission(role, 'read')).toBe(true)
174
+ expect(hasPermission(role, 'write')).toBe(true)
175
+ expect(hasPermission(role, 'admin')).toBe(true)
176
+ })
177
+
178
+ it('returns false when role does not have permission', () => {
179
+ const role = Role({
180
+ name: 'Test',
181
+ description: 'Test role',
182
+ skills: ['testing'],
183
+ permissions: ['read'],
184
+ })
185
+
186
+ expect(hasPermission(role, 'write')).toBe(false)
187
+ expect(hasPermission(role, 'admin')).toBe(false)
188
+ })
189
+
190
+ it('returns false when role has no permissions', () => {
191
+ const role = Role({
192
+ name: 'Test',
193
+ description: 'Test role',
194
+ skills: ['testing'],
195
+ })
196
+
197
+ expect(hasPermission(role, 'read')).toBe(false)
198
+ })
199
+
200
+ it('handles empty permissions array', () => {
201
+ const role = Role({
202
+ name: 'Test',
203
+ description: 'Test role',
204
+ skills: ['testing'],
205
+ permissions: [],
206
+ })
207
+
208
+ expect(hasPermission(role, 'read')).toBe(false)
209
+ })
210
+ })
211
+
212
+ describe('hasSkill', () => {
213
+ it('returns true when role has skill', () => {
214
+ const role = Role({
215
+ name: 'Test',
216
+ description: 'Test role',
217
+ skills: ['typescript', 'javascript', 'python'],
218
+ })
219
+
220
+ expect(hasSkill(role, 'typescript')).toBe(true)
221
+ expect(hasSkill(role, 'javascript')).toBe(true)
222
+ expect(hasSkill(role, 'python')).toBe(true)
223
+ })
224
+
225
+ it('returns false when role does not have skill', () => {
226
+ const role = Role({
227
+ name: 'Test',
228
+ description: 'Test role',
229
+ skills: ['typescript'],
230
+ })
231
+
232
+ expect(hasSkill(role, 'rust')).toBe(false)
233
+ expect(hasSkill(role, 'go')).toBe(false)
234
+ })
235
+
236
+ it('performs case-insensitive skill matching', () => {
237
+ const role = Role({
238
+ name: 'Test',
239
+ description: 'Test role',
240
+ skills: ['TypeScript', 'JavaScript'],
241
+ })
242
+
243
+ expect(hasSkill(role, 'typescript')).toBe(true)
244
+ expect(hasSkill(role, 'JAVASCRIPT')).toBe(true)
245
+ })
246
+
247
+ it('performs partial skill matching', () => {
248
+ const role = Role({
249
+ name: 'Test',
250
+ description: 'Test role',
251
+ skills: ['software design', 'system architecture'],
252
+ })
253
+
254
+ expect(hasSkill(role, 'design')).toBe(true)
255
+ expect(hasSkill(role, 'architecture')).toBe(true)
256
+ })
257
+ })
258
+
259
+ describe('getPermissions', () => {
260
+ it('returns all permissions from a role', () => {
261
+ const role = Role({
262
+ name: 'Test',
263
+ description: 'Test role',
264
+ skills: ['testing'],
265
+ permissions: ['read', 'write', 'admin'],
266
+ })
267
+
268
+ expect(getPermissions(role)).toEqual(['read', 'write', 'admin'])
269
+ })
270
+
271
+ it('returns empty array when no permissions', () => {
272
+ const role = Role({
273
+ name: 'Test',
274
+ description: 'Test role',
275
+ skills: ['testing'],
276
+ })
277
+
278
+ expect(getPermissions(role)).toEqual([])
279
+ })
280
+ })
281
+
282
+ describe('getSkills', () => {
283
+ it('returns all skills from a role', () => {
284
+ const role = Role({
285
+ name: 'Test',
286
+ description: 'Test role',
287
+ skills: ['typescript', 'javascript'],
288
+ })
289
+
290
+ expect(getSkills(role)).toEqual(['typescript', 'javascript'])
291
+ })
292
+ })
293
+
294
+ describe('mergeRoles', () => {
295
+ it('merges two roles with no overlap', () => {
296
+ const role1 = Role({
297
+ name: 'Role1',
298
+ description: 'First role',
299
+ skills: ['typescript'],
300
+ permissions: ['read'],
301
+ })
302
+
303
+ const role2 = Role({
304
+ name: 'Role2',
305
+ description: 'Second role',
306
+ skills: ['javascript'],
307
+ permissions: ['write'],
308
+ })
309
+
310
+ const merged = mergeRoles('Combined Role', role1, role2)
311
+
312
+ expect(merged.name).toBe('Combined Role')
313
+ expect(merged.permissions).toContain('read')
314
+ expect(merged.permissions).toContain('write')
315
+ expect(merged.skills).toContain('typescript')
316
+ expect(merged.skills).toContain('javascript')
317
+ })
318
+
319
+ it('deduplicates permissions and skills', () => {
320
+ const role1 = Role({
321
+ name: 'Role1',
322
+ description: 'First role',
323
+ skills: ['typescript', 'javascript'],
324
+ permissions: ['read', 'write'],
325
+ })
326
+
327
+ const role2 = Role({
328
+ name: 'Role2',
329
+ description: 'Second role',
330
+ skills: ['javascript', 'python'],
331
+ permissions: ['write', 'admin'],
332
+ })
333
+
334
+ const merged = mergeRoles('Combined', role1, role2)
335
+
336
+ expect(merged.permissions).toHaveLength(3)
337
+ expect(merged.skills).toHaveLength(3)
338
+ })
339
+
340
+ it('merges roles with empty arrays', () => {
341
+ const role1 = Role({
342
+ name: 'Role1',
343
+ description: 'First role',
344
+ skills: [],
345
+ permissions: [],
346
+ })
347
+
348
+ const role2 = Role({
349
+ name: 'Role2',
350
+ description: 'Second role',
351
+ skills: ['typescript'],
352
+ permissions: ['read'],
353
+ })
354
+
355
+ const merged = mergeRoles('Combined', role1, role2)
356
+
357
+ expect(merged.permissions).toEqual(['read'])
358
+ expect(merged.skills).toEqual(['typescript'])
359
+ })
360
+
361
+ it('merges roles with undefined permissions', () => {
362
+ const role1 = Role({
363
+ name: 'Role1',
364
+ description: 'First role',
365
+ skills: ['skill1'],
366
+ })
367
+
368
+ const role2 = Role({
369
+ name: 'Role2',
370
+ description: 'Second role',
371
+ skills: ['skill2'],
372
+ permissions: ['read'],
373
+ })
374
+
375
+ const merged = mergeRoles('Combined', role1, role2)
376
+
377
+ expect(merged.permissions).toEqual(['read'])
378
+ expect(merged.skills).toHaveLength(2)
379
+ })
380
+
381
+ it('merges outputs', () => {
382
+ const role1 = Role({
383
+ name: 'Role1',
384
+ description: 'First role',
385
+ skills: ['skill1'],
386
+ outputs: ['output1'],
387
+ })
388
+
389
+ const role2 = Role({
390
+ name: 'Role2',
391
+ description: 'Second role',
392
+ skills: ['skill2'],
393
+ outputs: ['output1', 'output2'],
394
+ })
395
+
396
+ const merged = mergeRoles('Combined', role1, role2)
397
+
398
+ expect(merged.outputs).toContain('output1')
399
+ expect(merged.outputs).toContain('output2')
400
+ // Deduplicated
401
+ expect(merged.outputs).toHaveLength(2)
402
+ })
403
+
404
+ it('combines descriptions', () => {
405
+ const role1 = Role({
406
+ name: 'Role1',
407
+ description: 'First description',
408
+ skills: ['skill1'],
409
+ })
410
+
411
+ const role2 = Role({
412
+ name: 'Role2',
413
+ description: 'Second description',
414
+ skills: ['skill2'],
415
+ })
416
+
417
+ const merged = mergeRoles('Combined', role1, role2)
418
+
419
+ expect(merged.description).toContain('First description')
420
+ expect(merged.description).toContain('Second description')
421
+ })
422
+ })
423
+ })