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
23 changes: 11 additions & 12 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Integration Tests
name: SDK Server Contract Tests

on:
pull_request:
Expand All @@ -25,7 +25,7 @@ permissions:

jobs:
integration-tests:
name: Integration Tests with Docker
name: SDK Server Contract Tests
runs-on: ubuntu-latest
timeout-minutes: 15

Expand Down Expand Up @@ -98,16 +98,15 @@ jobs:

echo "✓ Server is healthy"

- name: Run integration tests
- name: Run server contract integration tests
working-directory: capiscio-sdk-python/tests/integration
env:
API_BASE_URL: http://server:8080
run: |
docker compose run --rm test-runner pytest tests/integration/ \
--ignore=tests/integration/test_dv_badge_flow.py \
--ignore=tests/integration/test_dv_order_api.py \
--ignore=tests/integration/test_dv_sdk.py \
--ignore=tests/integration/test_mcp_service.py \
# Cross-product and server-dependent workflow coverage is owned by
# capiscio-e2e-tests. This workflow is intentionally narrow and
# validates the SDK's direct server contract surface only.
docker compose run --rm test-runner pytest tests/integration/test_server_integration.py \
-v --tb=short --junit-xml=/workspace/test-results.xml

- name: Upload test results
Expand Down Expand Up @@ -212,7 +211,7 @@ jobs:
run: docker compose down -v

summary:
name: Integration Tests Summary
name: Server Contract Test Summary
needs: [integration-tests]
runs-on: ubuntu-latest
if: always()
Expand All @@ -221,10 +220,10 @@ jobs:
- name: Check results
run: |
if [ "${{ needs.integration-tests.result }}" != "success" ]; then
echo "❌ Integration tests failed"
echo "❌ SDK server contract tests failed"
exit 1
fi
echo "✅ Integration tests passed!"
echo "✅ SDK server contract tests passed!"

- name: Add PR comment
if: github.event_name == 'pull_request' && needs.integration-tests.result == 'success'
Expand All @@ -235,5 +234,5 @@ jobs:
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '✅ Integration tests passed! Server validation, BadgeKeeper, and gRPC tests all working.'
body: '✅ SDK server contract tests passed (test_server_integration.py). Cross-product scenarios are validated in capiscio-e2e-tests.'
})
15 changes: 10 additions & 5 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,17 @@ jobs:
run: |
pytest tests/unit/ -v --tb=short --cov=capiscio_sdk --cov-report=xml --cov-report=term --cov-fail-under=70

# Integration tests require a running capiscio-server
# They run in capiscio-e2e-tests repo with full infrastructure
- name: Run integration tests (server-independent only)
# Server-dependent integration/E2E coverage is owned by capiscio-e2e-tests.
# This job keeps fast contract coverage for SDK-only integration behavior.
- name: Run integration contract tests (server-independent)
run: |
# Only run tests that don't require server connection
pytest tests/integration/ -v --tb=short -k "not server" --ignore=tests/integration/test_server_integration.py --ignore=tests/integration/test_dv_badge_flow.py --ignore=tests/integration/test_dv_order_api.py
# Only run tests that don't require server connection or external binaries
pytest tests/integration/ -v --tb=short -k "not server" \
--ignore=tests/integration/test_server_integration.py \
--ignore=tests/integration/test_dv_badge_flow.py \
--ignore=tests/integration/test_dv_order_api.py \
--ignore=tests/integration/test_dv_sdk.py \
--ignore=tests/integration/test_mcp_service.py
continue-on-error: true

- name: Upload coverage to Codecov
Expand Down
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,34 @@ print(agent.name) # Agent name
| `auto_badge` | Request badge automatically | `True` |
| `dev_mode` | Use self-signed badges (Level 0) | `False` |

### Name-Based Agent Lookup
### Agent Discovery & Recovery

When you specify a `name`, the SDK will:
1. Search for an existing agent with that name
2. If not found, **create a new agent** with that name
3. Return the agent identity
The SDK uses a smart discovery flow to find or create your agent:

1. **Local keys check** - Scans `~/.capiscio/keys/*/` for any agent subdirectory with valid keys
2. **DID-based verification** - Verifies local DID matches server's DID before reusing identity
3. **Name-based lookup** - Falls back to searching by name if no local keys found
4. **Auto-create** - Creates new agent if not found

```python
# First run: creates "my-research-agent"
# First run: creates "my-research-agent" + generates keys
agent = CapiscIO.connect(api_key="...", name="my-research-agent")

# Second run: finds existing "my-research-agent"
# Second run: finds agent by existing keys (even if name changed in dashboard)
agent = CapiscIO.connect(api_key="...", name="my-research-agent")
```

**Key directory structure:**
```
~/.capiscio/keys/
└── {agent-uuid}/
├── private.jwk # Ed25519 private key
├── public.jwk # Public key (contains DID in 'kid' field)
└── agent-card.json # Agent metadata
```

**Recovery behavior:** If the SDK finds existing keys but the agent's DID isn't registered with the server, it will automatically complete registration. This handles crash recovery scenarios gracefully.

### Using Environment Variables

```python
Expand Down
Loading
Loading