Skip to content

Commit aa3a7f0

Browse files
authored
Merge branch 'main' into feature/support-gemini-tools
2 parents f095a05 + 1df45be commit aa3a7f0

File tree

120 files changed

+12300
-639
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+12300
-639
lines changed

.codecov.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
coverage:
2+
status:
3+
project:
4+
default:
5+
target: 90% # overall coverage threshold
6+
patch:
7+
default:
8+
target: 90% # patch coverage threshold
9+
base: auto
10+
# Only post patch coverage on decreases
11+
only_pulls: true
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: PR Size Labeler
2+
3+
on:
4+
pull_request_target:
5+
branches: main
6+
7+
jobs:
8+
label-size:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
pull-requests: write
12+
issues: write
13+
steps:
14+
- name: Calculate PR size and apply label
15+
uses: actions/github-script@v8
16+
with:
17+
script: |
18+
const pr = context.payload.pull_request;
19+
const totalChanges = pr.additions + pr.deletions;
20+
21+
// Remove existing size labels
22+
const labels = await github.rest.issues.listLabelsOnIssue({
23+
owner: context.repo.owner,
24+
repo: context.repo.repo,
25+
issue_number: context.payload.pull_request.number
26+
});
27+
28+
for (const label of labels.data) {
29+
if (label.name.startsWith('size/')) {
30+
await github.rest.issues.removeLabel({
31+
owner: context.repo.owner,
32+
repo: context.repo.repo,
33+
issue_number: context.payload.pull_request.number,
34+
name: label.name
35+
});
36+
}
37+
}
38+
39+
// Determine and apply new size label
40+
let sizeLabel;
41+
if (totalChanges <= 20) sizeLabel = 'size/xs';
42+
else if (totalChanges <= 100) sizeLabel = 'size/s';
43+
else if (totalChanges <= 500) sizeLabel = 'size/m';
44+
else if (totalChanges <= 1000) sizeLabel = 'size/l';
45+
else {
46+
sizeLabel = 'size/xl';
47+
}
48+
49+
await github.rest.issues.addLabels({
50+
owner: context.repo.owner,
51+
repo: context.repo.repo,
52+
issue_number: context.payload.pull_request.number,
53+
labels: [sizeLabel]
54+
});
55+
56+
if (sizeLabel === 'size/xl') {
57+
core.setFailed(`PR is too large (${totalChanges} lines). Please split into smaller PRs.`);
58+
}

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ __pycache__*
1111
.vscode
1212
dist
1313
repl_state
14-
.kiro
14+
.kiro
15+
uv.lock

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ dependencies = [
3030
"boto3>=1.26.0,<2.0.0",
3131
"botocore>=1.29.0,<2.0.0",
3232
"docstring_parser>=0.15,<1.0",
33+
"jsonschema>=4.0.0,<5.0.0",
3334
"mcp>=1.11.0,<2.0.0",
3435
"pydantic>=2.4.0,<3.0.0",
3536
"typing-extensions>=4.13.2,<5.0.0",

src/strands/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,12 @@
55
from .tools.decorator import tool
66
from .types.tools import ToolContext
77

8-
__all__ = ["Agent", "agent", "models", "tool", "types", "telemetry", "ToolContext"]
8+
__all__ = [
9+
"Agent",
10+
"agent",
11+
"models",
12+
"tool",
13+
"ToolContext",
14+
"types",
15+
"telemetry",
16+
]

src/strands/_async.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Private async execution utilities."""
2+
3+
import asyncio
4+
from concurrent.futures import ThreadPoolExecutor
5+
from typing import Awaitable, Callable, TypeVar
6+
7+
T = TypeVar("T")
8+
9+
10+
def run_async(async_func: Callable[[], Awaitable[T]]) -> T:
11+
"""Run an async function in a separate thread to avoid event loop conflicts.
12+
13+
This utility handles the common pattern of running async code from sync contexts
14+
by using ThreadPoolExecutor to isolate the async execution.
15+
16+
Args:
17+
async_func: A callable that returns an awaitable
18+
19+
Returns:
20+
The result of the async function
21+
"""
22+
23+
async def execute_async() -> T:
24+
return await async_func()
25+
26+
def execute() -> T:
27+
return asyncio.run(execute_async())
28+
29+
with ThreadPoolExecutor() as executor:
30+
future = executor.submit(execute)
31+
return future.result()

0 commit comments

Comments
 (0)