Metadata-Version: 2.5
Name: diteko
Version: 0.1.0
Summary: Generate, export and run tests for Amazon Connect contact flows with Diteko (Grammatical Evolution).
Author: Lehlohonolo Sehako
License-Expression: MIT
License-File: LICENSE
Keywords: amazon-connect,contact-flow,cxblueprint,grammatical-evolution,ivr,mcp,testing
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Telephony
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Provides-Extra: cxblueprint
Requires-Dist: cxblueprint>=0.1.0.post15; extra == 'cxblueprint'
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp<3,>=1.26.0; extra == 'mcp'
Description-Content-Type: text/markdown

# diteko (Python)

Generate, export and run tests for Amazon Connect contact flows, from Python. It is the
testing counterpart to [cxblueprint](https://pypi.org/project/cxblueprint/): build or
export a flow, then let Diteko derive its grammar, evolve a test suite with Grammatical
Evolution, export it, and run it on Connect's native testing.

The SDK is a client: it talks to a running Diteko deployment over its REST API, so you need
one to point it at. Diteko has no application-level authentication, so point the SDK only
at a deployment inside your network or behind your VPN.

```bash
pip install diteko               # SDK
pip install "diteko[mcp]"        # + MCP server for Claude Desktop / Cursor / VS Code
pip install "diteko[cxblueprint]"
```

## The pipeline

```python
from diteko import Diteko

dk = Diteko("http://localhost:8888")

project = dk.projects.from_json("claims.json")          # Connect export or cxblueprint output
project.grammar.generate()                              # derive, store and validate the grammar
run = project.evolve(preset="standard", focus="balanced").wait()
suite = run.suite(top=30, selection="coverage")         # or selection="fitness"

for test in suite:
    print(test.test_id, test.keys, test.fitness)

suite.export_xlsx("claims-tests.xlsx")                  # manual test script (ISO/IEC/IEEE 29119-3)
suite.export_native("claims-native.json")               # Amazon Connect native test cases
result = suite.publish_to_connect(dry_run=True)         # dry run unless you say otherwise
print(result.passed, result.failed, result.verdicts)
```

### Straight from cxblueprint

```python
from cxblueprint import Flow
from diteko import Diteko

flow = Flow.build("Burger Order")
menu = flow.get_input("Press 1 for Classic or 2 for Veggie", timeout=10)
# ... build the flow as usual ...

project = Diteko().projects.from_cxblueprint(flow)      # compiles locally, uploads the JSON
```

### Other ways in

```python
dk.projects.import_from_connect("08e145dc-d959-4094-9021-6f10d8590be2")   # from the instance
dk.projects.list()                                      # every project and its next step
dk.projects.get(21601).suite(top=10).export_xlsx()
```

### Grammars as BNF or JSON

The two forms are exact reflections of each other. Both are validated by the same parser,
and both keep comments.

```python
g = project.grammar.latest()
spec = g.to_json()                    # {"format": "diteko-grammar/v1", "start": ..., "rules": [...]}
g.replace(spec, format="json").save() # edit as JSON, store as canonical BNF
dk.convert_grammar(bnf_text, "bnf", "json")
```

### Presets

| `preset`   | calls × generations |
| ---------- | ------------------- |
| `quick`    | 40 × 15             |
| `standard` | 100 × 50            |
| `thorough` | 200 × 120           |

| `focus`     | favours                                              |
| ----------- | ---------------------------------------------------- |
| `balanced`  | blocks and branches, plus happy paths and recoveries |
| `coverage`  | visiting as much of the flow as possible             |
| `errors`    | timeouts and wrong keys that still end properly      |
| `transfers` | calls that reach an agent queue                      |

Pass `population=`, `generations=`, `weights={"state_coverage": 1.0}` or `seed=` to go beyond them.

## MCP server

```bash
DITEKO_URL=http://localhost:8888 diteko-mcp
```

```json
{ "mcpServers": { "diteko": { "command": "diteko-mcp", "env": { "DITEKO_URL": "http://localhost:8888" } } } }
```

| Tool               | Does                                                                                   |
| ------------------ | -------------------------------------------------------------------------------------- |
| `list_projects`    | every flow under test and its next step                                                |
| `import_flow`      | register a flow from JSON text, a file path, or a Connect flow id                      |
| `generate_grammar` | derive, store and validate a flow's grammar                                            |
| `convert_grammar`  | BNF ⇄ JSON                                                                             |
| `start_evolution`  | start a run (`size`, `focus`, `seed`)                                                  |
| `get_run`          | a run's progress                                                                       |
| `export_suite`     | `xlsx`, `json` or `native` to a file                                                   |
| `publish_suite`    | run on Connect; **`dry_run` defaults to true**, since a live run bills the AWS account |

Each tool carries MCP annotations: read-only tools say so, and `publish_suite` is marked as reaching an external system. Works with `mcp` 1.x and 2.x.

## Development

```bash
cd clients/python
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev,mcp]"
pytest                                   # against an in-memory fake of the API
DITEKO_URL=http://localhost:8888 pytest  # also runs the live test against a local stack
```
