Skip to content

Commit 0e31f5d

Browse files
Merge branch 'main' into u/xiaoyun/0419
2 parents c7a0981 + 093c1a2 commit 0e31f5d

33 files changed

+1173
-93
lines changed

.github/workflows/build.yml

+61-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ name: Build
66
on:
77
push:
88
branches: ["main"]
9-
paths:
10-
- "autogen/**"
11-
- "test/**"
12-
- ".github/workflows/build.yml"
13-
- "setup.py"
149
pull_request:
1510
branches: ["main"]
1611
merge_group:
@@ -21,7 +16,39 @@ concurrency:
2116
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
2217
permissions: {}
2318
jobs:
19+
paths-filter:
20+
runs-on: ubuntu-latest
21+
outputs:
22+
hasChanges: ${{ steps.filter.outputs.autogen == 'true' || steps.filter.outputs.test == 'true' || steps.filter.outputs.workflows == 'true' || steps.filter.outputs.setup == 'true' }}
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: dorny/paths-filter@v2
26+
id: filter
27+
with:
28+
filters: |
29+
autogen:
30+
- "autogen/**"
31+
test:
32+
- "test/**"
33+
workflows:
34+
- ".github/workflows/**"
35+
setup:
36+
- "setup.py"
37+
- name: autogen has changes
38+
run: echo "autogen has changes"
39+
if: steps.filter.outputs.autogen == 'true'
40+
- name: test has changes
41+
run: echo "test has changes"
42+
if: steps.filter.outputs.test == 'true'
43+
- name: workflows has changes
44+
run: echo "workflows has changes"
45+
if: steps.filter.outputs.workflows == 'true'
46+
- name: setup has changes
47+
run: echo "setup has changes"
48+
if: steps.filter.outputs.setup == 'true'
2449
build:
50+
needs: paths-filter
51+
if: needs.paths-filter.outputs.hasChanges == 'true'
2552
runs-on: ${{ matrix.os }}
2653
env:
2754
AUTOGEN_USE_DOCKER: ${{ matrix.os != 'ubuntu-latest' && 'False' }}
@@ -82,3 +109,32 @@ jobs:
82109
with:
83110
file: ./coverage.xml
84111
flags: unittests
112+
build-check:
113+
if: always()
114+
runs-on: ubuntu-latest
115+
needs: [build]
116+
steps:
117+
- name: Get Date
118+
shell: bash
119+
run: |
120+
echo "date=$(date +'%m/%d/%Y %H:%M:%S')" >> "$GITHUB_ENV"
121+
122+
- name: Run Type is ${{ github.event_name }}
123+
if: ${{ github.event_name != 'schedule' && github.event_name != 'workflow_dispatch'}}
124+
shell: bash
125+
run: |
126+
echo "run_type=${{ github.event_name }}" >> "$GITHUB_ENV"
127+
128+
- name: Fail workflow if build failed
129+
id: check_build_failed
130+
if: contains(join(needs.*.result, ','), 'failure')
131+
uses: actions/github-script@v6
132+
with:
133+
script: core.setFailed('Build Failed!')
134+
135+
- name: Fail workflow if build cancelled
136+
id: check_build_cancelled
137+
if: contains(join(needs.*.result, ','), 'cancelled')
138+
uses: actions/github-script@v6
139+
with:
140+
script: core.setFailed('Build Cancelled!')

.github/workflows/dotnet-build.yml

+26-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ on:
77
workflow_dispatch:
88
pull_request:
99
branches: [ "main" ]
10-
paths:
11-
- 'dotnet/**'
1210
push:
1311
branches: [ "main" ]
12+
merge_group:
13+
types: [checks_requested]
1414

1515
concurrency:
1616
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref }}
@@ -21,9 +21,31 @@ permissions:
2121
packages: write
2222

2323
jobs:
24+
paths-filter:
25+
runs-on: ubuntu-latest
26+
outputs:
27+
hasChanges: ${{ steps.filter.outputs.dotnet == 'true'}}
28+
steps:
29+
- uses: actions/checkout@v4
30+
- uses: dorny/paths-filter@v2
31+
id: filter
32+
with:
33+
filters: |
34+
dotnet:
35+
- "dotnet/**"
36+
workflows:
37+
- ".github/workflows/**"
38+
- name: dotnet has changes
39+
run: echo "dotnet has changes"
40+
if: steps.filter.outputs.dotnet == 'true'
41+
- name: workflows has changes
42+
run: echo "workflows has changes"
43+
if: steps.filter.outputs.workflows == 'true'
2444
build:
2545
name: Dotnet Build
2646
runs-on: ubuntu-latest
47+
needs: paths-filter
48+
if: needs.paths-filter.outputs.hasChanges == 'true'
2749
defaults:
2850
run:
2951
working-directory: dotnet
@@ -52,7 +74,7 @@ jobs:
5274
defaults:
5375
run:
5476
working-directory: dotnet
55-
if: success() && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dotnet')
77+
if: success() && (github.ref == 'refs/heads/main')
5678
needs: build
5779
steps:
5880
- uses: actions/checkout@v4
@@ -142,4 +164,4 @@ jobs:
142164
ls -R ./output/nightly
143165
dotnet nuget push --api-key ${{ secrets.MYGET_TOKEN }} --source "https://www.myget.org/F/agentchat/api/v3/index.json" ./output/nightly/*.nupkg --skip-duplicate
144166
env:
145-
MYGET_TOKEN: ${{ secrets.MYGET_TOKEN }}
167+
MYGET_TOKEN: ${{ secrets.MYGET_TOKEN }}

.github/workflows/lfs-check.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ jobs:
1010
uses: actions/checkout@v4
1111
with:
1212
lfs: true
13-
- name: Check Git LFS files for consistency
13+
- name: "Check Git LFS files for consistency, if you see error like 'pointer: unexpectedGitObject ... should have been a pointer but was not', please install Git LFS locally, delete the problematic file, and then add it back again. This ensures it's properly tracked."
1414
run: |
1515
git lfs fsck

autogen/code_utils.py

+2
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ def _cmd(lang: str) -> str:
251251
return lang
252252
if lang in ["shell"]:
253253
return "sh"
254+
if lang == "javascript":
255+
return "node"
254256
if lang in ["ps1", "pwsh", "powershell"]:
255257
powershell_command = get_powershell_command()
256258
return powershell_command

autogen/coding/docker_commandline_code_executor.py

+55-19
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from pathlib import Path
99
from time import sleep
1010
from types import TracebackType
11-
from typing import Any, List, Optional, Type, Union
11+
from typing import Any, ClassVar, Dict, List, Optional, Type, Union
1212

1313
import docker
1414
from docker.errors import ImageNotFound
@@ -39,14 +39,30 @@ def _wait_for_ready(container: Any, timeout: int = 60, stop_time: float = 0.1) -
3939

4040

4141
class DockerCommandLineCodeExecutor(CodeExecutor):
42+
DEFAULT_EXECUTION_POLICY: ClassVar[Dict[str, bool]] = {
43+
"bash": True,
44+
"shell": True,
45+
"sh": True,
46+
"pwsh": True,
47+
"powershell": True,
48+
"ps1": True,
49+
"python": True,
50+
"javascript": False,
51+
"html": False,
52+
"css": False,
53+
}
54+
LANGUAGE_ALIASES: ClassVar[Dict[str, str]] = {"py": "python", "js": "javascript"}
55+
4256
def __init__(
4357
self,
4458
image: str = "python:3-slim",
4559
container_name: Optional[str] = None,
4660
timeout: int = 60,
4761
work_dir: Union[Path, str] = Path("."),
62+
bind_dir: Optional[Union[Path, str]] = None,
4863
auto_remove: bool = True,
4964
stop_container: bool = True,
65+
execution_policies: Optional[Dict[str, bool]] = None,
5066
):
5167
"""(Experimental) A code executor class that executes code through
5268
a command line environment in a Docker container.
@@ -67,6 +83,9 @@ def __init__(
6783
timeout (int, optional): The timeout for code execution. Defaults to 60.
6884
work_dir (Union[Path, str], optional): The working directory for the code
6985
execution. Defaults to Path(".").
86+
bind_dir (Union[Path, str], optional): The directory that will be bound
87+
to the code executor container. Useful for cases where you want to spawn
88+
the container from within a container. Defaults to work_dir.
7089
auto_remove (bool, optional): If true, will automatically remove the Docker
7190
container when it is stopped. Defaults to True.
7291
stop_container (bool, optional): If true, will automatically stop the
@@ -76,17 +95,19 @@ def __init__(
7695
Raises:
7796
ValueError: On argument error, or if the container fails to start.
7897
"""
79-
8098
if timeout < 1:
8199
raise ValueError("Timeout must be greater than or equal to 1.")
82100

83101
if isinstance(work_dir, str):
84102
work_dir = Path(work_dir)
85-
86103
work_dir.mkdir(exist_ok=True)
87104

88-
client = docker.from_env()
105+
if bind_dir is None:
106+
bind_dir = work_dir
107+
elif isinstance(bind_dir, str):
108+
bind_dir = Path(bind_dir)
89109

110+
client = docker.from_env()
90111
# Check if the image exists
91112
try:
92113
client.images.get(image)
@@ -105,7 +126,7 @@ def __init__(
105126
entrypoint="/bin/sh",
106127
tty=True,
107128
auto_remove=auto_remove,
108-
volumes={str(work_dir.resolve()): {"bind": "/workspace", "mode": "rw"}},
129+
volumes={str(bind_dir.resolve()): {"bind": "/workspace", "mode": "rw"}},
109130
working_dir="/workspace",
110131
)
111132
self._container.start()
@@ -118,7 +139,6 @@ def cleanup() -> None:
118139
container.stop()
119140
except docker.errors.NotFound:
120141
pass
121-
122142
atexit.unregister(cleanup)
123143

124144
if stop_container:
@@ -132,6 +152,10 @@ def cleanup() -> None:
132152

133153
self._timeout = timeout
134154
self._work_dir: Path = work_dir
155+
self._bind_dir: Path = bind_dir
156+
self.execution_policies = self.DEFAULT_EXECUTION_POLICY.copy()
157+
if execution_policies is not None:
158+
self.execution_policies.update(execution_policies)
135159

136160
@property
137161
def timeout(self) -> int:
@@ -143,6 +167,11 @@ def work_dir(self) -> Path:
143167
"""(Experimental) The working directory for the code execution."""
144168
return self._work_dir
145169

170+
@property
171+
def bind_dir(self) -> Path:
172+
"""(Experimental) The binding directory for the code execution container."""
173+
return self._bind_dir
174+
146175
@property
147176
def code_extractor(self) -> CodeExtractor:
148177
"""(Experimental) Export a code extractor that can be used by an agent."""
@@ -164,35 +193,42 @@ def execute_code_blocks(self, code_blocks: List[CodeBlock]) -> CommandLineCodeRe
164193
files = []
165194
last_exit_code = 0
166195
for code_block in code_blocks:
167-
lang = code_block.language
196+
lang = self.LANGUAGE_ALIASES.get(code_block.language.lower(), code_block.language.lower())
197+
if lang not in self.DEFAULT_EXECUTION_POLICY:
198+
outputs.append(f"Unsupported language {lang}\n")
199+
last_exit_code = 1
200+
break
201+
202+
execute_code = self.execution_policies.get(lang, False)
168203
code = silence_pip(code_block.code, lang)
169204

205+
# Check if there is a filename comment
170206
try:
171-
# Check if there is a filename comment
172-
filename = _get_file_name_from_content(code, Path("/workspace"))
207+
filename = _get_file_name_from_content(code, self._work_dir)
173208
except ValueError:
174-
return CommandLineCodeResult(exit_code=1, output="Filename is not in the workspace")
209+
outputs.append("Filename is not in the workspace")
210+
last_exit_code = 1
211+
break
175212

176-
if filename is None:
177-
# create a file with an automatically generated name
178-
code_hash = md5(code.encode()).hexdigest()
179-
filename = f"tmp_code_{code_hash}.{'py' if lang.startswith('python') else lang}"
213+
if not filename:
214+
filename = f"tmp_code_{md5(code.encode()).hexdigest()}.{lang}"
180215

181216
code_path = self._work_dir / filename
182217
with code_path.open("w", encoding="utf-8") as fout:
183218
fout.write(code)
219+
files.append(code_path)
184220

185-
command = ["timeout", str(self._timeout), _cmd(lang), filename]
221+
if not execute_code:
222+
outputs.append(f"Code saved to {str(code_path)}\n")
223+
continue
186224

225+
command = ["timeout", str(self._timeout), _cmd(lang), filename]
187226
result = self._container.exec_run(command)
188227
exit_code = result.exit_code
189228
output = result.output.decode("utf-8")
190229
if exit_code == 124:
191-
output += "\n"
192-
output += TIMEOUT_MSG
193-
230+
output += "\n" + TIMEOUT_MSG
194231
outputs.append(output)
195-
files.append(code_path)
196232

197233
last_exit_code = exit_code
198234
if exit_code != 0:

autogen/token_count_utils.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@ def get_max_token_limit(model: str = "gpt-3.5-turbo-0613") -> int:
1414
model = re.sub(r"^gpt4", "gpt-4", model)
1515

1616
max_token_limit = {
17-
"gpt-3.5-turbo": 4096,
17+
"gpt-3.5-turbo": 16385,
18+
"gpt-3.5-turbo-0125": 16385,
1819
"gpt-3.5-turbo-0301": 4096,
1920
"gpt-3.5-turbo-0613": 4096,
2021
"gpt-3.5-turbo-instruct": 4096,
2122
"gpt-3.5-turbo-16k": 16385,
2223
"gpt-3.5-turbo-16k-0613": 16385,
2324
"gpt-3.5-turbo-1106": 16385,
2425
"gpt-4": 8192,
26+
"gpt-4-turbo": 128000,
27+
"gpt-4-turbo-2024-04-09": 128000,
2528
"gpt-4-32k": 32768,
2629
"gpt-4-32k-0314": 32768, # deprecate in Sep
2730
"gpt-4-0314": 8192, # deprecate in Sep

dotnet/sample/AutoGen.BasicSamples/AutoGen.BasicSample.csproj

+6
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,10 @@
1616
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionVersion)" />
1717
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Web" Version="$(SemanticKernelExperimentalVersion)" />
1818
</ItemGroup>
19+
20+
<ItemGroup>
21+
<None Update="ImageResources\square.png">
22+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
23+
</None>
24+
</ItemGroup>
1925
</Project>

0 commit comments

Comments
 (0)