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
2 changes: 2 additions & 0 deletions .github/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@ The SDK has **7 test categories** with different execution strategies.
def test_something():
pass


# ❌ INCORRECT - No category marker, will NOT run in CI
def test_something_else():
pass


# βœ… CORRECT - Multiple markers including category
@pytest.mark.e2e
@pytest.mark.long_running
Expand Down
12 changes: 8 additions & 4 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,14 @@ make lint # Ruff formatting + MyPy type checking
```python
from aignostics.utils import BaseService, Health


class Service(BaseService):
def __init__(self):
super().__init__(SettingsClass) # Optional settings

def health(self) -> Health:
return Health(status=Health.Code.UP)

def info(self, mask_secrets: bool = True) -> dict:
return {"version": "1.0.0"}
```
Expand All @@ -114,6 +115,7 @@ from ._service import Service

cli = typer.Typer(name="module", help="Module description")


@cli.command("action")
def action_command(param: str):
"""Command description."""
Expand All @@ -126,6 +128,7 @@ def action_command(param: str):
```python
from nicegui import ui


def create_page():
ui.label("Module Interface")
# Components auto-register with GUI launcher
Expand Down Expand Up @@ -177,9 +180,10 @@ def create_page():
```python
from pydantic_settings import BaseSettings


class Settings(BaseSettings):
api_root: str = "https://platform.aignostics.com"

class Config:
env_prefix = "AIGNOSTICS_"
```
Expand All @@ -200,7 +204,7 @@ client = platform.Client()
run = client.runs.create(
application_id="heta",
application_version="1.0.0", # version number without 'v' prefix, omit for latest
items=[platform.InputItem(...)]
items=[platform.InputItem(...)],
)

# 3. Monitor & download
Expand Down
129 changes: 42 additions & 87 deletions API_REFERENCE_v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,12 @@ Base URLs:

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/applications', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/applications", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -208,15 +205,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/applications/{application_id}', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/applications/{application_id}", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -295,15 +289,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/applications/{application_id}/versions/{version}', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/applications/{application_id}/versions/{version}", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -571,15 +562,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/runs', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/runs", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -962,16 +950,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.post('/api/v1/runs', headers = headers)
headers = {"Content-Type": "application/json", "Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.post("/api/v1/runs", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -1188,15 +1172,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/runs/{run_id}', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/runs/{run_id}", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -1298,15 +1279,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.post('/api/v1/runs/{run_id}/cancel', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.post("/api/v1/runs/{run_id}/cancel", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -1380,15 +1358,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/runs/{run_id}/items', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/runs/{run_id}/items", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -1798,15 +1773,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/runs/{run_id}/items/{external_id}', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/runs/{run_id}/items/{external_id}", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -1899,15 +1871,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/runs/{run_id}/artifacts/{artifact_id}/file', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/runs/{run_id}/artifacts/{artifact_id}/file", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -1983,15 +1952,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.delete('/api/v1/runs/{run_id}/artifacts', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.delete("/api/v1/runs/{run_id}/artifacts", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -2062,16 +2028,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.put('/api/v1/runs/{run_id}/custom-metadata', headers = headers)
headers = {"Content-Type": "application/json", "Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.put("/api/v1/runs/{run_id}/custom-metadata", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -2171,16 +2133,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.put('/api/v1/runs/{run_id}/items/{external_id}/custom-metadata', headers = headers)
headers = {"Content-Type": "application/json", "Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.put("/api/v1/runs/{run_id}/items/{external_id}/custom-metadata", headers=headers)

print(r.json())
```

```javascript
Expand Down Expand Up @@ -2280,15 +2238,12 @@ OAuth2AuthorizationCodeBearer

```python
import requests
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer {access-token}'
}

r = requests.get('/api/v1/me', headers = headers)
headers = {"Accept": "application/json", "Authorization": "Bearer {access-token}"}

print(r.json())
r = requests.get("/api/v1/me", headers=headers)

print(r.json())
```

```javascript
Expand Down
22 changes: 12 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,7 @@ for app in client.applications.list():
print(app.application_id)

# Submit run
run = client.runs.create(
application_id="heta",
files=["slide.svs"]
)
run = client.runs.create(application_id="heta", files=["slide.svs"])
```

### Service Discovery Pattern
Expand Down Expand Up @@ -464,6 +461,7 @@ This ensures the JSON Schema is automatically regenerated during documentation b
```python
from aignostics.utils import BaseService, Health


class Service(BaseService):
"""Module service implementation."""

Expand All @@ -484,6 +482,7 @@ from ._service import Service

cli = typer.Typer(name="module", help="Module description")


@cli.command("action")
def action_command(param: str):
"""Action description."""
Expand Down Expand Up @@ -709,8 +708,10 @@ details = run.details()
if details.output.state == RunState.TERMINATED:
if details.output.termination_reason == RunTerminationReason.ALL_ITEMS_PROCESSED:
print(f"βœ… Run complete: {details.output.statistics.succeeded} items succeeded")
print(f"❌ Failures: {details.output.statistics.user_error} user errors, "
f"{details.output.statistics.system_error} system errors")
print(
f"❌ Failures: {details.output.statistics.user_error} user errors, "
f"{details.output.statistics.system_error} system errors"
)
```

See `platform/CLAUDE.md` for complete state machine diagrams and migration guide.
Expand Down Expand Up @@ -866,10 +867,10 @@ The test suite uses pytest-xdist for parallel execution with intelligent distrib
```python
# Worker factors control parallelism
XDIST_WORKER_FACTOR = {
"unit": 0.0, # No parallelization (fast, no overhead needed)
"integration": 0.2, # 20% of logical CPUs
"e2e": 1.0, # 100% of logical CPUs (I/O bound)
"default": 1.0 # 100% for mixed test runs
"unit": 0.0, # No parallelization (fast, no overhead needed)
"integration": 0.2, # 20% of logical CPUs
"e2e": 1.0, # 100% of logical CPUs (I/O bound)
"default": 1.0, # 100% for mixed test runs
}

# Calculate workers: max(1, int(cpu_count * factor))
Expand Down Expand Up @@ -1009,6 +1010,7 @@ uv run pytest -m "e2e and not long_running" -v
import pytest
from unittest.mock import patch


@pytest.mark.unit
def test_sdk_metadata_minimal(monkeypatch):
"""Test SDK metadata with clean environment."""
Expand Down
Loading
Loading