spinekit 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spinekit-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- spinekit-0.2.0/.github/workflows/ci.yml +35 -0
- spinekit-0.2.0/.github/workflows/docs.yml +39 -0
- spinekit-0.2.0/.github/workflows/release.yml +44 -0
- spinekit-0.2.0/.gitignore +21 -0
- spinekit-0.2.0/.python-version +1 -0
- spinekit-0.2.0/.release-please-manifest.json +3 -0
- spinekit-0.2.0/CHANGELOG.md +54 -0
- spinekit-0.2.0/CODE_OF_CONDUCT.md +57 -0
- spinekit-0.2.0/LICENSE +21 -0
- spinekit-0.2.0/PKG-INFO +149 -0
- spinekit-0.2.0/README.md +89 -0
- spinekit-0.2.0/docs/architecture.md +94 -0
- spinekit-0.2.0/docs/assets/favicon.svg +8 -0
- spinekit-0.2.0/docs/assets/logo-hero.svg +14 -0
- spinekit-0.2.0/docs/assets/logo.svg +10 -0
- spinekit-0.2.0/docs/concepts/guards.md +48 -0
- spinekit-0.2.0/docs/concepts/hitl.md +60 -0
- spinekit-0.2.0/docs/concepts/kernel.md +68 -0
- spinekit-0.2.0/docs/concepts/middleware.md +67 -0
- spinekit-0.2.0/docs/concepts/observability.md +63 -0
- spinekit-0.2.0/docs/concepts/providers.md +53 -0
- spinekit-0.2.0/docs/concepts/state.md +60 -0
- spinekit-0.2.0/docs/concepts/tools.md +72 -0
- spinekit-0.2.0/docs/contributing.md +102 -0
- spinekit-0.2.0/docs/deepdive/eval.md +121 -0
- spinekit-0.2.0/docs/deepdive/mcp.md +100 -0
- spinekit-0.2.0/docs/develop/backend.md +92 -0
- spinekit-0.2.0/docs/develop/middleware.md +88 -0
- spinekit-0.2.0/docs/develop/provider.md +96 -0
- spinekit-0.2.0/docs/develop/publish.md +117 -0
- spinekit-0.2.0/docs/guides/deployment.md +61 -0
- spinekit-0.2.0/docs/guides/eval.md +61 -0
- spinekit-0.2.0/docs/guides/examples.md +314 -0
- spinekit-0.2.0/docs/guides/guardrails.md +65 -0
- spinekit-0.2.0/docs/guides/mcp.md +38 -0
- spinekit-0.2.0/docs/guides/memory.md +79 -0
- spinekit-0.2.0/docs/guides/models.md +88 -0
- spinekit-0.2.0/docs/guides/orchestration.md +52 -0
- spinekit-0.2.0/docs/guides/patterns.md +180 -0
- spinekit-0.2.0/docs/index.md +57 -0
- spinekit-0.2.0/docs/install.md +65 -0
- spinekit-0.2.0/docs/quickstart.md +81 -0
- spinekit-0.2.0/docs/reference/api.md +123 -0
- spinekit-0.2.0/docs/reference/cli.md +156 -0
- spinekit-0.2.0/docs/reference/data-model.md +174 -0
- spinekit-0.2.0/docs/reference/middleware.md +58 -0
- spinekit-0.2.0/docs/reference/plugins.md +70 -0
- spinekit-0.2.0/docs/stylesheets/extra.css +133 -0
- spinekit-0.2.0/mkdocs.yml +136 -0
- spinekit-0.2.0/overrides/home.html +42 -0
- spinekit-0.2.0/packages/spine-a2a/src/spine_a2a/__init__.py +17 -0
- spinekit-0.2.0/packages/spine-a2a/src/spine_a2a/client.py +101 -0
- spinekit-0.2.0/packages/spine-a2a/src/spine_a2a/py.typed +0 -0
- spinekit-0.2.0/packages/spine-a2a/tests/test_a2a.py +74 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/__init__.py +27 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/embeddings.py +68 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/memory.py +99 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/migrations.py +39 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/pgvector.py +140 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/postgres.py +85 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/py.typed +0 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/redis.py +58 -0
- spinekit-0.2.0/packages/spine-backends/src/spine_backends/sqlite.py +103 -0
- spinekit-0.2.0/packages/spine-backends/tests/test_conformance.py +76 -0
- spinekit-0.2.0/packages/spine-backends/tests/test_memory.py +88 -0
- spinekit-0.2.0/packages/spine-backends/tests/test_sqlite.py +75 -0
- spinekit-0.2.0/packages/spine-cli/src/spine_cli/__init__.py +5 -0
- spinekit-0.2.0/packages/spine-cli/src/spine_cli/app.py +363 -0
- spinekit-0.2.0/packages/spine-cli/src/spine_cli/builder.py +86 -0
- spinekit-0.2.0/packages/spine-cli/src/spine_cli/config.py +92 -0
- spinekit-0.2.0/packages/spine-cli/src/spine_cli/plugins.py +54 -0
- spinekit-0.2.0/packages/spine-cli/src/spine_cli/py.typed +0 -0
- spinekit-0.2.0/packages/spine-cli/src/spine_cli/templates.py +122 -0
- spinekit-0.2.0/packages/spine-cli/tests/test_cli.py +204 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/__init__.py +117 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/agent.py +540 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/checkpoint.py +39 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/control.py +25 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/errors.py +23 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/guards.py +45 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/interrupt.py +24 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/memory.py +48 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/messages.py +123 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/middleware.py +157 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/provider.py +103 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/py.typed +0 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/registry.py +76 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/result.py +55 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/state.py +58 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/testing.py +87 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/tools.py +147 -0
- spinekit-0.2.0/packages/spine-core/src/spine_core/trace.py +59 -0
- spinekit-0.2.0/packages/spine-core/tests/test_hitl.py +102 -0
- spinekit-0.2.0/packages/spine-core/tests/test_kernel.py +269 -0
- spinekit-0.2.0/packages/spine-core/tests/test_state.py +79 -0
- spinekit-0.2.0/packages/spine-eval/src/spine_eval/__init__.py +42 -0
- spinekit-0.2.0/packages/spine-eval/src/spine_eval/loader.py +37 -0
- spinekit-0.2.0/packages/spine-eval/src/spine_eval/models.py +120 -0
- spinekit-0.2.0/packages/spine-eval/src/spine_eval/py.typed +0 -0
- spinekit-0.2.0/packages/spine-eval/src/spine_eval/runner.py +71 -0
- spinekit-0.2.0/packages/spine-eval/src/spine_eval/scorers.py +132 -0
- spinekit-0.2.0/packages/spine-eval/tests/test_eval.py +165 -0
- spinekit-0.2.0/packages/spine-mcp/src/spine_mcp/__init__.py +17 -0
- spinekit-0.2.0/packages/spine-mcp/src/spine_mcp/py.typed +0 -0
- spinekit-0.2.0/packages/spine-mcp/src/spine_mcp/toolset.py +126 -0
- spinekit-0.2.0/packages/spine-mcp/tests/test_mcp.py +89 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/__init__.py +72 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/cache.py +80 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/compaction.py +39 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/cost.py +35 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/fallback.py +30 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/guardrails.py +170 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/loopguard.py +43 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/memory.py +66 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/multitenancy.py +52 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/py.typed +0 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/reliability.py +120 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/replay.py +63 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/retry.py +43 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/sandbox.py +99 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/structured.py +79 -0
- spinekit-0.2.0/packages/spine-middleware/src/spine_middleware/tooling.py +43 -0
- spinekit-0.2.0/packages/spine-middleware/tests/test_cache.py +73 -0
- spinekit-0.2.0/packages/spine-middleware/tests/test_guardrails.py +82 -0
- spinekit-0.2.0/packages/spine-middleware/tests/test_memory_recall.py +49 -0
- spinekit-0.2.0/packages/spine-middleware/tests/test_middleware.py +130 -0
- spinekit-0.2.0/packages/spine-middleware/tests/test_multitenancy.py +48 -0
- spinekit-0.2.0/packages/spine-middleware/tests/test_reliability.py +114 -0
- spinekit-0.2.0/packages/spine-middleware/tests/test_replay.py +51 -0
- spinekit-0.2.0/packages/spine-middleware/tests/test_sandbox.py +45 -0
- spinekit-0.2.0/packages/spine-orchestration/src/spine_orchestration/__init__.py +7 -0
- spinekit-0.2.0/packages/spine-orchestration/src/spine_orchestration/patterns.py +106 -0
- spinekit-0.2.0/packages/spine-orchestration/src/spine_orchestration/py.typed +0 -0
- spinekit-0.2.0/packages/spine-orchestration/tests/test_orchestration.py +68 -0
- spinekit-0.2.0/packages/spine-otel/src/spine_otel/__init__.py +15 -0
- spinekit-0.2.0/packages/spine-otel/src/spine_otel/middleware.py +150 -0
- spinekit-0.2.0/packages/spine-otel/src/spine_otel/py.typed +0 -0
- spinekit-0.2.0/packages/spine-otel/tests/test_otel.py +111 -0
- spinekit-0.2.0/packages/spine-providers/src/spine_providers/__init__.py +15 -0
- spinekit-0.2.0/packages/spine-providers/src/spine_providers/anthropic.py +258 -0
- spinekit-0.2.0/packages/spine-providers/src/spine_providers/openai.py +273 -0
- spinekit-0.2.0/packages/spine-providers/src/spine_providers/py.typed +0 -0
- spinekit-0.2.0/packages/spine-providers/tests/test_anthropic.py +179 -0
- spinekit-0.2.0/packages/spine-providers/tests/test_openai.py +171 -0
- spinekit-0.2.0/pyproject.toml +165 -0
- spinekit-0.2.0/release-please-config.json +22 -0
- spinekit-0.2.0/uv.lock +1918 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!-- Thanks for contributing to Spine! -->
|
|
2
|
+
|
|
3
|
+
## What & why
|
|
4
|
+
|
|
5
|
+
<!-- What does this change, and why? Link any issue. -->
|
|
6
|
+
|
|
7
|
+
## Checklist
|
|
8
|
+
|
|
9
|
+
- [ ] Gates pass locally: `uv run pytest && uv run ruff check . && uv run ruff format --check . && uv run mypy`
|
|
10
|
+
- [ ] Added/updated tests (no network — use `ScriptedProvider` / fakes)
|
|
11
|
+
- [ ] New feature is a **middleware / backend / adapter**, not a kernel edit
|
|
12
|
+
- [ ] Updated docs / package `README.md` if behavior changed
|
|
13
|
+
- [ ] Conventional commit message (`feat:`, `fix:`, `docs:`, …)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
gates:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v5
|
|
16
|
+
with:
|
|
17
|
+
enable-cache: true
|
|
18
|
+
|
|
19
|
+
- name: Sync workspace
|
|
20
|
+
run: uv sync
|
|
21
|
+
|
|
22
|
+
- name: Lint (ruff)
|
|
23
|
+
run: uv run ruff check .
|
|
24
|
+
|
|
25
|
+
- name: Format check (ruff)
|
|
26
|
+
run: uv run ruff format --check .
|
|
27
|
+
|
|
28
|
+
- name: Type check (mypy --strict)
|
|
29
|
+
run: uv run mypy
|
|
30
|
+
|
|
31
|
+
- name: Tests
|
|
32
|
+
run: uv run pytest
|
|
33
|
+
|
|
34
|
+
- name: Docs build (strict)
|
|
35
|
+
run: uv run mkdocs build --strict
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: pages
|
|
15
|
+
cancel-in-progress: false
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: astral-sh/setup-uv@v5
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
- run: uv sync
|
|
26
|
+
- run: uv run mkdocs build --strict
|
|
27
|
+
- uses: actions/upload-pages-artifact@v3
|
|
28
|
+
with:
|
|
29
|
+
path: site
|
|
30
|
+
|
|
31
|
+
deploy:
|
|
32
|
+
needs: build
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
environment:
|
|
35
|
+
name: github-pages
|
|
36
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
37
|
+
steps:
|
|
38
|
+
- id: deployment
|
|
39
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# release-please opens/maintains a "Release PR" as commits land on main.
|
|
4
|
+
# Merging that PR bumps the version, updates CHANGELOG.md, and creates the
|
|
5
|
+
# GitHub release + tag — which, in the SAME run, publishes to PyPI via OIDC.
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
permissions: {}
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release-please:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
pull-requests: write
|
|
18
|
+
outputs:
|
|
19
|
+
release_created: ${{ steps.rp.outputs.release_created }}
|
|
20
|
+
tag_name: ${{ steps.rp.outputs.tag_name }}
|
|
21
|
+
steps:
|
|
22
|
+
- id: rp
|
|
23
|
+
uses: googleapis/release-please-action@v4
|
|
24
|
+
with:
|
|
25
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
+
|
|
27
|
+
publish:
|
|
28
|
+
needs: release-please
|
|
29
|
+
if: ${{ needs.release-please.outputs.release_created == 'true' }}
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
permissions:
|
|
32
|
+
id-token: write # OIDC trusted publishing — no stored secret
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: astral-sh/setup-uv@v5
|
|
36
|
+
with:
|
|
37
|
+
enable-cache: true
|
|
38
|
+
- name: Build the spinekit distribution
|
|
39
|
+
run: |
|
|
40
|
+
rm -rf dist
|
|
41
|
+
uv build --out-dir dist
|
|
42
|
+
ls -la dist
|
|
43
|
+
- name: Publish to PyPI
|
|
44
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# Docs build output
|
|
13
|
+
/site/
|
|
14
|
+
|
|
15
|
+
# Tooling caches
|
|
16
|
+
.hypothesis/
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.ruff_cache/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.coverage
|
|
21
|
+
htmlcov/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.2.0](https://github.com/Research-Analytics-Solutions/spine/compare/v0.1.0...v0.2.0) (2026-06-18)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **a2a:** agent-to-agent adapter — call a remote agent as a tool ([473bdfe](https://github.com/Research-Analytics-Solutions/spine/commit/473bdfe9803dd722a27a7624ab71b64e3a2d3550))
|
|
9
|
+
* **backends:** Redis + Postgres checkpoint backends + conformance suite ([a9d8990](https://github.com/Research-Analytics-Solutions/spine/commit/a9d8990e41e8f6383dc26c1f11524de2ba9b89c9))
|
|
10
|
+
* **backends:** spine-backends with durable SQLite checkpoint ([9974652](https://github.com/Research-Analytics-Solutions/spine/commit/997465223cb3c3d7d01d3ace2eda755bfc01a1e2))
|
|
11
|
+
* **cli:** config-driven agent build + chat/trace commands ([8da432e](https://github.com/Research-Analytics-Solutions/spine/commit/8da432e3157e7e26861e5c01e8814f4e67c79423))
|
|
12
|
+
* **cli:** spine dev — live-streaming trace viewer ([5b2ed12](https://github.com/Research-Analytics-Solutions/spine/commit/5b2ed127d9520a364ee54b21f52f9a77d24c63d1))
|
|
13
|
+
* **cli:** spine-cli with init/run/doctor/plugin (Typer + Rich) ([422d1b5](https://github.com/Research-Analytics-Solutions/spine/commit/422d1b579c3f810e93b8f4a96f246ef29d1d77f6))
|
|
14
|
+
* **core:** parallel tool calls, cooperative cancellation, sub-agents ([14ce08f](https://github.com/Research-Analytics-Solutions/spine/commit/14ce08f1d32f72c3d71e0cf3db495e20408b376c))
|
|
15
|
+
* **core:** spine-core kernel — loop, guards, middleware, tools, HITL ([450df11](https://github.com/Research-Analytics-Solutions/spine/commit/450df1135b10b8fe5032b217eb75fba93fa9c9ca))
|
|
16
|
+
* **eval:** spine-eval harness + spine eval CLI command ([316c27b](https://github.com/Research-Analytics-Solutions/spine/commit/316c27bb6c1ee849bab4767c52907f404393c716))
|
|
17
|
+
* **mcp:** spine-mcp adapter + raw_tool core primitive ([80676fb](https://github.com/Research-Analytics-Solutions/spine/commit/80676fb403ba607b29d1e52f3b1d8317418ccd5b))
|
|
18
|
+
* **memory:** pluggable embedders + multiple memory types ([7f5a1b8](https://github.com/Research-Analytics-Solutions/spine/commit/7f5a1b8aa6a0649364fc6c776ffb497944835385))
|
|
19
|
+
* **memory:** semantic memory protocol, vector backend, recall middleware ([e59b306](https://github.com/Research-Analytics-Solutions/spine/commit/e59b306a80defc8ea8a8eebc0440d149d9d34f3b))
|
|
20
|
+
* **middleware:** deterministic replay (Recorder/Replayer) ([327c39b](https://github.com/Research-Analytics-Solutions/spine/commit/327c39b458d2af8e6bcaedd87741ec945a39559b))
|
|
21
|
+
* **middleware:** guardrails — PII redaction, injection screening, content policy ([a714367](https://github.com/Research-Analytics-Solutions/spine/commit/a714367e0510648086f28e14b27a8fea9eb311e6))
|
|
22
|
+
* **middleware:** prompt/response Cache + kernel cache-hit short-circuit ([0deab9c](https://github.com/Research-Analytics-Solutions/spine/commit/0deab9c55a9c44764b0744d4bf1cc225e0624501))
|
|
23
|
+
* **middleware:** tool timeout/truncation, circuit breaker, idempotency, rate limit ([de4e27a](https://github.com/Research-Analytics-Solutions/spine/commit/de4e27a7b8c03a5a91966182c810ffbe40f655e2))
|
|
24
|
+
* **middleware:** V1 middleware suite + kernel control primitives ([a6d7766](https://github.com/Research-Analytics-Solutions/spine/commit/a6d776663bdb644d5e24d7f28a8bd225c28d8617))
|
|
25
|
+
* **multimodal:** image/file content parts on Message + provider mapping ([4993441](https://github.com/Research-Analytics-Solutions/spine/commit/4993441cb2f3accf475a216e15c60ed1cc51f896))
|
|
26
|
+
* **multitenancy:** tenant_id on state + per-tenant budget guard ([b306e11](https://github.com/Research-Analytics-Solutions/spine/commit/b306e11a65323ea736fe24f07585150973906458))
|
|
27
|
+
* **orchestration:** sequential, supervisor, handoff patterns ([d2adb2e](https://github.com/Research-Analytics-Solutions/spine/commit/d2adb2eceb769e5dc5c7f73f8917adc2fdb382f4))
|
|
28
|
+
* **otel:** spine-otel — one OpenTelemetry span tree per run ([2453bf2](https://github.com/Research-Analytics-Solutions/spine/commit/2453bf2f8383389b022d2b838cf143ab497fe160))
|
|
29
|
+
* **providers:** add OpenAI adapter ([6005eb9](https://github.com/Research-Analytics-Solutions/spine/commit/6005eb955a8a313fa1ce5af9e96bf7d438342f9a))
|
|
30
|
+
* **providers:** spine-providers with Anthropic adapter ([cbe1171](https://github.com/Research-Analytics-Solutions/spine/commit/cbe1171a53a139fc51dec356ec3adf89189f2a1c))
|
|
31
|
+
* **sandbox:** resource-limited subprocess sandbox for sync tools ([5622d1a](https://github.com/Research-Analytics-Solutions/spine/commit/5622d1a4dfc0266fae16357a6de33919384bccef))
|
|
32
|
+
* **streaming:** token-level streaming through provider + kernel ([85df88a](https://github.com/Research-Analytics-Solutions/spine/commit/85df88aff07f9672d1d8e06e2d309422f243dea7))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* **core:** auto-resolve provider scheme via plugin entry points ([4f2213d](https://github.com/Research-Analytics-Solutions/spine/commit/4f2213d419393153d62703495f691932168cb98c))
|
|
38
|
+
* **core:** bound provider-retry loop; make resume token durable ([1b6c434](https://github.com/Research-Analytics-Solutions/spine/commit/1b6c434c15e74864c734ebd387df50da3383e32d))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### Documentation
|
|
42
|
+
|
|
43
|
+
* contributor guide, plugin development & publishing, eval/MCP deep dives ([81b126f](https://github.com/Research-Analytics-Solutions/spine/commit/81b126f4cdbdc5fa02a8de5ea4a399b9bdddfbc4))
|
|
44
|
+
* deep reference — data model, cookbook, patterns, expanded CLI & API ([409701a](https://github.com/Research-Analytics-Solutions/spine/commit/409701a834202fdc5aef938814bc6ae7c66cc16f))
|
|
45
|
+
* fix mermaid diagram invisibility in dark mode ([359985d](https://github.com/Research-Analytics-Solutions/spine/commit/359985ddde0d6fe42c8f4824f55b43c4d2b67b3b))
|
|
46
|
+
* landing page hero, logo, mermaid + grid-card fixes ([13f929b](https://github.com/Research-Analytics-Solutions/spine/commit/13f929b05ddeae0f54eaee1c6d4cefe1adb38c1f))
|
|
47
|
+
* mkdocs-material documentation site ([4e63082](https://github.com/Research-Analytics-Solutions/spine/commit/4e630824e14303896c3d0c2e0254654f9d6bb4d2))
|
|
48
|
+
* reconcile with single spinekit distribution ([878a934](https://github.com/Research-Analytics-Solutions/spine/commit/878a934cfbc2611b62edadfde1d090bb6f0e69ef))
|
|
49
|
+
* replace ASCII four-planes box with a styled mermaid diagram ([86c3de3](https://github.com/Research-Analytics-Solutions/spine/commit/86c3de382c21bc0b53b860c5be504fabeda66ecb))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
### Build & Packaging
|
|
53
|
+
|
|
54
|
+
* repackage as a single 'spinekit' distribution with extras ([a4e3765](https://github.com/Research-Analytics-Solutions/spine/commit/a4e37655c38751990134a3b6cbb62e584c31d5f1))
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
|
10
|
+
orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment:
|
|
18
|
+
|
|
19
|
+
- Demonstrating empathy and kindness toward other people
|
|
20
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
21
|
+
- Giving and gracefully accepting constructive feedback
|
|
22
|
+
- Accepting responsibility and apologizing to those affected by our mistakes
|
|
23
|
+
- Focusing on what is best for the overall community
|
|
24
|
+
|
|
25
|
+
Examples of unacceptable behavior:
|
|
26
|
+
|
|
27
|
+
- The use of sexualized language or imagery, and sexual attention or advances
|
|
28
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
29
|
+
- Public or private harassment
|
|
30
|
+
- Publishing others' private information without explicit permission
|
|
31
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
32
|
+
professional setting
|
|
33
|
+
|
|
34
|
+
## Enforcement Responsibilities
|
|
35
|
+
|
|
36
|
+
Project maintainers are responsible for clarifying and enforcing our standards
|
|
37
|
+
and will take appropriate and fair corrective action in response to any behavior
|
|
38
|
+
that they deem inappropriate, threatening, offensive, or harmful.
|
|
39
|
+
|
|
40
|
+
## Scope
|
|
41
|
+
|
|
42
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
43
|
+
an individual is officially representing the community in public spaces.
|
|
44
|
+
|
|
45
|
+
## Enforcement
|
|
46
|
+
|
|
47
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
48
|
+
reported to the project maintainers responsible for enforcement. All complaints
|
|
49
|
+
will be reviewed and investigated promptly and fairly.
|
|
50
|
+
|
|
51
|
+
## Attribution
|
|
52
|
+
|
|
53
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
54
|
+
version 2.1, available at
|
|
55
|
+
<https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.
|
|
56
|
+
|
|
57
|
+
[homepage]: https://www.contributor-covenant.org
|
spinekit-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Research Analytics Solutions
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
spinekit-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spinekit
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: A lightweight, modular, protocol-native runtime for production AI agents.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Research-Analytics-Solutions/spine
|
|
6
|
+
Project-URL: Documentation, https://research-analytics-solutions.github.io/spine/
|
|
7
|
+
Project-URL: Repository, https://github.com/Research-Analytics-Solutions/spine
|
|
8
|
+
Author: Research Analytics Solutions
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: a2a,agents,ai,kernel,llm,mcp,runtime
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Requires-Dist: anyio>=4.4
|
|
20
|
+
Requires-Dist: pydantic>=2.7
|
|
21
|
+
Provides-Extra: a2a
|
|
22
|
+
Requires-Dist: httpx>=0.27; extra == 'a2a'
|
|
23
|
+
Provides-Extra: all
|
|
24
|
+
Requires-Dist: anthropic>=0.40; extra == 'all'
|
|
25
|
+
Requires-Dist: asyncpg>=0.29; extra == 'all'
|
|
26
|
+
Requires-Dist: httpx>=0.27; extra == 'all'
|
|
27
|
+
Requires-Dist: mcp>=1.2; extra == 'all'
|
|
28
|
+
Requires-Dist: openai>=1.40; extra == 'all'
|
|
29
|
+
Requires-Dist: opentelemetry-api>=1.27; extra == 'all'
|
|
30
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27; extra == 'all'
|
|
31
|
+
Requires-Dist: opentelemetry-sdk>=1.27; extra == 'all'
|
|
32
|
+
Requires-Dist: pyyaml>=6.0; extra == 'all'
|
|
33
|
+
Requires-Dist: redis>=5.0; extra == 'all'
|
|
34
|
+
Requires-Dist: rich>=13.7; extra == 'all'
|
|
35
|
+
Requires-Dist: typer>=0.12; extra == 'all'
|
|
36
|
+
Provides-Extra: anthropic
|
|
37
|
+
Requires-Dist: anthropic>=0.40; extra == 'anthropic'
|
|
38
|
+
Provides-Extra: cli
|
|
39
|
+
Requires-Dist: rich>=13.7; extra == 'cli'
|
|
40
|
+
Requires-Dist: typer>=0.12; extra == 'cli'
|
|
41
|
+
Provides-Extra: eval
|
|
42
|
+
Requires-Dist: pyyaml>=6.0; extra == 'eval'
|
|
43
|
+
Provides-Extra: mcp
|
|
44
|
+
Requires-Dist: mcp>=1.2; extra == 'mcp'
|
|
45
|
+
Provides-Extra: openai
|
|
46
|
+
Requires-Dist: openai>=1.40; extra == 'openai'
|
|
47
|
+
Provides-Extra: otel
|
|
48
|
+
Requires-Dist: opentelemetry-api>=1.27; extra == 'otel'
|
|
49
|
+
Requires-Dist: opentelemetry-sdk>=1.27; extra == 'otel'
|
|
50
|
+
Provides-Extra: otlp
|
|
51
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27; extra == 'otlp'
|
|
52
|
+
Provides-Extra: postgres
|
|
53
|
+
Requires-Dist: asyncpg>=0.29; extra == 'postgres'
|
|
54
|
+
Provides-Extra: providers
|
|
55
|
+
Requires-Dist: anthropic>=0.40; extra == 'providers'
|
|
56
|
+
Requires-Dist: openai>=1.40; extra == 'providers'
|
|
57
|
+
Provides-Extra: redis
|
|
58
|
+
Requires-Dist: redis>=5.0; extra == 'redis'
|
|
59
|
+
Description-Content-Type: text/markdown
|
|
60
|
+
|
|
61
|
+
<p align="center">
|
|
62
|
+
<img src="docs/assets/logo-hero.svg" alt="Spine" width="110" />
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
<h1 align="center">Spine</h1>
|
|
66
|
+
|
|
67
|
+
<p align="center">
|
|
68
|
+
<strong>A lightweight, modular, protocol-native runtime for production AI agents.</strong>
|
|
69
|
+
</p>
|
|
70
|
+
|
|
71
|
+
<p align="center">
|
|
72
|
+
<a href="https://github.com/Research-Analytics-Solutions/spine/actions/workflows/ci.yml"><img src="https://github.com/Research-Analytics-Solutions/spine/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
73
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"></a>
|
|
74
|
+
<img src="https://img.shields.io/badge/python-3.12%2B-blue.svg" alt="Python 3.12+">
|
|
75
|
+
<a href="https://research-analytics-solutions.github.io/spine/"><img src="https://img.shields.io/badge/docs-mkdocs--material-526CFE.svg" alt="Docs"></a>
|
|
76
|
+
</p>
|
|
77
|
+
|
|
78
|
+
<p align="center">
|
|
79
|
+
<a href="https://research-analytics-solutions.github.io/spine/">Documentation</a> ·
|
|
80
|
+
<a href="https://research-analytics-solutions.github.io/spine/quickstart/">Quickstart</a> ·
|
|
81
|
+
<a href="https://research-analytics-solutions.github.io/spine/guides/examples/">Cookbook</a> ·
|
|
82
|
+
<a href="https://research-analytics-solutions.github.io/spine/contributing/">Contributing</a>
|
|
83
|
+
</p>
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
Spine is the *kernel* for AI agents — a tiny, load-bearing runtime that everything
|
|
88
|
+
else plugs into. Where monolithic frameworks bundle heavy abstractions, Spine
|
|
89
|
+
ships a small core and pushes every feature into **opt-in middleware, swappable
|
|
90
|
+
backends, and protocol adapters**.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from spine_core import Agent
|
|
94
|
+
|
|
95
|
+
agent = Agent("openai:gpt-4o-mini")
|
|
96
|
+
print((await agent.run("say hello")).answer)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Three guarantees
|
|
100
|
+
|
|
101
|
+
- **No hidden prompts** — every model call consumes inspectable, typed `Message` objects.
|
|
102
|
+
- **No runaway loops** — guards are enforced inside the kernel, every iteration.
|
|
103
|
+
- **Deterministic replay** — any run can be recorded and replayed step-for-step.
|
|
104
|
+
|
|
105
|
+
## Install
|
|
106
|
+
|
|
107
|
+
One package, lean core, opt-in extras:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install spinekit # kernel only (pydantic + anyio)
|
|
111
|
+
pip install "spinekit[openai]" # + OpenAI
|
|
112
|
+
pip install "spinekit[anthropic,redis,cli]" # pick parts
|
|
113
|
+
pip install "spinekit[all]" # everything
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Import name stays `spine_core`. See the [install guide](https://research-analytics-solutions.github.io/spine/install/).
|
|
117
|
+
|
|
118
|
+
## What's in the box
|
|
119
|
+
|
|
120
|
+
| Module | Extra | What |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| `spine_core` | — | the kernel — loop, state, guards, tracer, protocols, HITL, streaming |
|
|
123
|
+
| `spine_middleware` | — | retry, fallback, guardrails, cache, memory recall, sandbox, replay, … |
|
|
124
|
+
| `spine_backends` | `redis` / `postgres` | checkpoints (SQLite always; Redis/Postgres) + memory (vector/buffer/pgvector) |
|
|
125
|
+
| `spine_providers` | `openai` / `anthropic` | OpenAI + Anthropic (and any OpenAI-compatible endpoint) |
|
|
126
|
+
| `spine_mcp` · `spine_a2a` · `spine_otel` | `mcp` · `a2a` · `otel` | MCP tools · remote agents · OpenTelemetry |
|
|
127
|
+
| `spine_eval` | `eval` | dataset + scorers + Cost/Latency/Efficacy/Reliability report |
|
|
128
|
+
| `spine_orchestration` | — | sequential / supervisor / handoff |
|
|
129
|
+
| `spine_cli` | `cli` | `init` / `run` / `chat` / `dev` / `trace` / `eval` / `doctor` / `plugin` |
|
|
130
|
+
|
|
131
|
+
## Develop
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
uv sync # install workspace + dev deps
|
|
135
|
+
uv run pytest # tests
|
|
136
|
+
uv run ruff check . # lint
|
|
137
|
+
uv run mypy # strict type-check
|
|
138
|
+
uv run mkdocs serve # preview docs at http://127.0.0.1:8000
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
See the [Contributing guide](https://research-analytics-solutions.github.io/spine/contributing/)
|
|
142
|
+
to build your own [middleware](https://research-analytics-solutions.github.io/spine/develop/middleware/),
|
|
143
|
+
[provider](https://research-analytics-solutions.github.io/spine/develop/provider/), or
|
|
144
|
+
[backend](https://research-analytics-solutions.github.io/spine/develop/publish/) and publish it
|
|
145
|
+
as a plugin.
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
[MIT](LICENSE) © 2026 Research Analytics Solutions
|
spinekit-0.2.0/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/assets/logo-hero.svg" alt="Spine" width="110" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Spine</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>A lightweight, modular, protocol-native runtime for production AI agents.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://github.com/Research-Analytics-Solutions/spine/actions/workflows/ci.yml"><img src="https://github.com/Research-Analytics-Solutions/spine/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
13
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"></a>
|
|
14
|
+
<img src="https://img.shields.io/badge/python-3.12%2B-blue.svg" alt="Python 3.12+">
|
|
15
|
+
<a href="https://research-analytics-solutions.github.io/spine/"><img src="https://img.shields.io/badge/docs-mkdocs--material-526CFE.svg" alt="Docs"></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="https://research-analytics-solutions.github.io/spine/">Documentation</a> ·
|
|
20
|
+
<a href="https://research-analytics-solutions.github.io/spine/quickstart/">Quickstart</a> ·
|
|
21
|
+
<a href="https://research-analytics-solutions.github.io/spine/guides/examples/">Cookbook</a> ·
|
|
22
|
+
<a href="https://research-analytics-solutions.github.io/spine/contributing/">Contributing</a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
Spine is the *kernel* for AI agents — a tiny, load-bearing runtime that everything
|
|
28
|
+
else plugs into. Where monolithic frameworks bundle heavy abstractions, Spine
|
|
29
|
+
ships a small core and pushes every feature into **opt-in middleware, swappable
|
|
30
|
+
backends, and protocol adapters**.
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from spine_core import Agent
|
|
34
|
+
|
|
35
|
+
agent = Agent("openai:gpt-4o-mini")
|
|
36
|
+
print((await agent.run("say hello")).answer)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Three guarantees
|
|
40
|
+
|
|
41
|
+
- **No hidden prompts** — every model call consumes inspectable, typed `Message` objects.
|
|
42
|
+
- **No runaway loops** — guards are enforced inside the kernel, every iteration.
|
|
43
|
+
- **Deterministic replay** — any run can be recorded and replayed step-for-step.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
One package, lean core, opt-in extras:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install spinekit # kernel only (pydantic + anyio)
|
|
51
|
+
pip install "spinekit[openai]" # + OpenAI
|
|
52
|
+
pip install "spinekit[anthropic,redis,cli]" # pick parts
|
|
53
|
+
pip install "spinekit[all]" # everything
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Import name stays `spine_core`. See the [install guide](https://research-analytics-solutions.github.io/spine/install/).
|
|
57
|
+
|
|
58
|
+
## What's in the box
|
|
59
|
+
|
|
60
|
+
| Module | Extra | What |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `spine_core` | — | the kernel — loop, state, guards, tracer, protocols, HITL, streaming |
|
|
63
|
+
| `spine_middleware` | — | retry, fallback, guardrails, cache, memory recall, sandbox, replay, … |
|
|
64
|
+
| `spine_backends` | `redis` / `postgres` | checkpoints (SQLite always; Redis/Postgres) + memory (vector/buffer/pgvector) |
|
|
65
|
+
| `spine_providers` | `openai` / `anthropic` | OpenAI + Anthropic (and any OpenAI-compatible endpoint) |
|
|
66
|
+
| `spine_mcp` · `spine_a2a` · `spine_otel` | `mcp` · `a2a` · `otel` | MCP tools · remote agents · OpenTelemetry |
|
|
67
|
+
| `spine_eval` | `eval` | dataset + scorers + Cost/Latency/Efficacy/Reliability report |
|
|
68
|
+
| `spine_orchestration` | — | sequential / supervisor / handoff |
|
|
69
|
+
| `spine_cli` | `cli` | `init` / `run` / `chat` / `dev` / `trace` / `eval` / `doctor` / `plugin` |
|
|
70
|
+
|
|
71
|
+
## Develop
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv sync # install workspace + dev deps
|
|
75
|
+
uv run pytest # tests
|
|
76
|
+
uv run ruff check . # lint
|
|
77
|
+
uv run mypy # strict type-check
|
|
78
|
+
uv run mkdocs serve # preview docs at http://127.0.0.1:8000
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
See the [Contributing guide](https://research-analytics-solutions.github.io/spine/contributing/)
|
|
82
|
+
to build your own [middleware](https://research-analytics-solutions.github.io/spine/develop/middleware/),
|
|
83
|
+
[provider](https://research-analytics-solutions.github.io/spine/develop/provider/), or
|
|
84
|
+
[backend](https://research-analytics-solutions.github.io/spine/develop/publish/) and publish it
|
|
85
|
+
as a plugin.
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
[MIT](LICENSE) © 2026 Research Analytics Solutions
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## Design principles
|
|
4
|
+
|
|
5
|
+
These are binding constraints, not aspirations.
|
|
6
|
+
|
|
7
|
+
1. **Tiny kernel.** The core is the execution loop, the state model, and the
|
|
8
|
+
guard checks — importable with zero third-party runtime dependencies beyond
|
|
9
|
+
the standard library + Pydantic + anyio.
|
|
10
|
+
2. **Everything is a plugin.** Each feature is exactly one of: **middleware**
|
|
11
|
+
(wraps a step), **backend** (implements a protocol), or **adapter** (bridges a
|
|
12
|
+
standard). If a feature requires editing the kernel, it was modeled wrong.
|
|
13
|
+
3. **Pay only for what you import.** A beginner imports nothing extra and writes
|
|
14
|
+
3 lines. An enterprise stacks a dozen middlewares. Same kernel.
|
|
15
|
+
4. **Protocol-first.** Consume MCP and A2A rather than inventing proprietary
|
|
16
|
+
equivalents. Lock-in is a non-goal.
|
|
17
|
+
5. **Observable & deterministic by default.** Every step emits a trace event and
|
|
18
|
+
an OpenTelemetry span. No hidden state, no hidden prompts.
|
|
19
|
+
6. **Async-first.** The core is `async`; a thin synchronous facade sits on top.
|
|
20
|
+
7. **Typed and validated.** Pydantic v2 at every boundary.
|
|
21
|
+
|
|
22
|
+
## The four planes
|
|
23
|
+
|
|
24
|
+
```mermaid
|
|
25
|
+
flowchart TB
|
|
26
|
+
API["<b>Developer API</b><br/><code>Agent()</code> · <code>@tool</code> · <code>middleware=[...]</code>"]
|
|
27
|
+
|
|
28
|
+
subgraph KERNEL ["🧠 KERNEL · we own"]
|
|
29
|
+
direction LR
|
|
30
|
+
K1[Step loop] ~~~ K2[State] ~~~ K3[Guards] ~~~ K4[Tracer]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
subgraph MW ["🧩 MIDDLEWARE · opt-in, chainable"]
|
|
34
|
+
direction LR
|
|
35
|
+
M1[Retry] ~~~ M2[Guardrails] ~~~ M3[Cache] ~~~ M4[Compaction] ~~~ M5[Memory]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
subgraph BE ["🔌 BACKENDS · swappable, behind protocols"]
|
|
39
|
+
direction LR
|
|
40
|
+
B1[Providers] ~~~ B2[Checkpoints] ~~~ B3[Memory stores]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
subgraph AD ["🌐 ADAPTERS · bridge open standards"]
|
|
44
|
+
direction LR
|
|
45
|
+
A1[MCP] ~~~ A2[A2A] ~~~ A3[OTLP]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
API --> KERNEL --> MW --> BE --> AD
|
|
49
|
+
|
|
50
|
+
%% stroke-only accents — no fill/text-color overrides, so text follows the
|
|
51
|
+
%% Material theme and stays readable in both light and dark mode.
|
|
52
|
+
classDef api stroke:#6366f1,stroke-width:2px;
|
|
53
|
+
classDef kernel stroke:#4f46e5,stroke-width:2.5px;
|
|
54
|
+
classDef plane stroke:#94a3b8,stroke-width:1.5px;
|
|
55
|
+
class API api;
|
|
56
|
+
class KERNEL kernel;
|
|
57
|
+
class MW,BE,AD plane;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The kernel never *constructs* behavior; it *invokes hooks*. Middlewares attach to
|
|
61
|
+
defined hook points; backends sit behind tiny protocols; adapters translate open
|
|
62
|
+
standards.
|
|
63
|
+
|
|
64
|
+
## Repository layout
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
spine/
|
|
68
|
+
├── packages/
|
|
69
|
+
│ ├── spine-core/ # kernel, protocols, guards, tracer
|
|
70
|
+
│ ├── spine-cli/ # Typer CLI + templates + dev server
|
|
71
|
+
│ ├── spine-providers/ # OpenAI, Anthropic adapters
|
|
72
|
+
│ ├── spine-middleware/ # the middleware suite
|
|
73
|
+
│ ├── spine-backends/ # sqlite/redis/postgres + vector/buffer/pgvector
|
|
74
|
+
│ ├── spine-mcp/ # MCP client adapter
|
|
75
|
+
│ ├── spine-a2a/ # A2A adapter
|
|
76
|
+
│ ├── spine-otel/ # OpenTelemetry middleware
|
|
77
|
+
│ ├── spine-eval/ # eval harness + scorers
|
|
78
|
+
│ └── spine-orchestration/# sequential / supervisor / handoff
|
|
79
|
+
└── docs/
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The source is organized by plane under `packages/*/src/` (import names
|
|
83
|
+
`spine_core`, `spine_providers`, …), but it all ships as **one distribution,
|
|
84
|
+
`spinekit`** — a lean core (Pydantic + anyio) with heavy dependencies as opt-in
|
|
85
|
+
extras (`spinekit[openai]`, `spinekit[redis]`, `spinekit[all]`, …). The code is
|
|
86
|
+
small; only the third-party dependencies are optional.
|
|
87
|
+
|
|
88
|
+
## The bet
|
|
89
|
+
|
|
90
|
+
The integration layer that made monolithic frameworks valuable has been
|
|
91
|
+
commoditized by open standards. The durable value sits in the **reliability
|
|
92
|
+
runtime** — the execution loop, guards, durable state, and observability that
|
|
93
|
+
decide whether an agent survives production. Spine owns that core and lets the
|
|
94
|
+
standards do the integration.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none" role="img" aria-label="Spine">
|
|
2
|
+
<rect width="32" height="32" rx="7" fill="#5b5bd6"/>
|
|
3
|
+
<rect x="14.4" y="4" width="3.2" height="24" rx="1.6" fill="#ffffff" opacity="0.55"/>
|
|
4
|
+
<rect x="8.5" y="5.5" width="15" height="3.1" rx="1.55" fill="#ffffff"/>
|
|
5
|
+
<rect x="7.2" y="10.8" width="17.6" height="3.1" rx="1.55" fill="#ffffff"/>
|
|
6
|
+
<rect x="7.2" y="16.1" width="17.6" height="3.1" rx="1.55" fill="#ffffff"/>
|
|
7
|
+
<rect x="8.5" y="21.4" width="15" height="3.1" rx="1.55" fill="#ffffff"/>
|
|
8
|
+
</svg>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" fill="none" role="img" aria-label="Spine">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="g" x1="0" y1="0" x2="96" y2="96" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#818cf8"/>
|
|
5
|
+
<stop offset="1" stop-color="#4f46e5"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<rect x="42" y="10" width="12" height="76" rx="6" fill="url(#g)" opacity="0.45"/>
|
|
9
|
+
<rect x="24" y="14" width="48" height="10.5" rx="5.25" fill="url(#g)"/>
|
|
10
|
+
<rect x="19" y="31" width="58" height="10.5" rx="5.25" fill="url(#g)"/>
|
|
11
|
+
<rect x="19" y="48" width="58" height="10.5" rx="5.25" fill="url(#g)"/>
|
|
12
|
+
<rect x="24" y="65" width="48" height="10.5" rx="5.25" fill="url(#g)"/>
|
|
13
|
+
<rect x="32" y="82" width="32" height="8" rx="4" fill="url(#g)" opacity="0.8"/>
|
|
14
|
+
</svg>
|