@dolusoft/claude-collab 0.1.1 → 0.1.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.
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -1
- package/dist/mcp-main.js +3 -2
- package/dist/mcp-main.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1646,12 +1646,13 @@ var HubClient = class {
|
|
|
1646
1646
|
format,
|
|
1647
1647
|
requestId
|
|
1648
1648
|
});
|
|
1649
|
-
await this.waitForResponse(
|
|
1649
|
+
const questionSent = await this.waitForResponse(
|
|
1650
1650
|
(msg) => msg.type === "QUESTION_SENT" && "requestId" in msg && msg.requestId === requestId,
|
|
1651
1651
|
5e3
|
|
1652
1652
|
);
|
|
1653
|
+
const questionId = questionSent.questionId;
|
|
1653
1654
|
const answer = await this.waitForResponse(
|
|
1654
|
-
(msg) => msg.type === "ANSWER",
|
|
1655
|
+
(msg) => msg.type === "ANSWER" && msg.questionId === questionId,
|
|
1655
1656
|
timeoutMs
|
|
1656
1657
|
);
|
|
1657
1658
|
return answer;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/domain/entities/member.entity.ts","../src/domain/events/base.event.ts","../src/domain/events/member-joined.event.ts","../src/shared/types/branded-types.ts","../src/shared/utils/id-generator.ts","../src/shared/errors/domain-errors.ts","../src/application/use-cases/join-team.use-case.ts","../src/domain/entities/question.entity.ts","../src/config/index.ts","../src/domain/value-objects/message-content.vo.ts","../src/domain/events/question-asked.event.ts","../src/application/use-cases/ask-question.use-case.ts","../src/application/use-cases/get-inbox.use-case.ts","../src/domain/entities/answer.entity.ts","../src/domain/events/question-answered.event.ts","../src/application/use-cases/reply-question.use-case.ts","../src/infrastructure/repositories/in-memory-member.repository.ts","../src/domain/entities/team.entity.ts","../src/infrastructure/repositories/in-memory-team.repository.ts","../src/infrastructure/repositories/in-memory-question.repository.ts","../src/infrastructure/repositories/in-memory-answer.repository.ts","../src/infrastructure/websocket/message-protocol.ts","../src/infrastructure/websocket/hub-server.ts","../src/infrastructure/websocket/hub-client.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/infrastructure/hub-launcher/auto-start.service.ts","../src/cli.ts"],"names":["uuidv4","WebSocket","z"],"mappings":"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","file":"cli.js","sourcesContent":["/**\r\n * Member Entity\r\n * Represents a connected Claude Code terminal in the collaboration network\r\n * @module domain/entities/member\r\n */\r\n\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * Member status enumeration\r\n */\r\nexport enum MemberStatus {\r\n /** Member is connected and active */\r\n ONLINE = 'ONLINE',\r\n /** Member is connected but idle */\r\n IDLE = 'IDLE',\r\n /** Member has disconnected */\r\n OFFLINE = 'OFFLINE',\r\n}\r\n\r\n/**\r\n * Properties required to create a Member\r\n */\r\nexport interface MemberProps {\r\n readonly id: MemberId;\r\n readonly teamId: TeamId;\r\n readonly displayName: string;\r\n readonly connectedAt: Date;\r\n readonly status: MemberStatus;\r\n}\r\n\r\n/**\r\n * Member entity - a connected Claude Code terminal\r\n */\r\nexport class Member {\r\n private readonly _id: MemberId;\r\n private readonly _teamId: TeamId;\r\n private readonly _displayName: string;\r\n private readonly _connectedAt: Date;\r\n private _status: MemberStatus;\r\n private _lastActivityAt: Date;\r\n\r\n private constructor(props: MemberProps) {\r\n this._id = props.id;\r\n this._teamId = props.teamId;\r\n this._displayName = props.displayName;\r\n this._connectedAt = props.connectedAt;\r\n this._status = props.status;\r\n this._lastActivityAt = props.connectedAt;\r\n }\r\n\r\n /**\r\n * Creates a new Member instance\r\n */\r\n public static create(props: MemberProps): Member {\r\n if (!props.displayName.trim()) {\r\n throw new Error('Display name cannot be empty');\r\n }\r\n return new Member(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes a Member from persistence\r\n */\r\n public static reconstitute(props: MemberProps & { lastActivityAt: Date }): Member {\r\n const member = new Member(props);\r\n member._lastActivityAt = props.lastActivityAt;\r\n return member;\r\n }\r\n\r\n // Getters\r\n public get id(): MemberId {\r\n return this._id;\r\n }\r\n\r\n public get teamId(): TeamId {\r\n return this._teamId;\r\n }\r\n\r\n public get displayName(): string {\r\n return this._displayName;\r\n }\r\n\r\n public get connectedAt(): Date {\r\n return this._connectedAt;\r\n }\r\n\r\n public get status(): MemberStatus {\r\n return this._status;\r\n }\r\n\r\n public get lastActivityAt(): Date {\r\n return this._lastActivityAt;\r\n }\r\n\r\n public get isOnline(): boolean {\r\n return this._status === MemberStatus.ONLINE || this._status === MemberStatus.IDLE;\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Marks the member as online\r\n */\r\n public goOnline(): void {\r\n this._status = MemberStatus.ONLINE;\r\n this._lastActivityAt = new Date();\r\n }\r\n\r\n /**\r\n * Marks the member as idle\r\n */\r\n public goIdle(): void {\r\n this._status = MemberStatus.IDLE;\r\n }\r\n\r\n /**\r\n * Marks the member as offline\r\n */\r\n public goOffline(): void {\r\n this._status = MemberStatus.OFFLINE;\r\n }\r\n\r\n /**\r\n * Records activity from this member\r\n */\r\n public recordActivity(): void {\r\n this._lastActivityAt = new Date();\r\n if (this._status === MemberStatus.IDLE) {\r\n this._status = MemberStatus.ONLINE;\r\n }\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): MemberProps & { lastActivityAt: Date } {\r\n return {\r\n id: this._id,\r\n teamId: this._teamId,\r\n displayName: this._displayName,\r\n connectedAt: this._connectedAt,\r\n status: this._status,\r\n lastActivityAt: this._lastActivityAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * Base Domain Event\r\n * @module domain/events/base\r\n */\r\n\r\nimport { v4 as uuidv4 } from 'uuid';\r\n\r\n/**\r\n * Base interface for all domain events\r\n */\r\nexport interface DomainEvent {\r\n readonly eventId: string;\r\n readonly eventType: string;\r\n readonly timestamp: Date;\r\n readonly payload: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Base class for domain events\r\n */\r\nexport abstract class BaseDomainEvent implements DomainEvent {\r\n public readonly eventId: string;\r\n public readonly timestamp: Date;\r\n\r\n constructor() {\r\n this.eventId = uuidv4();\r\n this.timestamp = new Date();\r\n }\r\n\r\n public abstract get eventType(): string;\r\n public abstract get payload(): Record<string, unknown>;\r\n\r\n /**\r\n * Converts event to JSON\r\n */\r\n public toJSON(): DomainEvent {\r\n return {\r\n eventId: this.eventId,\r\n eventType: this.eventType,\r\n timestamp: this.timestamp,\r\n payload: this.payload,\r\n };\r\n }\r\n}\r\n","/**\r\n * MemberJoined Domain Event\r\n * Raised when a member joins a team\r\n * @module domain/events/member-joined\r\n */\r\n\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a member joins a team\r\n */\r\nexport class MemberJoinedEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'MEMBER_JOINED';\r\n\r\n constructor(\r\n public readonly memberId: MemberId,\r\n public readonly teamId: TeamId,\r\n public readonly displayName: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return MemberJoinedEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n memberId: this.memberId,\r\n teamId: this.teamId,\r\n displayName: this.displayName,\r\n };\r\n }\r\n}\r\n","/**\r\n * Branded types for type-safe IDs\r\n * @module shared/types/branded-types\r\n */\r\n\r\ndeclare const brand: unique symbol;\r\n\r\n/**\r\n * Creates a branded type for nominal typing\r\n */\r\nexport type Brand<T, B> = T & { readonly [brand]: B };\r\n\r\n/**\r\n * Member ID - unique identifier for a connected Claude Code terminal\r\n */\r\nexport type MemberId = Brand<string, 'MemberId'>;\r\n\r\n/**\r\n * Team ID - identifier for a team channel (e.g., \"frontend\", \"backend\")\r\n */\r\nexport type TeamId = Brand<string, 'TeamId'>;\r\n\r\n/**\r\n * Question ID - unique identifier for a question\r\n */\r\nexport type QuestionId = Brand<string, 'QuestionId'>;\r\n\r\n/**\r\n * Answer ID - unique identifier for an answer\r\n */\r\nexport type AnswerId = Brand<string, 'AnswerId'>;\r\n\r\n/**\r\n * Type guard functions for branded types\r\n */\r\nexport const MemberId = {\r\n create: (id: string): MemberId => id as MemberId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n\r\nexport const TeamId = {\r\n create: (id: string): TeamId => id.toLowerCase().trim() as TeamId,\r\n isValid: (id: string): boolean => /^[a-z][a-z0-9-]*$/.test(id.toLowerCase().trim()),\r\n};\r\n\r\nexport const QuestionId = {\r\n create: (id: string): QuestionId => id as QuestionId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n\r\nexport const AnswerId = {\r\n create: (id: string): AnswerId => id as AnswerId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n","/**\r\n * ID generation utilities\r\n * @module shared/utils/id-generator\r\n */\r\n\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type { MemberId, TeamId, QuestionId, AnswerId } from '../types/branded-types.js';\r\nimport {\r\n MemberId as MemberIdFactory,\r\n TeamId as TeamIdFactory,\r\n QuestionId as QuestionIdFactory,\r\n AnswerId as AnswerIdFactory,\r\n} from '../types/branded-types.js';\r\n\r\n/**\r\n * Generates a new unique Member ID\r\n */\r\nexport function generateMemberId(): MemberId {\r\n return MemberIdFactory.create(uuidv4());\r\n}\r\n\r\n/**\r\n * Creates a Team ID from a team name\r\n */\r\nexport function createTeamId(name: string): TeamId {\r\n return TeamIdFactory.create(name);\r\n}\r\n\r\n/**\r\n * Generates a new unique Question ID\r\n */\r\nexport function generateQuestionId(): QuestionId {\r\n return QuestionIdFactory.create(`q_${uuidv4()}`);\r\n}\r\n\r\n/**\r\n * Generates a new unique Answer ID\r\n */\r\nexport function generateAnswerId(): AnswerId {\r\n return AnswerIdFactory.create(`a_${uuidv4()}`);\r\n}\r\n","/**\r\n * Domain-specific errors\r\n * @module shared/errors/domain-errors\r\n */\r\n\r\n/**\r\n * Base class for all domain errors\r\n */\r\nexport abstract class DomainError extends Error {\r\n public readonly code: string;\r\n public readonly timestamp: Date;\r\n\r\n constructor(message: string, code: string) {\r\n super(message);\r\n this.name = this.constructor.name;\r\n this.code = code;\r\n this.timestamp = new Date();\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when an entity is not found\r\n */\r\nexport class EntityNotFoundError extends DomainError {\r\n constructor(entityName: string, id: string) {\r\n super(`${entityName} with id '${id}' not found`, 'ENTITY_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a team is not found\r\n */\r\nexport class TeamNotFoundError extends DomainError {\r\n constructor(teamId: string) {\r\n super(`Team '${teamId}' not found`, 'TEAM_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a member is not found\r\n */\r\nexport class MemberNotFoundError extends DomainError {\r\n constructor(memberId: string) {\r\n super(`Member '${memberId}' not found`, 'MEMBER_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a question is not found\r\n */\r\nexport class QuestionNotFoundError extends DomainError {\r\n constructor(questionId: string) {\r\n super(`Question '${questionId}' not found`, 'QUESTION_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a question has already been answered\r\n */\r\nexport class QuestionAlreadyAnsweredError extends DomainError {\r\n constructor(questionId: string) {\r\n super(`Question '${questionId}' has already been answered`, 'QUESTION_ALREADY_ANSWERED');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a member is already in a team\r\n */\r\nexport class MemberAlreadyInTeamError extends DomainError {\r\n constructor(memberId: string, teamId: string) {\r\n super(`Member '${memberId}' is already in team '${teamId}'`, 'MEMBER_ALREADY_IN_TEAM');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a timeout occurs\r\n */\r\nexport class TimeoutError extends DomainError {\r\n constructor(operation: string, timeoutMs: number) {\r\n super(`Operation '${operation}' timed out after ${timeoutMs}ms`, 'TIMEOUT');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when connection fails\r\n */\r\nexport class ConnectionError extends DomainError {\r\n constructor(message: string) {\r\n super(message, 'CONNECTION_ERROR');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when validation fails\r\n */\r\nexport class ValidationError extends DomainError {\r\n public readonly field: string;\r\n\r\n constructor(field: string, message: string) {\r\n super(message, 'VALIDATION_ERROR');\r\n this.field = field;\r\n }\r\n}\r\n","/**\r\n * JoinTeam Use Case\r\n * Handles joining a team channel\r\n * @module application/use-cases/join-team\r\n */\r\n\r\nimport type { JoinTeamInput, JoinTeamOutput } from '../dtos/join-team.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport { Member, MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport { MemberJoinedEvent } from '../../domain/events/member-joined.event.js';\r\nimport { generateMemberId, createTeamId } from '../../shared/utils/id-generator.js';\r\nimport { ValidationError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: MemberJoinedEvent) => void | Promise<void>;\r\n\r\n/**\r\n * JoinTeam use case dependencies\r\n */\r\nexport interface JoinTeamDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly onMemberJoined?: EventHandler;\r\n}\r\n\r\n/**\r\n * JoinTeam use case\r\n * Creates a new member and adds them to a team\r\n */\r\nexport class JoinTeamUseCase {\r\n constructor(private readonly deps: JoinTeamDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: JoinTeamInput): Promise<JoinTeamOutput> {\r\n // Validate input\r\n if (!input.teamName.trim()) {\r\n throw new ValidationError('teamName', 'Team name cannot be empty');\r\n }\r\n if (!input.displayName.trim()) {\r\n throw new ValidationError('displayName', 'Display name cannot be empty');\r\n }\r\n\r\n // Get or create team\r\n const team = await this.deps.teamRepository.getOrCreate(input.teamName);\r\n\r\n // Create member\r\n const memberId = generateMemberId();\r\n const member = Member.create({\r\n id: memberId,\r\n teamId: team.id,\r\n displayName: input.displayName.trim(),\r\n connectedAt: new Date(),\r\n status: MemberStatus.ONLINE,\r\n });\r\n\r\n // Save member\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Add member to team\r\n team.addMember(memberId);\r\n await this.deps.teamRepository.save(team);\r\n\r\n // Emit event\r\n if (this.deps.onMemberJoined) {\r\n const event = new MemberJoinedEvent(memberId, team.id, member.displayName);\r\n await this.deps.onMemberJoined(event);\r\n }\r\n\r\n return {\r\n memberId,\r\n teamId: team.id,\r\n teamName: team.name,\r\n displayName: member.displayName,\r\n status: member.status,\r\n memberCount: team.memberCount,\r\n };\r\n }\r\n}\r\n","/**\r\n * Question Entity\r\n * Represents a question sent from one member to a team\r\n * @module domain/entities/question\r\n */\r\n\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport type { MessageContent } from '../value-objects/message-content.vo.js';\r\nimport { QuestionAlreadyAnsweredError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Question status enumeration\r\n */\r\nexport enum QuestionStatus {\r\n /** Question is waiting for an answer */\r\n PENDING = 'PENDING',\r\n /** Question has been answered */\r\n ANSWERED = 'ANSWERED',\r\n /** Question timed out without an answer */\r\n TIMEOUT = 'TIMEOUT',\r\n /** Question was cancelled */\r\n CANCELLED = 'CANCELLED',\r\n}\r\n\r\n/**\r\n * Properties required to create a Question\r\n */\r\nexport interface QuestionProps {\r\n readonly id: QuestionId;\r\n readonly fromMemberId: MemberId;\r\n readonly toTeamId: TeamId;\r\n readonly content: MessageContent;\r\n readonly createdAt: Date;\r\n readonly status: QuestionStatus;\r\n readonly answeredAt?: Date;\r\n readonly answeredByMemberId?: MemberId;\r\n}\r\n\r\n/**\r\n * Question entity - a message awaiting response\r\n */\r\nexport class Question {\r\n private readonly _id: QuestionId;\r\n private readonly _fromMemberId: MemberId;\r\n private readonly _toTeamId: TeamId;\r\n private readonly _content: MessageContent;\r\n private readonly _createdAt: Date;\r\n private _status: QuestionStatus;\r\n private _answeredAt?: Date;\r\n private _answeredByMemberId?: MemberId;\r\n\r\n private constructor(props: QuestionProps) {\r\n this._id = props.id;\r\n this._fromMemberId = props.fromMemberId;\r\n this._toTeamId = props.toTeamId;\r\n this._content = props.content;\r\n this._createdAt = props.createdAt;\r\n this._status = props.status;\r\n this._answeredAt = props.answeredAt;\r\n this._answeredByMemberId = props.answeredByMemberId;\r\n }\r\n\r\n /**\r\n * Creates a new Question instance\r\n */\r\n public static create(props: Omit<QuestionProps, 'status' | 'answeredAt' | 'answeredByMemberId'>): Question {\r\n return new Question({\r\n ...props,\r\n status: QuestionStatus.PENDING,\r\n });\r\n }\r\n\r\n /**\r\n * Reconstitutes a Question from persistence\r\n */\r\n public static reconstitute(props: QuestionProps): Question {\r\n return new Question(props);\r\n }\r\n\r\n // Getters\r\n public get id(): QuestionId {\r\n return this._id;\r\n }\r\n\r\n public get fromMemberId(): MemberId {\r\n return this._fromMemberId;\r\n }\r\n\r\n public get toTeamId(): TeamId {\r\n return this._toTeamId;\r\n }\r\n\r\n public get content(): MessageContent {\r\n return this._content;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n public get status(): QuestionStatus {\r\n return this._status;\r\n }\r\n\r\n public get answeredAt(): Date | undefined {\r\n return this._answeredAt;\r\n }\r\n\r\n public get answeredByMemberId(): MemberId | undefined {\r\n return this._answeredByMemberId;\r\n }\r\n\r\n public get isPending(): boolean {\r\n return this._status === QuestionStatus.PENDING;\r\n }\r\n\r\n public get isAnswered(): boolean {\r\n return this._status === QuestionStatus.ANSWERED;\r\n }\r\n\r\n public get isTimedOut(): boolean {\r\n return this._status === QuestionStatus.TIMEOUT;\r\n }\r\n\r\n public get isCancelled(): boolean {\r\n return this._status === QuestionStatus.CANCELLED;\r\n }\r\n\r\n public get canBeAnswered(): boolean {\r\n return this._status === QuestionStatus.PENDING;\r\n }\r\n\r\n /**\r\n * Calculates the age of the question in milliseconds\r\n */\r\n public get ageMs(): number {\r\n return Date.now() - this._createdAt.getTime();\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Marks the question as answered\r\n * @throws QuestionAlreadyAnsweredError if already answered\r\n */\r\n public markAsAnswered(answeredByMemberId: MemberId): void {\r\n if (!this.canBeAnswered) {\r\n throw new QuestionAlreadyAnsweredError(this._id);\r\n }\r\n this._status = QuestionStatus.ANSWERED;\r\n this._answeredAt = new Date();\r\n this._answeredByMemberId = answeredByMemberId;\r\n }\r\n\r\n /**\r\n * Marks the question as timed out\r\n */\r\n public markAsTimedOut(): void {\r\n if (this._status === QuestionStatus.PENDING) {\r\n this._status = QuestionStatus.TIMEOUT;\r\n }\r\n }\r\n\r\n /**\r\n * Marks the question as cancelled\r\n */\r\n public markAsCancelled(): void {\r\n if (this._status === QuestionStatus.PENDING) {\r\n this._status = QuestionStatus.CANCELLED;\r\n }\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): QuestionProps {\r\n return {\r\n id: this._id,\r\n fromMemberId: this._fromMemberId,\r\n toTeamId: this._toTeamId,\r\n content: this._content,\r\n createdAt: this._createdAt,\r\n status: this._status,\r\n answeredAt: this._answeredAt,\r\n answeredByMemberId: this._answeredByMemberId,\r\n };\r\n }\r\n}\r\n","/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * WebSocket Hub configuration\r\n */\r\n hub: {\r\n /**\r\n * Default port for the Hub server\r\n */\r\n port: parseInt(process.env['CLAUDE_COLLAB_PORT'] ?? '9999', 10),\r\n\r\n /**\r\n * Host to bind the Hub server to\r\n */\r\n host: process.env['CLAUDE_COLLAB_HOST'] ?? 'localhost',\r\n\r\n /**\r\n * Heartbeat interval in milliseconds\r\n */\r\n heartbeatInterval: 30000,\r\n\r\n /**\r\n * Client timeout in milliseconds (no heartbeat received)\r\n */\r\n clientTimeout: 60000,\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n\r\n /**\r\n * Auto-start configuration\r\n */\r\n autoStart: {\r\n /**\r\n * Whether to auto-start the hub if not running\r\n */\r\n enabled: true,\r\n\r\n /**\r\n * Maximum retries when connecting to hub\r\n */\r\n maxRetries: 3,\r\n\r\n /**\r\n * Delay between retries in milliseconds\r\n */\r\n retryDelay: 1000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * MessageContent Value Object\r\n * Represents the content of a message with format information\r\n * @module domain/value-objects/message-content\r\n */\r\n\r\nimport { ValidationError } from '../../shared/errors/domain-errors.js';\r\nimport { config } from '../../config/index.js';\r\n\r\n/**\r\n * Message format type\r\n */\r\nexport type MessageFormat = 'plain' | 'markdown';\r\n\r\n/**\r\n * Properties for creating a MessageContent\r\n */\r\nexport interface MessageContentProps {\r\n readonly text: string;\r\n readonly format: MessageFormat;\r\n}\r\n\r\n/**\r\n * MessageContent value object\r\n * Immutable representation of message content\r\n */\r\nexport class MessageContent {\r\n private readonly _text: string;\r\n private readonly _format: MessageFormat;\r\n\r\n private constructor(text: string, format: MessageFormat) {\r\n this._text = text;\r\n this._format = format;\r\n }\r\n\r\n /**\r\n * Creates a new MessageContent\r\n * @throws ValidationError if content is invalid\r\n */\r\n public static create(text: string, format: MessageFormat = 'markdown'): MessageContent {\r\n const trimmedText = text.trim();\r\n\r\n if (!trimmedText) {\r\n throw new ValidationError('text', 'Message content cannot be empty');\r\n }\r\n\r\n if (trimmedText.length > config.communication.maxMessageLength) {\r\n throw new ValidationError(\r\n 'text',\r\n `Message content exceeds maximum length of ${config.communication.maxMessageLength} characters`\r\n );\r\n }\r\n\r\n return new MessageContent(trimmedText, format);\r\n }\r\n\r\n /**\r\n * Creates a plain text message\r\n */\r\n public static plain(text: string): MessageContent {\r\n return MessageContent.create(text, 'plain');\r\n }\r\n\r\n /**\r\n * Creates a markdown message\r\n */\r\n public static markdown(text: string): MessageContent {\r\n return MessageContent.create(text, 'markdown');\r\n }\r\n\r\n /**\r\n * Reconstitutes from persistence\r\n */\r\n public static reconstitute(props: MessageContentProps): MessageContent {\r\n return new MessageContent(props.text, props.format);\r\n }\r\n\r\n // Getters\r\n public get text(): string {\r\n return this._text;\r\n }\r\n\r\n public get format(): MessageFormat {\r\n return this._format;\r\n }\r\n\r\n public get length(): number {\r\n return this._text.length;\r\n }\r\n\r\n public get isMarkdown(): boolean {\r\n return this._format === 'markdown';\r\n }\r\n\r\n public get isPlain(): boolean {\r\n return this._format === 'plain';\r\n }\r\n\r\n /**\r\n * Returns a preview of the content (first 100 chars)\r\n */\r\n public get preview(): string {\r\n if (this._text.length <= 100) {\r\n return this._text;\r\n }\r\n return `${this._text.substring(0, 97)}...`;\r\n }\r\n\r\n /**\r\n * Checks equality with another MessageContent\r\n */\r\n public equals(other: MessageContent): boolean {\r\n return this._text === other._text && this._format === other._format;\r\n }\r\n\r\n /**\r\n * Converts to plain object for serialization\r\n */\r\n public toJSON(): MessageContentProps {\r\n return {\r\n text: this._text,\r\n format: this._format,\r\n };\r\n }\r\n\r\n /**\r\n * String representation\r\n */\r\n public toString(): string {\r\n return this._text;\r\n }\r\n}\r\n","/**\r\n * QuestionAsked Domain Event\r\n * Raised when a question is asked to a team\r\n * @module domain/events/question-asked\r\n */\r\n\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a question is asked\r\n */\r\nexport class QuestionAskedEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'QUESTION_ASKED';\r\n\r\n constructor(\r\n public readonly questionId: QuestionId,\r\n public readonly fromMemberId: MemberId,\r\n public readonly toTeamId: TeamId,\r\n public readonly contentPreview: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return QuestionAskedEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n questionId: this.questionId,\r\n fromMemberId: this.fromMemberId,\r\n toTeamId: this.toTeamId,\r\n contentPreview: this.contentPreview,\r\n };\r\n }\r\n}\r\n","/**\r\n * AskQuestion Use Case\r\n * Handles asking a question to another team\r\n * @module application/use-cases/ask-question\r\n */\r\n\r\nimport type { AskQuestionInput, AskQuestionOutput } from '../dtos/ask-question.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { Question } from '../../domain/entities/question.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { QuestionAskedEvent } from '../../domain/events/question-asked.event.js';\r\nimport { generateQuestionId, createTeamId } from '../../shared/utils/id-generator.js';\r\nimport {\r\n MemberNotFoundError,\r\n TeamNotFoundError,\r\n ValidationError,\r\n} from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: QuestionAskedEvent) => void | Promise<void>;\r\n\r\n/**\r\n * AskQuestion use case dependencies\r\n */\r\nexport interface AskQuestionDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n readonly onQuestionAsked?: EventHandler;\r\n}\r\n\r\n/**\r\n * AskQuestion use case\r\n * Creates and sends a question to a team\r\n */\r\nexport class AskQuestionUseCase {\r\n constructor(private readonly deps: AskQuestionDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: AskQuestionInput): Promise<AskQuestionOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.fromMemberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.fromMemberId);\r\n }\r\n\r\n // Validate target team exists\r\n const targetTeamId = createTeamId(input.toTeamName);\r\n const targetTeam = await this.deps.teamRepository.findById(targetTeamId);\r\n if (!targetTeam) {\r\n throw new TeamNotFoundError(input.toTeamName);\r\n }\r\n\r\n // Validate not asking own team\r\n if (member.teamId === targetTeamId) {\r\n throw new ValidationError('toTeamName', 'Cannot ask question to your own team');\r\n }\r\n\r\n // Create message content\r\n const content = MessageContent.create(input.content, input.format ?? 'markdown');\r\n\r\n // Create question\r\n const questionId = generateQuestionId();\r\n const question = Question.create({\r\n id: questionId,\r\n fromMemberId: input.fromMemberId,\r\n toTeamId: targetTeamId,\r\n content,\r\n createdAt: new Date(),\r\n });\r\n\r\n // Save question\r\n await this.deps.questionRepository.save(question);\r\n\r\n // Record member activity\r\n member.recordActivity();\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Emit event\r\n if (this.deps.onQuestionAsked) {\r\n const event = new QuestionAskedEvent(\r\n questionId,\r\n input.fromMemberId,\r\n targetTeamId,\r\n content.preview\r\n );\r\n await this.deps.onQuestionAsked(event);\r\n }\r\n\r\n return {\r\n questionId,\r\n toTeamId: targetTeamId,\r\n status: question.status,\r\n createdAt: question.createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * GetInbox Use Case\r\n * Retrieves pending questions for a team member\r\n * @module application/use-cases/get-inbox\r\n */\r\n\r\nimport type { GetInboxInput, GetInboxOutput, InboxQuestionItem } from '../dtos/get-inbox.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { QuestionStatus } from '../../domain/entities/question.entity.js';\r\nimport { MemberNotFoundError, TeamNotFoundError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * GetInbox use case dependencies\r\n */\r\nexport interface GetInboxDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n}\r\n\r\n/**\r\n * GetInbox use case\r\n * Retrieves questions directed to the member's team\r\n */\r\nexport class GetInboxUseCase {\r\n constructor(private readonly deps: GetInboxDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: GetInboxInput): Promise<GetInboxOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.memberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.memberId);\r\n }\r\n\r\n // Validate team exists\r\n const team = await this.deps.teamRepository.findById(input.teamId);\r\n if (!team) {\r\n throw new TeamNotFoundError(input.teamId);\r\n }\r\n\r\n // Get questions for team\r\n const allQuestions = await this.deps.questionRepository.findPendingByTeamId(input.teamId);\r\n\r\n // Filter based on includeAnswered flag\r\n const questions = input.includeAnswered\r\n ? allQuestions\r\n : allQuestions.filter((q) => q.isPending);\r\n\r\n // Map to DTOs with member info\r\n const questionItems: InboxQuestionItem[] = [];\r\n\r\n for (const question of questions) {\r\n const fromMember = await this.deps.memberRepository.findById(question.fromMemberId);\r\n const fromTeam = fromMember\r\n ? await this.deps.teamRepository.findById(fromMember.teamId)\r\n : null;\r\n\r\n questionItems.push({\r\n questionId: question.id,\r\n fromMemberId: question.fromMemberId,\r\n fromDisplayName: fromMember?.displayName ?? 'Unknown',\r\n fromTeamName: fromTeam?.name ?? 'Unknown',\r\n content: question.content.text,\r\n format: question.content.format,\r\n status: question.status,\r\n createdAt: question.createdAt,\r\n ageMs: question.ageMs,\r\n });\r\n }\r\n\r\n // Sort by creation date (newest first)\r\n questionItems.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\r\n\r\n const pendingCount = questionItems.filter((q) => q.status === QuestionStatus.PENDING).length;\r\n\r\n return {\r\n teamId: team.id,\r\n teamName: team.name,\r\n questions: questionItems,\r\n totalCount: questionItems.length,\r\n pendingCount,\r\n };\r\n }\r\n}\r\n","/**\r\n * Answer Entity\r\n * Represents a response to a question\r\n * @module domain/entities/answer\r\n */\r\n\r\nimport type { AnswerId, QuestionId, MemberId } from '../../shared/types/branded-types.js';\r\nimport type { MessageContent } from '../value-objects/message-content.vo.js';\r\n\r\n/**\r\n * Properties required to create an Answer\r\n */\r\nexport interface AnswerProps {\r\n readonly id: AnswerId;\r\n readonly questionId: QuestionId;\r\n readonly fromMemberId: MemberId;\r\n readonly content: MessageContent;\r\n readonly createdAt: Date;\r\n}\r\n\r\n/**\r\n * Answer entity - a response to a question\r\n */\r\nexport class Answer {\r\n private readonly _id: AnswerId;\r\n private readonly _questionId: QuestionId;\r\n private readonly _fromMemberId: MemberId;\r\n private readonly _content: MessageContent;\r\n private readonly _createdAt: Date;\r\n\r\n private constructor(props: AnswerProps) {\r\n this._id = props.id;\r\n this._questionId = props.questionId;\r\n this._fromMemberId = props.fromMemberId;\r\n this._content = props.content;\r\n this._createdAt = props.createdAt;\r\n }\r\n\r\n /**\r\n * Creates a new Answer instance\r\n */\r\n public static create(props: AnswerProps): Answer {\r\n return new Answer(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes an Answer from persistence\r\n */\r\n public static reconstitute(props: AnswerProps): Answer {\r\n return new Answer(props);\r\n }\r\n\r\n // Getters\r\n public get id(): AnswerId {\r\n return this._id;\r\n }\r\n\r\n public get questionId(): QuestionId {\r\n return this._questionId;\r\n }\r\n\r\n public get fromMemberId(): MemberId {\r\n return this._fromMemberId;\r\n }\r\n\r\n public get content(): MessageContent {\r\n return this._content;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): AnswerProps {\r\n return {\r\n id: this._id,\r\n questionId: this._questionId,\r\n fromMemberId: this._fromMemberId,\r\n content: this._content,\r\n createdAt: this._createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * QuestionAnswered Domain Event\r\n * Raised when a question is answered\r\n * @module domain/events/question-answered\r\n */\r\n\r\nimport type { QuestionId, AnswerId, MemberId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a question is answered\r\n */\r\nexport class QuestionAnsweredEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'QUESTION_ANSWERED';\r\n\r\n constructor(\r\n public readonly questionId: QuestionId,\r\n public readonly answerId: AnswerId,\r\n public readonly answeredByMemberId: MemberId,\r\n public readonly contentPreview: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return QuestionAnsweredEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n questionId: this.questionId,\r\n answerId: this.answerId,\r\n answeredByMemberId: this.answeredByMemberId,\r\n contentPreview: this.contentPreview,\r\n };\r\n }\r\n}\r\n","/**\r\n * ReplyQuestion Use Case\r\n * Handles replying to a question\r\n * @module application/use-cases/reply-question\r\n */\r\n\r\nimport type { ReplyQuestionInput, ReplyQuestionOutput } from '../dtos/reply-question.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { Answer } from '../../domain/entities/answer.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { QuestionAnsweredEvent } from '../../domain/events/question-answered.event.js';\r\nimport { generateAnswerId } from '../../shared/utils/id-generator.js';\r\nimport {\r\n MemberNotFoundError,\r\n QuestionNotFoundError,\r\n QuestionAlreadyAnsweredError,\r\n} from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: QuestionAnsweredEvent) => void | Promise<void>;\r\n\r\n/**\r\n * Answer repository interface (simplified for this use case)\r\n */\r\nexport interface IAnswerRepository {\r\n save(answer: Answer): Promise<void>;\r\n}\r\n\r\n/**\r\n * ReplyQuestion use case dependencies\r\n */\r\nexport interface ReplyQuestionDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n readonly answerRepository: IAnswerRepository;\r\n readonly onQuestionAnswered?: EventHandler;\r\n}\r\n\r\n/**\r\n * ReplyQuestion use case\r\n * Creates an answer to a question\r\n */\r\nexport class ReplyQuestionUseCase {\r\n constructor(private readonly deps: ReplyQuestionDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: ReplyQuestionInput): Promise<ReplyQuestionOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.fromMemberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.fromMemberId);\r\n }\r\n\r\n // Validate question exists\r\n const question = await this.deps.questionRepository.findById(input.questionId);\r\n if (!question) {\r\n throw new QuestionNotFoundError(input.questionId);\r\n }\r\n\r\n // Check if question can be answered\r\n if (!question.canBeAnswered) {\r\n throw new QuestionAlreadyAnsweredError(input.questionId);\r\n }\r\n\r\n // Create message content\r\n const content = MessageContent.create(input.content, input.format ?? 'markdown');\r\n\r\n // Create answer\r\n const answerId = generateAnswerId();\r\n const answer = Answer.create({\r\n id: answerId,\r\n questionId: input.questionId,\r\n fromMemberId: input.fromMemberId,\r\n content,\r\n createdAt: new Date(),\r\n });\r\n\r\n // Mark question as answered\r\n question.markAsAnswered(input.fromMemberId);\r\n\r\n // Save answer and update question\r\n await this.deps.answerRepository.save(answer);\r\n await this.deps.questionRepository.save(question);\r\n\r\n // Record member activity\r\n member.recordActivity();\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Emit event\r\n if (this.deps.onQuestionAnswered) {\r\n const event = new QuestionAnsweredEvent(\r\n input.questionId,\r\n answerId,\r\n input.fromMemberId,\r\n content.preview\r\n );\r\n await this.deps.onQuestionAnswered(event);\r\n }\r\n\r\n return {\r\n answerId,\r\n questionId: input.questionId,\r\n deliveredToMemberId: question.fromMemberId,\r\n createdAt: answer.createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * In-Memory Member Repository\r\n * @module infrastructure/repositories/in-memory-member\r\n */\r\n\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { Member } from '../../domain/entities/member.entity.js';\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IMemberRepository\r\n */\r\nexport class InMemoryMemberRepository implements IMemberRepository {\r\n private readonly members = new Map<MemberId, Member>();\r\n\r\n async save(member: Member): Promise<void> {\r\n this.members.set(member.id, member);\r\n }\r\n\r\n async findById(id: MemberId): Promise<Member | null> {\r\n return this.members.get(id) ?? null;\r\n }\r\n\r\n async findByTeamId(teamId: TeamId): Promise<Member[]> {\r\n return [...this.members.values()].filter((m) => m.teamId === teamId);\r\n }\r\n\r\n async findOnlineByTeamId(teamId: TeamId): Promise<Member[]> {\r\n return [...this.members.values()].filter((m) => m.teamId === teamId && m.isOnline);\r\n }\r\n\r\n async delete(id: MemberId): Promise<boolean> {\r\n return this.members.delete(id);\r\n }\r\n\r\n async exists(id: MemberId): Promise<boolean> {\r\n return this.members.has(id);\r\n }\r\n\r\n async findAll(): Promise<Member[]> {\r\n return [...this.members.values()];\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.members.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of members\r\n */\r\n get count(): number {\r\n return this.members.size;\r\n }\r\n}\r\n","/**\r\n * Team Entity\r\n * Represents a communication channel for a group of members\r\n * @module domain/entities/team\r\n */\r\n\r\nimport type { TeamId, MemberId } from '../../shared/types/branded-types.js';\r\nimport type { Member } from './member.entity.js';\r\n\r\n/**\r\n * Properties required to create a Team\r\n */\r\nexport interface TeamProps {\r\n readonly id: TeamId;\r\n readonly name: string;\r\n readonly createdAt: Date;\r\n}\r\n\r\n/**\r\n * Team entity - a communication channel\r\n */\r\nexport class Team {\r\n private readonly _id: TeamId;\r\n private readonly _name: string;\r\n private readonly _createdAt: Date;\r\n private readonly _memberIds: Set<MemberId>;\r\n\r\n private constructor(props: TeamProps) {\r\n this._id = props.id;\r\n this._name = props.name;\r\n this._createdAt = props.createdAt;\r\n this._memberIds = new Set();\r\n }\r\n\r\n /**\r\n * Creates a new Team instance\r\n */\r\n public static create(props: TeamProps): Team {\r\n if (!props.name.trim()) {\r\n throw new Error('Team name cannot be empty');\r\n }\r\n return new Team(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes a Team from persistence\r\n */\r\n public static reconstitute(props: TeamProps & { memberIds: MemberId[] }): Team {\r\n const team = new Team(props);\r\n for (const memberId of props.memberIds) {\r\n team._memberIds.add(memberId);\r\n }\r\n return team;\r\n }\r\n\r\n // Getters\r\n public get id(): TeamId {\r\n return this._id;\r\n }\r\n\r\n public get name(): string {\r\n return this._name;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n public get memberIds(): ReadonlySet<MemberId> {\r\n return this._memberIds;\r\n }\r\n\r\n public get memberCount(): number {\r\n return this._memberIds.size;\r\n }\r\n\r\n public get isEmpty(): boolean {\r\n return this._memberIds.size === 0;\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Adds a member to the team\r\n * @returns true if the member was added, false if already present\r\n */\r\n public addMember(memberId: MemberId): boolean {\r\n if (this._memberIds.has(memberId)) {\r\n return false;\r\n }\r\n this._memberIds.add(memberId);\r\n return true;\r\n }\r\n\r\n /**\r\n * Removes a member from the team\r\n * @returns true if the member was removed, false if not present\r\n */\r\n public removeMember(memberId: MemberId): boolean {\r\n return this._memberIds.delete(memberId);\r\n }\r\n\r\n /**\r\n * Checks if a member is in the team\r\n */\r\n public hasMember(memberId: MemberId): boolean {\r\n return this._memberIds.has(memberId);\r\n }\r\n\r\n /**\r\n * Gets all member IDs except the specified one\r\n * Useful for broadcasting to other team members\r\n */\r\n public getOtherMemberIds(excludeMemberId: MemberId): MemberId[] {\r\n return [...this._memberIds].filter((id) => id !== excludeMemberId);\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): TeamProps & { memberIds: MemberId[] } {\r\n return {\r\n id: this._id,\r\n name: this._name,\r\n createdAt: this._createdAt,\r\n memberIds: [...this._memberIds],\r\n };\r\n }\r\n}\r\n","/**\r\n * In-Memory Team Repository\r\n * @module infrastructure/repositories/in-memory-team\r\n */\r\n\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { Team } from '../../domain/entities/team.entity.js';\r\nimport type { TeamId } from '../../shared/types/branded-types.js';\r\nimport { Team as TeamEntity } from '../../domain/entities/team.entity.js';\r\nimport { createTeamId } from '../../shared/utils/id-generator.js';\r\n\r\n/**\r\n * In-memory implementation of ITeamRepository\r\n */\r\nexport class InMemoryTeamRepository implements ITeamRepository {\r\n private readonly teams = new Map<TeamId, Team>();\r\n\r\n async save(team: Team): Promise<void> {\r\n this.teams.set(team.id, team);\r\n }\r\n\r\n async findById(id: TeamId): Promise<Team | null> {\r\n return this.teams.get(id) ?? null;\r\n }\r\n\r\n async findByName(name: string): Promise<Team | null> {\r\n const teamId = createTeamId(name);\r\n return this.teams.get(teamId) ?? null;\r\n }\r\n\r\n async getOrCreate(name: string): Promise<Team> {\r\n const existing = await this.findByName(name);\r\n if (existing) {\r\n return existing;\r\n }\r\n\r\n const teamId = createTeamId(name);\r\n const team = TeamEntity.create({\r\n id: teamId,\r\n name: name.trim(),\r\n createdAt: new Date(),\r\n });\r\n\r\n await this.save(team);\r\n return team;\r\n }\r\n\r\n async delete(id: TeamId): Promise<boolean> {\r\n return this.teams.delete(id);\r\n }\r\n\r\n async exists(id: TeamId): Promise<boolean> {\r\n return this.teams.has(id);\r\n }\r\n\r\n async findAll(): Promise<Team[]> {\r\n return [...this.teams.values()];\r\n }\r\n\r\n async findNonEmpty(): Promise<Team[]> {\r\n return [...this.teams.values()].filter((t) => !t.isEmpty);\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.teams.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of teams\r\n */\r\n get count(): number {\r\n return this.teams.size;\r\n }\r\n}\r\n","/**\r\n * In-Memory Question Repository\r\n * @module infrastructure/repositories/in-memory-question\r\n */\r\n\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport type { Question } from '../../domain/entities/question.entity.js';\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IQuestionRepository\r\n */\r\nexport class InMemoryQuestionRepository implements IQuestionRepository {\r\n private readonly questions = new Map<QuestionId, Question>();\r\n\r\n async save(question: Question): Promise<void> {\r\n this.questions.set(question.id, question);\r\n }\r\n\r\n async findById(id: QuestionId): Promise<Question | null> {\r\n return this.questions.get(id) ?? null;\r\n }\r\n\r\n async findPendingByTeamId(teamId: TeamId): Promise<Question[]> {\r\n return [...this.questions.values()].filter((q) => q.toTeamId === teamId && q.isPending);\r\n }\r\n\r\n async findByFromMemberId(memberId: MemberId): Promise<Question[]> {\r\n return [...this.questions.values()].filter((q) => q.fromMemberId === memberId);\r\n }\r\n\r\n async findPendingByFromMemberId(memberId: MemberId): Promise<Question[]> {\r\n return [...this.questions.values()].filter(\r\n (q) => q.fromMemberId === memberId && q.isPending\r\n );\r\n }\r\n\r\n async delete(id: QuestionId): Promise<boolean> {\r\n return this.questions.delete(id);\r\n }\r\n\r\n async exists(id: QuestionId): Promise<boolean> {\r\n return this.questions.has(id);\r\n }\r\n\r\n async findAll(): Promise<Question[]> {\r\n return [...this.questions.values()];\r\n }\r\n\r\n async markTimedOut(olderThanMs: number): Promise<number> {\r\n let count = 0;\r\n const now = Date.now();\r\n\r\n for (const question of this.questions.values()) {\r\n if (question.isPending && now - question.createdAt.getTime() > olderThanMs) {\r\n question.markAsTimedOut();\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.questions.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of questions\r\n */\r\n get count(): number {\r\n return this.questions.size;\r\n }\r\n}\r\n","/**\r\n * In-Memory Answer Repository\r\n * @module infrastructure/repositories/in-memory-answer\r\n */\r\n\r\nimport type { IAnswerRepository } from '../../application/use-cases/reply-question.use-case.js';\r\nimport type { Answer } from '../../domain/entities/answer.entity.js';\r\nimport type { AnswerId, QuestionId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IAnswerRepository\r\n */\r\nexport class InMemoryAnswerRepository implements IAnswerRepository {\r\n private readonly answers = new Map<AnswerId, Answer>();\r\n\r\n async save(answer: Answer): Promise<void> {\r\n this.answers.set(answer.id, answer);\r\n }\r\n\r\n async findById(id: AnswerId): Promise<Answer | null> {\r\n return this.answers.get(id) ?? null;\r\n }\r\n\r\n async findByQuestionId(questionId: QuestionId): Promise<Answer | null> {\r\n for (const answer of this.answers.values()) {\r\n if (answer.questionId === questionId) {\r\n return answer;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n async findAll(): Promise<Answer[]> {\r\n return [...this.answers.values()];\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.answers.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of answers\r\n */\r\n get count(): number {\r\n return this.answers.size;\r\n }\r\n}\r\n","/**\r\n * WebSocket Message Protocol\r\n * Defines the message format between Hub and Clients\r\n * @module infrastructure/websocket/message-protocol\r\n */\r\n\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport type { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport type { QuestionStatus } from '../../domain/entities/question.entity.js';\r\n\r\n// ============================================================================\r\n// Client → Hub Messages\r\n// ============================================================================\r\n\r\nexport type ClientMessageType = 'JOIN' | 'LEAVE' | 'ASK' | 'REPLY' | 'PING' | 'GET_INBOX';\r\n\r\nexport interface JoinMessage {\r\n type: 'JOIN';\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport interface LeaveMessage {\r\n type: 'LEAVE';\r\n}\r\n\r\nexport interface AskMessage {\r\n type: 'ASK';\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string; // For correlating response\r\n}\r\n\r\nexport interface ReplyMessage {\r\n type: 'REPLY';\r\n questionId: QuestionId;\r\n content: string;\r\n format: MessageFormat;\r\n}\r\n\r\nexport interface PingMessage {\r\n type: 'PING';\r\n}\r\n\r\nexport interface GetInboxMessage {\r\n type: 'GET_INBOX';\r\n requestId: string;\r\n}\r\n\r\nexport type ClientMessage =\r\n | JoinMessage\r\n | LeaveMessage\r\n | AskMessage\r\n | ReplyMessage\r\n | PingMessage\r\n | GetInboxMessage;\r\n\r\n// ============================================================================\r\n// Hub → Client Messages\r\n// ============================================================================\r\n\r\nexport type HubMessageType =\r\n | 'JOINED'\r\n | 'LEFT'\r\n | 'MEMBER_JOINED'\r\n | 'MEMBER_LEFT'\r\n | 'QUESTION'\r\n | 'ANSWER'\r\n | 'QUESTION_SENT'\r\n | 'INBOX'\r\n | 'PONG'\r\n | 'ERROR';\r\n\r\nexport interface MemberInfo {\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n teamName: string;\r\n displayName: string;\r\n status: MemberStatus;\r\n}\r\n\r\nexport interface JoinedMessage {\r\n type: 'JOINED';\r\n member: MemberInfo;\r\n memberCount: number;\r\n}\r\n\r\nexport interface LeftMessage {\r\n type: 'LEFT';\r\n memberId: MemberId;\r\n}\r\n\r\nexport interface MemberJoinedMessage {\r\n type: 'MEMBER_JOINED';\r\n member: MemberInfo;\r\n}\r\n\r\nexport interface MemberLeftMessage {\r\n type: 'MEMBER_LEFT';\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n}\r\n\r\nexport interface QuestionMessage {\r\n type: 'QUESTION';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: string;\r\n}\r\n\r\nexport interface AnswerMessage {\r\n type: 'ANSWER';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n requestId?: string; // Correlates with original ASK request\r\n}\r\n\r\nexport interface QuestionSentMessage {\r\n type: 'QUESTION_SENT';\r\n questionId: QuestionId;\r\n toTeamId: TeamId;\r\n status: QuestionStatus;\r\n requestId: string;\r\n}\r\n\r\nexport interface InboxQuestionInfo {\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n status: QuestionStatus;\r\n createdAt: string;\r\n ageMs: number;\r\n}\r\n\r\nexport interface InboxMessage {\r\n type: 'INBOX';\r\n questions: InboxQuestionInfo[];\r\n totalCount: number;\r\n pendingCount: number;\r\n requestId: string;\r\n}\r\n\r\nexport interface PongMessage {\r\n type: 'PONG';\r\n timestamp: string;\r\n}\r\n\r\nexport interface ErrorMessage {\r\n type: 'ERROR';\r\n code: string;\r\n message: string;\r\n requestId?: string;\r\n}\r\n\r\nexport type HubMessage =\r\n | JoinedMessage\r\n | LeftMessage\r\n | MemberJoinedMessage\r\n | MemberLeftMessage\r\n | QuestionMessage\r\n | AnswerMessage\r\n | QuestionSentMessage\r\n | InboxMessage\r\n | PongMessage\r\n | ErrorMessage;\r\n\r\n// ============================================================================\r\n// Serialization Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Serializes a message to JSON string\r\n */\r\nexport function serializeMessage<T extends ClientMessage | HubMessage>(message: T): string {\r\n return JSON.stringify(message);\r\n}\r\n\r\n/**\r\n * Parses a client message from JSON string\r\n */\r\nexport function parseClientMessage(data: string): ClientMessage {\r\n const parsed = JSON.parse(data) as ClientMessage;\r\n validateClientMessage(parsed);\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Parses a hub message from JSON string\r\n */\r\nexport function parseHubMessage(data: string): HubMessage {\r\n return JSON.parse(data) as HubMessage;\r\n}\r\n\r\n/**\r\n * Validates a client message\r\n */\r\nfunction validateClientMessage(message: ClientMessage): void {\r\n if (!message.type) {\r\n throw new Error('Message must have a type');\r\n }\r\n\r\n const validTypes: ClientMessageType[] = ['JOIN', 'LEAVE', 'ASK', 'REPLY', 'PING', 'GET_INBOX'];\r\n if (!validTypes.includes(message.type)) {\r\n throw new Error(`Invalid message type: ${message.type}`);\r\n }\r\n}\r\n\r\n/**\r\n * Creates an error message\r\n */\r\nexport function createErrorMessage(\r\n code: string,\r\n message: string,\r\n requestId?: string\r\n): ErrorMessage {\r\n return {\r\n type: 'ERROR',\r\n code,\r\n message,\r\n requestId,\r\n };\r\n}\r\n","/**\r\n * WebSocket Hub Server\r\n * Central server that manages client connections and message routing\r\n * @module infrastructure/websocket/hub-server\r\n */\r\n\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { Member } from '../../domain/entities/member.entity.js';\r\nimport type { Question } from '../../domain/entities/question.entity.js';\r\nimport { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport { QuestionStatus } from '../../domain/entities/question.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { JoinTeamUseCase } from '../../application/use-cases/join-team.use-case.js';\r\nimport { AskQuestionUseCase } from '../../application/use-cases/ask-question.use-case.js';\r\nimport { GetInboxUseCase } from '../../application/use-cases/get-inbox.use-case.js';\r\nimport { ReplyQuestionUseCase } from '../../application/use-cases/reply-question.use-case.js';\r\nimport { InMemoryMemberRepository } from '../repositories/in-memory-member.repository.js';\r\nimport { InMemoryTeamRepository } from '../repositories/in-memory-team.repository.js';\r\nimport { InMemoryQuestionRepository } from '../repositories/in-memory-question.repository.js';\r\nimport { InMemoryAnswerRepository } from '../repositories/in-memory-answer.repository.js';\r\nimport { config } from '../../config/index.js';\r\nimport {\r\n type ClientMessage,\r\n type HubMessage,\r\n type MemberInfo,\r\n parseClientMessage,\r\n serializeMessage,\r\n createErrorMessage,\r\n} from './message-protocol.js';\r\n\r\n/**\r\n * Log helper with timestamp\r\n */\r\nfunction log(level: 'INFO' | 'ERROR' | 'WARN' | 'DEBUG', message: string, data?: unknown): void {\r\n const timestamp = new Date().toISOString();\r\n const prefix = `[${timestamp}] [HUB-${level}]`;\r\n\r\n if (data) {\r\n console.log(`${prefix} ${message}`, JSON.stringify(data, null, 2));\r\n } else {\r\n console.log(`${prefix} ${message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Client connection state\r\n */\r\ninterface ClientConnection {\r\n ws: WebSocket;\r\n memberId?: MemberId;\r\n teamId?: TeamId;\r\n lastPing: Date;\r\n}\r\n\r\n/**\r\n * Hub server options\r\n */\r\nexport interface HubServerOptions {\r\n port?: number;\r\n host?: string;\r\n}\r\n\r\n/**\r\n * WebSocket Hub Server\r\n */\r\nexport class HubServer {\r\n private wss: WebSocketServer | null = null;\r\n private readonly clients = new Map<WebSocket, ClientConnection>();\r\n private readonly memberToWs = new Map<MemberId, WebSocket>();\r\n\r\n // Repositories\r\n private readonly memberRepository = new InMemoryMemberRepository();\r\n private readonly teamRepository = new InMemoryTeamRepository();\r\n private readonly questionRepository = new InMemoryQuestionRepository();\r\n private readonly answerRepository = new InMemoryAnswerRepository();\r\n\r\n // Use cases\r\n private joinTeamUseCase!: JoinTeamUseCase;\r\n private askQuestionUseCase!: AskQuestionUseCase;\r\n private getInboxUseCase!: GetInboxUseCase;\r\n private replyQuestionUseCase!: ReplyQuestionUseCase;\r\n\r\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\r\n private timeoutCheckInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n constructor(private readonly options: HubServerOptions = {}) {\r\n this.initializeUseCases();\r\n }\r\n\r\n private initializeUseCases(): void {\r\n this.joinTeamUseCase = new JoinTeamUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n onMemberJoined: async (event) => {\r\n await this.broadcastToTeam(event.teamId, event.memberId, {\r\n type: 'MEMBER_JOINED',\r\n member: await this.getMemberInfo(event.memberId),\r\n });\r\n },\r\n });\r\n\r\n this.askQuestionUseCase = new AskQuestionUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n questionRepository: this.questionRepository,\r\n onQuestionAsked: async (event) => {\r\n const question = await this.questionRepository.findById(event.questionId);\r\n if (question) {\r\n await this.deliverQuestion(question);\r\n }\r\n },\r\n });\r\n\r\n this.getInboxUseCase = new GetInboxUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n questionRepository: this.questionRepository,\r\n });\r\n\r\n this.replyQuestionUseCase = new ReplyQuestionUseCase({\r\n memberRepository: this.memberRepository,\r\n questionRepository: this.questionRepository,\r\n answerRepository: this.answerRepository,\r\n onQuestionAnswered: async (event) => {\r\n const question = await this.questionRepository.findById(event.questionId);\r\n const answer = await this.answerRepository.findByQuestionId(event.questionId);\r\n if (question && answer) {\r\n await this.deliverAnswer(question, answer, event.answeredByMemberId);\r\n }\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Starts the hub server\r\n */\r\n async start(): Promise<void> {\r\n const port = this.options.port ?? config.hub.port;\r\n const host = this.options.host ?? config.hub.host;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n this.wss = new WebSocketServer({ port, host });\r\n\r\n this.wss.on('connection', (ws) => {\r\n this.handleConnection(ws);\r\n });\r\n\r\n this.wss.on('error', (error) => {\r\n log('ERROR', 'Hub server error', { error: error.message, stack: error.stack });\r\n reject(error);\r\n });\r\n\r\n this.wss.on('listening', () => {\r\n log('INFO', `Hub server started successfully`, { host, port });\r\n this.startHeartbeat();\r\n this.startTimeoutCheck();\r\n resolve();\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Stops the hub server\r\n */\r\n async stop(): Promise<void> {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n this.heartbeatInterval = null;\r\n }\r\n\r\n if (this.timeoutCheckInterval) {\r\n clearInterval(this.timeoutCheckInterval);\r\n this.timeoutCheckInterval = null;\r\n }\r\n\r\n return new Promise((resolve) => {\r\n if (this.wss) {\r\n // Close all client connections\r\n for (const [ws] of this.clients) {\r\n ws.close();\r\n }\r\n this.clients.clear();\r\n this.memberToWs.clear();\r\n\r\n this.wss.close(() => {\r\n this.wss = null;\r\n log('INFO', 'Hub server stopped gracefully');\r\n resolve();\r\n });\r\n } else {\r\n resolve();\r\n }\r\n });\r\n }\r\n\r\n private handleConnection(ws: WebSocket): void {\r\n const connection: ClientConnection = {\r\n ws,\r\n lastPing: new Date(),\r\n };\r\n this.clients.set(ws, connection);\r\n\r\n log('INFO', 'New client connected', { totalClients: this.clients.size });\r\n\r\n ws.on('message', async (data) => {\r\n await this.handleMessage(ws, data.toString());\r\n });\r\n\r\n ws.on('close', async () => {\r\n await this.handleDisconnect(ws);\r\n });\r\n\r\n ws.on('error', (error) => {\r\n log('ERROR', 'Client connection error', { error: error.message });\r\n });\r\n }\r\n\r\n private async handleMessage(ws: WebSocket, data: string): Promise<void> {\r\n const connection = this.clients.get(ws);\r\n if (!connection) return;\r\n\r\n try {\r\n const message = parseClientMessage(data);\r\n connection.lastPing = new Date();\r\n\r\n log('DEBUG', `Received message from client`, {\r\n type: message.type,\r\n memberId: connection.memberId,\r\n });\r\n\r\n switch (message.type) {\r\n case 'JOIN':\r\n await this.handleJoin(ws, connection, message.teamName, message.displayName);\r\n break;\r\n case 'LEAVE':\r\n await this.handleLeave(ws, connection);\r\n break;\r\n case 'ASK':\r\n await this.handleAsk(ws, connection, message);\r\n break;\r\n case 'REPLY':\r\n await this.handleReply(ws, connection, message);\r\n break;\r\n case 'GET_INBOX':\r\n await this.handleGetInbox(ws, connection, message.requestId);\r\n break;\r\n case 'PING':\r\n this.send(ws, { type: 'PONG', timestamp: new Date().toISOString() });\r\n break;\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n log('ERROR', 'Failed to handle message', {\r\n error: errorMessage,\r\n memberId: connection.memberId,\r\n });\r\n this.send(ws, createErrorMessage('INVALID_MESSAGE', errorMessage));\r\n }\r\n }\r\n\r\n private async handleJoin(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n teamName: string,\r\n displayName: string\r\n ): Promise<void> {\r\n try {\r\n log('INFO', 'Member attempting to join', { teamName, displayName });\r\n\r\n const result = await this.joinTeamUseCase.execute({ teamName, displayName });\r\n\r\n connection.memberId = result.memberId;\r\n connection.teamId = result.teamId;\r\n this.memberToWs.set(result.memberId, ws);\r\n\r\n const memberInfo = await this.getMemberInfo(result.memberId);\r\n this.send(ws, {\r\n type: 'JOINED',\r\n member: memberInfo,\r\n memberCount: result.memberCount,\r\n });\r\n\r\n log('INFO', 'Member joined successfully', {\r\n memberId: result.memberId,\r\n teamName,\r\n displayName,\r\n memberCount: result.memberCount,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Join failed';\r\n log('ERROR', 'Member join failed', { teamName, displayName, error: errorMessage });\r\n this.send(ws, createErrorMessage('JOIN_FAILED', errorMessage));\r\n }\r\n }\r\n\r\n private async handleLeave(ws: WebSocket, connection: ClientConnection): Promise<void> {\r\n if (connection.memberId && connection.teamId) {\r\n await this.removeMember(connection.memberId, connection.teamId);\r\n connection.memberId = undefined;\r\n connection.teamId = undefined;\r\n }\r\n\r\n this.send(ws, { type: 'LEFT', memberId: connection.memberId! });\r\n }\r\n\r\n private async handleAsk(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n message: { toTeam: string; content: string; format: 'plain' | 'markdown'; requestId: string }\r\n ): Promise<void> {\r\n if (!connection.memberId) {\r\n log('WARN', 'ASK attempt without joining team', { toTeam: message.toTeam });\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first', message.requestId));\r\n return;\r\n }\r\n\r\n try {\r\n log('INFO', 'Question asked', {\r\n fromMemberId: connection.memberId,\r\n toTeam: message.toTeam,\r\n contentPreview: message.content.substring(0, 50) + '...',\r\n });\r\n\r\n const result = await this.askQuestionUseCase.execute({\r\n fromMemberId: connection.memberId,\r\n toTeamName: message.toTeam,\r\n content: message.content,\r\n format: message.format,\r\n });\r\n\r\n this.send(ws, {\r\n type: 'QUESTION_SENT',\r\n questionId: result.questionId,\r\n toTeamId: result.toTeamId,\r\n status: result.status,\r\n requestId: message.requestId,\r\n });\r\n\r\n log('INFO', 'Question sent successfully', {\r\n questionId: result.questionId,\r\n fromMemberId: connection.memberId,\r\n toTeamId: result.toTeamId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Ask failed';\r\n log('ERROR', 'Question failed', {\r\n fromMemberId: connection.memberId,\r\n toTeam: message.toTeam,\r\n error: errorMessage,\r\n });\r\n this.send(ws, createErrorMessage('ASK_FAILED', errorMessage, message.requestId));\r\n }\r\n }\r\n\r\n private async handleReply(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n message: { questionId: QuestionId; content: string; format: 'plain' | 'markdown' }\r\n ): Promise<void> {\r\n if (!connection.memberId) {\r\n log('WARN', 'REPLY attempt without joining team', { questionId: message.questionId });\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first'));\r\n return;\r\n }\r\n\r\n try {\r\n log('INFO', 'Reply received', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n contentPreview: message.content.substring(0, 50) + '...',\r\n });\r\n\r\n await this.replyQuestionUseCase.execute({\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n content: message.content,\r\n format: message.format,\r\n });\r\n\r\n log('INFO', 'Reply delivered successfully', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Reply failed';\r\n log('ERROR', 'Reply failed', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n error: errorMessage,\r\n });\r\n this.send(ws, createErrorMessage('REPLY_FAILED', errorMessage));\r\n }\r\n }\r\n\r\n private async handleGetInbox(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n requestId: string\r\n ): Promise<void> {\r\n if (!connection.memberId || !connection.teamId) {\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first', requestId));\r\n return;\r\n }\r\n\r\n try {\r\n const result = await this.getInboxUseCase.execute({\r\n memberId: connection.memberId,\r\n teamId: connection.teamId,\r\n });\r\n\r\n const questions = await Promise.all(\r\n result.questions.map(async (q) => ({\r\n questionId: q.questionId,\r\n from: await this.getMemberInfo(q.fromMemberId),\r\n content: q.content,\r\n format: q.format,\r\n status: q.status as QuestionStatus,\r\n createdAt: q.createdAt.toISOString(),\r\n ageMs: q.ageMs,\r\n }))\r\n );\r\n\r\n this.send(ws, {\r\n type: 'INBOX',\r\n questions,\r\n totalCount: result.totalCount,\r\n pendingCount: result.pendingCount,\r\n requestId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Get inbox failed';\r\n this.send(ws, createErrorMessage('INBOX_FAILED', errorMessage, requestId));\r\n }\r\n }\r\n\r\n private async handleDisconnect(ws: WebSocket): Promise<void> {\r\n const connection = this.clients.get(ws);\r\n if (connection?.memberId && connection.teamId) {\r\n log('INFO', 'Client disconnecting', {\r\n memberId: connection.memberId,\r\n teamId: connection.teamId,\r\n });\r\n await this.removeMember(connection.memberId, connection.teamId);\r\n this.memberToWs.delete(connection.memberId);\r\n }\r\n this.clients.delete(ws);\r\n log('INFO', 'Client disconnected', { totalClients: this.clients.size });\r\n }\r\n\r\n private async removeMember(memberId: MemberId, teamId: TeamId): Promise<void> {\r\n const member = await this.memberRepository.findById(memberId);\r\n if (member) {\r\n member.goOffline();\r\n await this.memberRepository.save(member);\r\n }\r\n\r\n const team = await this.teamRepository.findById(teamId);\r\n if (team) {\r\n team.removeMember(memberId);\r\n await this.teamRepository.save(team);\r\n\r\n // Notify other team members\r\n await this.broadcastToTeam(teamId, memberId, {\r\n type: 'MEMBER_LEFT',\r\n memberId,\r\n teamId,\r\n });\r\n }\r\n }\r\n\r\n private async deliverQuestion(question: Question): Promise<void> {\r\n const team = await this.teamRepository.findById(question.toTeamId);\r\n if (!team) {\r\n log('WARN', 'Cannot deliver question - team not found', { toTeamId: question.toTeamId });\r\n return;\r\n }\r\n\r\n const fromMember = await this.memberRepository.findById(question.fromMemberId);\r\n if (!fromMember) {\r\n log('WARN', 'Cannot deliver question - from member not found', {\r\n fromMemberId: question.fromMemberId,\r\n });\r\n return;\r\n }\r\n\r\n const memberInfo = await this.getMemberInfo(question.fromMemberId);\r\n\r\n let deliveredCount = 0;\r\n for (const memberId of team.memberIds) {\r\n const ws = this.memberToWs.get(memberId);\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n this.send(ws, {\r\n type: 'QUESTION',\r\n questionId: question.id,\r\n from: memberInfo,\r\n content: question.content.text,\r\n format: question.content.format,\r\n createdAt: question.createdAt.toISOString(),\r\n });\r\n deliveredCount++;\r\n }\r\n }\r\n\r\n log('INFO', 'Question delivered to team', {\r\n questionId: question.id,\r\n toTeamId: question.toTeamId,\r\n teamSize: team.memberIds.size,\r\n deliveredCount,\r\n });\r\n }\r\n\r\n private async deliverAnswer(\r\n question: Question,\r\n answer: { content: MessageContent; createdAt: Date },\r\n answeredByMemberId: MemberId\r\n ): Promise<void> {\r\n const ws = this.memberToWs.get(question.fromMemberId);\r\n if (!ws || ws.readyState !== WebSocket.OPEN) {\r\n log('WARN', 'Cannot deliver answer - questioner not connected', {\r\n questionId: question.id,\r\n fromMemberId: question.fromMemberId,\r\n });\r\n return;\r\n }\r\n\r\n const memberInfo = await this.getMemberInfo(answeredByMemberId);\r\n\r\n this.send(ws, {\r\n type: 'ANSWER',\r\n questionId: question.id,\r\n from: memberInfo,\r\n content: answer.content.text,\r\n format: answer.content.format,\r\n answeredAt: answer.createdAt.toISOString(),\r\n });\r\n\r\n log('INFO', 'Answer delivered', {\r\n questionId: question.id,\r\n answeredBy: answeredByMemberId,\r\n deliveredTo: question.fromMemberId,\r\n });\r\n }\r\n\r\n private async broadcastToTeam(\r\n teamId: TeamId,\r\n excludeMemberId: MemberId,\r\n message: HubMessage\r\n ): Promise<void> {\r\n const team = await this.teamRepository.findById(teamId);\r\n if (!team) return;\r\n\r\n for (const memberId of team.getOtherMemberIds(excludeMemberId)) {\r\n const ws = this.memberToWs.get(memberId);\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n this.send(ws, message);\r\n }\r\n }\r\n }\r\n\r\n private async getMemberInfo(memberId: MemberId): Promise<MemberInfo> {\r\n const member = await this.memberRepository.findById(memberId);\r\n const team = member ? await this.teamRepository.findById(member.teamId) : null;\r\n\r\n return {\r\n memberId,\r\n teamId: member?.teamId ?? ('' as TeamId),\r\n teamName: team?.name ?? 'Unknown',\r\n displayName: member?.displayName ?? 'Unknown',\r\n status: member?.status ?? MemberStatus.OFFLINE,\r\n };\r\n }\r\n\r\n private send(ws: WebSocket, message: HubMessage): void {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(serializeMessage(message));\r\n }\r\n }\r\n\r\n private startHeartbeat(): void {\r\n this.heartbeatInterval = setInterval(() => {\r\n const now = new Date();\r\n for (const [ws, connection] of this.clients) {\r\n const timeSinceLastPing = now.getTime() - connection.lastPing.getTime();\r\n if (timeSinceLastPing > config.hub.clientTimeout) {\r\n ws.terminate();\r\n }\r\n }\r\n }, config.hub.heartbeatInterval);\r\n }\r\n\r\n private startTimeoutCheck(): void {\r\n this.timeoutCheckInterval = setInterval(async () => {\r\n await this.questionRepository.markTimedOut(config.communication.defaultTimeout);\r\n }, 5000);\r\n }\r\n\r\n /**\r\n * Gets the number of connected clients\r\n */\r\n get clientCount(): number {\r\n return this.clients.size;\r\n }\r\n\r\n /**\r\n * Checks if the server is running\r\n */\r\n get isRunning(): boolean {\r\n return this.wss !== null;\r\n }\r\n}\r\n","/**\r\n * WebSocket Hub Client\r\n * Client that connects to the Hub server\r\n * @module infrastructure/websocket/hub-client\r\n */\r\n\r\nimport WebSocket from 'ws';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport { config } from '../../config/index.js';\r\nimport {\r\n type ClientMessage,\r\n type HubMessage,\r\n type QuestionMessage,\r\n type AnswerMessage,\r\n type InboxMessage,\r\n type MemberInfo,\r\n serializeMessage,\r\n parseHubMessage,\r\n} from './message-protocol.js';\r\n\r\n/**\r\n * Pending request with timeout\r\n */\r\ninterface PendingRequest<T> {\r\n resolve: (value: T) => void;\r\n reject: (error: Error) => void;\r\n timeout: ReturnType<typeof setTimeout>;\r\n}\r\n\r\n/**\r\n * Hub client options\r\n */\r\nexport interface HubClientOptions {\r\n host?: string;\r\n port?: number;\r\n reconnect?: boolean;\r\n reconnectDelay?: number;\r\n maxReconnectAttempts?: number;\r\n}\r\n\r\n/**\r\n * Hub client events\r\n */\r\nexport interface HubClientEvents {\r\n onConnected?: () => void;\r\n onDisconnected?: () => void;\r\n onQuestion?: (question: QuestionMessage) => void;\r\n onAnswer?: (answer: AnswerMessage) => void;\r\n onMemberJoined?: (member: MemberInfo) => void;\r\n onMemberLeft?: (memberId: MemberId, teamId: TeamId) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * WebSocket Hub Client\r\n */\r\nexport class HubClient {\r\n private ws: WebSocket | null = null;\r\n private readonly pendingRequests = new Map<string, PendingRequest<HubMessage>>();\r\n private reconnectAttempts = 0;\r\n private isClosing = false;\r\n\r\n private memberId?: MemberId;\r\n private teamId?: TeamId;\r\n private teamName?: string;\r\n private displayName?: string;\r\n\r\n constructor(\r\n private readonly options: HubClientOptions = {},\r\n private readonly events: HubClientEvents = {}\r\n ) {}\r\n\r\n /**\r\n * Connects to the Hub server\r\n */\r\n async connect(): Promise<void> {\r\n const host = this.options.host ?? config.hub.host;\r\n const port = this.options.port ?? config.hub.port;\r\n const url = `ws://${host}:${port}`;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n this.ws = new WebSocket(url);\r\n\r\n this.ws.on('open', () => {\r\n this.reconnectAttempts = 0;\r\n this.startPingInterval();\r\n this.events.onConnected?.();\r\n resolve();\r\n });\r\n\r\n this.ws.on('message', (data) => {\r\n this.handleMessage(data.toString());\r\n });\r\n\r\n this.ws.on('close', () => {\r\n this.handleDisconnect();\r\n });\r\n\r\n this.ws.on('error', (error) => {\r\n this.events.onError?.(error);\r\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\r\n reject(error);\r\n }\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Disconnects from the Hub server\r\n */\r\n async disconnect(): Promise<void> {\r\n this.isClosing = true;\r\n\r\n if (this.memberId) {\r\n this.send({ type: 'LEAVE' });\r\n }\r\n\r\n return new Promise((resolve) => {\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n this.isClosing = false;\r\n resolve();\r\n });\r\n }\r\n\r\n /**\r\n * Joins a team\r\n */\r\n async join(teamName: string, displayName: string): Promise<MemberInfo> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'JOIN',\r\n teamName,\r\n displayName,\r\n });\r\n\r\n const response = await this.waitForResponse<{ type: 'JOINED'; member: MemberInfo }>(\r\n (msg) => msg.type === 'JOINED',\r\n 30000\r\n );\r\n\r\n this.memberId = response.member.memberId;\r\n this.teamId = response.member.teamId;\r\n this.teamName = teamName;\r\n this.displayName = displayName;\r\n\r\n return response.member;\r\n }\r\n\r\n /**\r\n * Asks a question to another team\r\n */\r\n async ask(\r\n toTeam: string,\r\n content: string,\r\n format: MessageFormat = 'markdown',\r\n timeoutMs: number = config.communication.defaultTimeout\r\n ): Promise<AnswerMessage> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'ASK',\r\n toTeam,\r\n content,\r\n format,\r\n requestId,\r\n });\r\n\r\n // Wait for QUESTION_SENT confirmation\r\n await this.waitForResponse(\r\n (msg) => msg.type === 'QUESTION_SENT' && 'requestId' in msg && msg.requestId === requestId,\r\n 5000\r\n );\r\n\r\n // Wait for ANSWER\r\n const answer = await this.waitForResponse<AnswerMessage>(\r\n (msg) => msg.type === 'ANSWER',\r\n timeoutMs\r\n );\r\n\r\n return answer;\r\n }\r\n\r\n /**\r\n * Gets the inbox (pending questions)\r\n */\r\n async getInbox(): Promise<InboxMessage> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'GET_INBOX',\r\n requestId,\r\n });\r\n\r\n return this.waitForResponse<InboxMessage>(\r\n (msg) => msg.type === 'INBOX' && msg.requestId === requestId,\r\n 5000\r\n );\r\n }\r\n\r\n /**\r\n * Replies to a question\r\n */\r\n async reply(questionId: QuestionId, content: string, format: MessageFormat = 'markdown'): Promise<void> {\r\n this.send({\r\n type: 'REPLY',\r\n questionId,\r\n content,\r\n format,\r\n });\r\n }\r\n\r\n /**\r\n * Checks if connected\r\n */\r\n get isConnected(): boolean {\r\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n /**\r\n * Gets the current member ID\r\n */\r\n get currentMemberId(): MemberId | undefined {\r\n return this.memberId;\r\n }\r\n\r\n /**\r\n * Gets the current team ID\r\n */\r\n get currentTeamId(): TeamId | undefined {\r\n return this.teamId;\r\n }\r\n\r\n private send(message: ClientMessage): void {\r\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\r\n this.ws.send(serializeMessage(message));\r\n }\r\n }\r\n\r\n private handleMessage(data: string): void {\r\n try {\r\n const message = parseHubMessage(data);\r\n\r\n // Check pending requests\r\n for (const [requestId, pending] of this.pendingRequests) {\r\n // This is handled by the filter function in waitForResponse\r\n }\r\n\r\n // Handle specific message types\r\n switch (message.type) {\r\n case 'QUESTION':\r\n this.events.onQuestion?.(message);\r\n break;\r\n case 'ANSWER':\r\n this.events.onAnswer?.(message);\r\n break;\r\n case 'MEMBER_JOINED':\r\n this.events.onMemberJoined?.(message.member);\r\n break;\r\n case 'MEMBER_LEFT':\r\n this.events.onMemberLeft?.(message.memberId, message.teamId);\r\n break;\r\n case 'ERROR':\r\n this.events.onError?.(new Error(`${message.code}: ${message.message}`));\r\n break;\r\n }\r\n\r\n // Resolve any matching pending requests\r\n this.resolvePendingRequest(message);\r\n } catch (error) {\r\n console.error('Failed to parse message:', error);\r\n }\r\n }\r\n\r\n private resolvePendingRequest(message: HubMessage): void {\r\n for (const [requestId, pending] of this.pendingRequests) {\r\n // The filter is stored separately, we'll match by message type patterns\r\n this.pendingRequests.delete(requestId);\r\n clearTimeout(pending.timeout);\r\n pending.resolve(message);\r\n break; // Only resolve one request per message\r\n }\r\n }\r\n\r\n private waitForResponse<T extends HubMessage>(\r\n filter: (msg: HubMessage) => boolean,\r\n timeoutMs: number\r\n ): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const requestId = uuidv4();\r\n\r\n const timeout = setTimeout(() => {\r\n this.pendingRequests.delete(requestId);\r\n reject(new Error('Request timed out'));\r\n }, timeoutMs);\r\n\r\n // Store filter function with the pending request\r\n const pending: PendingRequest<HubMessage> & { filter: (msg: HubMessage) => boolean } = {\r\n resolve: (msg) => {\r\n if (filter(msg)) {\r\n resolve(msg as T);\r\n }\r\n },\r\n reject,\r\n timeout,\r\n filter,\r\n };\r\n\r\n this.pendingRequests.set(requestId, pending);\r\n\r\n // Override handleMessage to check this specific filter\r\n const originalHandler = this.handleMessage.bind(this);\r\n const checkFilter = (data: string): void => {\r\n try {\r\n const message = parseHubMessage(data);\r\n if (filter(message)) {\r\n this.pendingRequests.delete(requestId);\r\n clearTimeout(timeout);\r\n resolve(message as T);\r\n }\r\n } catch {\r\n // Ignore parse errors here\r\n }\r\n originalHandler(data);\r\n };\r\n\r\n // Temporarily override\r\n if (this.ws) {\r\n this.ws.removeAllListeners('message');\r\n this.ws.on('message', (data) => checkFilter(data.toString()));\r\n }\r\n });\r\n }\r\n\r\n private handleDisconnect(): void {\r\n this.events.onDisconnected?.();\r\n\r\n if (this.isClosing) return;\r\n\r\n const shouldReconnect = this.options.reconnect ?? true;\r\n const maxAttempts = this.options.maxReconnectAttempts ?? config.autoStart.maxRetries;\r\n\r\n if (shouldReconnect && this.reconnectAttempts < maxAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = this.options.reconnectDelay ?? config.autoStart.retryDelay;\r\n\r\n setTimeout(() => {\r\n this.connect()\r\n .then(() => {\r\n if (this.teamName && this.displayName) {\r\n return this.join(this.teamName, this.displayName);\r\n }\r\n })\r\n .catch((error) => {\r\n this.events.onError?.(error);\r\n });\r\n }, delay);\r\n }\r\n }\r\n\r\n private pingInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n private startPingInterval(): void {\r\n this.pingInterval = setInterval(() => {\r\n this.send({ type: 'PING' });\r\n }, config.hub.heartbeatInterval);\r\n }\r\n}\r\n","/**\r\n * Join Tool\r\n * Joins a team channel for collaboration\r\n * @module presentation/mcp/tools/join\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\n\r\n/**\r\n * Join tool input schema\r\n */\r\nconst joinSchema = {\r\n team: z.string().describe('Team name to join (e.g., \"frontend\", \"backend\", \"devops\")'),\r\n displayName: z\r\n .string()\r\n .optional()\r\n .describe('Display name for this terminal (default: team + \" Claude\")'),\r\n};\r\n\r\n/**\r\n * Registers the join tool with the MCP server\r\n */\r\nexport function registerJoinTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('join', joinSchema, async (args) => {\r\n const teamName = args.team;\r\n const displayName = args.displayName ?? `${teamName} Claude`;\r\n\r\n try {\r\n // Ensure connected to hub\r\n if (!hubClient.isConnected) {\r\n await hubClient.connect();\r\n }\r\n\r\n // Join the team\r\n const member = await hubClient.join(teamName, displayName);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Successfully joined team \"${member.teamName}\" as \"${member.displayName}\".\\n\\nYour member ID: ${member.memberId}\\nTeam ID: ${member.teamId}\\nStatus: ${member.status}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to join team: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Ask Tool\r\n * Asks a question to another team and waits for response\r\n * @module presentation/mcp/tools/ask\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\nimport { config } from '../../../config/index.js';\r\n\r\n/**\r\n * Ask tool input schema\r\n */\r\nconst askSchema = {\r\n team: z.string().describe('Target team name to ask (e.g., \"backend\", \"frontend\")'),\r\n question: z.string().describe('The question to ask (supports markdown)'),\r\n timeout: z\r\n .number()\r\n .optional()\r\n .describe(`Timeout in seconds to wait for answer (default: ${config.communication.defaultTimeout / 1000}s)`),\r\n};\r\n\r\n/**\r\n * Registers the ask tool with the MCP server\r\n */\r\nexport function registerAskTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('ask', askSchema, async (args) => {\r\n const targetTeam = args.team;\r\n const question = args.question;\r\n const timeoutMs = (args.timeout ?? config.communication.defaultTimeout / 1000) * 1000;\r\n\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Ask the question and wait for answer\r\n const answer = await hubClient.ask(targetTeam, question, 'markdown', timeoutMs);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**Answer from ${answer.from.displayName} (${answer.from.teamName}):**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n\r\n if (errorMessage.includes('timed out')) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `No response received from team \"${targetTeam}\" within ${timeoutMs / 1000} seconds. The question has been delivered but no one answered yet.`,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to ask question: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Inbox Tool\r\n * Lists pending questions directed to the current team\r\n * @module presentation/mcp/tools/inbox\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\n\r\n/**\r\n * Inbox tool input schema (no required parameters)\r\n */\r\nconst inboxSchema = {};\r\n\r\n/**\r\n * Registers the inbox tool with the MCP server\r\n */\r\nexport function registerInboxTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('inbox', inboxSchema, async () => {\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Get inbox\r\n const inbox = await hubClient.getInbox();\r\n\r\n if (inbox.questions.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'No pending questions in your inbox.',\r\n },\r\n ],\r\n };\r\n }\r\n\r\n // Format questions list\r\n const questionsList = inbox.questions\r\n .map((q, i) => {\r\n const ageSeconds = Math.floor(q.ageMs / 1000);\r\n const ageStr = ageSeconds < 60 ? `${ageSeconds}s ago` : `${Math.floor(ageSeconds / 60)}m ago`;\r\n\r\n return `### ${i + 1}. Question from ${q.from.displayName} (${q.from.teamName}) - ${ageStr}\r\n**ID:** \\`${q.questionId}\\`\r\n**Status:** ${q.status}\r\n\r\n${q.content}\r\n\r\n---`;\r\n })\r\n .join('\\n\\n');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `# Inbox (${inbox.pendingCount} pending, ${inbox.totalCount} total)\\n\\n${questionsList}\\n\\nUse the \"reply\" tool with the question ID to answer a question.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to get inbox: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Reply Tool\r\n * Replies to a pending question\r\n * @module presentation/mcp/tools/reply\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\nimport type { QuestionId } from '../../../shared/types/branded-types.js';\r\n\r\n/**\r\n * Reply tool input schema\r\n */\r\nconst replySchema = {\r\n questionId: z.string().describe('The ID of the question to reply to (from inbox)'),\r\n answer: z.string().describe('Your answer to the question (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the reply tool with the MCP server\r\n */\r\nexport function registerReplyTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('reply', replySchema, async (args) => {\r\n const questionId = args.questionId as QuestionId;\r\n const answer = args.answer;\r\n\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Send the reply\r\n await hubClient.reply(questionId, answer, 'markdown');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Reply sent successfully to question \\`${questionId}\\`.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send reply: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * MCP Server\r\n * Provides MCP tools for Claude Code integration\r\n * @module presentation/mcp/server\r\n */\r\n\r\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport type { HubClient } from '../../infrastructure/websocket/hub-client.js';\r\nimport { registerJoinTool } from './tools/join.tool.js';\r\nimport { registerAskTool } from './tools/ask.tool.js';\r\nimport { registerInboxTool } from './tools/inbox.tool.js';\r\nimport { registerReplyTool } from './tools/reply.tool.js';\r\n\r\n/**\r\n * MCP Server options\r\n */\r\nexport interface McpServerOptions {\r\n hubClient: HubClient;\r\n}\r\n\r\n/**\r\n * Creates and configures the MCP server with all tools\r\n */\r\nexport function createMcpServer(options: McpServerOptions): McpServer {\r\n const server = new McpServer({\r\n name: 'claude-collab',\r\n version: '0.1.0',\r\n });\r\n\r\n // Register all tools\r\n registerJoinTool(server, options.hubClient);\r\n registerAskTool(server, options.hubClient);\r\n registerInboxTool(server, options.hubClient);\r\n registerReplyTool(server, options.hubClient);\r\n\r\n return server;\r\n}\r\n\r\n/**\r\n * Starts the MCP server with stdio transport\r\n */\r\nexport async function startMcpServer(options: McpServerOptions): Promise<void> {\r\n const server = createMcpServer(options);\r\n const transport = new StdioServerTransport();\r\n\r\n await server.connect(transport);\r\n}\r\n","/**\r\n * Auto-Start Service\r\n * Automatically starts the Hub server if not running\r\n * @module infrastructure/hub-launcher/auto-start\r\n */\r\n\r\nimport { spawn, type ChildProcess } from 'child_process';\r\nimport { createConnection } from 'net';\r\nimport { config } from '../../config/index.js';\r\n\r\n/**\r\n * Auto-start service options\r\n */\r\nexport interface AutoStartOptions {\r\n host?: string;\r\n port?: number;\r\n maxRetries?: number;\r\n retryDelay?: number;\r\n}\r\n\r\n/**\r\n * Checks if the Hub server is running\r\n */\r\nexport async function isHubRunning(\r\n host: string = config.hub.host,\r\n port: number = config.hub.port\r\n): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const socket = createConnection({ host, port }, () => {\r\n socket.end();\r\n resolve(true);\r\n });\r\n\r\n socket.on('error', () => {\r\n resolve(false);\r\n });\r\n\r\n socket.setTimeout(1000, () => {\r\n socket.destroy();\r\n resolve(false);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Waits for the Hub server to become available\r\n */\r\nexport async function waitForHub(\r\n host: string = config.hub.host,\r\n port: number = config.hub.port,\r\n maxRetries: number = config.autoStart.maxRetries,\r\n retryDelay: number = config.autoStart.retryDelay\r\n): Promise<boolean> {\r\n for (let i = 0; i < maxRetries; i++) {\r\n if (await isHubRunning(host, port)) {\r\n return true;\r\n }\r\n await new Promise((resolve) => setTimeout(resolve, retryDelay));\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Starts the Hub server as a background process\r\n */\r\nexport function startHubProcess(options: AutoStartOptions = {}): ChildProcess {\r\n const host = options.host ?? config.hub.host;\r\n const port = options.port ?? config.hub.port;\r\n\r\n // Start hub-main.js as a detached process\r\n const hubProcess = spawn(\r\n process.execPath,\r\n [\r\n '--experimental-specifier-resolution=node',\r\n new URL('../../hub-main.js', import.meta.url).pathname,\r\n '--host',\r\n host,\r\n '--port',\r\n port.toString(),\r\n ],\r\n {\r\n detached: true,\r\n stdio: 'ignore',\r\n }\r\n );\r\n\r\n hubProcess.unref();\r\n return hubProcess;\r\n}\r\n\r\n/**\r\n * Ensures the Hub is running, starting it if necessary\r\n */\r\nexport async function ensureHubRunning(options: AutoStartOptions = {}): Promise<boolean> {\r\n const host = options.host ?? config.hub.host;\r\n const port = options.port ?? config.hub.port;\r\n const maxRetries = options.maxRetries ?? config.autoStart.maxRetries;\r\n const retryDelay = options.retryDelay ?? config.autoStart.retryDelay;\r\n\r\n // Check if already running\r\n if (await isHubRunning(host, port)) {\r\n return true;\r\n }\r\n\r\n // Try to start the hub\r\n console.log(`Hub not running. Starting hub on ${host}:${port}...`);\r\n startHubProcess({ host, port });\r\n\r\n // Wait for it to become available\r\n const isRunning = await waitForHub(host, port, maxRetries, retryDelay);\r\n\r\n if (isRunning) {\r\n console.log('Hub started successfully');\r\n } else {\r\n console.error('Failed to start hub');\r\n }\r\n\r\n return isRunning;\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * CLI entry point\r\n * Provides command-line interface for claude-collab\r\n * @module cli\r\n */\r\n\r\nimport { Command } from 'commander';\r\nimport { HubServer } from './infrastructure/websocket/hub-server.js';\r\nimport { HubClient } from './infrastructure/websocket/hub-client.js';\r\nimport { startMcpServer } from './presentation/mcp/server.js';\r\nimport { ensureHubRunning } from './infrastructure/hub-launcher/auto-start.service.js';\r\nimport { config } from './config/index.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('claude-collab')\r\n .description('Real-time team collaboration between Claude Code terminals')\r\n .version('0.1.0');\r\n\r\n// Hub commands\r\nconst hubCmd = program.command('hub').description('Hub server commands');\r\n\r\nhubCmd\r\n .command('start')\r\n .description('Start the Hub server')\r\n .option('-p, --port <port>', 'Port to listen on', String(config.hub.port))\r\n .option('--host <host>', 'Host to bind to', config.hub.host)\r\n .action(async (options: { port: string; host: string }) => {\r\n const port = parseInt(options.port, 10);\r\n const host = options.host;\r\n\r\n const server = new HubServer({ host, port });\r\n\r\n // Handle shutdown signals\r\n const shutdown = async (): Promise<void> => {\r\n console.log('\\nShutting down hub server...');\r\n await server.stop();\r\n process.exit(0);\r\n };\r\n\r\n process.on('SIGINT', shutdown);\r\n process.on('SIGTERM', shutdown);\r\n\r\n try {\r\n await server.start();\r\n console.log(`Claude Collab Hub Server running on ${host}:${port}`);\r\n } catch (error) {\r\n console.error('Failed to start hub server:', error);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// Client command\r\nprogram\r\n .command('client')\r\n .description('Start MCP client (connects to Claude Code)')\r\n .option('-t, --team <team>', 'Team to auto-join (e.g., frontend, backend)')\r\n .option('--auto-hub', 'Auto-start hub if not running', false)\r\n .option('-p, --port <port>', 'Hub port to connect to', String(config.hub.port))\r\n .option('--host <host>', 'Hub host to connect to', config.hub.host)\r\n .action(\r\n async (options: { team?: string; autoHub: boolean; port: string; host: string }) => {\r\n const port = parseInt(options.port, 10);\r\n const host = options.host;\r\n\r\n // Auto-start hub if requested\r\n if (options.autoHub) {\r\n const hubRunning = await ensureHubRunning({ host, port });\r\n if (!hubRunning) {\r\n console.error('Failed to start hub server. Exiting.');\r\n process.exit(1);\r\n }\r\n }\r\n\r\n // Create hub client\r\n const hubClient = new HubClient(\r\n { host, port, reconnect: true },\r\n {\r\n onError: (error) => {\r\n console.error('Hub client error:', error.message);\r\n },\r\n onQuestion: (question) => {\r\n console.error(`[Question received from ${question.from.displayName}]`);\r\n },\r\n }\r\n );\r\n\r\n // Connect to hub\r\n try {\r\n await hubClient.connect();\r\n\r\n // Auto-join team if specified\r\n if (options.team) {\r\n await hubClient.join(options.team, `${options.team} Claude`);\r\n console.error(`Auto-joined team: ${options.team}`);\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to connect to hub: ${errorMessage}`);\r\n console.error('Make sure the hub server is running or use --auto-hub flag.');\r\n process.exit(1);\r\n }\r\n\r\n // Start MCP server\r\n await startMcpServer({ hubClient });\r\n }\r\n );\r\n\r\nprogram.parse();\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/domain/entities/member.entity.ts","../src/domain/events/base.event.ts","../src/domain/events/member-joined.event.ts","../src/shared/types/branded-types.ts","../src/shared/utils/id-generator.ts","../src/shared/errors/domain-errors.ts","../src/application/use-cases/join-team.use-case.ts","../src/domain/entities/question.entity.ts","../src/config/index.ts","../src/domain/value-objects/message-content.vo.ts","../src/domain/events/question-asked.event.ts","../src/application/use-cases/ask-question.use-case.ts","../src/application/use-cases/get-inbox.use-case.ts","../src/domain/entities/answer.entity.ts","../src/domain/events/question-answered.event.ts","../src/application/use-cases/reply-question.use-case.ts","../src/infrastructure/repositories/in-memory-member.repository.ts","../src/domain/entities/team.entity.ts","../src/infrastructure/repositories/in-memory-team.repository.ts","../src/infrastructure/repositories/in-memory-question.repository.ts","../src/infrastructure/repositories/in-memory-answer.repository.ts","../src/infrastructure/websocket/message-protocol.ts","../src/infrastructure/websocket/hub-server.ts","../src/infrastructure/websocket/hub-client.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/infrastructure/hub-launcher/auto-start.service.ts","../src/cli.ts"],"names":["uuidv4","WebSocket","z"],"mappings":"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","file":"cli.js","sourcesContent":["/**\r\n * Member Entity\r\n * Represents a connected Claude Code terminal in the collaboration network\r\n * @module domain/entities/member\r\n */\r\n\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * Member status enumeration\r\n */\r\nexport enum MemberStatus {\r\n /** Member is connected and active */\r\n ONLINE = 'ONLINE',\r\n /** Member is connected but idle */\r\n IDLE = 'IDLE',\r\n /** Member has disconnected */\r\n OFFLINE = 'OFFLINE',\r\n}\r\n\r\n/**\r\n * Properties required to create a Member\r\n */\r\nexport interface MemberProps {\r\n readonly id: MemberId;\r\n readonly teamId: TeamId;\r\n readonly displayName: string;\r\n readonly connectedAt: Date;\r\n readonly status: MemberStatus;\r\n}\r\n\r\n/**\r\n * Member entity - a connected Claude Code terminal\r\n */\r\nexport class Member {\r\n private readonly _id: MemberId;\r\n private readonly _teamId: TeamId;\r\n private readonly _displayName: string;\r\n private readonly _connectedAt: Date;\r\n private _status: MemberStatus;\r\n private _lastActivityAt: Date;\r\n\r\n private constructor(props: MemberProps) {\r\n this._id = props.id;\r\n this._teamId = props.teamId;\r\n this._displayName = props.displayName;\r\n this._connectedAt = props.connectedAt;\r\n this._status = props.status;\r\n this._lastActivityAt = props.connectedAt;\r\n }\r\n\r\n /**\r\n * Creates a new Member instance\r\n */\r\n public static create(props: MemberProps): Member {\r\n if (!props.displayName.trim()) {\r\n throw new Error('Display name cannot be empty');\r\n }\r\n return new Member(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes a Member from persistence\r\n */\r\n public static reconstitute(props: MemberProps & { lastActivityAt: Date }): Member {\r\n const member = new Member(props);\r\n member._lastActivityAt = props.lastActivityAt;\r\n return member;\r\n }\r\n\r\n // Getters\r\n public get id(): MemberId {\r\n return this._id;\r\n }\r\n\r\n public get teamId(): TeamId {\r\n return this._teamId;\r\n }\r\n\r\n public get displayName(): string {\r\n return this._displayName;\r\n }\r\n\r\n public get connectedAt(): Date {\r\n return this._connectedAt;\r\n }\r\n\r\n public get status(): MemberStatus {\r\n return this._status;\r\n }\r\n\r\n public get lastActivityAt(): Date {\r\n return this._lastActivityAt;\r\n }\r\n\r\n public get isOnline(): boolean {\r\n return this._status === MemberStatus.ONLINE || this._status === MemberStatus.IDLE;\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Marks the member as online\r\n */\r\n public goOnline(): void {\r\n this._status = MemberStatus.ONLINE;\r\n this._lastActivityAt = new Date();\r\n }\r\n\r\n /**\r\n * Marks the member as idle\r\n */\r\n public goIdle(): void {\r\n this._status = MemberStatus.IDLE;\r\n }\r\n\r\n /**\r\n * Marks the member as offline\r\n */\r\n public goOffline(): void {\r\n this._status = MemberStatus.OFFLINE;\r\n }\r\n\r\n /**\r\n * Records activity from this member\r\n */\r\n public recordActivity(): void {\r\n this._lastActivityAt = new Date();\r\n if (this._status === MemberStatus.IDLE) {\r\n this._status = MemberStatus.ONLINE;\r\n }\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): MemberProps & { lastActivityAt: Date } {\r\n return {\r\n id: this._id,\r\n teamId: this._teamId,\r\n displayName: this._displayName,\r\n connectedAt: this._connectedAt,\r\n status: this._status,\r\n lastActivityAt: this._lastActivityAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * Base Domain Event\r\n * @module domain/events/base\r\n */\r\n\r\nimport { v4 as uuidv4 } from 'uuid';\r\n\r\n/**\r\n * Base interface for all domain events\r\n */\r\nexport interface DomainEvent {\r\n readonly eventId: string;\r\n readonly eventType: string;\r\n readonly timestamp: Date;\r\n readonly payload: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Base class for domain events\r\n */\r\nexport abstract class BaseDomainEvent implements DomainEvent {\r\n public readonly eventId: string;\r\n public readonly timestamp: Date;\r\n\r\n constructor() {\r\n this.eventId = uuidv4();\r\n this.timestamp = new Date();\r\n }\r\n\r\n public abstract get eventType(): string;\r\n public abstract get payload(): Record<string, unknown>;\r\n\r\n /**\r\n * Converts event to JSON\r\n */\r\n public toJSON(): DomainEvent {\r\n return {\r\n eventId: this.eventId,\r\n eventType: this.eventType,\r\n timestamp: this.timestamp,\r\n payload: this.payload,\r\n };\r\n }\r\n}\r\n","/**\r\n * MemberJoined Domain Event\r\n * Raised when a member joins a team\r\n * @module domain/events/member-joined\r\n */\r\n\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a member joins a team\r\n */\r\nexport class MemberJoinedEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'MEMBER_JOINED';\r\n\r\n constructor(\r\n public readonly memberId: MemberId,\r\n public readonly teamId: TeamId,\r\n public readonly displayName: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return MemberJoinedEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n memberId: this.memberId,\r\n teamId: this.teamId,\r\n displayName: this.displayName,\r\n };\r\n }\r\n}\r\n","/**\r\n * Branded types for type-safe IDs\r\n * @module shared/types/branded-types\r\n */\r\n\r\ndeclare const brand: unique symbol;\r\n\r\n/**\r\n * Creates a branded type for nominal typing\r\n */\r\nexport type Brand<T, B> = T & { readonly [brand]: B };\r\n\r\n/**\r\n * Member ID - unique identifier for a connected Claude Code terminal\r\n */\r\nexport type MemberId = Brand<string, 'MemberId'>;\r\n\r\n/**\r\n * Team ID - identifier for a team channel (e.g., \"frontend\", \"backend\")\r\n */\r\nexport type TeamId = Brand<string, 'TeamId'>;\r\n\r\n/**\r\n * Question ID - unique identifier for a question\r\n */\r\nexport type QuestionId = Brand<string, 'QuestionId'>;\r\n\r\n/**\r\n * Answer ID - unique identifier for an answer\r\n */\r\nexport type AnswerId = Brand<string, 'AnswerId'>;\r\n\r\n/**\r\n * Type guard functions for branded types\r\n */\r\nexport const MemberId = {\r\n create: (id: string): MemberId => id as MemberId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n\r\nexport const TeamId = {\r\n create: (id: string): TeamId => id.toLowerCase().trim() as TeamId,\r\n isValid: (id: string): boolean => /^[a-z][a-z0-9-]*$/.test(id.toLowerCase().trim()),\r\n};\r\n\r\nexport const QuestionId = {\r\n create: (id: string): QuestionId => id as QuestionId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n\r\nexport const AnswerId = {\r\n create: (id: string): AnswerId => id as AnswerId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n","/**\r\n * ID generation utilities\r\n * @module shared/utils/id-generator\r\n */\r\n\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type { MemberId, TeamId, QuestionId, AnswerId } from '../types/branded-types.js';\r\nimport {\r\n MemberId as MemberIdFactory,\r\n TeamId as TeamIdFactory,\r\n QuestionId as QuestionIdFactory,\r\n AnswerId as AnswerIdFactory,\r\n} from '../types/branded-types.js';\r\n\r\n/**\r\n * Generates a new unique Member ID\r\n */\r\nexport function generateMemberId(): MemberId {\r\n return MemberIdFactory.create(uuidv4());\r\n}\r\n\r\n/**\r\n * Creates a Team ID from a team name\r\n */\r\nexport function createTeamId(name: string): TeamId {\r\n return TeamIdFactory.create(name);\r\n}\r\n\r\n/**\r\n * Generates a new unique Question ID\r\n */\r\nexport function generateQuestionId(): QuestionId {\r\n return QuestionIdFactory.create(`q_${uuidv4()}`);\r\n}\r\n\r\n/**\r\n * Generates a new unique Answer ID\r\n */\r\nexport function generateAnswerId(): AnswerId {\r\n return AnswerIdFactory.create(`a_${uuidv4()}`);\r\n}\r\n","/**\r\n * Domain-specific errors\r\n * @module shared/errors/domain-errors\r\n */\r\n\r\n/**\r\n * Base class for all domain errors\r\n */\r\nexport abstract class DomainError extends Error {\r\n public readonly code: string;\r\n public readonly timestamp: Date;\r\n\r\n constructor(message: string, code: string) {\r\n super(message);\r\n this.name = this.constructor.name;\r\n this.code = code;\r\n this.timestamp = new Date();\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when an entity is not found\r\n */\r\nexport class EntityNotFoundError extends DomainError {\r\n constructor(entityName: string, id: string) {\r\n super(`${entityName} with id '${id}' not found`, 'ENTITY_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a team is not found\r\n */\r\nexport class TeamNotFoundError extends DomainError {\r\n constructor(teamId: string) {\r\n super(`Team '${teamId}' not found`, 'TEAM_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a member is not found\r\n */\r\nexport class MemberNotFoundError extends DomainError {\r\n constructor(memberId: string) {\r\n super(`Member '${memberId}' not found`, 'MEMBER_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a question is not found\r\n */\r\nexport class QuestionNotFoundError extends DomainError {\r\n constructor(questionId: string) {\r\n super(`Question '${questionId}' not found`, 'QUESTION_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a question has already been answered\r\n */\r\nexport class QuestionAlreadyAnsweredError extends DomainError {\r\n constructor(questionId: string) {\r\n super(`Question '${questionId}' has already been answered`, 'QUESTION_ALREADY_ANSWERED');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a member is already in a team\r\n */\r\nexport class MemberAlreadyInTeamError extends DomainError {\r\n constructor(memberId: string, teamId: string) {\r\n super(`Member '${memberId}' is already in team '${teamId}'`, 'MEMBER_ALREADY_IN_TEAM');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a timeout occurs\r\n */\r\nexport class TimeoutError extends DomainError {\r\n constructor(operation: string, timeoutMs: number) {\r\n super(`Operation '${operation}' timed out after ${timeoutMs}ms`, 'TIMEOUT');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when connection fails\r\n */\r\nexport class ConnectionError extends DomainError {\r\n constructor(message: string) {\r\n super(message, 'CONNECTION_ERROR');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when validation fails\r\n */\r\nexport class ValidationError extends DomainError {\r\n public readonly field: string;\r\n\r\n constructor(field: string, message: string) {\r\n super(message, 'VALIDATION_ERROR');\r\n this.field = field;\r\n }\r\n}\r\n","/**\r\n * JoinTeam Use Case\r\n * Handles joining a team channel\r\n * @module application/use-cases/join-team\r\n */\r\n\r\nimport type { JoinTeamInput, JoinTeamOutput } from '../dtos/join-team.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport { Member, MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport { MemberJoinedEvent } from '../../domain/events/member-joined.event.js';\r\nimport { generateMemberId, createTeamId } from '../../shared/utils/id-generator.js';\r\nimport { ValidationError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: MemberJoinedEvent) => void | Promise<void>;\r\n\r\n/**\r\n * JoinTeam use case dependencies\r\n */\r\nexport interface JoinTeamDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly onMemberJoined?: EventHandler;\r\n}\r\n\r\n/**\r\n * JoinTeam use case\r\n * Creates a new member and adds them to a team\r\n */\r\nexport class JoinTeamUseCase {\r\n constructor(private readonly deps: JoinTeamDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: JoinTeamInput): Promise<JoinTeamOutput> {\r\n // Validate input\r\n if (!input.teamName.trim()) {\r\n throw new ValidationError('teamName', 'Team name cannot be empty');\r\n }\r\n if (!input.displayName.trim()) {\r\n throw new ValidationError('displayName', 'Display name cannot be empty');\r\n }\r\n\r\n // Get or create team\r\n const team = await this.deps.teamRepository.getOrCreate(input.teamName);\r\n\r\n // Create member\r\n const memberId = generateMemberId();\r\n const member = Member.create({\r\n id: memberId,\r\n teamId: team.id,\r\n displayName: input.displayName.trim(),\r\n connectedAt: new Date(),\r\n status: MemberStatus.ONLINE,\r\n });\r\n\r\n // Save member\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Add member to team\r\n team.addMember(memberId);\r\n await this.deps.teamRepository.save(team);\r\n\r\n // Emit event\r\n if (this.deps.onMemberJoined) {\r\n const event = new MemberJoinedEvent(memberId, team.id, member.displayName);\r\n await this.deps.onMemberJoined(event);\r\n }\r\n\r\n return {\r\n memberId,\r\n teamId: team.id,\r\n teamName: team.name,\r\n displayName: member.displayName,\r\n status: member.status,\r\n memberCount: team.memberCount,\r\n };\r\n }\r\n}\r\n","/**\r\n * Question Entity\r\n * Represents a question sent from one member to a team\r\n * @module domain/entities/question\r\n */\r\n\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport type { MessageContent } from '../value-objects/message-content.vo.js';\r\nimport { QuestionAlreadyAnsweredError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Question status enumeration\r\n */\r\nexport enum QuestionStatus {\r\n /** Question is waiting for an answer */\r\n PENDING = 'PENDING',\r\n /** Question has been answered */\r\n ANSWERED = 'ANSWERED',\r\n /** Question timed out without an answer */\r\n TIMEOUT = 'TIMEOUT',\r\n /** Question was cancelled */\r\n CANCELLED = 'CANCELLED',\r\n}\r\n\r\n/**\r\n * Properties required to create a Question\r\n */\r\nexport interface QuestionProps {\r\n readonly id: QuestionId;\r\n readonly fromMemberId: MemberId;\r\n readonly toTeamId: TeamId;\r\n readonly content: MessageContent;\r\n readonly createdAt: Date;\r\n readonly status: QuestionStatus;\r\n readonly answeredAt?: Date;\r\n readonly answeredByMemberId?: MemberId;\r\n}\r\n\r\n/**\r\n * Question entity - a message awaiting response\r\n */\r\nexport class Question {\r\n private readonly _id: QuestionId;\r\n private readonly _fromMemberId: MemberId;\r\n private readonly _toTeamId: TeamId;\r\n private readonly _content: MessageContent;\r\n private readonly _createdAt: Date;\r\n private _status: QuestionStatus;\r\n private _answeredAt?: Date;\r\n private _answeredByMemberId?: MemberId;\r\n\r\n private constructor(props: QuestionProps) {\r\n this._id = props.id;\r\n this._fromMemberId = props.fromMemberId;\r\n this._toTeamId = props.toTeamId;\r\n this._content = props.content;\r\n this._createdAt = props.createdAt;\r\n this._status = props.status;\r\n this._answeredAt = props.answeredAt;\r\n this._answeredByMemberId = props.answeredByMemberId;\r\n }\r\n\r\n /**\r\n * Creates a new Question instance\r\n */\r\n public static create(props: Omit<QuestionProps, 'status' | 'answeredAt' | 'answeredByMemberId'>): Question {\r\n return new Question({\r\n ...props,\r\n status: QuestionStatus.PENDING,\r\n });\r\n }\r\n\r\n /**\r\n * Reconstitutes a Question from persistence\r\n */\r\n public static reconstitute(props: QuestionProps): Question {\r\n return new Question(props);\r\n }\r\n\r\n // Getters\r\n public get id(): QuestionId {\r\n return this._id;\r\n }\r\n\r\n public get fromMemberId(): MemberId {\r\n return this._fromMemberId;\r\n }\r\n\r\n public get toTeamId(): TeamId {\r\n return this._toTeamId;\r\n }\r\n\r\n public get content(): MessageContent {\r\n return this._content;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n public get status(): QuestionStatus {\r\n return this._status;\r\n }\r\n\r\n public get answeredAt(): Date | undefined {\r\n return this._answeredAt;\r\n }\r\n\r\n public get answeredByMemberId(): MemberId | undefined {\r\n return this._answeredByMemberId;\r\n }\r\n\r\n public get isPending(): boolean {\r\n return this._status === QuestionStatus.PENDING;\r\n }\r\n\r\n public get isAnswered(): boolean {\r\n return this._status === QuestionStatus.ANSWERED;\r\n }\r\n\r\n public get isTimedOut(): boolean {\r\n return this._status === QuestionStatus.TIMEOUT;\r\n }\r\n\r\n public get isCancelled(): boolean {\r\n return this._status === QuestionStatus.CANCELLED;\r\n }\r\n\r\n public get canBeAnswered(): boolean {\r\n return this._status === QuestionStatus.PENDING;\r\n }\r\n\r\n /**\r\n * Calculates the age of the question in milliseconds\r\n */\r\n public get ageMs(): number {\r\n return Date.now() - this._createdAt.getTime();\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Marks the question as answered\r\n * @throws QuestionAlreadyAnsweredError if already answered\r\n */\r\n public markAsAnswered(answeredByMemberId: MemberId): void {\r\n if (!this.canBeAnswered) {\r\n throw new QuestionAlreadyAnsweredError(this._id);\r\n }\r\n this._status = QuestionStatus.ANSWERED;\r\n this._answeredAt = new Date();\r\n this._answeredByMemberId = answeredByMemberId;\r\n }\r\n\r\n /**\r\n * Marks the question as timed out\r\n */\r\n public markAsTimedOut(): void {\r\n if (this._status === QuestionStatus.PENDING) {\r\n this._status = QuestionStatus.TIMEOUT;\r\n }\r\n }\r\n\r\n /**\r\n * Marks the question as cancelled\r\n */\r\n public markAsCancelled(): void {\r\n if (this._status === QuestionStatus.PENDING) {\r\n this._status = QuestionStatus.CANCELLED;\r\n }\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): QuestionProps {\r\n return {\r\n id: this._id,\r\n fromMemberId: this._fromMemberId,\r\n toTeamId: this._toTeamId,\r\n content: this._content,\r\n createdAt: this._createdAt,\r\n status: this._status,\r\n answeredAt: this._answeredAt,\r\n answeredByMemberId: this._answeredByMemberId,\r\n };\r\n }\r\n}\r\n","/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * WebSocket Hub configuration\r\n */\r\n hub: {\r\n /**\r\n * Default port for the Hub server\r\n */\r\n port: parseInt(process.env['CLAUDE_COLLAB_PORT'] ?? '9999', 10),\r\n\r\n /**\r\n * Host to bind the Hub server to\r\n */\r\n host: process.env['CLAUDE_COLLAB_HOST'] ?? 'localhost',\r\n\r\n /**\r\n * Heartbeat interval in milliseconds\r\n */\r\n heartbeatInterval: 30000,\r\n\r\n /**\r\n * Client timeout in milliseconds (no heartbeat received)\r\n */\r\n clientTimeout: 60000,\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n\r\n /**\r\n * Auto-start configuration\r\n */\r\n autoStart: {\r\n /**\r\n * Whether to auto-start the hub if not running\r\n */\r\n enabled: true,\r\n\r\n /**\r\n * Maximum retries when connecting to hub\r\n */\r\n maxRetries: 3,\r\n\r\n /**\r\n * Delay between retries in milliseconds\r\n */\r\n retryDelay: 1000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * MessageContent Value Object\r\n * Represents the content of a message with format information\r\n * @module domain/value-objects/message-content\r\n */\r\n\r\nimport { ValidationError } from '../../shared/errors/domain-errors.js';\r\nimport { config } from '../../config/index.js';\r\n\r\n/**\r\n * Message format type\r\n */\r\nexport type MessageFormat = 'plain' | 'markdown';\r\n\r\n/**\r\n * Properties for creating a MessageContent\r\n */\r\nexport interface MessageContentProps {\r\n readonly text: string;\r\n readonly format: MessageFormat;\r\n}\r\n\r\n/**\r\n * MessageContent value object\r\n * Immutable representation of message content\r\n */\r\nexport class MessageContent {\r\n private readonly _text: string;\r\n private readonly _format: MessageFormat;\r\n\r\n private constructor(text: string, format: MessageFormat) {\r\n this._text = text;\r\n this._format = format;\r\n }\r\n\r\n /**\r\n * Creates a new MessageContent\r\n * @throws ValidationError if content is invalid\r\n */\r\n public static create(text: string, format: MessageFormat = 'markdown'): MessageContent {\r\n const trimmedText = text.trim();\r\n\r\n if (!trimmedText) {\r\n throw new ValidationError('text', 'Message content cannot be empty');\r\n }\r\n\r\n if (trimmedText.length > config.communication.maxMessageLength) {\r\n throw new ValidationError(\r\n 'text',\r\n `Message content exceeds maximum length of ${config.communication.maxMessageLength} characters`\r\n );\r\n }\r\n\r\n return new MessageContent(trimmedText, format);\r\n }\r\n\r\n /**\r\n * Creates a plain text message\r\n */\r\n public static plain(text: string): MessageContent {\r\n return MessageContent.create(text, 'plain');\r\n }\r\n\r\n /**\r\n * Creates a markdown message\r\n */\r\n public static markdown(text: string): MessageContent {\r\n return MessageContent.create(text, 'markdown');\r\n }\r\n\r\n /**\r\n * Reconstitutes from persistence\r\n */\r\n public static reconstitute(props: MessageContentProps): MessageContent {\r\n return new MessageContent(props.text, props.format);\r\n }\r\n\r\n // Getters\r\n public get text(): string {\r\n return this._text;\r\n }\r\n\r\n public get format(): MessageFormat {\r\n return this._format;\r\n }\r\n\r\n public get length(): number {\r\n return this._text.length;\r\n }\r\n\r\n public get isMarkdown(): boolean {\r\n return this._format === 'markdown';\r\n }\r\n\r\n public get isPlain(): boolean {\r\n return this._format === 'plain';\r\n }\r\n\r\n /**\r\n * Returns a preview of the content (first 100 chars)\r\n */\r\n public get preview(): string {\r\n if (this._text.length <= 100) {\r\n return this._text;\r\n }\r\n return `${this._text.substring(0, 97)}...`;\r\n }\r\n\r\n /**\r\n * Checks equality with another MessageContent\r\n */\r\n public equals(other: MessageContent): boolean {\r\n return this._text === other._text && this._format === other._format;\r\n }\r\n\r\n /**\r\n * Converts to plain object for serialization\r\n */\r\n public toJSON(): MessageContentProps {\r\n return {\r\n text: this._text,\r\n format: this._format,\r\n };\r\n }\r\n\r\n /**\r\n * String representation\r\n */\r\n public toString(): string {\r\n return this._text;\r\n }\r\n}\r\n","/**\r\n * QuestionAsked Domain Event\r\n * Raised when a question is asked to a team\r\n * @module domain/events/question-asked\r\n */\r\n\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a question is asked\r\n */\r\nexport class QuestionAskedEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'QUESTION_ASKED';\r\n\r\n constructor(\r\n public readonly questionId: QuestionId,\r\n public readonly fromMemberId: MemberId,\r\n public readonly toTeamId: TeamId,\r\n public readonly contentPreview: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return QuestionAskedEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n questionId: this.questionId,\r\n fromMemberId: this.fromMemberId,\r\n toTeamId: this.toTeamId,\r\n contentPreview: this.contentPreview,\r\n };\r\n }\r\n}\r\n","/**\r\n * AskQuestion Use Case\r\n * Handles asking a question to another team\r\n * @module application/use-cases/ask-question\r\n */\r\n\r\nimport type { AskQuestionInput, AskQuestionOutput } from '../dtos/ask-question.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { Question } from '../../domain/entities/question.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { QuestionAskedEvent } from '../../domain/events/question-asked.event.js';\r\nimport { generateQuestionId, createTeamId } from '../../shared/utils/id-generator.js';\r\nimport {\r\n MemberNotFoundError,\r\n TeamNotFoundError,\r\n ValidationError,\r\n} from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: QuestionAskedEvent) => void | Promise<void>;\r\n\r\n/**\r\n * AskQuestion use case dependencies\r\n */\r\nexport interface AskQuestionDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n readonly onQuestionAsked?: EventHandler;\r\n}\r\n\r\n/**\r\n * AskQuestion use case\r\n * Creates and sends a question to a team\r\n */\r\nexport class AskQuestionUseCase {\r\n constructor(private readonly deps: AskQuestionDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: AskQuestionInput): Promise<AskQuestionOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.fromMemberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.fromMemberId);\r\n }\r\n\r\n // Validate target team exists\r\n const targetTeamId = createTeamId(input.toTeamName);\r\n const targetTeam = await this.deps.teamRepository.findById(targetTeamId);\r\n if (!targetTeam) {\r\n throw new TeamNotFoundError(input.toTeamName);\r\n }\r\n\r\n // Validate not asking own team\r\n if (member.teamId === targetTeamId) {\r\n throw new ValidationError('toTeamName', 'Cannot ask question to your own team');\r\n }\r\n\r\n // Create message content\r\n const content = MessageContent.create(input.content, input.format ?? 'markdown');\r\n\r\n // Create question\r\n const questionId = generateQuestionId();\r\n const question = Question.create({\r\n id: questionId,\r\n fromMemberId: input.fromMemberId,\r\n toTeamId: targetTeamId,\r\n content,\r\n createdAt: new Date(),\r\n });\r\n\r\n // Save question\r\n await this.deps.questionRepository.save(question);\r\n\r\n // Record member activity\r\n member.recordActivity();\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Emit event\r\n if (this.deps.onQuestionAsked) {\r\n const event = new QuestionAskedEvent(\r\n questionId,\r\n input.fromMemberId,\r\n targetTeamId,\r\n content.preview\r\n );\r\n await this.deps.onQuestionAsked(event);\r\n }\r\n\r\n return {\r\n questionId,\r\n toTeamId: targetTeamId,\r\n status: question.status,\r\n createdAt: question.createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * GetInbox Use Case\r\n * Retrieves pending questions for a team member\r\n * @module application/use-cases/get-inbox\r\n */\r\n\r\nimport type { GetInboxInput, GetInboxOutput, InboxQuestionItem } from '../dtos/get-inbox.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { QuestionStatus } from '../../domain/entities/question.entity.js';\r\nimport { MemberNotFoundError, TeamNotFoundError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * GetInbox use case dependencies\r\n */\r\nexport interface GetInboxDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n}\r\n\r\n/**\r\n * GetInbox use case\r\n * Retrieves questions directed to the member's team\r\n */\r\nexport class GetInboxUseCase {\r\n constructor(private readonly deps: GetInboxDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: GetInboxInput): Promise<GetInboxOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.memberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.memberId);\r\n }\r\n\r\n // Validate team exists\r\n const team = await this.deps.teamRepository.findById(input.teamId);\r\n if (!team) {\r\n throw new TeamNotFoundError(input.teamId);\r\n }\r\n\r\n // Get questions for team\r\n const allQuestions = await this.deps.questionRepository.findPendingByTeamId(input.teamId);\r\n\r\n // Filter based on includeAnswered flag\r\n const questions = input.includeAnswered\r\n ? allQuestions\r\n : allQuestions.filter((q) => q.isPending);\r\n\r\n // Map to DTOs with member info\r\n const questionItems: InboxQuestionItem[] = [];\r\n\r\n for (const question of questions) {\r\n const fromMember = await this.deps.memberRepository.findById(question.fromMemberId);\r\n const fromTeam = fromMember\r\n ? await this.deps.teamRepository.findById(fromMember.teamId)\r\n : null;\r\n\r\n questionItems.push({\r\n questionId: question.id,\r\n fromMemberId: question.fromMemberId,\r\n fromDisplayName: fromMember?.displayName ?? 'Unknown',\r\n fromTeamName: fromTeam?.name ?? 'Unknown',\r\n content: question.content.text,\r\n format: question.content.format,\r\n status: question.status,\r\n createdAt: question.createdAt,\r\n ageMs: question.ageMs,\r\n });\r\n }\r\n\r\n // Sort by creation date (newest first)\r\n questionItems.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\r\n\r\n const pendingCount = questionItems.filter((q) => q.status === QuestionStatus.PENDING).length;\r\n\r\n return {\r\n teamId: team.id,\r\n teamName: team.name,\r\n questions: questionItems,\r\n totalCount: questionItems.length,\r\n pendingCount,\r\n };\r\n }\r\n}\r\n","/**\r\n * Answer Entity\r\n * Represents a response to a question\r\n * @module domain/entities/answer\r\n */\r\n\r\nimport type { AnswerId, QuestionId, MemberId } from '../../shared/types/branded-types.js';\r\nimport type { MessageContent } from '../value-objects/message-content.vo.js';\r\n\r\n/**\r\n * Properties required to create an Answer\r\n */\r\nexport interface AnswerProps {\r\n readonly id: AnswerId;\r\n readonly questionId: QuestionId;\r\n readonly fromMemberId: MemberId;\r\n readonly content: MessageContent;\r\n readonly createdAt: Date;\r\n}\r\n\r\n/**\r\n * Answer entity - a response to a question\r\n */\r\nexport class Answer {\r\n private readonly _id: AnswerId;\r\n private readonly _questionId: QuestionId;\r\n private readonly _fromMemberId: MemberId;\r\n private readonly _content: MessageContent;\r\n private readonly _createdAt: Date;\r\n\r\n private constructor(props: AnswerProps) {\r\n this._id = props.id;\r\n this._questionId = props.questionId;\r\n this._fromMemberId = props.fromMemberId;\r\n this._content = props.content;\r\n this._createdAt = props.createdAt;\r\n }\r\n\r\n /**\r\n * Creates a new Answer instance\r\n */\r\n public static create(props: AnswerProps): Answer {\r\n return new Answer(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes an Answer from persistence\r\n */\r\n public static reconstitute(props: AnswerProps): Answer {\r\n return new Answer(props);\r\n }\r\n\r\n // Getters\r\n public get id(): AnswerId {\r\n return this._id;\r\n }\r\n\r\n public get questionId(): QuestionId {\r\n return this._questionId;\r\n }\r\n\r\n public get fromMemberId(): MemberId {\r\n return this._fromMemberId;\r\n }\r\n\r\n public get content(): MessageContent {\r\n return this._content;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): AnswerProps {\r\n return {\r\n id: this._id,\r\n questionId: this._questionId,\r\n fromMemberId: this._fromMemberId,\r\n content: this._content,\r\n createdAt: this._createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * QuestionAnswered Domain Event\r\n * Raised when a question is answered\r\n * @module domain/events/question-answered\r\n */\r\n\r\nimport type { QuestionId, AnswerId, MemberId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a question is answered\r\n */\r\nexport class QuestionAnsweredEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'QUESTION_ANSWERED';\r\n\r\n constructor(\r\n public readonly questionId: QuestionId,\r\n public readonly answerId: AnswerId,\r\n public readonly answeredByMemberId: MemberId,\r\n public readonly contentPreview: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return QuestionAnsweredEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n questionId: this.questionId,\r\n answerId: this.answerId,\r\n answeredByMemberId: this.answeredByMemberId,\r\n contentPreview: this.contentPreview,\r\n };\r\n }\r\n}\r\n","/**\r\n * ReplyQuestion Use Case\r\n * Handles replying to a question\r\n * @module application/use-cases/reply-question\r\n */\r\n\r\nimport type { ReplyQuestionInput, ReplyQuestionOutput } from '../dtos/reply-question.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { Answer } from '../../domain/entities/answer.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { QuestionAnsweredEvent } from '../../domain/events/question-answered.event.js';\r\nimport { generateAnswerId } from '../../shared/utils/id-generator.js';\r\nimport {\r\n MemberNotFoundError,\r\n QuestionNotFoundError,\r\n QuestionAlreadyAnsweredError,\r\n} from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: QuestionAnsweredEvent) => void | Promise<void>;\r\n\r\n/**\r\n * Answer repository interface (simplified for this use case)\r\n */\r\nexport interface IAnswerRepository {\r\n save(answer: Answer): Promise<void>;\r\n}\r\n\r\n/**\r\n * ReplyQuestion use case dependencies\r\n */\r\nexport interface ReplyQuestionDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n readonly answerRepository: IAnswerRepository;\r\n readonly onQuestionAnswered?: EventHandler;\r\n}\r\n\r\n/**\r\n * ReplyQuestion use case\r\n * Creates an answer to a question\r\n */\r\nexport class ReplyQuestionUseCase {\r\n constructor(private readonly deps: ReplyQuestionDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: ReplyQuestionInput): Promise<ReplyQuestionOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.fromMemberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.fromMemberId);\r\n }\r\n\r\n // Validate question exists\r\n const question = await this.deps.questionRepository.findById(input.questionId);\r\n if (!question) {\r\n throw new QuestionNotFoundError(input.questionId);\r\n }\r\n\r\n // Check if question can be answered\r\n if (!question.canBeAnswered) {\r\n throw new QuestionAlreadyAnsweredError(input.questionId);\r\n }\r\n\r\n // Create message content\r\n const content = MessageContent.create(input.content, input.format ?? 'markdown');\r\n\r\n // Create answer\r\n const answerId = generateAnswerId();\r\n const answer = Answer.create({\r\n id: answerId,\r\n questionId: input.questionId,\r\n fromMemberId: input.fromMemberId,\r\n content,\r\n createdAt: new Date(),\r\n });\r\n\r\n // Mark question as answered\r\n question.markAsAnswered(input.fromMemberId);\r\n\r\n // Save answer and update question\r\n await this.deps.answerRepository.save(answer);\r\n await this.deps.questionRepository.save(question);\r\n\r\n // Record member activity\r\n member.recordActivity();\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Emit event\r\n if (this.deps.onQuestionAnswered) {\r\n const event = new QuestionAnsweredEvent(\r\n input.questionId,\r\n answerId,\r\n input.fromMemberId,\r\n content.preview\r\n );\r\n await this.deps.onQuestionAnswered(event);\r\n }\r\n\r\n return {\r\n answerId,\r\n questionId: input.questionId,\r\n deliveredToMemberId: question.fromMemberId,\r\n createdAt: answer.createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * In-Memory Member Repository\r\n * @module infrastructure/repositories/in-memory-member\r\n */\r\n\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { Member } from '../../domain/entities/member.entity.js';\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IMemberRepository\r\n */\r\nexport class InMemoryMemberRepository implements IMemberRepository {\r\n private readonly members = new Map<MemberId, Member>();\r\n\r\n async save(member: Member): Promise<void> {\r\n this.members.set(member.id, member);\r\n }\r\n\r\n async findById(id: MemberId): Promise<Member | null> {\r\n return this.members.get(id) ?? null;\r\n }\r\n\r\n async findByTeamId(teamId: TeamId): Promise<Member[]> {\r\n return [...this.members.values()].filter((m) => m.teamId === teamId);\r\n }\r\n\r\n async findOnlineByTeamId(teamId: TeamId): Promise<Member[]> {\r\n return [...this.members.values()].filter((m) => m.teamId === teamId && m.isOnline);\r\n }\r\n\r\n async delete(id: MemberId): Promise<boolean> {\r\n return this.members.delete(id);\r\n }\r\n\r\n async exists(id: MemberId): Promise<boolean> {\r\n return this.members.has(id);\r\n }\r\n\r\n async findAll(): Promise<Member[]> {\r\n return [...this.members.values()];\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.members.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of members\r\n */\r\n get count(): number {\r\n return this.members.size;\r\n }\r\n}\r\n","/**\r\n * Team Entity\r\n * Represents a communication channel for a group of members\r\n * @module domain/entities/team\r\n */\r\n\r\nimport type { TeamId, MemberId } from '../../shared/types/branded-types.js';\r\nimport type { Member } from './member.entity.js';\r\n\r\n/**\r\n * Properties required to create a Team\r\n */\r\nexport interface TeamProps {\r\n readonly id: TeamId;\r\n readonly name: string;\r\n readonly createdAt: Date;\r\n}\r\n\r\n/**\r\n * Team entity - a communication channel\r\n */\r\nexport class Team {\r\n private readonly _id: TeamId;\r\n private readonly _name: string;\r\n private readonly _createdAt: Date;\r\n private readonly _memberIds: Set<MemberId>;\r\n\r\n private constructor(props: TeamProps) {\r\n this._id = props.id;\r\n this._name = props.name;\r\n this._createdAt = props.createdAt;\r\n this._memberIds = new Set();\r\n }\r\n\r\n /**\r\n * Creates a new Team instance\r\n */\r\n public static create(props: TeamProps): Team {\r\n if (!props.name.trim()) {\r\n throw new Error('Team name cannot be empty');\r\n }\r\n return new Team(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes a Team from persistence\r\n */\r\n public static reconstitute(props: TeamProps & { memberIds: MemberId[] }): Team {\r\n const team = new Team(props);\r\n for (const memberId of props.memberIds) {\r\n team._memberIds.add(memberId);\r\n }\r\n return team;\r\n }\r\n\r\n // Getters\r\n public get id(): TeamId {\r\n return this._id;\r\n }\r\n\r\n public get name(): string {\r\n return this._name;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n public get memberIds(): ReadonlySet<MemberId> {\r\n return this._memberIds;\r\n }\r\n\r\n public get memberCount(): number {\r\n return this._memberIds.size;\r\n }\r\n\r\n public get isEmpty(): boolean {\r\n return this._memberIds.size === 0;\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Adds a member to the team\r\n * @returns true if the member was added, false if already present\r\n */\r\n public addMember(memberId: MemberId): boolean {\r\n if (this._memberIds.has(memberId)) {\r\n return false;\r\n }\r\n this._memberIds.add(memberId);\r\n return true;\r\n }\r\n\r\n /**\r\n * Removes a member from the team\r\n * @returns true if the member was removed, false if not present\r\n */\r\n public removeMember(memberId: MemberId): boolean {\r\n return this._memberIds.delete(memberId);\r\n }\r\n\r\n /**\r\n * Checks if a member is in the team\r\n */\r\n public hasMember(memberId: MemberId): boolean {\r\n return this._memberIds.has(memberId);\r\n }\r\n\r\n /**\r\n * Gets all member IDs except the specified one\r\n * Useful for broadcasting to other team members\r\n */\r\n public getOtherMemberIds(excludeMemberId: MemberId): MemberId[] {\r\n return [...this._memberIds].filter((id) => id !== excludeMemberId);\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): TeamProps & { memberIds: MemberId[] } {\r\n return {\r\n id: this._id,\r\n name: this._name,\r\n createdAt: this._createdAt,\r\n memberIds: [...this._memberIds],\r\n };\r\n }\r\n}\r\n","/**\r\n * In-Memory Team Repository\r\n * @module infrastructure/repositories/in-memory-team\r\n */\r\n\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { Team } from '../../domain/entities/team.entity.js';\r\nimport type { TeamId } from '../../shared/types/branded-types.js';\r\nimport { Team as TeamEntity } from '../../domain/entities/team.entity.js';\r\nimport { createTeamId } from '../../shared/utils/id-generator.js';\r\n\r\n/**\r\n * In-memory implementation of ITeamRepository\r\n */\r\nexport class InMemoryTeamRepository implements ITeamRepository {\r\n private readonly teams = new Map<TeamId, Team>();\r\n\r\n async save(team: Team): Promise<void> {\r\n this.teams.set(team.id, team);\r\n }\r\n\r\n async findById(id: TeamId): Promise<Team | null> {\r\n return this.teams.get(id) ?? null;\r\n }\r\n\r\n async findByName(name: string): Promise<Team | null> {\r\n const teamId = createTeamId(name);\r\n return this.teams.get(teamId) ?? null;\r\n }\r\n\r\n async getOrCreate(name: string): Promise<Team> {\r\n const existing = await this.findByName(name);\r\n if (existing) {\r\n return existing;\r\n }\r\n\r\n const teamId = createTeamId(name);\r\n const team = TeamEntity.create({\r\n id: teamId,\r\n name: name.trim(),\r\n createdAt: new Date(),\r\n });\r\n\r\n await this.save(team);\r\n return team;\r\n }\r\n\r\n async delete(id: TeamId): Promise<boolean> {\r\n return this.teams.delete(id);\r\n }\r\n\r\n async exists(id: TeamId): Promise<boolean> {\r\n return this.teams.has(id);\r\n }\r\n\r\n async findAll(): Promise<Team[]> {\r\n return [...this.teams.values()];\r\n }\r\n\r\n async findNonEmpty(): Promise<Team[]> {\r\n return [...this.teams.values()].filter((t) => !t.isEmpty);\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.teams.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of teams\r\n */\r\n get count(): number {\r\n return this.teams.size;\r\n }\r\n}\r\n","/**\r\n * In-Memory Question Repository\r\n * @module infrastructure/repositories/in-memory-question\r\n */\r\n\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport type { Question } from '../../domain/entities/question.entity.js';\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IQuestionRepository\r\n */\r\nexport class InMemoryQuestionRepository implements IQuestionRepository {\r\n private readonly questions = new Map<QuestionId, Question>();\r\n\r\n async save(question: Question): Promise<void> {\r\n this.questions.set(question.id, question);\r\n }\r\n\r\n async findById(id: QuestionId): Promise<Question | null> {\r\n return this.questions.get(id) ?? null;\r\n }\r\n\r\n async findPendingByTeamId(teamId: TeamId): Promise<Question[]> {\r\n return [...this.questions.values()].filter((q) => q.toTeamId === teamId && q.isPending);\r\n }\r\n\r\n async findByFromMemberId(memberId: MemberId): Promise<Question[]> {\r\n return [...this.questions.values()].filter((q) => q.fromMemberId === memberId);\r\n }\r\n\r\n async findPendingByFromMemberId(memberId: MemberId): Promise<Question[]> {\r\n return [...this.questions.values()].filter(\r\n (q) => q.fromMemberId === memberId && q.isPending\r\n );\r\n }\r\n\r\n async delete(id: QuestionId): Promise<boolean> {\r\n return this.questions.delete(id);\r\n }\r\n\r\n async exists(id: QuestionId): Promise<boolean> {\r\n return this.questions.has(id);\r\n }\r\n\r\n async findAll(): Promise<Question[]> {\r\n return [...this.questions.values()];\r\n }\r\n\r\n async markTimedOut(olderThanMs: number): Promise<number> {\r\n let count = 0;\r\n const now = Date.now();\r\n\r\n for (const question of this.questions.values()) {\r\n if (question.isPending && now - question.createdAt.getTime() > olderThanMs) {\r\n question.markAsTimedOut();\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.questions.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of questions\r\n */\r\n get count(): number {\r\n return this.questions.size;\r\n }\r\n}\r\n","/**\r\n * In-Memory Answer Repository\r\n * @module infrastructure/repositories/in-memory-answer\r\n */\r\n\r\nimport type { IAnswerRepository } from '../../application/use-cases/reply-question.use-case.js';\r\nimport type { Answer } from '../../domain/entities/answer.entity.js';\r\nimport type { AnswerId, QuestionId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IAnswerRepository\r\n */\r\nexport class InMemoryAnswerRepository implements IAnswerRepository {\r\n private readonly answers = new Map<AnswerId, Answer>();\r\n\r\n async save(answer: Answer): Promise<void> {\r\n this.answers.set(answer.id, answer);\r\n }\r\n\r\n async findById(id: AnswerId): Promise<Answer | null> {\r\n return this.answers.get(id) ?? null;\r\n }\r\n\r\n async findByQuestionId(questionId: QuestionId): Promise<Answer | null> {\r\n for (const answer of this.answers.values()) {\r\n if (answer.questionId === questionId) {\r\n return answer;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n async findAll(): Promise<Answer[]> {\r\n return [...this.answers.values()];\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.answers.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of answers\r\n */\r\n get count(): number {\r\n return this.answers.size;\r\n }\r\n}\r\n","/**\r\n * WebSocket Message Protocol\r\n * Defines the message format between Hub and Clients\r\n * @module infrastructure/websocket/message-protocol\r\n */\r\n\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport type { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport type { QuestionStatus } from '../../domain/entities/question.entity.js';\r\n\r\n// ============================================================================\r\n// Client → Hub Messages\r\n// ============================================================================\r\n\r\nexport type ClientMessageType = 'JOIN' | 'LEAVE' | 'ASK' | 'REPLY' | 'PING' | 'GET_INBOX';\r\n\r\nexport interface JoinMessage {\r\n type: 'JOIN';\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport interface LeaveMessage {\r\n type: 'LEAVE';\r\n}\r\n\r\nexport interface AskMessage {\r\n type: 'ASK';\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string; // For correlating response\r\n}\r\n\r\nexport interface ReplyMessage {\r\n type: 'REPLY';\r\n questionId: QuestionId;\r\n content: string;\r\n format: MessageFormat;\r\n}\r\n\r\nexport interface PingMessage {\r\n type: 'PING';\r\n}\r\n\r\nexport interface GetInboxMessage {\r\n type: 'GET_INBOX';\r\n requestId: string;\r\n}\r\n\r\nexport type ClientMessage =\r\n | JoinMessage\r\n | LeaveMessage\r\n | AskMessage\r\n | ReplyMessage\r\n | PingMessage\r\n | GetInboxMessage;\r\n\r\n// ============================================================================\r\n// Hub → Client Messages\r\n// ============================================================================\r\n\r\nexport type HubMessageType =\r\n | 'JOINED'\r\n | 'LEFT'\r\n | 'MEMBER_JOINED'\r\n | 'MEMBER_LEFT'\r\n | 'QUESTION'\r\n | 'ANSWER'\r\n | 'QUESTION_SENT'\r\n | 'INBOX'\r\n | 'PONG'\r\n | 'ERROR';\r\n\r\nexport interface MemberInfo {\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n teamName: string;\r\n displayName: string;\r\n status: MemberStatus;\r\n}\r\n\r\nexport interface JoinedMessage {\r\n type: 'JOINED';\r\n member: MemberInfo;\r\n memberCount: number;\r\n}\r\n\r\nexport interface LeftMessage {\r\n type: 'LEFT';\r\n memberId: MemberId;\r\n}\r\n\r\nexport interface MemberJoinedMessage {\r\n type: 'MEMBER_JOINED';\r\n member: MemberInfo;\r\n}\r\n\r\nexport interface MemberLeftMessage {\r\n type: 'MEMBER_LEFT';\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n}\r\n\r\nexport interface QuestionMessage {\r\n type: 'QUESTION';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: string;\r\n}\r\n\r\nexport interface AnswerMessage {\r\n type: 'ANSWER';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n requestId?: string; // Correlates with original ASK request\r\n}\r\n\r\nexport interface QuestionSentMessage {\r\n type: 'QUESTION_SENT';\r\n questionId: QuestionId;\r\n toTeamId: TeamId;\r\n status: QuestionStatus;\r\n requestId: string;\r\n}\r\n\r\nexport interface InboxQuestionInfo {\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n status: QuestionStatus;\r\n createdAt: string;\r\n ageMs: number;\r\n}\r\n\r\nexport interface InboxMessage {\r\n type: 'INBOX';\r\n questions: InboxQuestionInfo[];\r\n totalCount: number;\r\n pendingCount: number;\r\n requestId: string;\r\n}\r\n\r\nexport interface PongMessage {\r\n type: 'PONG';\r\n timestamp: string;\r\n}\r\n\r\nexport interface ErrorMessage {\r\n type: 'ERROR';\r\n code: string;\r\n message: string;\r\n requestId?: string;\r\n}\r\n\r\nexport type HubMessage =\r\n | JoinedMessage\r\n | LeftMessage\r\n | MemberJoinedMessage\r\n | MemberLeftMessage\r\n | QuestionMessage\r\n | AnswerMessage\r\n | QuestionSentMessage\r\n | InboxMessage\r\n | PongMessage\r\n | ErrorMessage;\r\n\r\n// ============================================================================\r\n// Serialization Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Serializes a message to JSON string\r\n */\r\nexport function serializeMessage<T extends ClientMessage | HubMessage>(message: T): string {\r\n return JSON.stringify(message);\r\n}\r\n\r\n/**\r\n * Parses a client message from JSON string\r\n */\r\nexport function parseClientMessage(data: string): ClientMessage {\r\n const parsed = JSON.parse(data) as ClientMessage;\r\n validateClientMessage(parsed);\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Parses a hub message from JSON string\r\n */\r\nexport function parseHubMessage(data: string): HubMessage {\r\n return JSON.parse(data) as HubMessage;\r\n}\r\n\r\n/**\r\n * Validates a client message\r\n */\r\nfunction validateClientMessage(message: ClientMessage): void {\r\n if (!message.type) {\r\n throw new Error('Message must have a type');\r\n }\r\n\r\n const validTypes: ClientMessageType[] = ['JOIN', 'LEAVE', 'ASK', 'REPLY', 'PING', 'GET_INBOX'];\r\n if (!validTypes.includes(message.type)) {\r\n throw new Error(`Invalid message type: ${message.type}`);\r\n }\r\n}\r\n\r\n/**\r\n * Creates an error message\r\n */\r\nexport function createErrorMessage(\r\n code: string,\r\n message: string,\r\n requestId?: string\r\n): ErrorMessage {\r\n return {\r\n type: 'ERROR',\r\n code,\r\n message,\r\n requestId,\r\n };\r\n}\r\n","/**\r\n * WebSocket Hub Server\r\n * Central server that manages client connections and message routing\r\n * @module infrastructure/websocket/hub-server\r\n */\r\n\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { Member } from '../../domain/entities/member.entity.js';\r\nimport type { Question } from '../../domain/entities/question.entity.js';\r\nimport { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport { QuestionStatus } from '../../domain/entities/question.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { JoinTeamUseCase } from '../../application/use-cases/join-team.use-case.js';\r\nimport { AskQuestionUseCase } from '../../application/use-cases/ask-question.use-case.js';\r\nimport { GetInboxUseCase } from '../../application/use-cases/get-inbox.use-case.js';\r\nimport { ReplyQuestionUseCase } from '../../application/use-cases/reply-question.use-case.js';\r\nimport { InMemoryMemberRepository } from '../repositories/in-memory-member.repository.js';\r\nimport { InMemoryTeamRepository } from '../repositories/in-memory-team.repository.js';\r\nimport { InMemoryQuestionRepository } from '../repositories/in-memory-question.repository.js';\r\nimport { InMemoryAnswerRepository } from '../repositories/in-memory-answer.repository.js';\r\nimport { config } from '../../config/index.js';\r\nimport {\r\n type ClientMessage,\r\n type HubMessage,\r\n type MemberInfo,\r\n parseClientMessage,\r\n serializeMessage,\r\n createErrorMessage,\r\n} from './message-protocol.js';\r\n\r\n/**\r\n * Log helper with timestamp\r\n */\r\nfunction log(level: 'INFO' | 'ERROR' | 'WARN' | 'DEBUG', message: string, data?: unknown): void {\r\n const timestamp = new Date().toISOString();\r\n const prefix = `[${timestamp}] [HUB-${level}]`;\r\n\r\n if (data) {\r\n console.log(`${prefix} ${message}`, JSON.stringify(data, null, 2));\r\n } else {\r\n console.log(`${prefix} ${message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Client connection state\r\n */\r\ninterface ClientConnection {\r\n ws: WebSocket;\r\n memberId?: MemberId;\r\n teamId?: TeamId;\r\n lastPing: Date;\r\n}\r\n\r\n/**\r\n * Hub server options\r\n */\r\nexport interface HubServerOptions {\r\n port?: number;\r\n host?: string;\r\n}\r\n\r\n/**\r\n * WebSocket Hub Server\r\n */\r\nexport class HubServer {\r\n private wss: WebSocketServer | null = null;\r\n private readonly clients = new Map<WebSocket, ClientConnection>();\r\n private readonly memberToWs = new Map<MemberId, WebSocket>();\r\n\r\n // Repositories\r\n private readonly memberRepository = new InMemoryMemberRepository();\r\n private readonly teamRepository = new InMemoryTeamRepository();\r\n private readonly questionRepository = new InMemoryQuestionRepository();\r\n private readonly answerRepository = new InMemoryAnswerRepository();\r\n\r\n // Use cases\r\n private joinTeamUseCase!: JoinTeamUseCase;\r\n private askQuestionUseCase!: AskQuestionUseCase;\r\n private getInboxUseCase!: GetInboxUseCase;\r\n private replyQuestionUseCase!: ReplyQuestionUseCase;\r\n\r\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\r\n private timeoutCheckInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n constructor(private readonly options: HubServerOptions = {}) {\r\n this.initializeUseCases();\r\n }\r\n\r\n private initializeUseCases(): void {\r\n this.joinTeamUseCase = new JoinTeamUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n onMemberJoined: async (event) => {\r\n await this.broadcastToTeam(event.teamId, event.memberId, {\r\n type: 'MEMBER_JOINED',\r\n member: await this.getMemberInfo(event.memberId),\r\n });\r\n },\r\n });\r\n\r\n this.askQuestionUseCase = new AskQuestionUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n questionRepository: this.questionRepository,\r\n onQuestionAsked: async (event) => {\r\n const question = await this.questionRepository.findById(event.questionId);\r\n if (question) {\r\n await this.deliverQuestion(question);\r\n }\r\n },\r\n });\r\n\r\n this.getInboxUseCase = new GetInboxUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n questionRepository: this.questionRepository,\r\n });\r\n\r\n this.replyQuestionUseCase = new ReplyQuestionUseCase({\r\n memberRepository: this.memberRepository,\r\n questionRepository: this.questionRepository,\r\n answerRepository: this.answerRepository,\r\n onQuestionAnswered: async (event) => {\r\n const question = await this.questionRepository.findById(event.questionId);\r\n const answer = await this.answerRepository.findByQuestionId(event.questionId);\r\n if (question && answer) {\r\n await this.deliverAnswer(question, answer, event.answeredByMemberId);\r\n }\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Starts the hub server\r\n */\r\n async start(): Promise<void> {\r\n const port = this.options.port ?? config.hub.port;\r\n const host = this.options.host ?? config.hub.host;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n this.wss = new WebSocketServer({ port, host });\r\n\r\n this.wss.on('connection', (ws) => {\r\n this.handleConnection(ws);\r\n });\r\n\r\n this.wss.on('error', (error) => {\r\n log('ERROR', 'Hub server error', { error: error.message, stack: error.stack });\r\n reject(error);\r\n });\r\n\r\n this.wss.on('listening', () => {\r\n log('INFO', `Hub server started successfully`, { host, port });\r\n this.startHeartbeat();\r\n this.startTimeoutCheck();\r\n resolve();\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Stops the hub server\r\n */\r\n async stop(): Promise<void> {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n this.heartbeatInterval = null;\r\n }\r\n\r\n if (this.timeoutCheckInterval) {\r\n clearInterval(this.timeoutCheckInterval);\r\n this.timeoutCheckInterval = null;\r\n }\r\n\r\n return new Promise((resolve) => {\r\n if (this.wss) {\r\n // Close all client connections\r\n for (const [ws] of this.clients) {\r\n ws.close();\r\n }\r\n this.clients.clear();\r\n this.memberToWs.clear();\r\n\r\n this.wss.close(() => {\r\n this.wss = null;\r\n log('INFO', 'Hub server stopped gracefully');\r\n resolve();\r\n });\r\n } else {\r\n resolve();\r\n }\r\n });\r\n }\r\n\r\n private handleConnection(ws: WebSocket): void {\r\n const connection: ClientConnection = {\r\n ws,\r\n lastPing: new Date(),\r\n };\r\n this.clients.set(ws, connection);\r\n\r\n log('INFO', 'New client connected', { totalClients: this.clients.size });\r\n\r\n ws.on('message', async (data) => {\r\n await this.handleMessage(ws, data.toString());\r\n });\r\n\r\n ws.on('close', async () => {\r\n await this.handleDisconnect(ws);\r\n });\r\n\r\n ws.on('error', (error) => {\r\n log('ERROR', 'Client connection error', { error: error.message });\r\n });\r\n }\r\n\r\n private async handleMessage(ws: WebSocket, data: string): Promise<void> {\r\n const connection = this.clients.get(ws);\r\n if (!connection) return;\r\n\r\n try {\r\n const message = parseClientMessage(data);\r\n connection.lastPing = new Date();\r\n\r\n log('DEBUG', `Received message from client`, {\r\n type: message.type,\r\n memberId: connection.memberId,\r\n });\r\n\r\n switch (message.type) {\r\n case 'JOIN':\r\n await this.handleJoin(ws, connection, message.teamName, message.displayName);\r\n break;\r\n case 'LEAVE':\r\n await this.handleLeave(ws, connection);\r\n break;\r\n case 'ASK':\r\n await this.handleAsk(ws, connection, message);\r\n break;\r\n case 'REPLY':\r\n await this.handleReply(ws, connection, message);\r\n break;\r\n case 'GET_INBOX':\r\n await this.handleGetInbox(ws, connection, message.requestId);\r\n break;\r\n case 'PING':\r\n this.send(ws, { type: 'PONG', timestamp: new Date().toISOString() });\r\n break;\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n log('ERROR', 'Failed to handle message', {\r\n error: errorMessage,\r\n memberId: connection.memberId,\r\n });\r\n this.send(ws, createErrorMessage('INVALID_MESSAGE', errorMessage));\r\n }\r\n }\r\n\r\n private async handleJoin(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n teamName: string,\r\n displayName: string\r\n ): Promise<void> {\r\n try {\r\n log('INFO', 'Member attempting to join', { teamName, displayName });\r\n\r\n const result = await this.joinTeamUseCase.execute({ teamName, displayName });\r\n\r\n connection.memberId = result.memberId;\r\n connection.teamId = result.teamId;\r\n this.memberToWs.set(result.memberId, ws);\r\n\r\n const memberInfo = await this.getMemberInfo(result.memberId);\r\n this.send(ws, {\r\n type: 'JOINED',\r\n member: memberInfo,\r\n memberCount: result.memberCount,\r\n });\r\n\r\n log('INFO', 'Member joined successfully', {\r\n memberId: result.memberId,\r\n teamName,\r\n displayName,\r\n memberCount: result.memberCount,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Join failed';\r\n log('ERROR', 'Member join failed', { teamName, displayName, error: errorMessage });\r\n this.send(ws, createErrorMessage('JOIN_FAILED', errorMessage));\r\n }\r\n }\r\n\r\n private async handleLeave(ws: WebSocket, connection: ClientConnection): Promise<void> {\r\n if (connection.memberId && connection.teamId) {\r\n await this.removeMember(connection.memberId, connection.teamId);\r\n connection.memberId = undefined;\r\n connection.teamId = undefined;\r\n }\r\n\r\n this.send(ws, { type: 'LEFT', memberId: connection.memberId! });\r\n }\r\n\r\n private async handleAsk(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n message: { toTeam: string; content: string; format: 'plain' | 'markdown'; requestId: string }\r\n ): Promise<void> {\r\n if (!connection.memberId) {\r\n log('WARN', 'ASK attempt without joining team', { toTeam: message.toTeam });\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first', message.requestId));\r\n return;\r\n }\r\n\r\n try {\r\n log('INFO', 'Question asked', {\r\n fromMemberId: connection.memberId,\r\n toTeam: message.toTeam,\r\n contentPreview: message.content.substring(0, 50) + '...',\r\n });\r\n\r\n const result = await this.askQuestionUseCase.execute({\r\n fromMemberId: connection.memberId,\r\n toTeamName: message.toTeam,\r\n content: message.content,\r\n format: message.format,\r\n });\r\n\r\n this.send(ws, {\r\n type: 'QUESTION_SENT',\r\n questionId: result.questionId,\r\n toTeamId: result.toTeamId,\r\n status: result.status,\r\n requestId: message.requestId,\r\n });\r\n\r\n log('INFO', 'Question sent successfully', {\r\n questionId: result.questionId,\r\n fromMemberId: connection.memberId,\r\n toTeamId: result.toTeamId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Ask failed';\r\n log('ERROR', 'Question failed', {\r\n fromMemberId: connection.memberId,\r\n toTeam: message.toTeam,\r\n error: errorMessage,\r\n });\r\n this.send(ws, createErrorMessage('ASK_FAILED', errorMessage, message.requestId));\r\n }\r\n }\r\n\r\n private async handleReply(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n message: { questionId: QuestionId; content: string; format: 'plain' | 'markdown' }\r\n ): Promise<void> {\r\n if (!connection.memberId) {\r\n log('WARN', 'REPLY attempt without joining team', { questionId: message.questionId });\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first'));\r\n return;\r\n }\r\n\r\n try {\r\n log('INFO', 'Reply received', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n contentPreview: message.content.substring(0, 50) + '...',\r\n });\r\n\r\n await this.replyQuestionUseCase.execute({\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n content: message.content,\r\n format: message.format,\r\n });\r\n\r\n log('INFO', 'Reply delivered successfully', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Reply failed';\r\n log('ERROR', 'Reply failed', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n error: errorMessage,\r\n });\r\n this.send(ws, createErrorMessage('REPLY_FAILED', errorMessage));\r\n }\r\n }\r\n\r\n private async handleGetInbox(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n requestId: string\r\n ): Promise<void> {\r\n if (!connection.memberId || !connection.teamId) {\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first', requestId));\r\n return;\r\n }\r\n\r\n try {\r\n const result = await this.getInboxUseCase.execute({\r\n memberId: connection.memberId,\r\n teamId: connection.teamId,\r\n });\r\n\r\n const questions = await Promise.all(\r\n result.questions.map(async (q) => ({\r\n questionId: q.questionId,\r\n from: await this.getMemberInfo(q.fromMemberId),\r\n content: q.content,\r\n format: q.format,\r\n status: q.status as QuestionStatus,\r\n createdAt: q.createdAt.toISOString(),\r\n ageMs: q.ageMs,\r\n }))\r\n );\r\n\r\n this.send(ws, {\r\n type: 'INBOX',\r\n questions,\r\n totalCount: result.totalCount,\r\n pendingCount: result.pendingCount,\r\n requestId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Get inbox failed';\r\n this.send(ws, createErrorMessage('INBOX_FAILED', errorMessage, requestId));\r\n }\r\n }\r\n\r\n private async handleDisconnect(ws: WebSocket): Promise<void> {\r\n const connection = this.clients.get(ws);\r\n if (connection?.memberId && connection.teamId) {\r\n log('INFO', 'Client disconnecting', {\r\n memberId: connection.memberId,\r\n teamId: connection.teamId,\r\n });\r\n await this.removeMember(connection.memberId, connection.teamId);\r\n this.memberToWs.delete(connection.memberId);\r\n }\r\n this.clients.delete(ws);\r\n log('INFO', 'Client disconnected', { totalClients: this.clients.size });\r\n }\r\n\r\n private async removeMember(memberId: MemberId, teamId: TeamId): Promise<void> {\r\n const member = await this.memberRepository.findById(memberId);\r\n if (member) {\r\n member.goOffline();\r\n await this.memberRepository.save(member);\r\n }\r\n\r\n const team = await this.teamRepository.findById(teamId);\r\n if (team) {\r\n team.removeMember(memberId);\r\n await this.teamRepository.save(team);\r\n\r\n // Notify other team members\r\n await this.broadcastToTeam(teamId, memberId, {\r\n type: 'MEMBER_LEFT',\r\n memberId,\r\n teamId,\r\n });\r\n }\r\n }\r\n\r\n private async deliverQuestion(question: Question): Promise<void> {\r\n const team = await this.teamRepository.findById(question.toTeamId);\r\n if (!team) {\r\n log('WARN', 'Cannot deliver question - team not found', { toTeamId: question.toTeamId });\r\n return;\r\n }\r\n\r\n const fromMember = await this.memberRepository.findById(question.fromMemberId);\r\n if (!fromMember) {\r\n log('WARN', 'Cannot deliver question - from member not found', {\r\n fromMemberId: question.fromMemberId,\r\n });\r\n return;\r\n }\r\n\r\n const memberInfo = await this.getMemberInfo(question.fromMemberId);\r\n\r\n let deliveredCount = 0;\r\n for (const memberId of team.memberIds) {\r\n const ws = this.memberToWs.get(memberId);\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n this.send(ws, {\r\n type: 'QUESTION',\r\n questionId: question.id,\r\n from: memberInfo,\r\n content: question.content.text,\r\n format: question.content.format,\r\n createdAt: question.createdAt.toISOString(),\r\n });\r\n deliveredCount++;\r\n }\r\n }\r\n\r\n log('INFO', 'Question delivered to team', {\r\n questionId: question.id,\r\n toTeamId: question.toTeamId,\r\n teamSize: team.memberIds.size,\r\n deliveredCount,\r\n });\r\n }\r\n\r\n private async deliverAnswer(\r\n question: Question,\r\n answer: { content: MessageContent; createdAt: Date },\r\n answeredByMemberId: MemberId\r\n ): Promise<void> {\r\n const ws = this.memberToWs.get(question.fromMemberId);\r\n if (!ws || ws.readyState !== WebSocket.OPEN) {\r\n log('WARN', 'Cannot deliver answer - questioner not connected', {\r\n questionId: question.id,\r\n fromMemberId: question.fromMemberId,\r\n });\r\n return;\r\n }\r\n\r\n const memberInfo = await this.getMemberInfo(answeredByMemberId);\r\n\r\n this.send(ws, {\r\n type: 'ANSWER',\r\n questionId: question.id,\r\n from: memberInfo,\r\n content: answer.content.text,\r\n format: answer.content.format,\r\n answeredAt: answer.createdAt.toISOString(),\r\n });\r\n\r\n log('INFO', 'Answer delivered', {\r\n questionId: question.id,\r\n answeredBy: answeredByMemberId,\r\n deliveredTo: question.fromMemberId,\r\n });\r\n }\r\n\r\n private async broadcastToTeam(\r\n teamId: TeamId,\r\n excludeMemberId: MemberId,\r\n message: HubMessage\r\n ): Promise<void> {\r\n const team = await this.teamRepository.findById(teamId);\r\n if (!team) return;\r\n\r\n for (const memberId of team.getOtherMemberIds(excludeMemberId)) {\r\n const ws = this.memberToWs.get(memberId);\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n this.send(ws, message);\r\n }\r\n }\r\n }\r\n\r\n private async getMemberInfo(memberId: MemberId): Promise<MemberInfo> {\r\n const member = await this.memberRepository.findById(memberId);\r\n const team = member ? await this.teamRepository.findById(member.teamId) : null;\r\n\r\n return {\r\n memberId,\r\n teamId: member?.teamId ?? ('' as TeamId),\r\n teamName: team?.name ?? 'Unknown',\r\n displayName: member?.displayName ?? 'Unknown',\r\n status: member?.status ?? MemberStatus.OFFLINE,\r\n };\r\n }\r\n\r\n private send(ws: WebSocket, message: HubMessage): void {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(serializeMessage(message));\r\n }\r\n }\r\n\r\n private startHeartbeat(): void {\r\n this.heartbeatInterval = setInterval(() => {\r\n const now = new Date();\r\n for (const [ws, connection] of this.clients) {\r\n const timeSinceLastPing = now.getTime() - connection.lastPing.getTime();\r\n if (timeSinceLastPing > config.hub.clientTimeout) {\r\n ws.terminate();\r\n }\r\n }\r\n }, config.hub.heartbeatInterval);\r\n }\r\n\r\n private startTimeoutCheck(): void {\r\n this.timeoutCheckInterval = setInterval(async () => {\r\n await this.questionRepository.markTimedOut(config.communication.defaultTimeout);\r\n }, 5000);\r\n }\r\n\r\n /**\r\n * Gets the number of connected clients\r\n */\r\n get clientCount(): number {\r\n return this.clients.size;\r\n }\r\n\r\n /**\r\n * Checks if the server is running\r\n */\r\n get isRunning(): boolean {\r\n return this.wss !== null;\r\n }\r\n}\r\n","/**\r\n * WebSocket Hub Client\r\n * Client that connects to the Hub server\r\n * @module infrastructure/websocket/hub-client\r\n */\r\n\r\nimport WebSocket from 'ws';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport { config } from '../../config/index.js';\r\nimport {\r\n type ClientMessage,\r\n type HubMessage,\r\n type QuestionMessage,\r\n type AnswerMessage,\r\n type InboxMessage,\r\n type MemberInfo,\r\n serializeMessage,\r\n parseHubMessage,\r\n} from './message-protocol.js';\r\n\r\n/**\r\n * Pending request with timeout\r\n */\r\ninterface PendingRequest<T> {\r\n resolve: (value: T) => void;\r\n reject: (error: Error) => void;\r\n timeout: ReturnType<typeof setTimeout>;\r\n}\r\n\r\n/**\r\n * Hub client options\r\n */\r\nexport interface HubClientOptions {\r\n host?: string;\r\n port?: number;\r\n reconnect?: boolean;\r\n reconnectDelay?: number;\r\n maxReconnectAttempts?: number;\r\n}\r\n\r\n/**\r\n * Hub client events\r\n */\r\nexport interface HubClientEvents {\r\n onConnected?: () => void;\r\n onDisconnected?: () => void;\r\n onQuestion?: (question: QuestionMessage) => void;\r\n onAnswer?: (answer: AnswerMessage) => void;\r\n onMemberJoined?: (member: MemberInfo) => void;\r\n onMemberLeft?: (memberId: MemberId, teamId: TeamId) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * WebSocket Hub Client\r\n */\r\nexport class HubClient {\r\n private ws: WebSocket | null = null;\r\n private readonly pendingRequests = new Map<string, PendingRequest<HubMessage>>();\r\n private reconnectAttempts = 0;\r\n private isClosing = false;\r\n\r\n private memberId?: MemberId;\r\n private teamId?: TeamId;\r\n private teamName?: string;\r\n private displayName?: string;\r\n\r\n constructor(\r\n private readonly options: HubClientOptions = {},\r\n private readonly events: HubClientEvents = {}\r\n ) {}\r\n\r\n /**\r\n * Connects to the Hub server\r\n */\r\n async connect(): Promise<void> {\r\n const host = this.options.host ?? config.hub.host;\r\n const port = this.options.port ?? config.hub.port;\r\n const url = `ws://${host}:${port}`;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n this.ws = new WebSocket(url);\r\n\r\n this.ws.on('open', () => {\r\n this.reconnectAttempts = 0;\r\n this.startPingInterval();\r\n this.events.onConnected?.();\r\n resolve();\r\n });\r\n\r\n this.ws.on('message', (data) => {\r\n this.handleMessage(data.toString());\r\n });\r\n\r\n this.ws.on('close', () => {\r\n this.handleDisconnect();\r\n });\r\n\r\n this.ws.on('error', (error) => {\r\n this.events.onError?.(error);\r\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\r\n reject(error);\r\n }\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Disconnects from the Hub server\r\n */\r\n async disconnect(): Promise<void> {\r\n this.isClosing = true;\r\n\r\n if (this.memberId) {\r\n this.send({ type: 'LEAVE' });\r\n }\r\n\r\n return new Promise((resolve) => {\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n this.isClosing = false;\r\n resolve();\r\n });\r\n }\r\n\r\n /**\r\n * Joins a team\r\n */\r\n async join(teamName: string, displayName: string): Promise<MemberInfo> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'JOIN',\r\n teamName,\r\n displayName,\r\n });\r\n\r\n const response = await this.waitForResponse<{ type: 'JOINED'; member: MemberInfo }>(\r\n (msg) => msg.type === 'JOINED',\r\n 30000\r\n );\r\n\r\n this.memberId = response.member.memberId;\r\n this.teamId = response.member.teamId;\r\n this.teamName = teamName;\r\n this.displayName = displayName;\r\n\r\n return response.member;\r\n }\r\n\r\n /**\r\n * Asks a question to another team\r\n */\r\n async ask(\r\n toTeam: string,\r\n content: string,\r\n format: MessageFormat = 'markdown',\r\n timeoutMs: number = config.communication.defaultTimeout\r\n ): Promise<AnswerMessage> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'ASK',\r\n toTeam,\r\n content,\r\n format,\r\n requestId,\r\n });\r\n\r\n // Wait for QUESTION_SENT confirmation\r\n const questionSent = await this.waitForResponse<{\r\n type: 'QUESTION_SENT';\r\n questionId: QuestionId;\r\n requestId: string;\r\n }>(\r\n (msg) => msg.type === 'QUESTION_SENT' && 'requestId' in msg && msg.requestId === requestId,\r\n 5000\r\n );\r\n\r\n const questionId = questionSent.questionId;\r\n\r\n // Wait for ANSWER with matching questionId\r\n const answer = await this.waitForResponse<AnswerMessage>(\r\n (msg) => msg.type === 'ANSWER' && msg.questionId === questionId,\r\n timeoutMs\r\n );\r\n\r\n return answer;\r\n }\r\n\r\n /**\r\n * Gets the inbox (pending questions)\r\n */\r\n async getInbox(): Promise<InboxMessage> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'GET_INBOX',\r\n requestId,\r\n });\r\n\r\n return this.waitForResponse<InboxMessage>(\r\n (msg) => msg.type === 'INBOX' && msg.requestId === requestId,\r\n 5000\r\n );\r\n }\r\n\r\n /**\r\n * Replies to a question\r\n */\r\n async reply(questionId: QuestionId, content: string, format: MessageFormat = 'markdown'): Promise<void> {\r\n this.send({\r\n type: 'REPLY',\r\n questionId,\r\n content,\r\n format,\r\n });\r\n }\r\n\r\n /**\r\n * Checks if connected\r\n */\r\n get isConnected(): boolean {\r\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n /**\r\n * Gets the current member ID\r\n */\r\n get currentMemberId(): MemberId | undefined {\r\n return this.memberId;\r\n }\r\n\r\n /**\r\n * Gets the current team ID\r\n */\r\n get currentTeamId(): TeamId | undefined {\r\n return this.teamId;\r\n }\r\n\r\n private send(message: ClientMessage): void {\r\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\r\n this.ws.send(serializeMessage(message));\r\n }\r\n }\r\n\r\n private handleMessage(data: string): void {\r\n try {\r\n const message = parseHubMessage(data);\r\n\r\n // Check pending requests\r\n for (const [requestId, pending] of this.pendingRequests) {\r\n // This is handled by the filter function in waitForResponse\r\n }\r\n\r\n // Handle specific message types\r\n switch (message.type) {\r\n case 'QUESTION':\r\n this.events.onQuestion?.(message);\r\n break;\r\n case 'ANSWER':\r\n this.events.onAnswer?.(message);\r\n break;\r\n case 'MEMBER_JOINED':\r\n this.events.onMemberJoined?.(message.member);\r\n break;\r\n case 'MEMBER_LEFT':\r\n this.events.onMemberLeft?.(message.memberId, message.teamId);\r\n break;\r\n case 'ERROR':\r\n this.events.onError?.(new Error(`${message.code}: ${message.message}`));\r\n break;\r\n }\r\n\r\n // Resolve any matching pending requests\r\n this.resolvePendingRequest(message);\r\n } catch (error) {\r\n console.error('Failed to parse message:', error);\r\n }\r\n }\r\n\r\n private resolvePendingRequest(message: HubMessage): void {\r\n for (const [requestId, pending] of this.pendingRequests) {\r\n // The filter is stored separately, we'll match by message type patterns\r\n this.pendingRequests.delete(requestId);\r\n clearTimeout(pending.timeout);\r\n pending.resolve(message);\r\n break; // Only resolve one request per message\r\n }\r\n }\r\n\r\n private waitForResponse<T extends HubMessage>(\r\n filter: (msg: HubMessage) => boolean,\r\n timeoutMs: number\r\n ): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const requestId = uuidv4();\r\n\r\n const timeout = setTimeout(() => {\r\n this.pendingRequests.delete(requestId);\r\n reject(new Error('Request timed out'));\r\n }, timeoutMs);\r\n\r\n // Store filter function with the pending request\r\n const pending: PendingRequest<HubMessage> & { filter: (msg: HubMessage) => boolean } = {\r\n resolve: (msg) => {\r\n if (filter(msg)) {\r\n resolve(msg as T);\r\n }\r\n },\r\n reject,\r\n timeout,\r\n filter,\r\n };\r\n\r\n this.pendingRequests.set(requestId, pending);\r\n\r\n // Override handleMessage to check this specific filter\r\n const originalHandler = this.handleMessage.bind(this);\r\n const checkFilter = (data: string): void => {\r\n try {\r\n const message = parseHubMessage(data);\r\n if (filter(message)) {\r\n this.pendingRequests.delete(requestId);\r\n clearTimeout(timeout);\r\n resolve(message as T);\r\n }\r\n } catch {\r\n // Ignore parse errors here\r\n }\r\n originalHandler(data);\r\n };\r\n\r\n // Temporarily override\r\n if (this.ws) {\r\n this.ws.removeAllListeners('message');\r\n this.ws.on('message', (data) => checkFilter(data.toString()));\r\n }\r\n });\r\n }\r\n\r\n private handleDisconnect(): void {\r\n this.events.onDisconnected?.();\r\n\r\n if (this.isClosing) return;\r\n\r\n const shouldReconnect = this.options.reconnect ?? true;\r\n const maxAttempts = this.options.maxReconnectAttempts ?? config.autoStart.maxRetries;\r\n\r\n if (shouldReconnect && this.reconnectAttempts < maxAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = this.options.reconnectDelay ?? config.autoStart.retryDelay;\r\n\r\n setTimeout(() => {\r\n this.connect()\r\n .then(() => {\r\n if (this.teamName && this.displayName) {\r\n return this.join(this.teamName, this.displayName);\r\n }\r\n })\r\n .catch((error) => {\r\n this.events.onError?.(error);\r\n });\r\n }, delay);\r\n }\r\n }\r\n\r\n private pingInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n private startPingInterval(): void {\r\n this.pingInterval = setInterval(() => {\r\n this.send({ type: 'PING' });\r\n }, config.hub.heartbeatInterval);\r\n }\r\n}\r\n","/**\r\n * Join Tool\r\n * Joins a team channel for collaboration\r\n * @module presentation/mcp/tools/join\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\n\r\n/**\r\n * Join tool input schema\r\n */\r\nconst joinSchema = {\r\n team: z.string().describe('Team name to join (e.g., \"frontend\", \"backend\", \"devops\")'),\r\n displayName: z\r\n .string()\r\n .optional()\r\n .describe('Display name for this terminal (default: team + \" Claude\")'),\r\n};\r\n\r\n/**\r\n * Registers the join tool with the MCP server\r\n */\r\nexport function registerJoinTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('join', joinSchema, async (args) => {\r\n const teamName = args.team;\r\n const displayName = args.displayName ?? `${teamName} Claude`;\r\n\r\n try {\r\n // Ensure connected to hub\r\n if (!hubClient.isConnected) {\r\n await hubClient.connect();\r\n }\r\n\r\n // Join the team\r\n const member = await hubClient.join(teamName, displayName);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Successfully joined team \"${member.teamName}\" as \"${member.displayName}\".\\n\\nYour member ID: ${member.memberId}\\nTeam ID: ${member.teamId}\\nStatus: ${member.status}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to join team: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Ask Tool\r\n * Asks a question to another team and waits for response\r\n * @module presentation/mcp/tools/ask\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\nimport { config } from '../../../config/index.js';\r\n\r\n/**\r\n * Ask tool input schema\r\n */\r\nconst askSchema = {\r\n team: z.string().describe('Target team name to ask (e.g., \"backend\", \"frontend\")'),\r\n question: z.string().describe('The question to ask (supports markdown)'),\r\n timeout: z\r\n .number()\r\n .optional()\r\n .describe(`Timeout in seconds to wait for answer (default: ${config.communication.defaultTimeout / 1000}s)`),\r\n};\r\n\r\n/**\r\n * Registers the ask tool with the MCP server\r\n */\r\nexport function registerAskTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('ask', askSchema, async (args) => {\r\n const targetTeam = args.team;\r\n const question = args.question;\r\n const timeoutMs = (args.timeout ?? config.communication.defaultTimeout / 1000) * 1000;\r\n\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Ask the question and wait for answer\r\n const answer = await hubClient.ask(targetTeam, question, 'markdown', timeoutMs);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**Answer from ${answer.from.displayName} (${answer.from.teamName}):**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n\r\n if (errorMessage.includes('timed out')) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `No response received from team \"${targetTeam}\" within ${timeoutMs / 1000} seconds. The question has been delivered but no one answered yet.`,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to ask question: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Inbox Tool\r\n * Lists pending questions directed to the current team\r\n * @module presentation/mcp/tools/inbox\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\n\r\n/**\r\n * Inbox tool input schema (no required parameters)\r\n */\r\nconst inboxSchema = {};\r\n\r\n/**\r\n * Registers the inbox tool with the MCP server\r\n */\r\nexport function registerInboxTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('inbox', inboxSchema, async () => {\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Get inbox\r\n const inbox = await hubClient.getInbox();\r\n\r\n if (inbox.questions.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'No pending questions in your inbox.',\r\n },\r\n ],\r\n };\r\n }\r\n\r\n // Format questions list\r\n const questionsList = inbox.questions\r\n .map((q, i) => {\r\n const ageSeconds = Math.floor(q.ageMs / 1000);\r\n const ageStr = ageSeconds < 60 ? `${ageSeconds}s ago` : `${Math.floor(ageSeconds / 60)}m ago`;\r\n\r\n return `### ${i + 1}. Question from ${q.from.displayName} (${q.from.teamName}) - ${ageStr}\r\n**ID:** \\`${q.questionId}\\`\r\n**Status:** ${q.status}\r\n\r\n${q.content}\r\n\r\n---`;\r\n })\r\n .join('\\n\\n');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `# Inbox (${inbox.pendingCount} pending, ${inbox.totalCount} total)\\n\\n${questionsList}\\n\\nUse the \"reply\" tool with the question ID to answer a question.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to get inbox: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Reply Tool\r\n * Replies to a pending question\r\n * @module presentation/mcp/tools/reply\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\nimport type { QuestionId } from '../../../shared/types/branded-types.js';\r\n\r\n/**\r\n * Reply tool input schema\r\n */\r\nconst replySchema = {\r\n questionId: z.string().describe('The ID of the question to reply to (from inbox)'),\r\n answer: z.string().describe('Your answer to the question (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the reply tool with the MCP server\r\n */\r\nexport function registerReplyTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('reply', replySchema, async (args) => {\r\n const questionId = args.questionId as QuestionId;\r\n const answer = args.answer;\r\n\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Send the reply\r\n await hubClient.reply(questionId, answer, 'markdown');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Reply sent successfully to question \\`${questionId}\\`.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send reply: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * MCP Server\r\n * Provides MCP tools for Claude Code integration\r\n * @module presentation/mcp/server\r\n */\r\n\r\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport type { HubClient } from '../../infrastructure/websocket/hub-client.js';\r\nimport { registerJoinTool } from './tools/join.tool.js';\r\nimport { registerAskTool } from './tools/ask.tool.js';\r\nimport { registerInboxTool } from './tools/inbox.tool.js';\r\nimport { registerReplyTool } from './tools/reply.tool.js';\r\n\r\n/**\r\n * MCP Server options\r\n */\r\nexport interface McpServerOptions {\r\n hubClient: HubClient;\r\n}\r\n\r\n/**\r\n * Creates and configures the MCP server with all tools\r\n */\r\nexport function createMcpServer(options: McpServerOptions): McpServer {\r\n const server = new McpServer({\r\n name: 'claude-collab',\r\n version: '0.1.0',\r\n });\r\n\r\n // Register all tools\r\n registerJoinTool(server, options.hubClient);\r\n registerAskTool(server, options.hubClient);\r\n registerInboxTool(server, options.hubClient);\r\n registerReplyTool(server, options.hubClient);\r\n\r\n return server;\r\n}\r\n\r\n/**\r\n * Starts the MCP server with stdio transport\r\n */\r\nexport async function startMcpServer(options: McpServerOptions): Promise<void> {\r\n const server = createMcpServer(options);\r\n const transport = new StdioServerTransport();\r\n\r\n await server.connect(transport);\r\n}\r\n","/**\r\n * Auto-Start Service\r\n * Automatically starts the Hub server if not running\r\n * @module infrastructure/hub-launcher/auto-start\r\n */\r\n\r\nimport { spawn, type ChildProcess } from 'child_process';\r\nimport { createConnection } from 'net';\r\nimport { config } from '../../config/index.js';\r\n\r\n/**\r\n * Auto-start service options\r\n */\r\nexport interface AutoStartOptions {\r\n host?: string;\r\n port?: number;\r\n maxRetries?: number;\r\n retryDelay?: number;\r\n}\r\n\r\n/**\r\n * Checks if the Hub server is running\r\n */\r\nexport async function isHubRunning(\r\n host: string = config.hub.host,\r\n port: number = config.hub.port\r\n): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const socket = createConnection({ host, port }, () => {\r\n socket.end();\r\n resolve(true);\r\n });\r\n\r\n socket.on('error', () => {\r\n resolve(false);\r\n });\r\n\r\n socket.setTimeout(1000, () => {\r\n socket.destroy();\r\n resolve(false);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Waits for the Hub server to become available\r\n */\r\nexport async function waitForHub(\r\n host: string = config.hub.host,\r\n port: number = config.hub.port,\r\n maxRetries: number = config.autoStart.maxRetries,\r\n retryDelay: number = config.autoStart.retryDelay\r\n): Promise<boolean> {\r\n for (let i = 0; i < maxRetries; i++) {\r\n if (await isHubRunning(host, port)) {\r\n return true;\r\n }\r\n await new Promise((resolve) => setTimeout(resolve, retryDelay));\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Starts the Hub server as a background process\r\n */\r\nexport function startHubProcess(options: AutoStartOptions = {}): ChildProcess {\r\n const host = options.host ?? config.hub.host;\r\n const port = options.port ?? config.hub.port;\r\n\r\n // Start hub-main.js as a detached process\r\n const hubProcess = spawn(\r\n process.execPath,\r\n [\r\n '--experimental-specifier-resolution=node',\r\n new URL('../../hub-main.js', import.meta.url).pathname,\r\n '--host',\r\n host,\r\n '--port',\r\n port.toString(),\r\n ],\r\n {\r\n detached: true,\r\n stdio: 'ignore',\r\n }\r\n );\r\n\r\n hubProcess.unref();\r\n return hubProcess;\r\n}\r\n\r\n/**\r\n * Ensures the Hub is running, starting it if necessary\r\n */\r\nexport async function ensureHubRunning(options: AutoStartOptions = {}): Promise<boolean> {\r\n const host = options.host ?? config.hub.host;\r\n const port = options.port ?? config.hub.port;\r\n const maxRetries = options.maxRetries ?? config.autoStart.maxRetries;\r\n const retryDelay = options.retryDelay ?? config.autoStart.retryDelay;\r\n\r\n // Check if already running\r\n if (await isHubRunning(host, port)) {\r\n return true;\r\n }\r\n\r\n // Try to start the hub\r\n console.log(`Hub not running. Starting hub on ${host}:${port}...`);\r\n startHubProcess({ host, port });\r\n\r\n // Wait for it to become available\r\n const isRunning = await waitForHub(host, port, maxRetries, retryDelay);\r\n\r\n if (isRunning) {\r\n console.log('Hub started successfully');\r\n } else {\r\n console.error('Failed to start hub');\r\n }\r\n\r\n return isRunning;\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * CLI entry point\r\n * Provides command-line interface for claude-collab\r\n * @module cli\r\n */\r\n\r\nimport { Command } from 'commander';\r\nimport { HubServer } from './infrastructure/websocket/hub-server.js';\r\nimport { HubClient } from './infrastructure/websocket/hub-client.js';\r\nimport { startMcpServer } from './presentation/mcp/server.js';\r\nimport { ensureHubRunning } from './infrastructure/hub-launcher/auto-start.service.js';\r\nimport { config } from './config/index.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('claude-collab')\r\n .description('Real-time team collaboration between Claude Code terminals')\r\n .version('0.1.0');\r\n\r\n// Hub commands\r\nconst hubCmd = program.command('hub').description('Hub server commands');\r\n\r\nhubCmd\r\n .command('start')\r\n .description('Start the Hub server')\r\n .option('-p, --port <port>', 'Port to listen on', String(config.hub.port))\r\n .option('--host <host>', 'Host to bind to', config.hub.host)\r\n .action(async (options: { port: string; host: string }) => {\r\n const port = parseInt(options.port, 10);\r\n const host = options.host;\r\n\r\n const server = new HubServer({ host, port });\r\n\r\n // Handle shutdown signals\r\n const shutdown = async (): Promise<void> => {\r\n console.log('\\nShutting down hub server...');\r\n await server.stop();\r\n process.exit(0);\r\n };\r\n\r\n process.on('SIGINT', shutdown);\r\n process.on('SIGTERM', shutdown);\r\n\r\n try {\r\n await server.start();\r\n console.log(`Claude Collab Hub Server running on ${host}:${port}`);\r\n } catch (error) {\r\n console.error('Failed to start hub server:', error);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// Client command\r\nprogram\r\n .command('client')\r\n .description('Start MCP client (connects to Claude Code)')\r\n .option('-t, --team <team>', 'Team to auto-join (e.g., frontend, backend)')\r\n .option('--auto-hub', 'Auto-start hub if not running', false)\r\n .option('-p, --port <port>', 'Hub port to connect to', String(config.hub.port))\r\n .option('--host <host>', 'Hub host to connect to', config.hub.host)\r\n .action(\r\n async (options: { team?: string; autoHub: boolean; port: string; host: string }) => {\r\n const port = parseInt(options.port, 10);\r\n const host = options.host;\r\n\r\n // Auto-start hub if requested\r\n if (options.autoHub) {\r\n const hubRunning = await ensureHubRunning({ host, port });\r\n if (!hubRunning) {\r\n console.error('Failed to start hub server. Exiting.');\r\n process.exit(1);\r\n }\r\n }\r\n\r\n // Create hub client\r\n const hubClient = new HubClient(\r\n { host, port, reconnect: true },\r\n {\r\n onError: (error) => {\r\n console.error('Hub client error:', error.message);\r\n },\r\n onQuestion: (question) => {\r\n console.error(`[Question received from ${question.from.displayName}]`);\r\n },\r\n }\r\n );\r\n\r\n // Connect to hub\r\n try {\r\n await hubClient.connect();\r\n\r\n // Auto-join team if specified\r\n if (options.team) {\r\n await hubClient.join(options.team, `${options.team} Claude`);\r\n console.error(`Auto-joined team: ${options.team}`);\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to connect to hub: ${errorMessage}`);\r\n console.error('Make sure the hub server is running or use --auto-hub flag.');\r\n process.exit(1);\r\n }\r\n\r\n // Start MCP server\r\n await startMcpServer({ hubClient });\r\n }\r\n );\r\n\r\nprogram.parse();\r\n"]}
|
package/dist/mcp-main.js
CHANGED
|
@@ -152,12 +152,13 @@ var HubClient = class {
|
|
|
152
152
|
format,
|
|
153
153
|
requestId
|
|
154
154
|
});
|
|
155
|
-
await this.waitForResponse(
|
|
155
|
+
const questionSent = await this.waitForResponse(
|
|
156
156
|
(msg) => msg.type === "QUESTION_SENT" && "requestId" in msg && msg.requestId === requestId,
|
|
157
157
|
5e3
|
|
158
158
|
);
|
|
159
|
+
const questionId = questionSent.questionId;
|
|
159
160
|
const answer = await this.waitForResponse(
|
|
160
|
-
(msg) => msg.type === "ANSWER",
|
|
161
|
+
(msg) => msg.type === "ANSWER" && msg.questionId === questionId,
|
|
161
162
|
timeoutMs
|
|
162
163
|
);
|
|
163
164
|
return answer;
|
package/dist/mcp-main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/index.ts","../src/infrastructure/websocket/message-protocol.ts","../src/infrastructure/websocket/hub-client.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/infrastructure/hub-launcher/auto-start.service.ts","../src/mcp-main.ts"],"names":["uuidv4","args","z"],"mappings":"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","file":"mcp-main.js","sourcesContent":["/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * WebSocket Hub configuration\r\n */\r\n hub: {\r\n /**\r\n * Default port for the Hub server\r\n */\r\n port: parseInt(process.env['CLAUDE_COLLAB_PORT'] ?? '9999', 10),\r\n\r\n /**\r\n * Host to bind the Hub server to\r\n */\r\n host: process.env['CLAUDE_COLLAB_HOST'] ?? 'localhost',\r\n\r\n /**\r\n * Heartbeat interval in milliseconds\r\n */\r\n heartbeatInterval: 30000,\r\n\r\n /**\r\n * Client timeout in milliseconds (no heartbeat received)\r\n */\r\n clientTimeout: 60000,\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n\r\n /**\r\n * Auto-start configuration\r\n */\r\n autoStart: {\r\n /**\r\n * Whether to auto-start the hub if not running\r\n */\r\n enabled: true,\r\n\r\n /**\r\n * Maximum retries when connecting to hub\r\n */\r\n maxRetries: 3,\r\n\r\n /**\r\n * Delay between retries in milliseconds\r\n */\r\n retryDelay: 1000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * WebSocket Message Protocol\r\n * Defines the message format between Hub and Clients\r\n * @module infrastructure/websocket/message-protocol\r\n */\r\n\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport type { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport type { QuestionStatus } from '../../domain/entities/question.entity.js';\r\n\r\n// ============================================================================\r\n// Client → Hub Messages\r\n// ============================================================================\r\n\r\nexport type ClientMessageType = 'JOIN' | 'LEAVE' | 'ASK' | 'REPLY' | 'PING' | 'GET_INBOX';\r\n\r\nexport interface JoinMessage {\r\n type: 'JOIN';\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport interface LeaveMessage {\r\n type: 'LEAVE';\r\n}\r\n\r\nexport interface AskMessage {\r\n type: 'ASK';\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string; // For correlating response\r\n}\r\n\r\nexport interface ReplyMessage {\r\n type: 'REPLY';\r\n questionId: QuestionId;\r\n content: string;\r\n format: MessageFormat;\r\n}\r\n\r\nexport interface PingMessage {\r\n type: 'PING';\r\n}\r\n\r\nexport interface GetInboxMessage {\r\n type: 'GET_INBOX';\r\n requestId: string;\r\n}\r\n\r\nexport type ClientMessage =\r\n | JoinMessage\r\n | LeaveMessage\r\n | AskMessage\r\n | ReplyMessage\r\n | PingMessage\r\n | GetInboxMessage;\r\n\r\n// ============================================================================\r\n// Hub → Client Messages\r\n// ============================================================================\r\n\r\nexport type HubMessageType =\r\n | 'JOINED'\r\n | 'LEFT'\r\n | 'MEMBER_JOINED'\r\n | 'MEMBER_LEFT'\r\n | 'QUESTION'\r\n | 'ANSWER'\r\n | 'QUESTION_SENT'\r\n | 'INBOX'\r\n | 'PONG'\r\n | 'ERROR';\r\n\r\nexport interface MemberInfo {\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n teamName: string;\r\n displayName: string;\r\n status: MemberStatus;\r\n}\r\n\r\nexport interface JoinedMessage {\r\n type: 'JOINED';\r\n member: MemberInfo;\r\n memberCount: number;\r\n}\r\n\r\nexport interface LeftMessage {\r\n type: 'LEFT';\r\n memberId: MemberId;\r\n}\r\n\r\nexport interface MemberJoinedMessage {\r\n type: 'MEMBER_JOINED';\r\n member: MemberInfo;\r\n}\r\n\r\nexport interface MemberLeftMessage {\r\n type: 'MEMBER_LEFT';\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n}\r\n\r\nexport interface QuestionMessage {\r\n type: 'QUESTION';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: string;\r\n}\r\n\r\nexport interface AnswerMessage {\r\n type: 'ANSWER';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n requestId?: string; // Correlates with original ASK request\r\n}\r\n\r\nexport interface QuestionSentMessage {\r\n type: 'QUESTION_SENT';\r\n questionId: QuestionId;\r\n toTeamId: TeamId;\r\n status: QuestionStatus;\r\n requestId: string;\r\n}\r\n\r\nexport interface InboxQuestionInfo {\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n status: QuestionStatus;\r\n createdAt: string;\r\n ageMs: number;\r\n}\r\n\r\nexport interface InboxMessage {\r\n type: 'INBOX';\r\n questions: InboxQuestionInfo[];\r\n totalCount: number;\r\n pendingCount: number;\r\n requestId: string;\r\n}\r\n\r\nexport interface PongMessage {\r\n type: 'PONG';\r\n timestamp: string;\r\n}\r\n\r\nexport interface ErrorMessage {\r\n type: 'ERROR';\r\n code: string;\r\n message: string;\r\n requestId?: string;\r\n}\r\n\r\nexport type HubMessage =\r\n | JoinedMessage\r\n | LeftMessage\r\n | MemberJoinedMessage\r\n | MemberLeftMessage\r\n | QuestionMessage\r\n | AnswerMessage\r\n | QuestionSentMessage\r\n | InboxMessage\r\n | PongMessage\r\n | ErrorMessage;\r\n\r\n// ============================================================================\r\n// Serialization Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Serializes a message to JSON string\r\n */\r\nexport function serializeMessage<T extends ClientMessage | HubMessage>(message: T): string {\r\n return JSON.stringify(message);\r\n}\r\n\r\n/**\r\n * Parses a client message from JSON string\r\n */\r\nexport function parseClientMessage(data: string): ClientMessage {\r\n const parsed = JSON.parse(data) as ClientMessage;\r\n validateClientMessage(parsed);\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Parses a hub message from JSON string\r\n */\r\nexport function parseHubMessage(data: string): HubMessage {\r\n return JSON.parse(data) as HubMessage;\r\n}\r\n\r\n/**\r\n * Validates a client message\r\n */\r\nfunction validateClientMessage(message: ClientMessage): void {\r\n if (!message.type) {\r\n throw new Error('Message must have a type');\r\n }\r\n\r\n const validTypes: ClientMessageType[] = ['JOIN', 'LEAVE', 'ASK', 'REPLY', 'PING', 'GET_INBOX'];\r\n if (!validTypes.includes(message.type)) {\r\n throw new Error(`Invalid message type: ${message.type}`);\r\n }\r\n}\r\n\r\n/**\r\n * Creates an error message\r\n */\r\nexport function createErrorMessage(\r\n code: string,\r\n message: string,\r\n requestId?: string\r\n): ErrorMessage {\r\n return {\r\n type: 'ERROR',\r\n code,\r\n message,\r\n requestId,\r\n };\r\n}\r\n","/**\r\n * WebSocket Hub Client\r\n * Client that connects to the Hub server\r\n * @module infrastructure/websocket/hub-client\r\n */\r\n\r\nimport WebSocket from 'ws';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport { config } from '../../config/index.js';\r\nimport {\r\n type ClientMessage,\r\n type HubMessage,\r\n type QuestionMessage,\r\n type AnswerMessage,\r\n type InboxMessage,\r\n type MemberInfo,\r\n serializeMessage,\r\n parseHubMessage,\r\n} from './message-protocol.js';\r\n\r\n/**\r\n * Pending request with timeout\r\n */\r\ninterface PendingRequest<T> {\r\n resolve: (value: T) => void;\r\n reject: (error: Error) => void;\r\n timeout: ReturnType<typeof setTimeout>;\r\n}\r\n\r\n/**\r\n * Hub client options\r\n */\r\nexport interface HubClientOptions {\r\n host?: string;\r\n port?: number;\r\n reconnect?: boolean;\r\n reconnectDelay?: number;\r\n maxReconnectAttempts?: number;\r\n}\r\n\r\n/**\r\n * Hub client events\r\n */\r\nexport interface HubClientEvents {\r\n onConnected?: () => void;\r\n onDisconnected?: () => void;\r\n onQuestion?: (question: QuestionMessage) => void;\r\n onAnswer?: (answer: AnswerMessage) => void;\r\n onMemberJoined?: (member: MemberInfo) => void;\r\n onMemberLeft?: (memberId: MemberId, teamId: TeamId) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * WebSocket Hub Client\r\n */\r\nexport class HubClient {\r\n private ws: WebSocket | null = null;\r\n private readonly pendingRequests = new Map<string, PendingRequest<HubMessage>>();\r\n private reconnectAttempts = 0;\r\n private isClosing = false;\r\n\r\n private memberId?: MemberId;\r\n private teamId?: TeamId;\r\n private teamName?: string;\r\n private displayName?: string;\r\n\r\n constructor(\r\n private readonly options: HubClientOptions = {},\r\n private readonly events: HubClientEvents = {}\r\n ) {}\r\n\r\n /**\r\n * Connects to the Hub server\r\n */\r\n async connect(): Promise<void> {\r\n const host = this.options.host ?? config.hub.host;\r\n const port = this.options.port ?? config.hub.port;\r\n const url = `ws://${host}:${port}`;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n this.ws = new WebSocket(url);\r\n\r\n this.ws.on('open', () => {\r\n this.reconnectAttempts = 0;\r\n this.startPingInterval();\r\n this.events.onConnected?.();\r\n resolve();\r\n });\r\n\r\n this.ws.on('message', (data) => {\r\n this.handleMessage(data.toString());\r\n });\r\n\r\n this.ws.on('close', () => {\r\n this.handleDisconnect();\r\n });\r\n\r\n this.ws.on('error', (error) => {\r\n this.events.onError?.(error);\r\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\r\n reject(error);\r\n }\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Disconnects from the Hub server\r\n */\r\n async disconnect(): Promise<void> {\r\n this.isClosing = true;\r\n\r\n if (this.memberId) {\r\n this.send({ type: 'LEAVE' });\r\n }\r\n\r\n return new Promise((resolve) => {\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n this.isClosing = false;\r\n resolve();\r\n });\r\n }\r\n\r\n /**\r\n * Joins a team\r\n */\r\n async join(teamName: string, displayName: string): Promise<MemberInfo> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'JOIN',\r\n teamName,\r\n displayName,\r\n });\r\n\r\n const response = await this.waitForResponse<{ type: 'JOINED'; member: MemberInfo }>(\r\n (msg) => msg.type === 'JOINED',\r\n 30000\r\n );\r\n\r\n this.memberId = response.member.memberId;\r\n this.teamId = response.member.teamId;\r\n this.teamName = teamName;\r\n this.displayName = displayName;\r\n\r\n return response.member;\r\n }\r\n\r\n /**\r\n * Asks a question to another team\r\n */\r\n async ask(\r\n toTeam: string,\r\n content: string,\r\n format: MessageFormat = 'markdown',\r\n timeoutMs: number = config.communication.defaultTimeout\r\n ): Promise<AnswerMessage> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'ASK',\r\n toTeam,\r\n content,\r\n format,\r\n requestId,\r\n });\r\n\r\n // Wait for QUESTION_SENT confirmation\r\n await this.waitForResponse(\r\n (msg) => msg.type === 'QUESTION_SENT' && 'requestId' in msg && msg.requestId === requestId,\r\n 5000\r\n );\r\n\r\n // Wait for ANSWER\r\n const answer = await this.waitForResponse<AnswerMessage>(\r\n (msg) => msg.type === 'ANSWER',\r\n timeoutMs\r\n );\r\n\r\n return answer;\r\n }\r\n\r\n /**\r\n * Gets the inbox (pending questions)\r\n */\r\n async getInbox(): Promise<InboxMessage> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'GET_INBOX',\r\n requestId,\r\n });\r\n\r\n return this.waitForResponse<InboxMessage>(\r\n (msg) => msg.type === 'INBOX' && msg.requestId === requestId,\r\n 5000\r\n );\r\n }\r\n\r\n /**\r\n * Replies to a question\r\n */\r\n async reply(questionId: QuestionId, content: string, format: MessageFormat = 'markdown'): Promise<void> {\r\n this.send({\r\n type: 'REPLY',\r\n questionId,\r\n content,\r\n format,\r\n });\r\n }\r\n\r\n /**\r\n * Checks if connected\r\n */\r\n get isConnected(): boolean {\r\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n /**\r\n * Gets the current member ID\r\n */\r\n get currentMemberId(): MemberId | undefined {\r\n return this.memberId;\r\n }\r\n\r\n /**\r\n * Gets the current team ID\r\n */\r\n get currentTeamId(): TeamId | undefined {\r\n return this.teamId;\r\n }\r\n\r\n private send(message: ClientMessage): void {\r\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\r\n this.ws.send(serializeMessage(message));\r\n }\r\n }\r\n\r\n private handleMessage(data: string): void {\r\n try {\r\n const message = parseHubMessage(data);\r\n\r\n // Check pending requests\r\n for (const [requestId, pending] of this.pendingRequests) {\r\n // This is handled by the filter function in waitForResponse\r\n }\r\n\r\n // Handle specific message types\r\n switch (message.type) {\r\n case 'QUESTION':\r\n this.events.onQuestion?.(message);\r\n break;\r\n case 'ANSWER':\r\n this.events.onAnswer?.(message);\r\n break;\r\n case 'MEMBER_JOINED':\r\n this.events.onMemberJoined?.(message.member);\r\n break;\r\n case 'MEMBER_LEFT':\r\n this.events.onMemberLeft?.(message.memberId, message.teamId);\r\n break;\r\n case 'ERROR':\r\n this.events.onError?.(new Error(`${message.code}: ${message.message}`));\r\n break;\r\n }\r\n\r\n // Resolve any matching pending requests\r\n this.resolvePendingRequest(message);\r\n } catch (error) {\r\n console.error('Failed to parse message:', error);\r\n }\r\n }\r\n\r\n private resolvePendingRequest(message: HubMessage): void {\r\n for (const [requestId, pending] of this.pendingRequests) {\r\n // The filter is stored separately, we'll match by message type patterns\r\n this.pendingRequests.delete(requestId);\r\n clearTimeout(pending.timeout);\r\n pending.resolve(message);\r\n break; // Only resolve one request per message\r\n }\r\n }\r\n\r\n private waitForResponse<T extends HubMessage>(\r\n filter: (msg: HubMessage) => boolean,\r\n timeoutMs: number\r\n ): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const requestId = uuidv4();\r\n\r\n const timeout = setTimeout(() => {\r\n this.pendingRequests.delete(requestId);\r\n reject(new Error('Request timed out'));\r\n }, timeoutMs);\r\n\r\n // Store filter function with the pending request\r\n const pending: PendingRequest<HubMessage> & { filter: (msg: HubMessage) => boolean } = {\r\n resolve: (msg) => {\r\n if (filter(msg)) {\r\n resolve(msg as T);\r\n }\r\n },\r\n reject,\r\n timeout,\r\n filter,\r\n };\r\n\r\n this.pendingRequests.set(requestId, pending);\r\n\r\n // Override handleMessage to check this specific filter\r\n const originalHandler = this.handleMessage.bind(this);\r\n const checkFilter = (data: string): void => {\r\n try {\r\n const message = parseHubMessage(data);\r\n if (filter(message)) {\r\n this.pendingRequests.delete(requestId);\r\n clearTimeout(timeout);\r\n resolve(message as T);\r\n }\r\n } catch {\r\n // Ignore parse errors here\r\n }\r\n originalHandler(data);\r\n };\r\n\r\n // Temporarily override\r\n if (this.ws) {\r\n this.ws.removeAllListeners('message');\r\n this.ws.on('message', (data) => checkFilter(data.toString()));\r\n }\r\n });\r\n }\r\n\r\n private handleDisconnect(): void {\r\n this.events.onDisconnected?.();\r\n\r\n if (this.isClosing) return;\r\n\r\n const shouldReconnect = this.options.reconnect ?? true;\r\n const maxAttempts = this.options.maxReconnectAttempts ?? config.autoStart.maxRetries;\r\n\r\n if (shouldReconnect && this.reconnectAttempts < maxAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = this.options.reconnectDelay ?? config.autoStart.retryDelay;\r\n\r\n setTimeout(() => {\r\n this.connect()\r\n .then(() => {\r\n if (this.teamName && this.displayName) {\r\n return this.join(this.teamName, this.displayName);\r\n }\r\n })\r\n .catch((error) => {\r\n this.events.onError?.(error);\r\n });\r\n }, delay);\r\n }\r\n }\r\n\r\n private pingInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n private startPingInterval(): void {\r\n this.pingInterval = setInterval(() => {\r\n this.send({ type: 'PING' });\r\n }, config.hub.heartbeatInterval);\r\n }\r\n}\r\n","/**\r\n * Join Tool\r\n * Joins a team channel for collaboration\r\n * @module presentation/mcp/tools/join\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\n\r\n/**\r\n * Join tool input schema\r\n */\r\nconst joinSchema = {\r\n team: z.string().describe('Team name to join (e.g., \"frontend\", \"backend\", \"devops\")'),\r\n displayName: z\r\n .string()\r\n .optional()\r\n .describe('Display name for this terminal (default: team + \" Claude\")'),\r\n};\r\n\r\n/**\r\n * Registers the join tool with the MCP server\r\n */\r\nexport function registerJoinTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('join', joinSchema, async (args) => {\r\n const teamName = args.team;\r\n const displayName = args.displayName ?? `${teamName} Claude`;\r\n\r\n try {\r\n // Ensure connected to hub\r\n if (!hubClient.isConnected) {\r\n await hubClient.connect();\r\n }\r\n\r\n // Join the team\r\n const member = await hubClient.join(teamName, displayName);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Successfully joined team \"${member.teamName}\" as \"${member.displayName}\".\\n\\nYour member ID: ${member.memberId}\\nTeam ID: ${member.teamId}\\nStatus: ${member.status}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to join team: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Ask Tool\r\n * Asks a question to another team and waits for response\r\n * @module presentation/mcp/tools/ask\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\nimport { config } from '../../../config/index.js';\r\n\r\n/**\r\n * Ask tool input schema\r\n */\r\nconst askSchema = {\r\n team: z.string().describe('Target team name to ask (e.g., \"backend\", \"frontend\")'),\r\n question: z.string().describe('The question to ask (supports markdown)'),\r\n timeout: z\r\n .number()\r\n .optional()\r\n .describe(`Timeout in seconds to wait for answer (default: ${config.communication.defaultTimeout / 1000}s)`),\r\n};\r\n\r\n/**\r\n * Registers the ask tool with the MCP server\r\n */\r\nexport function registerAskTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('ask', askSchema, async (args) => {\r\n const targetTeam = args.team;\r\n const question = args.question;\r\n const timeoutMs = (args.timeout ?? config.communication.defaultTimeout / 1000) * 1000;\r\n\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Ask the question and wait for answer\r\n const answer = await hubClient.ask(targetTeam, question, 'markdown', timeoutMs);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**Answer from ${answer.from.displayName} (${answer.from.teamName}):**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n\r\n if (errorMessage.includes('timed out')) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `No response received from team \"${targetTeam}\" within ${timeoutMs / 1000} seconds. The question has been delivered but no one answered yet.`,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to ask question: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Inbox Tool\r\n * Lists pending questions directed to the current team\r\n * @module presentation/mcp/tools/inbox\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\n\r\n/**\r\n * Inbox tool input schema (no required parameters)\r\n */\r\nconst inboxSchema = {};\r\n\r\n/**\r\n * Registers the inbox tool with the MCP server\r\n */\r\nexport function registerInboxTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('inbox', inboxSchema, async () => {\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Get inbox\r\n const inbox = await hubClient.getInbox();\r\n\r\n if (inbox.questions.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'No pending questions in your inbox.',\r\n },\r\n ],\r\n };\r\n }\r\n\r\n // Format questions list\r\n const questionsList = inbox.questions\r\n .map((q, i) => {\r\n const ageSeconds = Math.floor(q.ageMs / 1000);\r\n const ageStr = ageSeconds < 60 ? `${ageSeconds}s ago` : `${Math.floor(ageSeconds / 60)}m ago`;\r\n\r\n return `### ${i + 1}. Question from ${q.from.displayName} (${q.from.teamName}) - ${ageStr}\r\n**ID:** \\`${q.questionId}\\`\r\n**Status:** ${q.status}\r\n\r\n${q.content}\r\n\r\n---`;\r\n })\r\n .join('\\n\\n');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `# Inbox (${inbox.pendingCount} pending, ${inbox.totalCount} total)\\n\\n${questionsList}\\n\\nUse the \"reply\" tool with the question ID to answer a question.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to get inbox: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Reply Tool\r\n * Replies to a pending question\r\n * @module presentation/mcp/tools/reply\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\nimport type { QuestionId } from '../../../shared/types/branded-types.js';\r\n\r\n/**\r\n * Reply tool input schema\r\n */\r\nconst replySchema = {\r\n questionId: z.string().describe('The ID of the question to reply to (from inbox)'),\r\n answer: z.string().describe('Your answer to the question (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the reply tool with the MCP server\r\n */\r\nexport function registerReplyTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('reply', replySchema, async (args) => {\r\n const questionId = args.questionId as QuestionId;\r\n const answer = args.answer;\r\n\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Send the reply\r\n await hubClient.reply(questionId, answer, 'markdown');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Reply sent successfully to question \\`${questionId}\\`.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send reply: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * MCP Server\r\n * Provides MCP tools for Claude Code integration\r\n * @module presentation/mcp/server\r\n */\r\n\r\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport type { HubClient } from '../../infrastructure/websocket/hub-client.js';\r\nimport { registerJoinTool } from './tools/join.tool.js';\r\nimport { registerAskTool } from './tools/ask.tool.js';\r\nimport { registerInboxTool } from './tools/inbox.tool.js';\r\nimport { registerReplyTool } from './tools/reply.tool.js';\r\n\r\n/**\r\n * MCP Server options\r\n */\r\nexport interface McpServerOptions {\r\n hubClient: HubClient;\r\n}\r\n\r\n/**\r\n * Creates and configures the MCP server with all tools\r\n */\r\nexport function createMcpServer(options: McpServerOptions): McpServer {\r\n const server = new McpServer({\r\n name: 'claude-collab',\r\n version: '0.1.0',\r\n });\r\n\r\n // Register all tools\r\n registerJoinTool(server, options.hubClient);\r\n registerAskTool(server, options.hubClient);\r\n registerInboxTool(server, options.hubClient);\r\n registerReplyTool(server, options.hubClient);\r\n\r\n return server;\r\n}\r\n\r\n/**\r\n * Starts the MCP server with stdio transport\r\n */\r\nexport async function startMcpServer(options: McpServerOptions): Promise<void> {\r\n const server = createMcpServer(options);\r\n const transport = new StdioServerTransport();\r\n\r\n await server.connect(transport);\r\n}\r\n","/**\r\n * Auto-Start Service\r\n * Automatically starts the Hub server if not running\r\n * @module infrastructure/hub-launcher/auto-start\r\n */\r\n\r\nimport { spawn, type ChildProcess } from 'child_process';\r\nimport { createConnection } from 'net';\r\nimport { config } from '../../config/index.js';\r\n\r\n/**\r\n * Auto-start service options\r\n */\r\nexport interface AutoStartOptions {\r\n host?: string;\r\n port?: number;\r\n maxRetries?: number;\r\n retryDelay?: number;\r\n}\r\n\r\n/**\r\n * Checks if the Hub server is running\r\n */\r\nexport async function isHubRunning(\r\n host: string = config.hub.host,\r\n port: number = config.hub.port\r\n): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const socket = createConnection({ host, port }, () => {\r\n socket.end();\r\n resolve(true);\r\n });\r\n\r\n socket.on('error', () => {\r\n resolve(false);\r\n });\r\n\r\n socket.setTimeout(1000, () => {\r\n socket.destroy();\r\n resolve(false);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Waits for the Hub server to become available\r\n */\r\nexport async function waitForHub(\r\n host: string = config.hub.host,\r\n port: number = config.hub.port,\r\n maxRetries: number = config.autoStart.maxRetries,\r\n retryDelay: number = config.autoStart.retryDelay\r\n): Promise<boolean> {\r\n for (let i = 0; i < maxRetries; i++) {\r\n if (await isHubRunning(host, port)) {\r\n return true;\r\n }\r\n await new Promise((resolve) => setTimeout(resolve, retryDelay));\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Starts the Hub server as a background process\r\n */\r\nexport function startHubProcess(options: AutoStartOptions = {}): ChildProcess {\r\n const host = options.host ?? config.hub.host;\r\n const port = options.port ?? config.hub.port;\r\n\r\n // Start hub-main.js as a detached process\r\n const hubProcess = spawn(\r\n process.execPath,\r\n [\r\n '--experimental-specifier-resolution=node',\r\n new URL('../../hub-main.js', import.meta.url).pathname,\r\n '--host',\r\n host,\r\n '--port',\r\n port.toString(),\r\n ],\r\n {\r\n detached: true,\r\n stdio: 'ignore',\r\n }\r\n );\r\n\r\n hubProcess.unref();\r\n return hubProcess;\r\n}\r\n\r\n/**\r\n * Ensures the Hub is running, starting it if necessary\r\n */\r\nexport async function ensureHubRunning(options: AutoStartOptions = {}): Promise<boolean> {\r\n const host = options.host ?? config.hub.host;\r\n const port = options.port ?? config.hub.port;\r\n const maxRetries = options.maxRetries ?? config.autoStart.maxRetries;\r\n const retryDelay = options.retryDelay ?? config.autoStart.retryDelay;\r\n\r\n // Check if already running\r\n if (await isHubRunning(host, port)) {\r\n return true;\r\n }\r\n\r\n // Try to start the hub\r\n console.log(`Hub not running. Starting hub on ${host}:${port}...`);\r\n startHubProcess({ host, port });\r\n\r\n // Wait for it to become available\r\n const isRunning = await waitForHub(host, port, maxRetries, retryDelay);\r\n\r\n if (isRunning) {\r\n console.log('Hub started successfully');\r\n } else {\r\n console.error('Failed to start hub');\r\n }\r\n\r\n return isRunning;\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * MCP Server entry point\r\n * This is the main entry point for the MCP client that connects to Claude Code\r\n * @module mcp-main\r\n */\r\n\r\nimport { HubClient } from './infrastructure/websocket/hub-client.js';\r\nimport { startMcpServer } from './presentation/mcp/server.js';\r\nimport { ensureHubRunning } from './infrastructure/hub-launcher/auto-start.service.js';\r\nimport { config } from './config/index.js';\r\n\r\nconst args = process.argv.slice(2);\r\n\r\ninterface ClientOptions {\r\n team?: string;\r\n host: string;\r\n port: number;\r\n autoHub: boolean;\r\n}\r\n\r\nfunction parseArgs(): ClientOptions {\r\n const options: ClientOptions = {\r\n host: config.hub.host,\r\n port: config.hub.port,\r\n autoHub: false,\r\n };\r\n\r\n for (let i = 0; i < args.length; i++) {\r\n const arg = args[i];\r\n const nextArg = args[i + 1];\r\n\r\n if (arg === '--team' && nextArg) {\r\n options.team = nextArg;\r\n i++;\r\n } else if (arg === '--host' && nextArg) {\r\n options.host = nextArg;\r\n i++;\r\n } else if (arg === '--port' && nextArg) {\r\n options.port = parseInt(nextArg, 10);\r\n i++;\r\n } else if (arg === '--auto-hub') {\r\n options.autoHub = true;\r\n } else if (arg === '-h' || arg === '--help') {\r\n console.error(`\r\nClaude Collab MCP Client\r\n\r\nUsage:\r\n mcp-main [options]\r\n\r\nOptions:\r\n --team <team> Team to auto-join (optional)\r\n --host <host> Hub host (default: ${config.hub.host})\r\n --port <port> Hub port (default: ${config.hub.port})\r\n --auto-hub Auto-start hub if not running\r\n -h, --help Show this help message\r\n`);\r\n process.exit(0);\r\n }\r\n }\r\n\r\n return options;\r\n}\r\n\r\nasync function main(): Promise<void> {\r\n const options = parseArgs();\r\n\r\n // Auto-start hub if requested\r\n if (options.autoHub) {\r\n const hubRunning = await ensureHubRunning({\r\n host: options.host,\r\n port: options.port,\r\n });\r\n\r\n if (!hubRunning) {\r\n console.error('Failed to start hub server. Exiting.');\r\n process.exit(1);\r\n }\r\n }\r\n\r\n // Create hub client\r\n const hubClient = new HubClient(\r\n {\r\n host: options.host,\r\n port: options.port,\r\n reconnect: true,\r\n },\r\n {\r\n onError: (error) => {\r\n console.error('Hub client error:', error.message);\r\n },\r\n onQuestion: (question) => {\r\n // Questions will be handled by inbox tool\r\n console.error(`[Question received from ${question.from.displayName}]`);\r\n },\r\n }\r\n );\r\n\r\n // Connect to hub\r\n try {\r\n await hubClient.connect();\r\n\r\n // Auto-join team if specified\r\n if (options.team) {\r\n await hubClient.join(options.team, `${options.team} Claude`);\r\n console.error(`Auto-joined team: ${options.team}`);\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to connect to hub: ${errorMessage}`);\r\n console.error('Make sure the hub server is running or use --auto-hub flag.');\r\n process.exit(1);\r\n }\r\n\r\n // Start MCP server\r\n await startMcpServer({ hubClient });\r\n}\r\n\r\nmain().catch((error) => {\r\n console.error('Unexpected error:', error);\r\n process.exit(1);\r\n});\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/index.ts","../src/infrastructure/websocket/message-protocol.ts","../src/infrastructure/websocket/hub-client.ts","../src/presentation/mcp/tools/join.tool.ts","../src/presentation/mcp/tools/ask.tool.ts","../src/presentation/mcp/tools/inbox.tool.ts","../src/presentation/mcp/tools/reply.tool.ts","../src/presentation/mcp/server.ts","../src/infrastructure/hub-launcher/auto-start.service.ts","../src/mcp-main.ts"],"names":["uuidv4","args","z"],"mappings":"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","file":"mcp-main.js","sourcesContent":["/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * WebSocket Hub configuration\r\n */\r\n hub: {\r\n /**\r\n * Default port for the Hub server\r\n */\r\n port: parseInt(process.env['CLAUDE_COLLAB_PORT'] ?? '9999', 10),\r\n\r\n /**\r\n * Host to bind the Hub server to\r\n */\r\n host: process.env['CLAUDE_COLLAB_HOST'] ?? 'localhost',\r\n\r\n /**\r\n * Heartbeat interval in milliseconds\r\n */\r\n heartbeatInterval: 30000,\r\n\r\n /**\r\n * Client timeout in milliseconds (no heartbeat received)\r\n */\r\n clientTimeout: 60000,\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n\r\n /**\r\n * Auto-start configuration\r\n */\r\n autoStart: {\r\n /**\r\n * Whether to auto-start the hub if not running\r\n */\r\n enabled: true,\r\n\r\n /**\r\n * Maximum retries when connecting to hub\r\n */\r\n maxRetries: 3,\r\n\r\n /**\r\n * Delay between retries in milliseconds\r\n */\r\n retryDelay: 1000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * WebSocket Message Protocol\r\n * Defines the message format between Hub and Clients\r\n * @module infrastructure/websocket/message-protocol\r\n */\r\n\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport type { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport type { QuestionStatus } from '../../domain/entities/question.entity.js';\r\n\r\n// ============================================================================\r\n// Client → Hub Messages\r\n// ============================================================================\r\n\r\nexport type ClientMessageType = 'JOIN' | 'LEAVE' | 'ASK' | 'REPLY' | 'PING' | 'GET_INBOX';\r\n\r\nexport interface JoinMessage {\r\n type: 'JOIN';\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport interface LeaveMessage {\r\n type: 'LEAVE';\r\n}\r\n\r\nexport interface AskMessage {\r\n type: 'ASK';\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string; // For correlating response\r\n}\r\n\r\nexport interface ReplyMessage {\r\n type: 'REPLY';\r\n questionId: QuestionId;\r\n content: string;\r\n format: MessageFormat;\r\n}\r\n\r\nexport interface PingMessage {\r\n type: 'PING';\r\n}\r\n\r\nexport interface GetInboxMessage {\r\n type: 'GET_INBOX';\r\n requestId: string;\r\n}\r\n\r\nexport type ClientMessage =\r\n | JoinMessage\r\n | LeaveMessage\r\n | AskMessage\r\n | ReplyMessage\r\n | PingMessage\r\n | GetInboxMessage;\r\n\r\n// ============================================================================\r\n// Hub → Client Messages\r\n// ============================================================================\r\n\r\nexport type HubMessageType =\r\n | 'JOINED'\r\n | 'LEFT'\r\n | 'MEMBER_JOINED'\r\n | 'MEMBER_LEFT'\r\n | 'QUESTION'\r\n | 'ANSWER'\r\n | 'QUESTION_SENT'\r\n | 'INBOX'\r\n | 'PONG'\r\n | 'ERROR';\r\n\r\nexport interface MemberInfo {\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n teamName: string;\r\n displayName: string;\r\n status: MemberStatus;\r\n}\r\n\r\nexport interface JoinedMessage {\r\n type: 'JOINED';\r\n member: MemberInfo;\r\n memberCount: number;\r\n}\r\n\r\nexport interface LeftMessage {\r\n type: 'LEFT';\r\n memberId: MemberId;\r\n}\r\n\r\nexport interface MemberJoinedMessage {\r\n type: 'MEMBER_JOINED';\r\n member: MemberInfo;\r\n}\r\n\r\nexport interface MemberLeftMessage {\r\n type: 'MEMBER_LEFT';\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n}\r\n\r\nexport interface QuestionMessage {\r\n type: 'QUESTION';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: string;\r\n}\r\n\r\nexport interface AnswerMessage {\r\n type: 'ANSWER';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n requestId?: string; // Correlates with original ASK request\r\n}\r\n\r\nexport interface QuestionSentMessage {\r\n type: 'QUESTION_SENT';\r\n questionId: QuestionId;\r\n toTeamId: TeamId;\r\n status: QuestionStatus;\r\n requestId: string;\r\n}\r\n\r\nexport interface InboxQuestionInfo {\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n status: QuestionStatus;\r\n createdAt: string;\r\n ageMs: number;\r\n}\r\n\r\nexport interface InboxMessage {\r\n type: 'INBOX';\r\n questions: InboxQuestionInfo[];\r\n totalCount: number;\r\n pendingCount: number;\r\n requestId: string;\r\n}\r\n\r\nexport interface PongMessage {\r\n type: 'PONG';\r\n timestamp: string;\r\n}\r\n\r\nexport interface ErrorMessage {\r\n type: 'ERROR';\r\n code: string;\r\n message: string;\r\n requestId?: string;\r\n}\r\n\r\nexport type HubMessage =\r\n | JoinedMessage\r\n | LeftMessage\r\n | MemberJoinedMessage\r\n | MemberLeftMessage\r\n | QuestionMessage\r\n | AnswerMessage\r\n | QuestionSentMessage\r\n | InboxMessage\r\n | PongMessage\r\n | ErrorMessage;\r\n\r\n// ============================================================================\r\n// Serialization Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Serializes a message to JSON string\r\n */\r\nexport function serializeMessage<T extends ClientMessage | HubMessage>(message: T): string {\r\n return JSON.stringify(message);\r\n}\r\n\r\n/**\r\n * Parses a client message from JSON string\r\n */\r\nexport function parseClientMessage(data: string): ClientMessage {\r\n const parsed = JSON.parse(data) as ClientMessage;\r\n validateClientMessage(parsed);\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Parses a hub message from JSON string\r\n */\r\nexport function parseHubMessage(data: string): HubMessage {\r\n return JSON.parse(data) as HubMessage;\r\n}\r\n\r\n/**\r\n * Validates a client message\r\n */\r\nfunction validateClientMessage(message: ClientMessage): void {\r\n if (!message.type) {\r\n throw new Error('Message must have a type');\r\n }\r\n\r\n const validTypes: ClientMessageType[] = ['JOIN', 'LEAVE', 'ASK', 'REPLY', 'PING', 'GET_INBOX'];\r\n if (!validTypes.includes(message.type)) {\r\n throw new Error(`Invalid message type: ${message.type}`);\r\n }\r\n}\r\n\r\n/**\r\n * Creates an error message\r\n */\r\nexport function createErrorMessage(\r\n code: string,\r\n message: string,\r\n requestId?: string\r\n): ErrorMessage {\r\n return {\r\n type: 'ERROR',\r\n code,\r\n message,\r\n requestId,\r\n };\r\n}\r\n","/**\r\n * WebSocket Hub Client\r\n * Client that connects to the Hub server\r\n * @module infrastructure/websocket/hub-client\r\n */\r\n\r\nimport WebSocket from 'ws';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport { config } from '../../config/index.js';\r\nimport {\r\n type ClientMessage,\r\n type HubMessage,\r\n type QuestionMessage,\r\n type AnswerMessage,\r\n type InboxMessage,\r\n type MemberInfo,\r\n serializeMessage,\r\n parseHubMessage,\r\n} from './message-protocol.js';\r\n\r\n/**\r\n * Pending request with timeout\r\n */\r\ninterface PendingRequest<T> {\r\n resolve: (value: T) => void;\r\n reject: (error: Error) => void;\r\n timeout: ReturnType<typeof setTimeout>;\r\n}\r\n\r\n/**\r\n * Hub client options\r\n */\r\nexport interface HubClientOptions {\r\n host?: string;\r\n port?: number;\r\n reconnect?: boolean;\r\n reconnectDelay?: number;\r\n maxReconnectAttempts?: number;\r\n}\r\n\r\n/**\r\n * Hub client events\r\n */\r\nexport interface HubClientEvents {\r\n onConnected?: () => void;\r\n onDisconnected?: () => void;\r\n onQuestion?: (question: QuestionMessage) => void;\r\n onAnswer?: (answer: AnswerMessage) => void;\r\n onMemberJoined?: (member: MemberInfo) => void;\r\n onMemberLeft?: (memberId: MemberId, teamId: TeamId) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * WebSocket Hub Client\r\n */\r\nexport class HubClient {\r\n private ws: WebSocket | null = null;\r\n private readonly pendingRequests = new Map<string, PendingRequest<HubMessage>>();\r\n private reconnectAttempts = 0;\r\n private isClosing = false;\r\n\r\n private memberId?: MemberId;\r\n private teamId?: TeamId;\r\n private teamName?: string;\r\n private displayName?: string;\r\n\r\n constructor(\r\n private readonly options: HubClientOptions = {},\r\n private readonly events: HubClientEvents = {}\r\n ) {}\r\n\r\n /**\r\n * Connects to the Hub server\r\n */\r\n async connect(): Promise<void> {\r\n const host = this.options.host ?? config.hub.host;\r\n const port = this.options.port ?? config.hub.port;\r\n const url = `ws://${host}:${port}`;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n this.ws = new WebSocket(url);\r\n\r\n this.ws.on('open', () => {\r\n this.reconnectAttempts = 0;\r\n this.startPingInterval();\r\n this.events.onConnected?.();\r\n resolve();\r\n });\r\n\r\n this.ws.on('message', (data) => {\r\n this.handleMessage(data.toString());\r\n });\r\n\r\n this.ws.on('close', () => {\r\n this.handleDisconnect();\r\n });\r\n\r\n this.ws.on('error', (error) => {\r\n this.events.onError?.(error);\r\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\r\n reject(error);\r\n }\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Disconnects from the Hub server\r\n */\r\n async disconnect(): Promise<void> {\r\n this.isClosing = true;\r\n\r\n if (this.memberId) {\r\n this.send({ type: 'LEAVE' });\r\n }\r\n\r\n return new Promise((resolve) => {\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n this.isClosing = false;\r\n resolve();\r\n });\r\n }\r\n\r\n /**\r\n * Joins a team\r\n */\r\n async join(teamName: string, displayName: string): Promise<MemberInfo> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'JOIN',\r\n teamName,\r\n displayName,\r\n });\r\n\r\n const response = await this.waitForResponse<{ type: 'JOINED'; member: MemberInfo }>(\r\n (msg) => msg.type === 'JOINED',\r\n 30000\r\n );\r\n\r\n this.memberId = response.member.memberId;\r\n this.teamId = response.member.teamId;\r\n this.teamName = teamName;\r\n this.displayName = displayName;\r\n\r\n return response.member;\r\n }\r\n\r\n /**\r\n * Asks a question to another team\r\n */\r\n async ask(\r\n toTeam: string,\r\n content: string,\r\n format: MessageFormat = 'markdown',\r\n timeoutMs: number = config.communication.defaultTimeout\r\n ): Promise<AnswerMessage> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'ASK',\r\n toTeam,\r\n content,\r\n format,\r\n requestId,\r\n });\r\n\r\n // Wait for QUESTION_SENT confirmation\r\n const questionSent = await this.waitForResponse<{\r\n type: 'QUESTION_SENT';\r\n questionId: QuestionId;\r\n requestId: string;\r\n }>(\r\n (msg) => msg.type === 'QUESTION_SENT' && 'requestId' in msg && msg.requestId === requestId,\r\n 5000\r\n );\r\n\r\n const questionId = questionSent.questionId;\r\n\r\n // Wait for ANSWER with matching questionId\r\n const answer = await this.waitForResponse<AnswerMessage>(\r\n (msg) => msg.type === 'ANSWER' && msg.questionId === questionId,\r\n timeoutMs\r\n );\r\n\r\n return answer;\r\n }\r\n\r\n /**\r\n * Gets the inbox (pending questions)\r\n */\r\n async getInbox(): Promise<InboxMessage> {\r\n const requestId = uuidv4();\r\n\r\n this.send({\r\n type: 'GET_INBOX',\r\n requestId,\r\n });\r\n\r\n return this.waitForResponse<InboxMessage>(\r\n (msg) => msg.type === 'INBOX' && msg.requestId === requestId,\r\n 5000\r\n );\r\n }\r\n\r\n /**\r\n * Replies to a question\r\n */\r\n async reply(questionId: QuestionId, content: string, format: MessageFormat = 'markdown'): Promise<void> {\r\n this.send({\r\n type: 'REPLY',\r\n questionId,\r\n content,\r\n format,\r\n });\r\n }\r\n\r\n /**\r\n * Checks if connected\r\n */\r\n get isConnected(): boolean {\r\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\r\n }\r\n\r\n /**\r\n * Gets the current member ID\r\n */\r\n get currentMemberId(): MemberId | undefined {\r\n return this.memberId;\r\n }\r\n\r\n /**\r\n * Gets the current team ID\r\n */\r\n get currentTeamId(): TeamId | undefined {\r\n return this.teamId;\r\n }\r\n\r\n private send(message: ClientMessage): void {\r\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\r\n this.ws.send(serializeMessage(message));\r\n }\r\n }\r\n\r\n private handleMessage(data: string): void {\r\n try {\r\n const message = parseHubMessage(data);\r\n\r\n // Check pending requests\r\n for (const [requestId, pending] of this.pendingRequests) {\r\n // This is handled by the filter function in waitForResponse\r\n }\r\n\r\n // Handle specific message types\r\n switch (message.type) {\r\n case 'QUESTION':\r\n this.events.onQuestion?.(message);\r\n break;\r\n case 'ANSWER':\r\n this.events.onAnswer?.(message);\r\n break;\r\n case 'MEMBER_JOINED':\r\n this.events.onMemberJoined?.(message.member);\r\n break;\r\n case 'MEMBER_LEFT':\r\n this.events.onMemberLeft?.(message.memberId, message.teamId);\r\n break;\r\n case 'ERROR':\r\n this.events.onError?.(new Error(`${message.code}: ${message.message}`));\r\n break;\r\n }\r\n\r\n // Resolve any matching pending requests\r\n this.resolvePendingRequest(message);\r\n } catch (error) {\r\n console.error('Failed to parse message:', error);\r\n }\r\n }\r\n\r\n private resolvePendingRequest(message: HubMessage): void {\r\n for (const [requestId, pending] of this.pendingRequests) {\r\n // The filter is stored separately, we'll match by message type patterns\r\n this.pendingRequests.delete(requestId);\r\n clearTimeout(pending.timeout);\r\n pending.resolve(message);\r\n break; // Only resolve one request per message\r\n }\r\n }\r\n\r\n private waitForResponse<T extends HubMessage>(\r\n filter: (msg: HubMessage) => boolean,\r\n timeoutMs: number\r\n ): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const requestId = uuidv4();\r\n\r\n const timeout = setTimeout(() => {\r\n this.pendingRequests.delete(requestId);\r\n reject(new Error('Request timed out'));\r\n }, timeoutMs);\r\n\r\n // Store filter function with the pending request\r\n const pending: PendingRequest<HubMessage> & { filter: (msg: HubMessage) => boolean } = {\r\n resolve: (msg) => {\r\n if (filter(msg)) {\r\n resolve(msg as T);\r\n }\r\n },\r\n reject,\r\n timeout,\r\n filter,\r\n };\r\n\r\n this.pendingRequests.set(requestId, pending);\r\n\r\n // Override handleMessage to check this specific filter\r\n const originalHandler = this.handleMessage.bind(this);\r\n const checkFilter = (data: string): void => {\r\n try {\r\n const message = parseHubMessage(data);\r\n if (filter(message)) {\r\n this.pendingRequests.delete(requestId);\r\n clearTimeout(timeout);\r\n resolve(message as T);\r\n }\r\n } catch {\r\n // Ignore parse errors here\r\n }\r\n originalHandler(data);\r\n };\r\n\r\n // Temporarily override\r\n if (this.ws) {\r\n this.ws.removeAllListeners('message');\r\n this.ws.on('message', (data) => checkFilter(data.toString()));\r\n }\r\n });\r\n }\r\n\r\n private handleDisconnect(): void {\r\n this.events.onDisconnected?.();\r\n\r\n if (this.isClosing) return;\r\n\r\n const shouldReconnect = this.options.reconnect ?? true;\r\n const maxAttempts = this.options.maxReconnectAttempts ?? config.autoStart.maxRetries;\r\n\r\n if (shouldReconnect && this.reconnectAttempts < maxAttempts) {\r\n this.reconnectAttempts++;\r\n const delay = this.options.reconnectDelay ?? config.autoStart.retryDelay;\r\n\r\n setTimeout(() => {\r\n this.connect()\r\n .then(() => {\r\n if (this.teamName && this.displayName) {\r\n return this.join(this.teamName, this.displayName);\r\n }\r\n })\r\n .catch((error) => {\r\n this.events.onError?.(error);\r\n });\r\n }, delay);\r\n }\r\n }\r\n\r\n private pingInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n private startPingInterval(): void {\r\n this.pingInterval = setInterval(() => {\r\n this.send({ type: 'PING' });\r\n }, config.hub.heartbeatInterval);\r\n }\r\n}\r\n","/**\r\n * Join Tool\r\n * Joins a team channel for collaboration\r\n * @module presentation/mcp/tools/join\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\n\r\n/**\r\n * Join tool input schema\r\n */\r\nconst joinSchema = {\r\n team: z.string().describe('Team name to join (e.g., \"frontend\", \"backend\", \"devops\")'),\r\n displayName: z\r\n .string()\r\n .optional()\r\n .describe('Display name for this terminal (default: team + \" Claude\")'),\r\n};\r\n\r\n/**\r\n * Registers the join tool with the MCP server\r\n */\r\nexport function registerJoinTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('join', joinSchema, async (args) => {\r\n const teamName = args.team;\r\n const displayName = args.displayName ?? `${teamName} Claude`;\r\n\r\n try {\r\n // Ensure connected to hub\r\n if (!hubClient.isConnected) {\r\n await hubClient.connect();\r\n }\r\n\r\n // Join the team\r\n const member = await hubClient.join(teamName, displayName);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Successfully joined team \"${member.teamName}\" as \"${member.displayName}\".\\n\\nYour member ID: ${member.memberId}\\nTeam ID: ${member.teamId}\\nStatus: ${member.status}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to join team: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Ask Tool\r\n * Asks a question to another team and waits for response\r\n * @module presentation/mcp/tools/ask\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\nimport { config } from '../../../config/index.js';\r\n\r\n/**\r\n * Ask tool input schema\r\n */\r\nconst askSchema = {\r\n team: z.string().describe('Target team name to ask (e.g., \"backend\", \"frontend\")'),\r\n question: z.string().describe('The question to ask (supports markdown)'),\r\n timeout: z\r\n .number()\r\n .optional()\r\n .describe(`Timeout in seconds to wait for answer (default: ${config.communication.defaultTimeout / 1000}s)`),\r\n};\r\n\r\n/**\r\n * Registers the ask tool with the MCP server\r\n */\r\nexport function registerAskTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('ask', askSchema, async (args) => {\r\n const targetTeam = args.team;\r\n const question = args.question;\r\n const timeoutMs = (args.timeout ?? config.communication.defaultTimeout / 1000) * 1000;\r\n\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Ask the question and wait for answer\r\n const answer = await hubClient.ask(targetTeam, question, 'markdown', timeoutMs);\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `**Answer from ${answer.from.displayName} (${answer.from.teamName}):**\\n\\n${answer.content}`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n\r\n if (errorMessage.includes('timed out')) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `No response received from team \"${targetTeam}\" within ${timeoutMs / 1000} seconds. The question has been delivered but no one answered yet.`,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to ask question: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Inbox Tool\r\n * Lists pending questions directed to the current team\r\n * @module presentation/mcp/tools/inbox\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\n\r\n/**\r\n * Inbox tool input schema (no required parameters)\r\n */\r\nconst inboxSchema = {};\r\n\r\n/**\r\n * Registers the inbox tool with the MCP server\r\n */\r\nexport function registerInboxTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('inbox', inboxSchema, async () => {\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Get inbox\r\n const inbox = await hubClient.getInbox();\r\n\r\n if (inbox.questions.length === 0) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'No pending questions in your inbox.',\r\n },\r\n ],\r\n };\r\n }\r\n\r\n // Format questions list\r\n const questionsList = inbox.questions\r\n .map((q, i) => {\r\n const ageSeconds = Math.floor(q.ageMs / 1000);\r\n const ageStr = ageSeconds < 60 ? `${ageSeconds}s ago` : `${Math.floor(ageSeconds / 60)}m ago`;\r\n\r\n return `### ${i + 1}. Question from ${q.from.displayName} (${q.from.teamName}) - ${ageStr}\r\n**ID:** \\`${q.questionId}\\`\r\n**Status:** ${q.status}\r\n\r\n${q.content}\r\n\r\n---`;\r\n })\r\n .join('\\n\\n');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `# Inbox (${inbox.pendingCount} pending, ${inbox.totalCount} total)\\n\\n${questionsList}\\n\\nUse the \"reply\" tool with the question ID to answer a question.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to get inbox: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * Reply Tool\r\n * Replies to a pending question\r\n * @module presentation/mcp/tools/reply\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport type { HubClient } from '../../../infrastructure/websocket/hub-client.js';\r\nimport type { QuestionId } from '../../../shared/types/branded-types.js';\r\n\r\n/**\r\n * Reply tool input schema\r\n */\r\nconst replySchema = {\r\n questionId: z.string().describe('The ID of the question to reply to (from inbox)'),\r\n answer: z.string().describe('Your answer to the question (supports markdown)'),\r\n};\r\n\r\n/**\r\n * Registers the reply tool with the MCP server\r\n */\r\nexport function registerReplyTool(server: McpServer, hubClient: HubClient): void {\r\n server.tool('reply', replySchema, async (args) => {\r\n const questionId = args.questionId as QuestionId;\r\n const answer = args.answer;\r\n\r\n try {\r\n // Check if joined a team\r\n if (!hubClient.currentTeamId) {\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: 'You must join a team first. Use the \"join\" tool to join a team.',\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n\r\n // Send the reply\r\n await hubClient.reply(questionId, answer, 'markdown');\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Reply sent successfully to question \\`${questionId}\\`.`,\r\n },\r\n ],\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Failed to send reply: ${errorMessage}`,\r\n },\r\n ],\r\n isError: true,\r\n };\r\n }\r\n });\r\n}\r\n","/**\r\n * MCP Server\r\n * Provides MCP tools for Claude Code integration\r\n * @module presentation/mcp/server\r\n */\r\n\r\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport type { HubClient } from '../../infrastructure/websocket/hub-client.js';\r\nimport { registerJoinTool } from './tools/join.tool.js';\r\nimport { registerAskTool } from './tools/ask.tool.js';\r\nimport { registerInboxTool } from './tools/inbox.tool.js';\r\nimport { registerReplyTool } from './tools/reply.tool.js';\r\n\r\n/**\r\n * MCP Server options\r\n */\r\nexport interface McpServerOptions {\r\n hubClient: HubClient;\r\n}\r\n\r\n/**\r\n * Creates and configures the MCP server with all tools\r\n */\r\nexport function createMcpServer(options: McpServerOptions): McpServer {\r\n const server = new McpServer({\r\n name: 'claude-collab',\r\n version: '0.1.0',\r\n });\r\n\r\n // Register all tools\r\n registerJoinTool(server, options.hubClient);\r\n registerAskTool(server, options.hubClient);\r\n registerInboxTool(server, options.hubClient);\r\n registerReplyTool(server, options.hubClient);\r\n\r\n return server;\r\n}\r\n\r\n/**\r\n * Starts the MCP server with stdio transport\r\n */\r\nexport async function startMcpServer(options: McpServerOptions): Promise<void> {\r\n const server = createMcpServer(options);\r\n const transport = new StdioServerTransport();\r\n\r\n await server.connect(transport);\r\n}\r\n","/**\r\n * Auto-Start Service\r\n * Automatically starts the Hub server if not running\r\n * @module infrastructure/hub-launcher/auto-start\r\n */\r\n\r\nimport { spawn, type ChildProcess } from 'child_process';\r\nimport { createConnection } from 'net';\r\nimport { config } from '../../config/index.js';\r\n\r\n/**\r\n * Auto-start service options\r\n */\r\nexport interface AutoStartOptions {\r\n host?: string;\r\n port?: number;\r\n maxRetries?: number;\r\n retryDelay?: number;\r\n}\r\n\r\n/**\r\n * Checks if the Hub server is running\r\n */\r\nexport async function isHubRunning(\r\n host: string = config.hub.host,\r\n port: number = config.hub.port\r\n): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const socket = createConnection({ host, port }, () => {\r\n socket.end();\r\n resolve(true);\r\n });\r\n\r\n socket.on('error', () => {\r\n resolve(false);\r\n });\r\n\r\n socket.setTimeout(1000, () => {\r\n socket.destroy();\r\n resolve(false);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Waits for the Hub server to become available\r\n */\r\nexport async function waitForHub(\r\n host: string = config.hub.host,\r\n port: number = config.hub.port,\r\n maxRetries: number = config.autoStart.maxRetries,\r\n retryDelay: number = config.autoStart.retryDelay\r\n): Promise<boolean> {\r\n for (let i = 0; i < maxRetries; i++) {\r\n if (await isHubRunning(host, port)) {\r\n return true;\r\n }\r\n await new Promise((resolve) => setTimeout(resolve, retryDelay));\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Starts the Hub server as a background process\r\n */\r\nexport function startHubProcess(options: AutoStartOptions = {}): ChildProcess {\r\n const host = options.host ?? config.hub.host;\r\n const port = options.port ?? config.hub.port;\r\n\r\n // Start hub-main.js as a detached process\r\n const hubProcess = spawn(\r\n process.execPath,\r\n [\r\n '--experimental-specifier-resolution=node',\r\n new URL('../../hub-main.js', import.meta.url).pathname,\r\n '--host',\r\n host,\r\n '--port',\r\n port.toString(),\r\n ],\r\n {\r\n detached: true,\r\n stdio: 'ignore',\r\n }\r\n );\r\n\r\n hubProcess.unref();\r\n return hubProcess;\r\n}\r\n\r\n/**\r\n * Ensures the Hub is running, starting it if necessary\r\n */\r\nexport async function ensureHubRunning(options: AutoStartOptions = {}): Promise<boolean> {\r\n const host = options.host ?? config.hub.host;\r\n const port = options.port ?? config.hub.port;\r\n const maxRetries = options.maxRetries ?? config.autoStart.maxRetries;\r\n const retryDelay = options.retryDelay ?? config.autoStart.retryDelay;\r\n\r\n // Check if already running\r\n if (await isHubRunning(host, port)) {\r\n return true;\r\n }\r\n\r\n // Try to start the hub\r\n console.log(`Hub not running. Starting hub on ${host}:${port}...`);\r\n startHubProcess({ host, port });\r\n\r\n // Wait for it to become available\r\n const isRunning = await waitForHub(host, port, maxRetries, retryDelay);\r\n\r\n if (isRunning) {\r\n console.log('Hub started successfully');\r\n } else {\r\n console.error('Failed to start hub');\r\n }\r\n\r\n return isRunning;\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * MCP Server entry point\r\n * This is the main entry point for the MCP client that connects to Claude Code\r\n * @module mcp-main\r\n */\r\n\r\nimport { HubClient } from './infrastructure/websocket/hub-client.js';\r\nimport { startMcpServer } from './presentation/mcp/server.js';\r\nimport { ensureHubRunning } from './infrastructure/hub-launcher/auto-start.service.js';\r\nimport { config } from './config/index.js';\r\n\r\nconst args = process.argv.slice(2);\r\n\r\ninterface ClientOptions {\r\n team?: string;\r\n host: string;\r\n port: number;\r\n autoHub: boolean;\r\n}\r\n\r\nfunction parseArgs(): ClientOptions {\r\n const options: ClientOptions = {\r\n host: config.hub.host,\r\n port: config.hub.port,\r\n autoHub: false,\r\n };\r\n\r\n for (let i = 0; i < args.length; i++) {\r\n const arg = args[i];\r\n const nextArg = args[i + 1];\r\n\r\n if (arg === '--team' && nextArg) {\r\n options.team = nextArg;\r\n i++;\r\n } else if (arg === '--host' && nextArg) {\r\n options.host = nextArg;\r\n i++;\r\n } else if (arg === '--port' && nextArg) {\r\n options.port = parseInt(nextArg, 10);\r\n i++;\r\n } else if (arg === '--auto-hub') {\r\n options.autoHub = true;\r\n } else if (arg === '-h' || arg === '--help') {\r\n console.error(`\r\nClaude Collab MCP Client\r\n\r\nUsage:\r\n mcp-main [options]\r\n\r\nOptions:\r\n --team <team> Team to auto-join (optional)\r\n --host <host> Hub host (default: ${config.hub.host})\r\n --port <port> Hub port (default: ${config.hub.port})\r\n --auto-hub Auto-start hub if not running\r\n -h, --help Show this help message\r\n`);\r\n process.exit(0);\r\n }\r\n }\r\n\r\n return options;\r\n}\r\n\r\nasync function main(): Promise<void> {\r\n const options = parseArgs();\r\n\r\n // Auto-start hub if requested\r\n if (options.autoHub) {\r\n const hubRunning = await ensureHubRunning({\r\n host: options.host,\r\n port: options.port,\r\n });\r\n\r\n if (!hubRunning) {\r\n console.error('Failed to start hub server. Exiting.');\r\n process.exit(1);\r\n }\r\n }\r\n\r\n // Create hub client\r\n const hubClient = new HubClient(\r\n {\r\n host: options.host,\r\n port: options.port,\r\n reconnect: true,\r\n },\r\n {\r\n onError: (error) => {\r\n console.error('Hub client error:', error.message);\r\n },\r\n onQuestion: (question) => {\r\n // Questions will be handled by inbox tool\r\n console.error(`[Question received from ${question.from.displayName}]`);\r\n },\r\n }\r\n );\r\n\r\n // Connect to hub\r\n try {\r\n await hubClient.connect();\r\n\r\n // Auto-join team if specified\r\n if (options.team) {\r\n await hubClient.join(options.team, `${options.team} Claude`);\r\n console.error(`Auto-joined team: ${options.team}`);\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n console.error(`Failed to connect to hub: ${errorMessage}`);\r\n console.error('Make sure the hub server is running or use --auto-hub flag.');\r\n process.exit(1);\r\n }\r\n\r\n // Start MCP server\r\n await startMcpServer({ hubClient });\r\n}\r\n\r\nmain().catch((error) => {\r\n console.error('Unexpected error:', error);\r\n process.exit(1);\r\n});\r\n"]}
|