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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 32 additions & 42 deletions .env.test.example
Original file line number Diff line number Diff line change
@@ -1,50 +1,40 @@
# Provider test environment variables (integration/e2e)
# Copy to .env.test and fill in real credentials.

# Legacy generic provider config (kept for compatibility)
KODE_SDK_TEST_PROVIDER_BASE_URL=https://api.openai-next.com/
KODE_SDK_TEST_PROVIDER_API_KEY=replace-with-your-api-key
KODE_SDK_TEST_PROVIDER_MODEL=kimi-k2-turbo-preview
# =============================================================================
# ANTHROPIC (Claude)
# =============================================================================
ANTHROPIC_API_KEY=replace-with-your-anthropic-key
ANTHROPIC_MODEL_ID=claude-sonnet-4-5-20250929
ANTHROPIC_BASE_URL=https://api.openai-next.com
ANTHROPIC_ENABLE_INTERTWINED=0
ANTHROPIC_ENABLE_PDF=0

# Anthropic Thinking model (for extended thinking tests)
ANTHROPIC_THINKING_MODEL_ID=claude-sonnet-4-5-20250929-thinking

# OpenAI
# =============================================================================
# OPENAI - Chat Completions API
# =============================================================================
OPENAI_API_KEY=replace-with-your-openai-key
OPENAI_MODEL_ID=gpt-4o
OPENAI_BASE_URL=https://api.openai.com/v1
# OPENAI_OPENAI_API=chat
# OPENAI_ENABLE_PDF=1
# OPENAI_ENABLE_INTERTWINED=1
# OPENAI_PROXY_URL=http://
OPENAI_MODEL_ID=gpt-4.1
OPENAI_BASE_URL=https://api.openai-next.com/v1
OPENAI_API=chat

# Gemini
# =============================================================================
# OPENAI - Responses API (for reasoning models)
# =============================================================================
OPENAI_RESPONSES_API_KEY=replace-with-your-openai-key
OPENAI_RESPONSES_MODEL_ID=gpt-5.2
OPENAI_RESPONSES_BASE_URL=https://api.openai-next.com/v1
OPENAI_RESPONSES_API=responses
OPENAI_RESPONSES_REASONING_EFFORT=medium

# =============================================================================
# GEMINI (Google)
# =============================================================================
GEMINI_API_KEY=replace-with-your-gemini-key
GEMINI_MODEL_ID=gemini-3.0-flash
GEMINI_MODEL_ID=gemini-3-flash-preview
GEMINI_BASE_URL=https://generativelanguage.googleapis.com/v1beta
# GEMINI_ENABLE_PDF=1
# GEMINI_ENABLE_INTERTWINED=1
# GEMINI_PROXY_URL=http://

# Anthropic
ANTHROPIC_API_KEY=replace-with-your-anthropic-key
ANTHROPIC_MODEL_ID=claude-3-5-sonnet-20241022
ANTHROPIC_BASE_URL=https://api.anthropic.com
# ANTHROPIC_ENABLE_PDF=1
# ANTHROPIC_ENABLE_INTERTWINED=1
# ANTHROPIC_EXTRA_HEADERS={"anthropic-beta":"interleaved-thinking-2025-05-14"}
# ANTHROPIC_EXTRA_BODY={"thinking":{"type":"enabled","budget_tokens":1024}}
# ANTHROPIC_PROXY_URL=http://

# GLM (OpenAI-compatible)
GLM_API_KEY=replace-with-your-glm-key
GLM_MODEL_ID=glm-4.5
GLM_BASE_URL=https://api.z.ai/api/paas/v4
# GLM_ENABLE_PDF=1
# GLM_ENABLE_INTERTWINED=1
# GLM_EXTRA_BODY={"thinking":{"type":"enabled","clear_thinking":false}}

# MiniMax (OpenAI-compatible)
MINIMAX_API_KEY=replace-with-your-minimax-key
MINIMAX_MODEL_ID=MiniMax-M2.1
MINIMAX_BASE_URL=https://api.minimax.chat/v1
# MINIMAX_ENABLE_PDF=1
# MINIMAX_ENABLE_INTERTWINED=1
# MINIMAX_EXTRA_BODY={"reasoning_split":true}
GEMINI_ENABLE_INTERTWINED=1
GEMINI_ENABLE_PDF=1
205 changes: 205 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
name: CI Tests

on:
push:
branches: [main, develop, 'feature/**', 'refactor/**']
pull_request:
branches: [main, develop]
workflow_dispatch:

env:
NODE_VERSION: '20'

jobs:
# ===========================================================================
# Stage 1: Fast checks (run on every commit)
# ===========================================================================
lint-and-typecheck:
name: Lint & TypeCheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: TypeScript check
run: npx tsc --noEmit

- name: Build
run: npm run build

unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run unit tests
run: npm run test:unit

# ===========================================================================
# Stage 2: Provider E2E tests (run on every commit)
# ===========================================================================
provider-e2e:
name: Provider E2E
runs-on: ubuntu-latest
needs: [lint-and-typecheck, unit-tests]
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
provider:
- anthropic
- openai
- gemini

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Create test environment
run: |
cat > .env.test << 'EOF'
# Anthropic
ANTHROPIC_API_KEY=${{ secrets.ANTHROPIC_API_KEY }}
ANTHROPIC_MODEL_ID=${{ vars.ANTHROPIC_MODEL_ID }}
ANTHROPIC_BASE_URL=${{ vars.ANTHROPIC_BASE_URL }}
ANTHROPIC_ENABLE_INTERTWINED=0
ANTHROPIC_ENABLE_PDF=0

# OpenAI Chat
OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}
OPENAI_MODEL_ID=${{ vars.OPENAI_MODEL_ID }}
OPENAI_BASE_URL=${{ vars.OPENAI_BASE_URL }}
OPENAI_API=chat

# OpenAI Responses
OPENAI_RESPONSES_API_KEY=${{ secrets.OPENAI_API_KEY }}
OPENAI_RESPONSES_MODEL_ID=${{ vars.OPENAI_RESPONSES_MODEL_ID }}
OPENAI_RESPONSES_BASE_URL=${{ vars.OPENAI_RESPONSES_BASE_URL }}
OPENAI_RESPONSES_API=responses
OPENAI_RESPONSES_REASONING_EFFORT=medium

# Gemini
GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }}
GEMINI_MODEL_ID=${{ vars.GEMINI_MODEL_ID }}
GEMINI_BASE_URL=${{ vars.GEMINI_BASE_URL }}
GEMINI_ENABLE_INTERTWINED=1
GEMINI_ENABLE_PDF=1
EOF

- name: Run Anthropic E2E
if: matrix.provider == 'anthropic'
run: npx ts-node tests/e2e/providers/anthropic.test.ts
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

- name: Run OpenAI E2E
if: matrix.provider == 'openai'
run: npx ts-node tests/e2e/providers/openai.test.ts
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

- name: Run Gemini E2E
if: matrix.provider == 'gemini'
run: npx ts-node tests/e2e/providers/gemini.test.ts
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}

# ===========================================================================
# Stage 3: Agent Integration tests (comprehensive agent workflow testing)
# ===========================================================================
agent-integration:
name: Agent Integration
runs-on: ubuntu-latest
needs: [provider-e2e]
timeout-minutes: 30

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Create test environment
run: |
cat > .env.test << 'EOF'
# Use OpenAI for integration tests (most reliable)
OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}
OPENAI_MODEL_ID=${{ vars.OPENAI_MODEL_ID }}
OPENAI_BASE_URL=${{ vars.OPENAI_BASE_URL }}
OPENAI_API=chat

# Anthropic backup
ANTHROPIC_API_KEY=${{ secrets.ANTHROPIC_API_KEY }}
ANTHROPIC_MODEL_ID=${{ vars.ANTHROPIC_MODEL_ID }}
ANTHROPIC_BASE_URL=${{ vars.ANTHROPIC_BASE_URL }}

# Gemini backup
GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }}
GEMINI_MODEL_ID=${{ vars.GEMINI_MODEL_ID }}
GEMINI_BASE_URL=${{ vars.GEMINI_BASE_URL }}
EOF

- name: Run Agent Integration Tests
run: npx ts-node tests/integration/agent/ci-integration.test.ts
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}

# ===========================================================================
# Summary job
# ===========================================================================
ci-summary:
name: CI Summary
runs-on: ubuntu-latest
needs: [lint-and-typecheck, unit-tests, provider-e2e, agent-integration]
if: always()
steps:
- name: Check results
run: |
echo "=== CI Results ==="
echo "Lint & TypeCheck: ${{ needs.lint-and-typecheck.result }}"
echo "Unit Tests: ${{ needs.unit-tests.result }}"
echo "Provider E2E: ${{ needs.provider-e2e.result }}"
echo "Agent Integration: ${{ needs.agent-integration.result }}"

if [ "${{ needs.lint-and-typecheck.result }}" == "failure" ] || \
[ "${{ needs.unit-tests.result }}" == "failure" ] || \
[ "${{ needs.provider-e2e.result }}" == "failure" ] || \
[ "${{ needs.agent-integration.result }}" == "failure" ]; then
echo "Some tests failed!"
exit 1
fi
echo "All CI checks passed!"
Loading