Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
687 changes: 687 additions & 0 deletions .claude/PRPs/plans/teams-editing-phase-2.plan.md

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions src/cli/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,14 @@ export * from './notify/send.js';
export * from './notify/target/add.js';
export * from './notify/target/list.js';
export * from './notify/target/remove.js';
export * from './teams/create.js';
export * from './teams/edit.js';
export * from './teams/remove.js';
export * from './teams/add-agent.js';
export * from './teams/edit-agent.js';
export * from './teams/remove-agent.js';
export * from './teams/add-human.js';
export * from './teams/edit-human.js';
export * from './teams/remove-human.js';
export * from './teams/import.js';
export * from './teams/export.js';
95 changes: 95 additions & 0 deletions src/cli/commands/teams/add-agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Args, Flags } from '@oclif/core';
import { TeamsEngine } from '../../../core/teams-engine.js';
import { BaseCommand } from '../../base-command.js';
import { formatOutput } from '../../formatter.js';

export default class AddAgent extends BaseCommand {
static override args = {
teamId: Args.string({
description: 'unique identifier of the team',
required: true,
}),
agentId: Args.string({
description:
'unique identifier for the agent (alphanumeric and hyphens only)',
required: true,
}),
};

static override description = 'Add an agent to a team';

static override examples = [
'<%= config.bin %> <%= command.id %> mobile-dev code-reviewer --name "Code Reviewer" --title "Senior Code Reviewer" --role "code review" --identity "experienced developer" --communication "professional and constructive"',
'<%= config.bin %> <%= command.id %> backend-api testing-agent --name "Test Agent" --title "QA Testing Agent" --role "quality assurance" --identity "thorough tester" --communication "detailed and methodical" --icon "🧪"',
];

static override flags = {
...BaseCommand.baseFlags,
name: Flags.string({
char: 'n',
description: 'human-readable name of the agent',
required: true,
}),
title: Flags.string({
char: 't',
description: 'formal title of the agent',
required: true,
}),
role: Flags.string({
char: 'r',
description: 'agent role/function',
required: true,
}),
identity: Flags.string({
description: 'agent identity description',
required: true,
}),
communication: Flags.string({
description: 'communication style',
required: true,
}),
principles: Flags.string({
description: 'guiding principles',
}),
icon: Flags.string({
char: 'i',
description: 'emoji icon for the agent',
}),
};

public async run(): Promise<void> {
const { args, flags } = await this.parse(AddAgent);

const engine = new TeamsEngine();

try {
const agent = await engine.addAgent(args.teamId, {
id: args.agentId,
name: flags.name,
title: flags.title,
icon: flags.icon,
persona: {
role: flags.role,
identity: flags.identity,
communication_style: flags.communication,
principles: flags.principles || '',
},
});

const isJsonMode = await this.getJsonMode();
if (isJsonMode) {
this.log(
formatOutput(agent, 'json', {
timestamp: new Date().toISOString(),
})
);
} else {
this.log(
`Added agent ${agent.id} to team ${args.teamId}: ${agent.name}`
);
}
} catch (error) {
this.handleError(`Failed to add agent: ${(error as Error).message}`);
}
}
}
103 changes: 103 additions & 0 deletions src/cli/commands/teams/add-human.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Args, Flags } from '@oclif/core';
import { TeamsEngine } from '../../../core/teams-engine.js';
import { BaseCommand } from '../../base-command.js';
import { formatOutput } from '../../formatter.js';

export default class AddHuman extends BaseCommand {
static override args = {
teamId: Args.string({
description: 'unique identifier of the team',
required: true,
}),
humanId: Args.string({
description:
'unique identifier for the human (alphanumeric and hyphens only)',
required: true,
}),
};

static override description = 'Add a human to a team';

static override examples = [
'<%= config.bin %> <%= command.id %> mobile-dev product-owner --name "Jane Smith" --title "Product Owner" --role "product management" --identity "experienced product manager" --communication "collaborative and clear"',
'<%= config.bin %> <%= command.id %> backend-api tech-lead --name "John Doe" --title "Technical Lead" --role "technical leadership" --identity "senior engineer" --communication "technical and mentoring" --expertise "backend systems" --icon "👨‍💻"',
];

static override flags = {
...BaseCommand.baseFlags,
name: Flags.string({
char: 'n',
description: 'human-readable name of the human',
required: true,
}),
title: Flags.string({
char: 't',
description: 'formal title of the human',
required: true,
}),
role: Flags.string({
char: 'r',
description: 'human role/function',
required: true,
}),
identity: Flags.string({
description: 'human identity description',
required: true,
}),
communication: Flags.string({
description: 'communication style',
required: true,
}),
principles: Flags.string({
description: 'guiding principles',
}),
expertise: Flags.string({
description: 'area of expertise',
}),
availability: Flags.string({
description: 'availability information',
}),
icon: Flags.string({
char: 'i',
description: 'emoji icon for the human',
}),
};

public async run(): Promise<void> {
const { args, flags } = await this.parse(AddHuman);

const engine = new TeamsEngine();

try {
const human = await engine.addHuman(args.teamId, {
id: args.humanId,
name: flags.name,
title: flags.title,
icon: flags.icon,
persona: {
role: flags.role,
identity: flags.identity,
communication_style: flags.communication,
principles: flags.principles || '',
expertise: flags.expertise,
availability: flags.availability,
},
});

const isJsonMode = await this.getJsonMode();
if (isJsonMode) {
this.log(
formatOutput(human, 'json', {
timestamp: new Date().toISOString(),
})
);
} else {
this.log(
`Added human ${human.id} to team ${args.teamId}: ${human.name}`
);
}
} catch (error) {
this.handleError(`Failed to add human: ${(error as Error).message}`);
}
}
}
73 changes: 73 additions & 0 deletions src/cli/commands/teams/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Args, Flags } from '@oclif/core';
import { TeamsEngine } from '../../../core/teams-engine.js';
import { BaseCommand } from '../../base-command.js';
import { formatOutput } from '../../formatter.js';

export default class Create extends BaseCommand {
static override args = {
id: Args.string({
description:
'unique identifier for the team (alphanumeric and hyphens only)',
required: true,
}),
};

static override description = 'Create a new team';

static override examples = [
'<%= config.bin %> <%= command.id %> mobile-dev --name "Mobile Team" --title "Mobile Development Team" --description "Team focused on mobile app development"',
'<%= config.bin %> <%= command.id %> backend-api --name "Backend Team" --title "API Development Team" --description "Team managing backend services" --icon "🔧"',
];

static override flags = {
...BaseCommand.baseFlags,
name: Flags.string({
char: 'n',
description: 'human-readable name of the team',
required: true,
}),
title: Flags.string({
char: 't',
description: 'formal title of the team',
required: true,
}),
description: Flags.string({
char: 'd',
description: 'detailed description of the team',
required: true,
}),
icon: Flags.string({
char: 'i',
description: 'emoji icon for the team',
}),
};

public async run(): Promise<void> {
const { args, flags } = await this.parse(Create);

const engine = new TeamsEngine();

try {
const team = await engine.createTeam({
id: args.id,
name: flags.name,
title: flags.title,
description: flags.description,
icon: flags.icon,
});

const isJsonMode = await this.getJsonMode();
if (isJsonMode) {
this.log(
formatOutput(team, 'json', {
timestamp: new Date().toISOString(),
})
);
} else {
this.log(`Created team ${team.id}: ${team.name}`);
}
} catch (error) {
this.handleError(`Failed to create team: ${(error as Error).message}`);
}
}
}
Loading