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.
- toolstream-0.1.0/.github/workflows/ci.yml +25 -0
- toolstream-0.1.0/.github/workflows/publish.yml +21 -0
- toolstream-0.1.0/.gitignore +17 -0
- toolstream-0.1.0/.rlsbl/bases/.github/workflows/ci.yml +25 -0
- toolstream-0.1.0/.rlsbl/bases/.github/workflows/publish.yml +21 -0
- toolstream-0.1.0/.rlsbl/bases/.gitignore +16 -0
- toolstream-0.1.0/.rlsbl/bases/.rlsbl/changes/unreleased.jsonl +0 -0
- toolstream-0.1.0/.rlsbl/bases/.rlsbl/hooks/post-release.sh +16 -0
- toolstream-0.1.0/.rlsbl/bases/.rlsbl/hooks/pre-checks.sh +5 -0
- toolstream-0.1.0/.rlsbl/bases/.rlsbl/hooks/pre-release.sh +10 -0
- toolstream-0.1.0/.rlsbl/bases/.rlsbl/lint/python.toml +25 -0
- toolstream-0.1.0/.rlsbl/bases/CHANGELOG.md +5 -0
- toolstream-0.1.0/.rlsbl/changes/.validated +1 -0
- toolstream-0.1.0/.rlsbl/changes/0.1.0.jsonl +15 -0
- toolstream-0.1.0/.rlsbl/changes/0.1.0.md +7 -0
- toolstream-0.1.0/.rlsbl/changes/unreleased.jsonl +0 -0
- toolstream-0.1.0/.rlsbl/config.json +12 -0
- toolstream-0.1.0/.rlsbl/hashes.json +11 -0
- toolstream-0.1.0/.rlsbl/hooks/post-release.sh +16 -0
- toolstream-0.1.0/.rlsbl/hooks/pre-checks.sh +5 -0
- toolstream-0.1.0/.rlsbl/hooks/pre-release.sh +10 -0
- toolstream-0.1.0/.rlsbl/lint/python.toml +25 -0
- toolstream-0.1.0/.rlsbl/managed-files.json +14 -0
- toolstream-0.1.0/.rlsbl/releases/unreleased.toml +0 -0
- toolstream-0.1.0/.rlsbl/releases/v0.1.0.toml +10 -0
- toolstream-0.1.0/.rlsbl/version +1 -0
- toolstream-0.1.0/CHANGELOG.md +11 -0
- toolstream-0.1.0/PKG-INFO +7 -0
- toolstream-0.1.0/npm/README.md +8 -0
- toolstream-0.1.0/npm/index.js +5 -0
- toolstream-0.1.0/npm/package.json +12 -0
- toolstream-0.1.0/pyproject.toml +26 -0
- toolstream-0.1.0/tests/__init__.py +0 -0
- toolstream-0.1.0/tests/conftest.py +98 -0
- toolstream-0.1.0/tests/fixtures/agents/explorer.agent.json +6 -0
- toolstream-0.1.0/tests/fixtures/agents/orchestrator.agent.json +7 -0
- toolstream-0.1.0/tests/test_agent.py +298 -0
- toolstream-0.1.0/tests/test_builtin_tools.py +282 -0
- toolstream-0.1.0/tests/test_direct.py +482 -0
- toolstream-0.1.0/tests/test_events.py +99 -0
- toolstream-0.1.0/tests/test_injection.py +219 -0
- toolstream-0.1.0/tests/test_integration.py +284 -0
- toolstream-0.1.0/tests/test_invoke.py +373 -0
- toolstream-0.1.0/tests/test_protocol.py +171 -0
- toolstream-0.1.0/tests/test_schema.py +519 -0
- toolstream-0.1.0/tests/test_session.py +89 -0
- toolstream-0.1.0/tests/test_tools.py +344 -0
- toolstream-0.1.0/toolstream/__init__.py +44 -0
- toolstream-0.1.0/toolstream/_agent.py +215 -0
- toolstream-0.1.0/toolstream/_builtin_tools.py +115 -0
- toolstream-0.1.0/toolstream/_context.py +14 -0
- toolstream-0.1.0/toolstream/_direct.py +292 -0
- toolstream-0.1.0/toolstream/_invoke.py +126 -0
- toolstream-0.1.0/toolstream/_protocol.py +87 -0
- toolstream-0.1.0/toolstream/_schema.py +259 -0
- toolstream-0.1.0/toolstream/_session.py +176 -0
- toolstream-0.1.0/toolstream/_tools.py +109 -0
- toolstream-0.1.0/toolstream/config.py +26 -0
- toolstream-0.1.0/toolstream/events.py +63 -0
- toolstream-0.1.0/toolstream/py.typed +0 -0
- 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,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
|
|
File without changes
|
|
@@ -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,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 @@
|
|
|
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}
|
|
File without changes
|
|
@@ -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,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,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
|