toolstream 0.1.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.
Files changed (61) hide show
  1. toolstream-0.1.0/.github/workflows/ci.yml +25 -0
  2. toolstream-0.1.0/.github/workflows/publish.yml +21 -0
  3. toolstream-0.1.0/.gitignore +17 -0
  4. toolstream-0.1.0/.rlsbl/bases/.github/workflows/ci.yml +25 -0
  5. toolstream-0.1.0/.rlsbl/bases/.github/workflows/publish.yml +21 -0
  6. toolstream-0.1.0/.rlsbl/bases/.gitignore +16 -0
  7. toolstream-0.1.0/.rlsbl/bases/.rlsbl/changes/unreleased.jsonl +0 -0
  8. toolstream-0.1.0/.rlsbl/bases/.rlsbl/hooks/post-release.sh +16 -0
  9. toolstream-0.1.0/.rlsbl/bases/.rlsbl/hooks/pre-checks.sh +5 -0
  10. toolstream-0.1.0/.rlsbl/bases/.rlsbl/hooks/pre-release.sh +10 -0
  11. toolstream-0.1.0/.rlsbl/bases/.rlsbl/lint/python.toml +25 -0
  12. toolstream-0.1.0/.rlsbl/bases/CHANGELOG.md +5 -0
  13. toolstream-0.1.0/.rlsbl/changes/.validated +1 -0
  14. toolstream-0.1.0/.rlsbl/changes/0.1.0.jsonl +15 -0
  15. toolstream-0.1.0/.rlsbl/changes/0.1.0.md +7 -0
  16. toolstream-0.1.0/.rlsbl/changes/unreleased.jsonl +0 -0
  17. toolstream-0.1.0/.rlsbl/config.json +12 -0
  18. toolstream-0.1.0/.rlsbl/hashes.json +11 -0
  19. toolstream-0.1.0/.rlsbl/hooks/post-release.sh +16 -0
  20. toolstream-0.1.0/.rlsbl/hooks/pre-checks.sh +5 -0
  21. toolstream-0.1.0/.rlsbl/hooks/pre-release.sh +10 -0
  22. toolstream-0.1.0/.rlsbl/lint/python.toml +25 -0
  23. toolstream-0.1.0/.rlsbl/managed-files.json +14 -0
  24. toolstream-0.1.0/.rlsbl/releases/unreleased.toml +0 -0
  25. toolstream-0.1.0/.rlsbl/releases/v0.1.0.toml +10 -0
  26. toolstream-0.1.0/.rlsbl/version +1 -0
  27. toolstream-0.1.0/CHANGELOG.md +11 -0
  28. toolstream-0.1.0/PKG-INFO +7 -0
  29. toolstream-0.1.0/npm/README.md +8 -0
  30. toolstream-0.1.0/npm/index.js +5 -0
  31. toolstream-0.1.0/npm/package.json +12 -0
  32. toolstream-0.1.0/pyproject.toml +26 -0
  33. toolstream-0.1.0/tests/__init__.py +0 -0
  34. toolstream-0.1.0/tests/conftest.py +98 -0
  35. toolstream-0.1.0/tests/fixtures/agents/explorer.agent.json +6 -0
  36. toolstream-0.1.0/tests/fixtures/agents/orchestrator.agent.json +7 -0
  37. toolstream-0.1.0/tests/test_agent.py +298 -0
  38. toolstream-0.1.0/tests/test_builtin_tools.py +282 -0
  39. toolstream-0.1.0/tests/test_direct.py +482 -0
  40. toolstream-0.1.0/tests/test_events.py +99 -0
  41. toolstream-0.1.0/tests/test_injection.py +219 -0
  42. toolstream-0.1.0/tests/test_integration.py +284 -0
  43. toolstream-0.1.0/tests/test_invoke.py +373 -0
  44. toolstream-0.1.0/tests/test_protocol.py +171 -0
  45. toolstream-0.1.0/tests/test_schema.py +519 -0
  46. toolstream-0.1.0/tests/test_session.py +89 -0
  47. toolstream-0.1.0/tests/test_tools.py +344 -0
  48. toolstream-0.1.0/toolstream/__init__.py +44 -0
  49. toolstream-0.1.0/toolstream/_agent.py +215 -0
  50. toolstream-0.1.0/toolstream/_builtin_tools.py +115 -0
  51. toolstream-0.1.0/toolstream/_context.py +14 -0
  52. toolstream-0.1.0/toolstream/_direct.py +292 -0
  53. toolstream-0.1.0/toolstream/_invoke.py +126 -0
  54. toolstream-0.1.0/toolstream/_protocol.py +87 -0
  55. toolstream-0.1.0/toolstream/_schema.py +259 -0
  56. toolstream-0.1.0/toolstream/_session.py +176 -0
  57. toolstream-0.1.0/toolstream/_tools.py +109 -0
  58. toolstream-0.1.0/toolstream/config.py +26 -0
  59. toolstream-0.1.0/toolstream/events.py +63 -0
  60. toolstream-0.1.0/toolstream/py.typed +0 -0
  61. toolstream-0.1.0/uv.lock +177 -0
@@ -0,0 +1,25 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+
10
+ env:
11
+ UV_NO_SOURCES: "1"
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ # requires-python: >= {{pypi.minRequiredPython}}
19
+ python-version: ["3.12", "3.13", "3.14"]
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+ - uses: astral-sh/setup-uv@v7
23
+ - run: uv python install ${{ matrix.python-version }}
24
+ - run: uv sync
25
+ - run: uv run python -c "import toolstream"
@@ -0,0 +1,21 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v6
17
+ - uses: astral-sh/setup-uv@v7
18
+ - run: uv build
19
+ - uses: pypa/gh-action-pypi-publish@release/v1
20
+ with:
21
+ skip-existing: true
@@ -0,0 +1,17 @@
1
+ node_modules/
2
+ __pycache__/
3
+ *.pyc
4
+ *.log
5
+ .DS_Store
6
+ coverage/
7
+ dist/
8
+ *.egg-info/
9
+ .rlsbl-notes-*.tmp
10
+ .rlsbl/lock
11
+ .credentials.json
12
+ .*-cache.json
13
+ .env
14
+ .env.local
15
+ *.local-only
16
+
17
+ .rlsbl-monorepo/lock
@@ -0,0 +1,25 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+
10
+ env:
11
+ UV_NO_SOURCES: "1"
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ # requires-python: >= {{pypi.minRequiredPython}}
19
+ python-version: ["3.12", "3.13", "3.14"]
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+ - uses: astral-sh/setup-uv@v7
23
+ - run: uv python install ${{ matrix.python-version }}
24
+ - run: uv sync
25
+ - run: uv run python -c "import toolstream"
@@ -0,0 +1,21 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v6
17
+ - uses: astral-sh/setup-uv@v7
18
+ - run: uv build
19
+ - uses: pypa/gh-action-pypi-publish@release/v1
20
+ with:
21
+ skip-existing: true
@@ -0,0 +1,16 @@
1
+ node_modules/
2
+ __pycache__/
3
+ *.pyc
4
+ *.log
5
+ .DS_Store
6
+ coverage/
7
+ dist/
8
+ *.egg-info/
9
+ .rlsbl-notes-*.tmp
10
+ .rlsbl/lock
11
+ .rlsbl-monorepo/lock
12
+ .credentials.json
13
+ .*-cache.json
14
+ .env
15
+ .env.local
16
+ *.local-only
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+ # Post-release hook. Runs after a successful release (non-fatal).
3
+ # Environment: RLSBL_VERSION is set to the released version.
4
+ # Customize this for your project (e.g., local install, deploy, notify).
5
+
6
+ set -euo pipefail
7
+
8
+ echo "Post-release: v$RLSBL_VERSION"
9
+
10
+ # Push to assembly for unified documentation site
11
+ if command -v selfdoc &>/dev/null && [ -f selfdoc.json ]; then
12
+ if python3 -c "import json; c=json.load(open('selfdoc.json')); exit(0 if c.get('assembly') or (c.get('topology') or {}).get('assembly') else 1)" 2>/dev/null; then
13
+ echo "Pushing to documentation assembly..."
14
+ selfdoc assembly push || echo "Warning: assembly push failed (non-fatal)"
15
+ fi
16
+ fi
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ # This hook runs BEFORE built-in pre-release checks (tests, lint).
4
+ # Use it for setup tasks: starting services, setting env vars, etc.
5
+ # Built-in checks run after this hook. Custom validation goes in pre-release.sh.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ # Project-specific pre-release checks.
4
+ # When this hook is customized (any change from the scaffold template),
5
+ # built-in tests and lint are skipped -- the hook is expected to handle them.
6
+ # Add custom validation here, e.g.:
7
+ # - Run tests and lint with project-specific flags
8
+ # - Check for uncommitted documentation
9
+ # - Verify external service connectivity
10
+ # - Run integration tests not covered by the test suite
@@ -0,0 +1,25 @@
1
+ [forbidden-imports]
2
+ modules = [
3
+ "argparse",
4
+ "click",
5
+ "typer",
6
+ "flask",
7
+ "fastapi",
8
+ "django",
9
+ "uvicorn",
10
+ "granian",
11
+ "starlette",
12
+ "tornado",
13
+ "bottle",
14
+ ]
15
+
16
+ [stdout]
17
+ enabled = true
18
+ ignore = []
19
+
20
+ [entry-point]
21
+ enabled = true
22
+ ignore = []
23
+
24
+ [files]
25
+ exclude = []
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ - Initial release
@@ -0,0 +1 @@
1
+ fc67d7d7fd04667ac82ff49e54875ee5cfa32b12
@@ -0,0 +1,15 @@
1
+ {"commits":["c55effaf38258e704c0fb226209331d1580acfab","c1ce7abe9bcdcb50345e89482afc9d6b3c778974","a9481027ed2223f6d224891c9a7c1a7cf37909cc","eef1c8f83910cc5b81a92f30617f5c78720a7f4a","62872272c9c0405fa125a5000e07fa68664851e7"],"user_facing":true,"description":"**New feature.** Typed streaming SDK for LLM tool-calling loops with async/sync sessions, tool registration, agent definitions, and direct API backend.","type":"feature"}
2
+ {"commits":["1669386f20681682a82b24ff8ada3594f724c3cd","d4bc8abb8e57eed561c634bbfb48ef6dc193ab15","89d9e4342a75286946e511805eb56b85b7fcf4d2","33be63efbb342dd71512e555f1c29bb8f1a7e596","a984925afc18ecd97698724649d00439ec2fda61"],"user_facing":false}
3
+ {"commits":["4dd50fedaf0d9e8f6319462fcbda94ee576e5c86","1ad69e4fc2f72ea04d70571f4ed89566d05aef02","4b87daaa2e4c067a147cb532a55c4352c0b3fbb6","a02905c95d26c2f5d85b02c1e99839a6767b8a65","f0007c69a636edfaa58566387e0c871775155443"],"user_facing":false}
4
+ {"commits":["48f8d679198e93f90d0a7f093fc871153432f630","78415fc02c7fc070f101dd1b3c8e79f052cf8607","bf8f7709477802d19549d0e5013ae93e01370d8a"],"user_facing":false}
5
+ {"commits":["26149d43fdd04d5e264a3ab9a19fea6091c0d3e0","f4607a61c8787982789f33a6f37b96f4b1b3e2a6","fc6772a1d11577ebdbf9d76886100ce7e96ce9a1","9f93e82b5845089e4191ddf115e294f9bb92a002","0852d267c46d995fc5b108d10c6e5139bab10020"],"user_facing":false}
6
+ {"commits":["e6d6102e24f0b512801a50df417b7533169a3724","28eb8ae8a65061759b9f0af8d93e4c3c641d7738","33fddaae9cb7b69c73e36cf96f0d5bfbfa6550fd","6af9091768435b243765db7d12d0d682d0010486","463bb9047017b64bd1c78d76854f35893ed972f2"],"user_facing":false}
7
+ {"commits":["0c2c142e7fcc6a64cc2edcbd2ac17b90f305ecfb","212e3a09205b013ec0e6affe31ca3496b536d71b","7e032734872527adf7e0b7765d8ff13c7b547e21","4f6e6840254384a6bc84af2ae882592619733be2"],"user_facing":false}
8
+ {"commits":["1e120368f06d2bcf2bd08a598d47b0c8325e4ce5","a35b1ed40b6bfed1adb21adaf83d10fbeb47c6e0","495c8a63467ef6353fc44dfefeb14b62145fc0bd","28ddb67d9d4b61748724816d7471c11d55fdff29","0695651f242154f42d735b208ac68980a8fff45f"],"user_facing":false}
9
+ {"commits":["b8ed602e225e66eecf2105517176e5aa9c928c56","2a2febcd235eae94175bbc7874d0a7e3ad6c7301","a016bdada30c37c165064243c3abb2760e9ef44f","b1945206f0a81b67b7fb64ad8578232129ef634d","d408e39ac29dcde7c4e7d483a0f79847e8210859"],"user_facing":false}
10
+ {"commits":["bba6f6362b31ebd896703a700481084c0c6c0be5","30fa6347b895bf263d61a336b0890d32f6f8b219","088c98e0f759a261ec8468e1339095b60ca2fb10","a4bea191e26aaea8f3b710e2c73bdeed54449d45","f1c995dffbca5f38b1a9e1734db0fb687b7f5895"],"user_facing":false}
11
+ {"commits":["b1a4603d793057bf1a9e2bd4c757871685d29154","98e5605d3bf3cf1681d81d26d500c9d5ba0efe1c","5a9489ef0bfa4cee9189c40c567c33cea31454b3","a171da6831bbd808c565e058b7830188031f158c","5b7b608d504faa37679f168afcac86785688e391"],"user_facing":false}
12
+ {"commits":["b2dfd283226ac361a3912e21c9ac7e239b7a8df9","9cf2a20523e76ebad80008affddb16829e5a10c6","b84b6383cf625ed39eefa05608e51c865974947c","a0aa9fe86be17d8482d583ae4794d62fa224069a","cfe8a844ff8ec17254c256625a2b5a4216a5e4d5"],"user_facing":false}
13
+ {"commits":["4d91e4a683c29b770be4fa23c86c422224fde968","76b5de6aa85b6c02ea5e072470fa2811f1ba27eb","14f61389136eb114c7fdbbc2f89bd4a87ab6a9ad","250e22fd2d90ca9ad1a2d006f5861f892c2432c2","707a8c463d70a9d93efdbe9a42f9891cbbe050ec"],"user_facing":false}
14
+ {"commits":["c3344480247105a363a94bd0268c20bd5b825e03","fa94248b24017a7b4fea2974bff0093df8fc6573","e62f6cc8f85546b16df0c15f89ad8680e1814d54","9445cdf9c6282e3c9da8be13b317d947e18f6889"],"user_facing":false}
15
+ {"commits":["e1b14fd6c7a16694dcf918aa77e4398e96323d96","18368bf426ad38fcdfdae7317f5ea723a6191b63"],"user_facing":false}
@@ -0,0 +1,7 @@
1
+ ## 0.1.0
2
+
3
+ Initial release: typed streaming SDK for LLM tool-calling loops
4
+
5
+ ### Features
6
+
7
+ - **New feature.** Typed streaming SDK for LLM tool-calling loops with async/sync sessions, tool registration, agent definitions, and direct API backend.
File without changes
@@ -0,0 +1,12 @@
1
+ {
2
+ "targets": [
3
+ "pypi"
4
+ ],
5
+ "private": false,
6
+ "pipelines": {
7
+ "pypi": {
8
+ "type": "pypi",
9
+ "local": false
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ ".github/workflows/ci.yml": "3c8019d75aad7546f505fe83725adab37a67037f2c09bf19bd8d1767cc4c7ee2",
3
+ ".github/workflows/publish.yml": "c86fe3682721199f304390f8acbaf57aef8b5e6d98cca4787aa70ef209979596",
4
+ "CHANGELOG.md": "7a6ec46141007c18090a0ff325e2dd68cd51588c4e0b5af7b580365e5eaaca85",
5
+ ".gitignore": "c0582f9b1c640f9f9a8acbbe02cd19fff50e66cc595f25e129b7cc9b6cd357db",
6
+ ".rlsbl/hooks/pre-checks.sh": "60c57d4563263124530e6f33aca77550ea2161ad3b33b3ba6ad1c03fea9eb6e2",
7
+ ".rlsbl/hooks/pre-release.sh": "799fe9a8ed742f5b4f7bc32856df8487b05ab28a37aaa0e9ecf854ea289c5305",
8
+ ".rlsbl/hooks/post-release.sh": "a7548df0ce46ee421865afbe50b0c327b301ad003519aa2f2521edb484c3865c",
9
+ ".rlsbl/changes/unreleased.jsonl": "11f98a6a99eb629a9b201adf81d5de7c4df6cfdac5fbf945dd62223ad1b397a8",
10
+ ".rlsbl/lint/python.toml": "9cfbcef2e010d5fad243437bf2fd8df54a1fae70ee0762f9d11da70fe207501c"
11
+ }
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+ # Post-release hook. Runs after a successful release (non-fatal).
3
+ # Environment: RLSBL_VERSION is set to the released version.
4
+ # Customize this for your project (e.g., local install, deploy, notify).
5
+
6
+ set -euo pipefail
7
+
8
+ echo "Post-release: v$RLSBL_VERSION"
9
+
10
+ # Push to assembly for unified documentation site
11
+ if command -v selfdoc &>/dev/null && [ -f selfdoc.json ]; then
12
+ if python3 -c "import json; c=json.load(open('selfdoc.json')); exit(0 if c.get('assembly') or (c.get('topology') or {}).get('assembly') else 1)" 2>/dev/null; then
13
+ echo "Pushing to documentation assembly..."
14
+ selfdoc assembly push || echo "Warning: assembly push failed (non-fatal)"
15
+ fi
16
+ fi
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ # This hook runs BEFORE built-in pre-release checks (tests, lint).
4
+ # Use it for setup tasks: starting services, setting env vars, etc.
5
+ # Built-in checks run after this hook. Custom validation goes in pre-release.sh.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ # Project-specific pre-release checks.
4
+ # When this hook is customized (any change from the scaffold template),
5
+ # built-in tests and lint are skipped -- the hook is expected to handle them.
6
+ # Add custom validation here, e.g.:
7
+ # - Run tests and lint with project-specific flags
8
+ # - Check for uncommitted documentation
9
+ # - Verify external service connectivity
10
+ # - Run integration tests not covered by the test suite
@@ -0,0 +1,25 @@
1
+ [forbidden-imports]
2
+ modules = [
3
+ "argparse",
4
+ "click",
5
+ "typer",
6
+ "flask",
7
+ "fastapi",
8
+ "django",
9
+ "uvicorn",
10
+ "granian",
11
+ "starlette",
12
+ "tornado",
13
+ "bottle",
14
+ ]
15
+
16
+ [stdout]
17
+ enabled = true
18
+ ignore = []
19
+
20
+ [entry-point]
21
+ enabled = true
22
+ ignore = []
23
+
24
+ [files]
25
+ exclude = []
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": 1,
3
+ "files": {
4
+ ".github/workflows/ci.yml": "3c8019d75aad7546f505fe83725adab37a67037f2c09bf19bd8d1767cc4c7ee2",
5
+ ".github/workflows/publish.yml": "c86fe3682721199f304390f8acbaf57aef8b5e6d98cca4787aa70ef209979596",
6
+ "CHANGELOG.md": "7a6ec46141007c18090a0ff325e2dd68cd51588c4e0b5af7b580365e5eaaca85",
7
+ ".gitignore": "c0582f9b1c640f9f9a8acbbe02cd19fff50e66cc595f25e129b7cc9b6cd357db",
8
+ ".rlsbl/hooks/pre-checks.sh": "60c57d4563263124530e6f33aca77550ea2161ad3b33b3ba6ad1c03fea9eb6e2",
9
+ ".rlsbl/hooks/pre-release.sh": "799fe9a8ed742f5b4f7bc32856df8487b05ab28a37aaa0e9ecf854ea289c5305",
10
+ ".rlsbl/hooks/post-release.sh": "a7548df0ce46ee421865afbe50b0c327b301ad003519aa2f2521edb484c3865c",
11
+ ".rlsbl/changes/unreleased.jsonl": "11f98a6a99eb629a9b201adf81d5de7c4df6cfdac5fbf945dd62223ad1b397a8",
12
+ ".rlsbl/lint/python.toml": "9cfbcef2e010d5fad243437bf2fd8df54a1fae70ee0762f9d11da70fe207501c"
13
+ }
14
+ }
File without changes
@@ -0,0 +1,10 @@
1
+ # Version bump type: patch, minor, or major
2
+ bump = "minor"
3
+ # Short description of this release (required)
4
+ description = "Initial release: typed streaming SDK for LLM tool-calling loops"
5
+ # Optional context explaining why these changes were made
6
+ context = ""
7
+ # Set to true to generate a blog post for this release
8
+ # blog = false
9
+ include = ["pypi"]
10
+ exclude = []
@@ -0,0 +1 @@
1
+ 0.74.1
@@ -0,0 +1,11 @@
1
+ <!-- Generated by rlsbl from .rlsbl/changes/ — do not edit -->
2
+
3
+ # Changelog
4
+
5
+ ## 0.1.0
6
+
7
+ Initial release: typed streaming SDK for LLM tool-calling loops
8
+
9
+ ### Features
10
+
11
+ - **New feature.** Typed streaming SDK for LLM tool-calling loops with async/sync sessions, tool registration, agent definitions, and direct API backend.
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: toolstream
3
+ Version: 0.1.0
4
+ Summary: Typed streaming SDK for LLM tool-calling loops
5
+ Keywords: rlsbl
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: httpx
@@ -0,0 +1,8 @@
1
+ # toolstream
2
+
3
+ This is a name-claim shim. The real package is on PyPI:
4
+
5
+ pip install toolstream
6
+
7
+ - PyPI: https://pypi.org/project/toolstream/
8
+ - GitHub: https://github.com/smm-h/toolstream
@@ -0,0 +1,5 @@
1
+ throw new Error(
2
+ "toolstream is a Python package. Install it with: pip install toolstream\n" +
3
+ "PyPI: https://pypi.org/project/toolstream/\n" +
4
+ "GitHub: https://github.com/smm-h/toolstream"
5
+ );
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "toolstream",
3
+ "version": "0.1.0",
4
+ "description": "Typed streaming SDK for LLM tool-calling loops (Python package — install via pip)",
5
+ "main": "index.js",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/smm-h/toolstream"
9
+ },
10
+ "keywords": ["llm", "streaming", "tool-calling", "ai", "sdk"],
11
+ "license": "UNLICENSED"
12
+ }
@@ -0,0 +1,26 @@
1
+ [project]
2
+ name = "toolstream"
3
+ version = "0.1.0"
4
+ requires-python = ">=3.11"
5
+ description = "Typed streaming SDK for LLM tool-calling loops"
6
+
7
+ dependencies = ["httpx"]
8
+ keywords = ["rlsbl"]
9
+
10
+ [build-system]
11
+ requires = ["hatchling"]
12
+ build-backend = "hatchling.build"
13
+
14
+ [tool.hatch.build.targets.wheel]
15
+ packages = ["toolstream"]
16
+
17
+ [dependency-groups]
18
+ dev = ["pytest", "pytest-asyncio"]
19
+
20
+ [tool.pytest.ini_options]
21
+ addopts = "--import-mode=importlib -m 'not slow'"
22
+ testpaths = ["tests"]
23
+ markers = [
24
+ "slow: marks tests as slow (deselect with '-m \"not slow\"')",
25
+ ]
26
+ asyncio_mode = "auto"
File without changes
@@ -0,0 +1,98 @@
1
+ """Shared fixtures for toolstream tests -- mock LLM responder."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from typing import Any
7
+
8
+ import httpx
9
+ import pytest
10
+
11
+ from toolstream.config import SessionConfig
12
+
13
+
14
+ def text_response(
15
+ content: str,
16
+ prompt_tokens: int = 10,
17
+ completion_tokens: int = 5,
18
+ ) -> dict:
19
+ """Build a canned text-only chat completion response."""
20
+ return {
21
+ "choices": [{
22
+ "message": {
23
+ "content": content,
24
+ "tool_calls": None,
25
+ },
26
+ "finish_reason": "stop",
27
+ }],
28
+ "usage": {
29
+ "prompt_tokens": prompt_tokens,
30
+ "completion_tokens": completion_tokens,
31
+ "total_tokens": prompt_tokens + completion_tokens,
32
+ },
33
+ }
34
+
35
+
36
+ def tool_call_response(
37
+ tool_name: str,
38
+ arguments: dict,
39
+ call_id: str = "call_1",
40
+ prompt_tokens: int = 10,
41
+ completion_tokens: int = 5,
42
+ ) -> dict:
43
+ """Build a canned tool-call chat completion response."""
44
+ return {
45
+ "choices": [{
46
+ "message": {
47
+ "content": None,
48
+ "tool_calls": [{
49
+ "id": call_id,
50
+ "type": "function",
51
+ "function": {
52
+ "name": tool_name,
53
+ "arguments": json.dumps(arguments),
54
+ },
55
+ }],
56
+ },
57
+ "finish_reason": "tool_calls",
58
+ }],
59
+ "usage": {
60
+ "prompt_tokens": prompt_tokens,
61
+ "completion_tokens": completion_tokens,
62
+ "total_tokens": prompt_tokens + completion_tokens,
63
+ },
64
+ }
65
+
66
+
67
+ def direct_config(**overrides: Any) -> SessionConfig:
68
+ """Build a SessionConfig suitable for DirectClient with mock http_client."""
69
+ defaults: dict[str, Any] = dict(
70
+ model="test-model",
71
+ api_key="test-key",
72
+ base_url="https://mock-gateway.test/v1/chat/completions",
73
+ system_prompt="You are a test assistant.",
74
+ )
75
+ defaults.update(overrides)
76
+ return SessionConfig(**defaults)
77
+
78
+
79
+ @pytest.fixture
80
+ def mock_llm_responses():
81
+ """Factory fixture: call with canned response dicts to get a mock httpx.AsyncClient."""
82
+
83
+ def factory(*responses: dict) -> httpx.AsyncClient:
84
+ it = iter(responses)
85
+
86
+ def handler(request: httpx.Request) -> httpx.Response:
87
+ try:
88
+ response_dict = next(it)
89
+ except StopIteration:
90
+ raise RuntimeError(
91
+ f"mock_llm_responses exhausted: expected at most "
92
+ f"{len(responses)} call(s)"
93
+ )
94
+ return httpx.Response(200, json=response_dict)
95
+
96
+ return httpx.AsyncClient(transport=httpx.MockTransport(handler))
97
+
98
+ return factory
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "explorer",
3
+ "version": "1.0",
4
+ "prompt_template": "You are an explorer agent. Task: {task}",
5
+ "description": "Test explorer agent"
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "orchestrator",
3
+ "version": "1.0",
4
+ "prompt_template": "You are an orchestrator. Task: {task}",
5
+ "description": "Test orchestrator agent",
6
+ "tools": [{"name": "read"}, {"name": "write"}]
7
+ }