Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3389c07
Add elicitation POC
chrisreddington Aug 4, 2025
e2ab29c
Update so that either player can go first
chrisreddington Aug 4, 2025
41b011c
Consolidate create_game tools
chrisreddington Aug 7, 2025
5454e71
Consolidate play tools
chrisreddington Aug 7, 2025
07d69b9
Merge pull request #1 from chrisreddington/elicitation
chrisreddington Aug 7, 2025
302c5d6
Initial plan
Copilot Aug 7, 2025
90ec8a8
Phase 1: Add shared constants infrastructure
Copilot Aug 7, 2025
ecc3323
Phase 2: Create DifficultyBadge component and consolidate UI
Copilot Aug 7, 2025
9467eff
Phase 3: Integrate shared constants across MCP server handlers
Copilot Aug 7, 2025
4572dbb
Port tests
chrisreddington Aug 7, 2025
41b8c01
Merge pull request #3 from chrisreddington/copilot/fix-2
chrisreddington Aug 7, 2025
44649ec
Initial plan
Copilot Aug 7, 2025
c8fa39f
Initial setup: Fix TypeScript build issues for consolidation work
Copilot Aug 7, 2025
ee6012f
Phase 1-2: Consolidate HTTP clients and remove dead code
Copilot Aug 7, 2025
d0f6d1c
Phase 3: Consolidate test mock patterns and shared test data
Copilot Aug 7, 2025
bf807ef
Phase 4: Consolidate test setup patterns and complete consolidation
Copilot Aug 7, 2025
c6d7e38
Update instructions and reduce type union duplication
chrisreddington Aug 7, 2025
fc8b73c
Add type to remove ide warnings
chrisreddington Aug 7, 2025
b33ed95
Merge pull request #5 from chrisreddington/copilot/fix-4
chrisreddington Aug 7, 2025
3920441
Fix RPS game complete bug, and add number of rounds support
chrisreddington Aug 7, 2025
3bbf4d8
Merge remote-tracking branch 'origin/main' - resolved conflicts in ro…
chrisreddington Aug 7, 2025
de6ddda
Fix MCP config
chrisreddington Aug 7, 2025
6644741
Fix "smart" elicitation
chrisreddington Aug 7, 2025
6af99ca
Add elicitation tests
chrisreddington Aug 7, 2025
b1c5231
Fix ESLint warnings
chrisreddington Aug 7, 2025
15f7c6a
Add eslint config across the board
chrisreddington Aug 7, 2025
ca4d8a3
Merge pull request #6 from chrisreddington/elicitation-take-two
chrisreddington Aug 7, 2025
963acfc
Initial plan
Copilot Aug 7, 2025
e3b0014
Fix all ESLint errors and missing return types in shared workspace
Copilot Aug 7, 2025
d91b6bc
Complete ESLint fixes - resolved 18 of 26 issues in shared workspace
Copilot Aug 7, 2025
6b84604
Merge pull request #8 from chrisreddington/copilot/fix-7
chrisreddington Aug 7, 2025
be70dc8
Fix linting errors for MCP workspace
chrisreddington Aug 7, 2025
c3c1213
Fix linting step
chrisreddington Aug 7, 2025
f66a85c
Update types
chrisreddington Aug 7, 2025
05d1746
Fixing quality checks
chrisreddington Aug 7, 2025
868d088
Bump the npm-development group with 4 updates
dependabot[bot] Aug 7, 2025
2be1209
Bump the npm-production group with 2 updates
dependabot[bot] Aug 7, 2025
ebc64b2
Merge pull request #10 from chrisreddington/dependabot/npm_and_yarn/n…
chrisreddington Aug 7, 2025
97b70d0
Merge pull request #11 from chrisreddington/dependabot/npm_and_yarn/n…
chrisreddington Aug 7, 2025
febb983
Update deps, CI and configs
chrisreddington Aug 7, 2025
3e32b7d
Replace lint web with lint all
chrisreddington Aug 7, 2025
9bce68f
Update tool call descriptions
chrisreddington Aug 7, 2025
56b8c71
Apply suggestion from @Copilot
chrisreddington Aug 8, 2025
c7be6db
Minor tweaks to init
chrisreddington Aug 8, 2025
65a7cac
Package cleanup
chrisreddington Aug 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/instructions/mcp-server.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ Implement consistent difficulty levels across all games:
```typescript
export function calculateTicTacToeMove(
gameState: TicTacToeGameState,
difficulty: 'easy' | 'medium' | 'hard' = 'medium'
difficulty: Difficulty = 'medium'
): TicTacToeMove {
const validMoves = getValidMoves(gameState)

Expand Down
83 changes: 83 additions & 0 deletions .github/instructions/shared-library.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,89 @@ export function getGameDisplayName(type: GameType): string {
}
```

## Constants and Common Values

### Centralized Constants and Derived Types
**Types are derived from constants using `as const` assertions - constants are the single source of truth:**

```typescript
// ✅ Constants define the source of truth
export const DIFFICULTIES = ['easy', 'medium', 'hard'] as const
export const GAME_TYPES = ['tic-tac-toe', 'rock-paper-scissors'] as const
export const PLAYER_IDS = { HUMAN: 'player1', PLAYER2: 'player2', AI: 'ai' } as const

// ✅ Types are derived from constants
export type Difficulty = typeof DIFFICULTIES[number]
export type GameType = typeof GAME_TYPES[number]
export type PlayerId = typeof PLAYER_IDS[keyof typeof PLAYER_IDS]

// ✅ Import the derived types
import type { Difficulty, GameType } from '@turn-based-mcp/shared'

// ❌ Don't define duplicate union types
export type Difficulty = 'easy' | 'medium' | 'hard' // This duplicates the constants!
```

### Available Constants
Key constants provided by the shared library:

```typescript
// Constants with derived types
export const GAME_TYPES = ['tic-tac-toe', 'rock-paper-scissors'] as const
export const DIFFICULTIES = ['easy', 'medium', 'hard'] as const
export const PLAYER_IDS = { HUMAN: 'player1', PLAYER2: 'player2', AI: 'ai' } as const
export const GAME_STATUSES = ['waiting', 'playing', 'finished'] as const

// Derived types (auto-generated from constants)
export type GameType = typeof GAME_TYPES[number]
export type Difficulty = typeof DIFFICULTIES[number]
export type PlayerId = typeof PLAYER_IDS[keyof typeof PLAYER_IDS]
export type GameStatus = typeof GAME_STATUSES[number]

// Default values
export const DEFAULT_PLAYER_NAME = 'Player'
export const DEFAULT_AI_DIFFICULTY: Difficulty = 'medium'

// UI display configuration
export const DIFFICULTY_DISPLAY = {
easy: { emoji: '😌', label: 'Easy' },
medium: { emoji: '🎯', label: 'Medium' },
hard: { emoji: '🔥', label: 'Hard' }
} as const
```

### Type Guards and Utilities
Use provided validation functions that work with the constants:

```typescript
// Type guards (check against the constant arrays)
export function isSupportedGameType(gameType: string): gameType is GameType
export function isValidDifficulty(difficulty: string): difficulty is Difficulty
export function isValidPlayerId(playerId: string): playerId is PlayerId

// Display helpers
export function getDifficultyDisplay(difficulty: Difficulty)
```

### Architecture Benefits
This approach ensures:
- **Single source of truth**: Constants define what values are valid
- **Type safety**: TypeScript derives exact types from the constant values
- **Runtime validation**: Type guards check against the same arrays used to derive types
- **Maintainability**: Add a new difficulty by updating one constant array

### Testing Constants
For mocking and test data, use shared testing utilities:

```typescript
// Test data from shared/src/testing/
import {
mockTicTacToeGameState,
mockRPSGameState,
createMockGameSession
} from '@turn-based-mcp/shared/testing'
```

## Testing Infrastructure

### Test Database Utilities
Expand Down
27 changes: 27 additions & 0 deletions .github/instructions/testing.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,33 @@ Follow these testing patterns for the turn-based games platform:
})
```

## Shared Testing Utilities

**Use centralized mock data and test utilities from the shared package:**

```typescript
// ✅ Import shared testing utilities
import {
mockTicTacToeGameState,
mockRPSGameState,
createMockGameSession,
setupTestDatabase,
clearTestDatabase
} from '@turn-based-mcp/shared/testing'

// ✅ Use shared constants in tests
import { DIFFICULTIES, GAME_TYPES } from '@turn-based-mcp/shared'

// ❌ Don't recreate mock data locally
const localMockGameState = { /* duplicated data */ } // Use shared mocks instead!
```

**Available shared testing utilities:**
- Mock game states: `mockTicTacToeGameState`, `mockRPSGameState`
- Factory functions: `createMockGameSession`, `createMockPlayer`
- Database utilities: `setupTestDatabase`, `clearTestDatabase`, `teardownTestDatabase`
- Type assertions and validation helpers

## Component Testing

- Always render components with realistic props
Expand Down
31 changes: 31 additions & 0 deletions .github/instructions/typescript.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,37 @@ Follow these TypeScript patterns for consistent, type-safe code:
- Use barrel exports (`index.ts`) for clean imports
- Re-export shared types from `@turn-based-mcp/shared`

### Shared Types and Constants
**Always import types derived from shared constants - don't duplicate union types:**

```typescript
// ✅ Import types derived from constants
import type { Difficulty, GameType, PlayerId } from '@turn-based-mcp/shared'
import { DIFFICULTIES, DEFAULT_AI_DIFFICULTY, GAME_TYPES, PLAYER_IDS } from '@turn-based-mcp/shared'

// ✅ Use the imported types
const [aiDifficulty, setAiDifficulty] = useState<Difficulty>('medium')
const playerIds: PlayerId[] = Object.values(PLAYER_IDS)

// ❌ Don't define duplicate union types
type Difficulty = 'easy' | 'medium' | 'hard' // This duplicates shared constants!
type PlayerId = 'player1' | 'player2' | 'ai' // Use the derived type instead!
```

**Key principle: Types are derived from constants using `as const` assertions:**
```typescript
// In shared/src/constants/game-constants.ts
export const DIFFICULTIES = ['easy', 'medium', 'hard'] as const
export type Difficulty = typeof DIFFICULTIES[number] // 'easy' | 'medium' | 'hard'
```

**Common types available from shared package:**
- `Difficulty` - AI difficulty levels (derived from `DIFFICULTIES`)
- `GameType` - Supported game types (derived from `GAME_TYPES`)
- `PlayerId` - Player identifiers (derived from `PLAYER_IDS`)
- `GameStatus` - Game state values (derived from `GAME_STATUSES`)
- Game-specific interfaces: `TicTacToeGameState`, `RPSGameState`, etc.

### Interface Design
- Use interfaces for object shapes and component props
- Include JSDoc comments for complex properties
Expand Down
36 changes: 20 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,30 @@ jobs:
run: npm ci

- name: Build shared package
run: npm run build --workspace=shared
run: npm run build --workspace=@turn-based-mcp/shared

- name: Verify shared build artifacts
run: |
test -f shared/dist/index.js || (echo 'shared/dist/index.js missing' && exit 1)
test -f shared/dist/testing/index.js || (echo 'shared/dist/testing/index.js missing' && exit 1)

- name: Type check all workspaces
run: npm run type-check

- name: Build web package
run: npm run build --workspace=web
run: npm run build --workspace=@turn-based-mcp/web

- name: Build mcp-server package
run: npm run build --workspace=mcp-server

- name: Lint web package
run: npm run lint --workspace=web

# Future: Add test steps when tests are implemented
# - name: Run tests - shared
# run: npm run test --workspace=shared
#
# - name: Run tests - web
# run: npm run test --workspace=web
#
# - name: Run tests - mcp-server
# run: npm run test --workspace=mcp-server
run: npm run build --workspace=@turn-based-mcp/mcp-server

- name: Run tests - shared
run: npm run test --workspace=@turn-based-mcp/shared

- name: Run tests - web
run: npm run test --workspace=@turn-based-mcp/web

- name: Run tests - mcp-server
run: npm run test --workspace=@turn-based-mcp/mcp-server

- name: Lint all packages
run: npm run lint:all
2 changes: 1 addition & 1 deletion .vscode/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"servers": {
"turn-based-games": {
"command": "node",
"args": ["dist/index.js"],
"args": ["dist/server.js"],
"cwd": "./mcp-server"
},
"playwright": {
Expand Down
31 changes: 31 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// @ts-check

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.{js,mjs,cjs,ts}'],
languageOptions: {
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
},
rules: {
// Add any global rules here
},
},
{
ignores: [
'**/node_modules/**',
'**/dist/**',
'**/.next/**',
'**/coverage/**',
'**/*.config.js',
'**/*.config.ts',
],
}
);
41 changes: 41 additions & 0 deletions mcp-server/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// @ts-check

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.{js,mjs,cjs,ts}'],
languageOptions: {
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
},
rules: {
// MCP server specific rules
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'@typescript-eslint/explicit-function-return-type': 'warn',
'@typescript-eslint/no-explicit-any': 'warn',
'no-console': 'off', // Console logging is often needed for MCP servers
},
},
{
files: ['**/*.test.ts', 'vitest.*.ts'],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
},
{
ignores: [
'node_modules/**',
'dist/**',
'coverage/**',
'*.config.js',
'*.config.ts',
],
}
);
39 changes: 0 additions & 39 deletions mcp-server/jest.config.cjs

This file was deleted.

27 changes: 0 additions & 27 deletions mcp-server/jest.setup.js

This file was deleted.

Loading