@compilr-dev/cli 0.6.0 → 0.6.2

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 (73) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +12 -0
  3. package/dist/agent.d.ts +2 -0
  4. package/dist/agent.js +66 -1
  5. package/dist/commands-v2/handlers/index.js +2 -2
  6. package/dist/commands-v2/handlers/project.d.ts +1 -0
  7. package/dist/commands-v2/handlers/project.js +36 -2
  8. package/dist/commands-v2/handlers/team.js +23 -3
  9. package/dist/compilr-diff-companion.vsix +0 -0
  10. package/dist/entitlements/index.d.ts +23 -0
  11. package/dist/entitlements/index.js +110 -0
  12. package/dist/guide/cli-guide-entries.d.ts +15 -0
  13. package/dist/guide/cli-guide-entries.js +99 -0
  14. package/dist/guide/index.d.ts +5 -4
  15. package/dist/guide/index.js +4 -3
  16. package/dist/guide/shared-content.js +188 -21
  17. package/dist/handlers/permission-handler.js +10 -3
  18. package/dist/index.js +23 -2
  19. package/dist/repl-v2.d.ts +16 -0
  20. package/dist/repl-v2.js +51 -17
  21. package/dist/tools/db-tools.d.ts +1 -1
  22. package/dist/tools/platform-adapter.d.ts +1 -1
  23. package/dist/tools/platform-adapter.js +6 -1
  24. package/dist/tools.js +6 -1
  25. package/dist/ui/overlay/impl/app-model-overlay-v2.d.ts +57 -0
  26. package/dist/ui/overlay/impl/app-model-overlay-v2.js +232 -0
  27. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.d.ts +23 -1
  28. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.js +203 -47
  29. package/dist/ui/overlay/impl/model-overlay-v2.js +2 -2
  30. package/dist/ui/overlay/impl/new-overlay-v2.d.ts +2 -2
  31. package/dist/ui/overlay/impl/new-overlay-v2.js +10 -17
  32. package/dist/ui/overlay/impl/team-overlay-v2.js +2 -2
  33. package/dist/ui/overlay/index.d.ts +1 -0
  34. package/dist/ui/overlay/index.js +1 -0
  35. package/dist/utils/update-checker.d.ts +6 -1
  36. package/dist/utils/update-checker.js +16 -1
  37. package/package.json +8 -7
  38. package/dist/.tsbuildinfo.app +0 -1
  39. package/dist/.tsbuildinfo.data +0 -1
  40. package/dist/.tsbuildinfo.domain +0 -1
  41. package/dist/.tsbuildinfo.foundation +0 -1
  42. package/dist/guide/guide-content.d.ts +0 -23
  43. package/dist/guide/guide-content.js +0 -196
  44. package/dist/multi-agent/activity.d.ts +0 -21
  45. package/dist/multi-agent/activity.js +0 -34
  46. package/dist/multi-agent/agent-selection.d.ts +0 -55
  47. package/dist/multi-agent/agent-selection.js +0 -90
  48. package/dist/multi-agent/artifacts.d.ts +0 -197
  49. package/dist/multi-agent/artifacts.js +0 -379
  50. package/dist/multi-agent/collision-utils.d.ts +0 -16
  51. package/dist/multi-agent/collision-utils.js +0 -28
  52. package/dist/multi-agent/context-resolver.d.ts +0 -97
  53. package/dist/multi-agent/context-resolver.js +0 -316
  54. package/dist/multi-agent/mention-parser.d.ts +0 -64
  55. package/dist/multi-agent/mention-parser.js +0 -146
  56. package/dist/multi-agent/shared-context.d.ts +0 -293
  57. package/dist/multi-agent/shared-context.js +0 -671
  58. package/dist/multi-agent/skill-requirements.d.ts +0 -66
  59. package/dist/multi-agent/skill-requirements.js +0 -178
  60. package/dist/multi-agent/task-assignment.d.ts +0 -69
  61. package/dist/multi-agent/task-assignment.js +0 -123
  62. package/dist/multi-agent/task-suggestion.d.ts +0 -31
  63. package/dist/multi-agent/task-suggestion.js +0 -72
  64. package/dist/multi-agent/team-agent.d.ts +0 -201
  65. package/dist/multi-agent/team-agent.js +0 -488
  66. package/dist/multi-agent/team.d.ts +0 -286
  67. package/dist/multi-agent/team.js +0 -610
  68. package/dist/multi-agent/tool-config.d.ts +0 -110
  69. package/dist/multi-agent/tool-config.js +0 -661
  70. package/dist/multi-agent/types.d.ts +0 -211
  71. package/dist/multi-agent/types.js +0 -617
  72. package/dist/tools/guide-tool.d.ts +0 -12
  73. package/dist/tools/guide-tool.js +0 -59
@@ -1,610 +0,0 @@
1
- /**
2
- * AgentTeam - Multi-agent orchestration
3
- *
4
- * Manages a team of persistent agents:
5
- * - Agent switching ($name prefix)
6
- * - Isolated contexts per agent
7
- * - Team-level persistence
8
- * - Event notifications
9
- */
10
- import { TeamAgent } from './team-agent.js';
11
- import { ROLE_EXPERTISE } from './types.js';
12
- import { SharedContextManager } from './shared-context.js';
13
- import { ArtifactStore } from './artifacts.js';
14
- import { getSessionRegistry } from './session-registry.js';
15
- import { resolveAgentIdCollision } from './collision-utils.js';
16
- /**
17
- * AgentTeam orchestrates multiple persistent agents
18
- */
19
- export class AgentTeam {
20
- /**
21
- * Team name
22
- */
23
- name;
24
- /**
25
- * Map of agent ID to TeamAgent
26
- */
27
- agents = new Map();
28
- /**
29
- * Currently active agent ID
30
- */
31
- _activeAgentId = 'default';
32
- /**
33
- * Coordinator agent ID (optional)
34
- */
35
- _coordinatorId;
36
- /**
37
- * Factory for creating agents
38
- */
39
- agentFactory;
40
- /**
41
- * Event handler
42
- */
43
- onEvent;
44
- /**
45
- * Shared context manager for cross-agent knowledge sharing
46
- */
47
- _sharedContext;
48
- /**
49
- * Artifact store for team artifacts
50
- */
51
- _artifactStore;
52
- /**
53
- * Track handoff source: targetAgentId → sourceAgentId
54
- * Used for one-hop prevention (agents that were handed a task
55
- * cannot re-hand it off, except back to the coordinator)
56
- */
57
- _handedFrom = new Map();
58
- /**
59
- * Creation timestamp
60
- */
61
- createdAt = new Date();
62
- /**
63
- * Last updated timestamp
64
- */
65
- updatedAt = new Date();
66
- constructor(config) {
67
- this.name = config.name ?? 'Team';
68
- this.agentFactory = config.agentFactory;
69
- this.onEvent = config.onEvent;
70
- // Initialize shared context (use provided or create new)
71
- this._sharedContext = config.sharedContext ?? new SharedContextManager();
72
- // Initialize artifact store (use provided or create in-memory)
73
- // Note: For persistence, pass a store loaded from disk
74
- this._artifactStore = config.artifactStore ?? new ArtifactStore('');
75
- // Create default agent
76
- const defaultAgent = TeamAgent.fromRole('default', 'default');
77
- this.agents.set('default', defaultAgent);
78
- // Add any initial agents
79
- if (config.initialAgents) {
80
- for (const agentConfig of config.initialAgents) {
81
- if (agentConfig.id !== 'default') {
82
- this.agents.set(agentConfig.id, new TeamAgent(agentConfig));
83
- }
84
- }
85
- }
86
- // Update shared context with team roster (simple list)
87
- this._sharedContext.setTeam(Array.from(this.agents.keys()), this._activeAgentId);
88
- // Build full team roster for team awareness
89
- this.updateTeamRoster();
90
- }
91
- /**
92
- * Get the currently active agent ID
93
- */
94
- get activeAgentId() {
95
- return this._activeAgentId;
96
- }
97
- /**
98
- * Get the coordinator agent ID (if set)
99
- */
100
- get coordinatorId() {
101
- return this._coordinatorId;
102
- }
103
- /**
104
- * Get the shared context manager
105
- */
106
- get sharedContext() {
107
- return this._sharedContext;
108
- }
109
- /**
110
- * Get the artifact store
111
- */
112
- get artifactStore() {
113
- return this._artifactStore;
114
- }
115
- /**
116
- * Get the currently active TeamAgent
117
- */
118
- getActive() {
119
- const agent = this.agents.get(this._activeAgentId);
120
- if (!agent) {
121
- // Fallback to default
122
- const defaultAgent = this.agents.get('default');
123
- if (!defaultAgent) {
124
- throw new Error('Default agent not found - this should never happen');
125
- }
126
- return defaultAgent;
127
- }
128
- return agent;
129
- }
130
- /**
131
- * Get the currently active Agent instance
132
- * Returns null if not initialized
133
- */
134
- getActiveAgent() {
135
- return this.getActive().agent;
136
- }
137
- /**
138
- * Get a specific TeamAgent by ID
139
- */
140
- get(id) {
141
- return this.agents.get(id);
142
- }
143
- /**
144
- * Set the agent instance for the default TeamAgent
145
- * Used when the agent is created before the team
146
- */
147
- setDefaultAgent(agent) {
148
- const defaultTeamAgent = this.agents.get('default');
149
- if (defaultTeamAgent) {
150
- defaultTeamAgent.setAgent(agent);
151
- }
152
- }
153
- /**
154
- * Check if an agent exists in the team
155
- */
156
- has(id) {
157
- return this.agents.has(id);
158
- }
159
- /**
160
- * Get all agent IDs
161
- */
162
- getAgentIds() {
163
- return Array.from(this.agents.keys());
164
- }
165
- /**
166
- * Get all TeamAgents
167
- */
168
- getAll() {
169
- return Array.from(this.agents.values());
170
- }
171
- /**
172
- * Get team size (number of agents)
173
- */
174
- get size() {
175
- return this.agents.size;
176
- }
177
- /**
178
- * Add a new agent to the team
179
- */
180
- async addAgent(config) {
181
- if (this.agents.has(config.id)) {
182
- throw new Error(`Agent '${config.id}' already exists in team`);
183
- }
184
- const teamAgent = new TeamAgent(config);
185
- this.agents.set(config.id, teamAgent);
186
- // Initialize the agent with shared context
187
- await teamAgent.initialize(this.agentFactory, this._sharedContext);
188
- // Update shared context roster
189
- this._sharedContext.addAgent(config.id);
190
- // Update full team roster for team awareness
191
- this.updateTeamRoster();
192
- this.updatedAt = new Date();
193
- this.emit({ type: 'agent:added', agentId: config.id });
194
- return teamAgent;
195
- }
196
- /**
197
- * Add an agent from a predefined role
198
- * @param role - The predefined role
199
- * @param id - Optional custom ID (defaults to role name)
200
- * @param modelTier - Optional model tier override (defaults to role's default tier)
201
- */
202
- async addAgentFromRole(role, id, modelTier) {
203
- let agentId = id ?? role;
204
- // Cross-terminal collision check
205
- const registry = getSessionRegistry();
206
- if (registry) {
207
- const globalIds = registry.getGlobalAgentIds();
208
- const localIds = Array.from(this.agents.keys());
209
- const resolved = resolveAgentIdCollision(agentId, localIds, globalIds);
210
- if (resolved.wasCollision) {
211
- const originalId = agentId;
212
- agentId = resolved.id;
213
- this.emit({ type: 'agent:collision', originalId, agentId: resolved.id });
214
- }
215
- }
216
- if (this.agents.has(agentId)) {
217
- throw new Error(`Agent '${agentId}' already exists in team`);
218
- }
219
- const teamAgent = TeamAgent.fromRole(role, agentId, modelTier);
220
- this.agents.set(agentId, teamAgent);
221
- // Initialize the agent with shared context
222
- await teamAgent.initialize(this.agentFactory, this._sharedContext);
223
- // Update shared context roster
224
- this._sharedContext.addAgent(agentId);
225
- // Update full team roster for team awareness
226
- this.updateTeamRoster();
227
- this.updatedAt = new Date();
228
- this.emit({ type: 'agent:added', agentId });
229
- return teamAgent;
230
- }
231
- /**
232
- * Add a custom agent from a CustomAgentDefinition
233
- */
234
- async addCustomAgent(def) {
235
- let agentId = def.id;
236
- // Cross-terminal collision check
237
- const registry = getSessionRegistry();
238
- if (registry) {
239
- const globalIds = registry.getGlobalAgentIds();
240
- const localIds = Array.from(this.agents.keys());
241
- const resolved = resolveAgentIdCollision(agentId, localIds, globalIds);
242
- if (resolved.wasCollision) {
243
- const originalId = agentId;
244
- agentId = resolved.id;
245
- def = { ...def, id: agentId };
246
- this.emit({ type: 'agent:collision', originalId, agentId: resolved.id });
247
- }
248
- }
249
- if (this.agents.has(agentId)) {
250
- throw new Error(`Agent '${agentId}' already exists in team`);
251
- }
252
- const teamAgent = TeamAgent.fromCustomDefinition(def);
253
- this.agents.set(agentId, teamAgent);
254
- // Initialize the agent with shared context
255
- await teamAgent.initialize(this.agentFactory, this._sharedContext);
256
- // Update shared context roster
257
- this._sharedContext.addAgent(def.id);
258
- // Update full team roster for team awareness
259
- this.updateTeamRoster();
260
- this.updatedAt = new Date();
261
- this.emit({ type: 'agent:added', agentId: def.id });
262
- return teamAgent;
263
- }
264
- /**
265
- * Remove an agent from the team
266
- */
267
- removeAgent(id) {
268
- if (id === 'default') {
269
- throw new Error("Cannot remove the default agent");
270
- }
271
- if (!this.agents.has(id)) {
272
- return false;
273
- }
274
- // If removing active agent, switch to default
275
- if (this._activeAgentId === id) {
276
- this._activeAgentId = 'default';
277
- this._sharedContext.setActiveAgent('default');
278
- }
279
- // If removing coordinator, clear coordinator
280
- if (this._coordinatorId === id) {
281
- this._coordinatorId = undefined;
282
- }
283
- this.agents.delete(id);
284
- // Update shared context roster
285
- this._sharedContext.removeAgent(id);
286
- // Update full team roster for team awareness
287
- this.updateTeamRoster();
288
- this.updatedAt = new Date();
289
- this.emit({ type: 'agent:removed', agentId: id });
290
- return true;
291
- }
292
- /**
293
- * Clear conversation history for all agents in the team
294
- * Used by /reset command to start fresh
295
- */
296
- clearAllHistories() {
297
- for (const agent of this.agents.values()) {
298
- agent.clearHistory();
299
- }
300
- // Clear shared context activity feed
301
- this._sharedContext.clearActivity();
302
- this.updatedAt = new Date();
303
- this.emit({ type: 'team:reset' });
304
- }
305
- /**
306
- * Callback for checking in-progress tasks when switching agents
307
- * Set by the REPL to provide task counts for warnings
308
- */
309
- _getInProgressTasksCallback;
310
- /**
311
- * Set the callback for getting in-progress tasks
312
- * Used by REPL to integrate with todo list and work items
313
- */
314
- setInProgressTasksCallback(callback) {
315
- this._getInProgressTasksCallback = callback;
316
- }
317
- /**
318
- * Switch to a different agent
319
- */
320
- async switchTo(id) {
321
- const agent = this.agents.get(id);
322
- if (!agent) {
323
- throw new Error(`Agent '${id}' not found in team`);
324
- }
325
- // Initialize if needed
326
- if (!agent.isInitialized) {
327
- await agent.initialize(this.agentFactory, this._sharedContext);
328
- }
329
- const previousId = this._activeAgentId;
330
- // Check for in-progress tasks owned by the outgoing agent
331
- if (previousId !== id && this._getInProgressTasksCallback) {
332
- const inProgressTasks = this._getInProgressTasksCallback(previousId);
333
- const hasTodos = inProgressTasks.todos.length > 0;
334
- const hasWorkItems = inProgressTasks.workItems.length > 0;
335
- if (hasTodos || hasWorkItems) {
336
- this.emit({
337
- type: 'agent:switch_warning',
338
- agentId: id,
339
- previousAgentId: previousId,
340
- message: `Agent "${previousId}" has in-progress tasks: ${hasTodos ? `${String(inProgressTasks.todos.length)} todo(s)` : ''}${hasTodos && hasWorkItems ? ', ' : ''}${hasWorkItems ? `${String(inProgressTasks.workItems.length)} work item(s)` : ''}`,
341
- });
342
- }
343
- }
344
- this._activeAgentId = id;
345
- this.updatedAt = new Date();
346
- // Update shared context active agent
347
- this._sharedContext.setActiveAgent(id);
348
- // Update roster active agent for team awareness
349
- this._sharedContext.setRosterActiveAgent(id);
350
- this.emit({
351
- type: 'agent:switched',
352
- agentId: id,
353
- previousAgentId: previousId,
354
- });
355
- return agent;
356
- }
357
- /**
358
- * Set the coordinator agent
359
- */
360
- setCoordinator(id) {
361
- if (id !== undefined && !this.agents.has(id)) {
362
- throw new Error(`Agent '${id}' not found in team`);
363
- }
364
- this._coordinatorId = id;
365
- this.updatedAt = new Date();
366
- }
367
- /**
368
- * Check if an agent is the coordinator
369
- * The default agent is considered coordinator if no explicit coordinator is set.
370
- */
371
- isCoordinator(id) {
372
- if (this._coordinatorId !== undefined) {
373
- return this._coordinatorId === id;
374
- }
375
- // If no coordinator explicitly set, default agent is the coordinator
376
- return id === 'default';
377
- }
378
- /**
379
- * Check if the active agent is the coordinator
380
- * The default agent is considered coordinator if no explicit coordinator is set.
381
- */
382
- isActiveCoordinator() {
383
- if (this._coordinatorId !== undefined) {
384
- return this._coordinatorId === this._activeAgentId;
385
- }
386
- // If no coordinator explicitly set, default agent is the coordinator
387
- return this._activeAgentId === 'default';
388
- }
389
- /**
390
- * Change an agent's model tier
391
- * This updates the tier and reinitializes the agent with the new model.
392
- * Conversation history is preserved.
393
- *
394
- * @param id - The agent ID
395
- * @param newTier - The new model tier
396
- * @returns The updated TeamAgent
397
- */
398
- async changeAgentTier(id, newTier) {
399
- const agent = this.agents.get(id);
400
- if (!agent) {
401
- throw new Error(`Agent '${id}' not found in team`);
402
- }
403
- // Set the new tier (this preserves state and clears the agent instance)
404
- agent.setModelTier(newTier);
405
- // Reinitialize with the new tier
406
- await agent.initialize(this.agentFactory, this._sharedContext);
407
- this.updatedAt = new Date();
408
- this.emit({ type: 'agent:switched', agentId: id, previousAgentId: id });
409
- return agent;
410
- }
411
- /**
412
- * Initialize all agents (lazy initialization)
413
- */
414
- async initializeAll() {
415
- for (const agent of this.agents.values()) {
416
- if (!agent.isInitialized) {
417
- await agent.initialize(this.agentFactory, this._sharedContext);
418
- }
419
- }
420
- }
421
- /**
422
- * Initialize only the active agent
423
- */
424
- async initializeActive() {
425
- const teamAgent = this.getActive();
426
- if (!teamAgent.isInitialized) {
427
- await teamAgent.initialize(this.agentFactory, this._sharedContext);
428
- }
429
- const agent = teamAgent.agent;
430
- if (!agent) {
431
- throw new Error('Agent not initialized after initialize() call');
432
- }
433
- return agent;
434
- }
435
- /**
436
- * Parse a message for $agent prefix and switch if needed
437
- * Returns the message without the prefix and whether a switch occurred
438
- */
439
- async parseAndSwitch(message) {
440
- const match = message.match(/^\$(\w+)\s*(.*)/s);
441
- if (!match) {
442
- return { message, switched: false, agentId: this._activeAgentId };
443
- }
444
- const [, agentId, remainingMessage] = match;
445
- // Check if agent exists
446
- if (!this.agents.has(agentId)) {
447
- // Return original message - let the agent handle invalid prefix
448
- return { message, switched: false, agentId: this._activeAgentId };
449
- }
450
- // Switch to the agent
451
- await this.switchTo(agentId);
452
- return {
453
- message: remainingMessage.trim() || message, // Keep original if no remaining message
454
- switched: true,
455
- agentId,
456
- };
457
- }
458
- /**
459
- * Get autocomplete suggestions for $agent prefix
460
- */
461
- getAgentSuggestions(prefix) {
462
- const results = [];
463
- const searchPrefix = prefix.toLowerCase();
464
- for (const [id, agent] of this.agents) {
465
- if (id.toLowerCase().startsWith(searchPrefix)) {
466
- results.push({
467
- id,
468
- label: agent.getFullLabel(),
469
- });
470
- }
471
- }
472
- return results;
473
- }
474
- // ---------------------------------------------------------------------------
475
- // Handoff Tracking (One-Hop Prevention)
476
- // ---------------------------------------------------------------------------
477
- /**
478
- * Record that sourceAgent handed off to targetAgent.
479
- * Used for one-hop prevention.
480
- */
481
- recordHandoff(targetAgentId, sourceAgentId) {
482
- this._handedFrom.set(targetAgentId, sourceAgentId);
483
- }
484
- /**
485
- * Check if an agent was handed a task (i.e., is a handoff target).
486
- * If true, this agent cannot re-hand off (except back to coordinator).
487
- */
488
- wasHandedTo(agentId) {
489
- return this._handedFrom.has(agentId);
490
- }
491
- /**
492
- * Get the source agent that handed off to the given agent.
493
- */
494
- getHandoffSource(agentId) {
495
- return this._handedFrom.get(agentId);
496
- }
497
- /**
498
- * Clear handoff tracking for an agent (after it completes its task).
499
- */
500
- clearHandoffRecord(agentId) {
501
- this._handedFrom.delete(agentId);
502
- }
503
- /**
504
- * Serialize the team for persistence
505
- */
506
- serialize() {
507
- const agents = [];
508
- for (const agent of this.agents.values()) {
509
- agents.push(agent.serialize());
510
- }
511
- return {
512
- metadata: {
513
- name: this.name,
514
- activeAgentId: this._activeAgentId,
515
- coordinatorId: this._coordinatorId,
516
- agentIds: Array.from(this.agents.keys()),
517
- createdAt: this.createdAt.toISOString(),
518
- updatedAt: this.updatedAt.toISOString(),
519
- },
520
- agents,
521
- };
522
- }
523
- /**
524
- * Restore team state from serialized data
525
- */
526
- static restore(data, agentFactory, onEvent, options) {
527
- const team = new AgentTeam({
528
- name: data.metadata.name,
529
- agentFactory,
530
- onEvent,
531
- sharedContext: options?.sharedContext,
532
- artifactStore: options?.artifactStore,
533
- });
534
- // Clear default agent if not in serialized data
535
- if (!data.metadata.agentIds.includes('default')) {
536
- team.agents.delete('default');
537
- }
538
- // Restore agents
539
- for (const agentData of data.agents) {
540
- const teamAgent = TeamAgent.fromSerialized(agentData);
541
- team.agents.set(agentData.id, teamAgent);
542
- }
543
- // Restore metadata
544
- team._activeAgentId = data.metadata.activeAgentId;
545
- team._coordinatorId = data.metadata.coordinatorId;
546
- // Update shared context with restored team roster (simple list)
547
- team._sharedContext.setTeam(Array.from(team.agents.keys()), team._activeAgentId);
548
- // Build full team roster for team awareness
549
- team.updateTeamRoster();
550
- team.emit({ type: 'team:restored' });
551
- return team;
552
- }
553
- /**
554
- * Emit a team event
555
- */
556
- emit(event) {
557
- this.onEvent?.(event);
558
- }
559
- // ---------------------------------------------------------------------------
560
- // Team Awareness - Roster Management
561
- // ---------------------------------------------------------------------------
562
- /**
563
- * Build and update the team roster in shared context
564
- * Called when team composition or active agent changes
565
- */
566
- updateTeamRoster() {
567
- const roster = this.buildTeamRoster();
568
- this._sharedContext.updateTeamRoster(roster);
569
- // Push updated roster to all initialized agents via anchors.
570
- // Anchors are re-injected on every LLM call, so agents always see the latest roster.
571
- if (this._sharedContext.hasTeamRoster()) {
572
- const rosterContent = this._sharedContext.formatTeamRoster();
573
- for (const [, teamAgent] of this.agents) {
574
- const agent = teamAgent.agent;
575
- if (agent && agent.hasAnchors()) {
576
- agent.addAnchor({
577
- id: 'team-roster',
578
- content: rosterContent,
579
- priority: 'info',
580
- scope: 'session',
581
- });
582
- }
583
- }
584
- }
585
- }
586
- /**
587
- * Build the team roster from current agents
588
- */
589
- buildTeamRoster() {
590
- const roster = [];
591
- for (const [id, agent] of this.agents) {
592
- const role = agent.role;
593
- // For custom agents, derive expertise from their specialty/description
594
- // since ROLE_EXPERTISE['custom'] is empty
595
- let expertise = ROLE_EXPERTISE[role];
596
- if (role === 'custom' && expertise.length === 0 && agent.description) {
597
- expertise = agent.description.split(',').map(s => s.trim()).filter(Boolean);
598
- }
599
- roster.push({
600
- id,
601
- displayName: agent.displayName,
602
- mascot: agent.mascot,
603
- role,
604
- expertise,
605
- isActive: id === this._activeAgentId,
606
- });
607
- }
608
- return roster;
609
- }
610
- }