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
package/src/team.ts ADDED
@@ -0,0 +1,466 @@
1
+ /**
2
+ * Team - Define and coordinate a team of agents and humans
3
+ *
4
+ * Teams enable collaboration and coordination between multiple agents
5
+ * and human workers working toward shared goals.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ import type {
11
+ Team as TeamType,
12
+ TeamMember,
13
+ Agent,
14
+ Role as RoleType,
15
+ Goal,
16
+ CommunicationChannel,
17
+ } from './types.js'
18
+
19
+ /**
20
+ * Create a team
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { Team, Agent, Role } from 'autonomous-agents'
25
+ *
26
+ * const productTeam = Team({
27
+ * name: 'Product Development',
28
+ * description: 'Cross-functional team building product features',
29
+ * members: [
30
+ * {
31
+ * id: 'pm-1',
32
+ * name: 'Sarah',
33
+ * type: 'human',
34
+ * role: Roles.ProductManager,
35
+ * status: 'active',
36
+ * availability: 'available',
37
+ * },
38
+ * {
39
+ * id: 'dev-agent-1',
40
+ * name: 'DevAgent',
41
+ * type: 'agent',
42
+ * role: Roles.SoftwareEngineer,
43
+ * status: 'active',
44
+ * availability: 'available',
45
+ * },
46
+ * ],
47
+ * goals: [
48
+ * {
49
+ * id: 'q1-goal',
50
+ * description: 'Launch new feature X',
51
+ * target: '100%',
52
+ * deadline: new Date('2024-03-31'),
53
+ * priority: 'high',
54
+ * },
55
+ * ],
56
+ * channels: [
57
+ * { id: 'team-slack', type: 'slack', config: { channel: '#product-dev' } },
58
+ * ],
59
+ * })
60
+ *
61
+ * // Add a new member
62
+ * team.addMember({
63
+ * id: 'designer-1',
64
+ * name: 'Alex',
65
+ * type: 'human',
66
+ * role: Roles.Designer,
67
+ * })
68
+ *
69
+ * // Broadcast to team
70
+ * await team.broadcast('Starting sprint planning!')
71
+ *
72
+ * // Get available members
73
+ * const available = team.getAvailableMembers()
74
+ * ```
75
+ */
76
+ export function Team(config: {
77
+ name: string
78
+ description?: string
79
+ members?: TeamMember[]
80
+ goals?: Goal[]
81
+ context?: Record<string, unknown>
82
+ channels?: CommunicationChannel[]
83
+ }): TeamInstance {
84
+ const team: TeamType = {
85
+ id: generateTeamId(config.name),
86
+ name: config.name,
87
+ description: config.description,
88
+ members: config.members || [],
89
+ goals: config.goals,
90
+ context: config.context,
91
+ channels: config.channels,
92
+ }
93
+
94
+ return {
95
+ ...team,
96
+ addMember,
97
+ removeMember,
98
+ getMember,
99
+ getMembers,
100
+ getAvailableMembers,
101
+ getMembersByRole,
102
+ getMembersByType,
103
+ updateMember,
104
+ addGoal,
105
+ updateGoal,
106
+ removeGoal,
107
+ getGoals,
108
+ addChannel,
109
+ removeChannel,
110
+ broadcast,
111
+ sendTo,
112
+ updateContext,
113
+ getContext,
114
+ }
115
+
116
+ /**
117
+ * Add a member to the team
118
+ */
119
+ function addMember(member: TeamMember): void {
120
+ const existing = team.members.find(m => m.id === member.id)
121
+ if (existing) {
122
+ throw new Error(`Member with id ${member.id} already exists`)
123
+ }
124
+ team.members.push(member)
125
+ }
126
+
127
+ /**
128
+ * Remove a member from the team
129
+ */
130
+ function removeMember(memberId: string): boolean {
131
+ const index = team.members.findIndex(m => m.id === memberId)
132
+ if (index === -1) return false
133
+ team.members.splice(index, 1)
134
+ return true
135
+ }
136
+
137
+ /**
138
+ * Get a specific member
139
+ */
140
+ function getMember(memberId: string): TeamMember | undefined {
141
+ return team.members.find(m => m.id === memberId)
142
+ }
143
+
144
+ /**
145
+ * Get all members
146
+ */
147
+ function getMembers(): TeamMember[] {
148
+ return [...team.members]
149
+ }
150
+
151
+ /**
152
+ * Get available members
153
+ */
154
+ function getAvailableMembers(): TeamMember[] {
155
+ return team.members.filter(
156
+ m => m.status === 'active' && m.availability === 'available'
157
+ )
158
+ }
159
+
160
+ /**
161
+ * Get members by role
162
+ */
163
+ function getMembersByRole(roleId: string): TeamMember[] {
164
+ return team.members.filter(m => m.role.id === roleId)
165
+ }
166
+
167
+ /**
168
+ * Get members by type
169
+ */
170
+ function getMembersByType(type: 'agent' | 'human'): TeamMember[] {
171
+ return team.members.filter(m => m.type === type)
172
+ }
173
+
174
+ /**
175
+ * Update a member
176
+ */
177
+ function updateMember(
178
+ memberId: string,
179
+ updates: Partial<Omit<TeamMember, 'id'>>
180
+ ): void {
181
+ const member = team.members.find(m => m.id === memberId)
182
+ if (!member) {
183
+ throw new Error(`Member with id ${memberId} not found`)
184
+ }
185
+ Object.assign(member, updates)
186
+ }
187
+
188
+ /**
189
+ * Add a goal
190
+ */
191
+ function addGoal(goal: Goal): void {
192
+ if (!team.goals) {
193
+ team.goals = []
194
+ }
195
+ team.goals.push(goal)
196
+ }
197
+
198
+ /**
199
+ * Update a goal
200
+ */
201
+ function updateGoal(goalId: string, updates: Partial<Omit<Goal, 'id'>>): void {
202
+ const goal = team.goals?.find(g => g.id === goalId)
203
+ if (!goal) {
204
+ throw new Error(`Goal with id ${goalId} not found`)
205
+ }
206
+ Object.assign(goal, updates)
207
+ }
208
+
209
+ /**
210
+ * Remove a goal
211
+ */
212
+ function removeGoal(goalId: string): boolean {
213
+ if (!team.goals) return false
214
+ const index = team.goals.findIndex(g => g.id === goalId)
215
+ if (index === -1) return false
216
+ team.goals.splice(index, 1)
217
+ return true
218
+ }
219
+
220
+ /**
221
+ * Get all goals
222
+ */
223
+ function getGoals(): Goal[] {
224
+ return team.goals ? [...team.goals] : []
225
+ }
226
+
227
+ /**
228
+ * Add a communication channel
229
+ */
230
+ function addChannel(channel: CommunicationChannel): void {
231
+ if (!team.channels) {
232
+ team.channels = []
233
+ }
234
+ team.channels.push(channel)
235
+ }
236
+
237
+ /**
238
+ * Remove a communication channel
239
+ */
240
+ function removeChannel(channelId: string): boolean {
241
+ if (!team.channels) return false
242
+ const index = team.channels.findIndex(c => c.id === channelId)
243
+ if (index === -1) return false
244
+ team.channels.splice(index, 1)
245
+ return true
246
+ }
247
+
248
+ /**
249
+ * Broadcast message to all team members
250
+ */
251
+ async function broadcast(message: string, channelType?: string): Promise<void> {
252
+ const channels = channelType
253
+ ? team.channels?.filter(c => c.type === channelType)
254
+ : team.channels
255
+
256
+ if (!channels || channels.length === 0) {
257
+ console.log(`[Team: ${team.name}] Broadcast: ${message}`)
258
+ return
259
+ }
260
+
261
+ // In a real implementation, this would send via the specified channels
262
+ for (const channel of channels) {
263
+ console.log(
264
+ `[Team: ${team.name}] [${channel.type}:${channel.id}] ${message}`
265
+ )
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Send message to specific team members
271
+ */
272
+ async function sendTo(
273
+ memberIds: string[],
274
+ message: string,
275
+ channelType?: string
276
+ ): Promise<void> {
277
+ const members = team.members.filter(m => memberIds.includes(m.id))
278
+
279
+ if (members.length === 0) {
280
+ throw new Error('No valid members found')
281
+ }
282
+
283
+ // In a real implementation, this would send via appropriate channels
284
+ for (const member of members) {
285
+ console.log(`[Team: ${team.name}] To ${member.name}: ${message}`)
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Update team context
291
+ */
292
+ function updateContext(key: string, value: unknown): void {
293
+ if (!team.context) {
294
+ team.context = {}
295
+ }
296
+ team.context[key] = value
297
+ }
298
+
299
+ /**
300
+ * Get team context
301
+ */
302
+ function getContext<T = unknown>(key?: string): T | Record<string, unknown> {
303
+ if (!team.context) return (key ? undefined : {}) as T | Record<string, unknown>
304
+ if (key) return team.context[key] as T
305
+ return { ...team.context }
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Team instance with methods
311
+ */
312
+ export interface TeamInstance extends TeamType {
313
+ /** Add a member to the team */
314
+ addMember(member: TeamMember): void
315
+ /** Remove a member from the team */
316
+ removeMember(memberId: string): boolean
317
+ /** Get a specific member */
318
+ getMember(memberId: string): TeamMember | undefined
319
+ /** Get all members */
320
+ getMembers(): TeamMember[]
321
+ /** Get available members */
322
+ getAvailableMembers(): TeamMember[]
323
+ /** Get members by role */
324
+ getMembersByRole(roleId: string): TeamMember[]
325
+ /** Get members by type */
326
+ getMembersByType(type: 'agent' | 'human'): TeamMember[]
327
+ /** Update a member */
328
+ updateMember(memberId: string, updates: Partial<Omit<TeamMember, 'id'>>): void
329
+ /** Add a goal */
330
+ addGoal(goal: Goal): void
331
+ /** Update a goal */
332
+ updateGoal(goalId: string, updates: Partial<Omit<Goal, 'id'>>): void
333
+ /** Remove a goal */
334
+ removeGoal(goalId: string): boolean
335
+ /** Get all goals */
336
+ getGoals(): Goal[]
337
+ /** Add a communication channel */
338
+ addChannel(channel: CommunicationChannel): void
339
+ /** Remove a communication channel */
340
+ removeChannel(channelId: string): boolean
341
+ /** Broadcast message to all team members */
342
+ broadcast(message: string, channelType?: string): Promise<void>
343
+ /** Send message to specific members */
344
+ sendTo(memberIds: string[], message: string, channelType?: string): Promise<void>
345
+ /** Update team context */
346
+ updateContext(key: string, value: unknown): void
347
+ /** Get team context */
348
+ getContext<T = unknown>(key?: string): T | Record<string, unknown>
349
+ }
350
+
351
+ /**
352
+ * Generate a team ID from name
353
+ */
354
+ function generateTeamId(name: string): string {
355
+ return `team-${name.toLowerCase().replace(/\s+/g, '-')}`
356
+ }
357
+
358
+ /**
359
+ * Create a team member entry
360
+ */
361
+ export function createTeamMember(config: {
362
+ id: string
363
+ name: string
364
+ type: 'agent' | 'human'
365
+ role: RoleType
366
+ status?: 'active' | 'inactive' | 'away'
367
+ availability?: 'available' | 'busy' | 'offline'
368
+ }): TeamMember {
369
+ return {
370
+ id: config.id,
371
+ name: config.name,
372
+ type: config.type,
373
+ role: config.role,
374
+ status: config.status || 'active',
375
+ availability: config.availability || 'available',
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Create a team member from an agent
381
+ */
382
+ export function teamMemberFromAgent(agent: Agent): TeamMember {
383
+ return {
384
+ id: agent.config.name,
385
+ name: agent.config.name,
386
+ type: 'agent',
387
+ role: agent.config.role,
388
+ status: agent.status === 'idle' || agent.status === 'completed' ? 'active' : 'active',
389
+ availability: agent.status === 'idle' ? 'available' : 'busy',
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Calculate team capacity based on available members
395
+ */
396
+ export function calculateTeamCapacity(team: TeamInstance): {
397
+ total: number
398
+ available: number
399
+ busy: number
400
+ offline: number
401
+ } {
402
+ const members = team.getMembers()
403
+ const available = members.filter(m => m.availability === 'available').length
404
+ const busy = members.filter(m => m.availability === 'busy').length
405
+ const offline = members.filter(m => m.availability === 'offline').length
406
+
407
+ return {
408
+ total: members.length,
409
+ available,
410
+ busy,
411
+ offline,
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Get team skills - aggregated from all members
417
+ */
418
+ export function getTeamSkills(team: TeamInstance): string[] {
419
+ const skills = new Set<string>()
420
+ team.getMembers().forEach(member => {
421
+ member.role.skills.forEach(skill => skills.add(skill))
422
+ })
423
+ return Array.from(skills)
424
+ }
425
+
426
+ /**
427
+ * Check if team has a specific skill
428
+ */
429
+ export function teamHasSkill(team: TeamInstance, skill: string): boolean {
430
+ return team.getMembers().some(member =>
431
+ member.role.skills.some(s =>
432
+ s.toLowerCase() === skill.toLowerCase() ||
433
+ s.toLowerCase().includes(skill.toLowerCase())
434
+ )
435
+ )
436
+ }
437
+
438
+ /**
439
+ * Find best member for a task based on role skills
440
+ */
441
+ export function findBestMemberForTask(
442
+ team: TeamInstance,
443
+ requiredSkills: string[]
444
+ ): TeamMember | null {
445
+ const availableMembers = team.getAvailableMembers()
446
+
447
+ if (availableMembers.length === 0) return null
448
+
449
+ // Score each member based on skill matches
450
+ const scored = availableMembers.map(member => {
451
+ const matchingSkills = requiredSkills.filter(skill =>
452
+ member.role.skills.some(s =>
453
+ s.toLowerCase().includes(skill.toLowerCase())
454
+ )
455
+ )
456
+ return {
457
+ member,
458
+ score: matchingSkills.length,
459
+ }
460
+ })
461
+
462
+ // Sort by score descending
463
+ scored.sort((a, b) => b.score - a.score)
464
+
465
+ return scored.length > 0 && scored[0]!.score > 0 ? scored[0]!.member : null
466
+ }