langfun 0.1.2.dev202509120804__py3-none-any.whl → 0.1.2.dev202512150805__py3-none-any.whl
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.
- langfun/__init__.py +1 -1
- langfun/core/__init__.py +7 -1
- langfun/core/agentic/__init__.py +8 -1
- langfun/core/agentic/action.py +740 -112
- langfun/core/agentic/action_eval.py +9 -2
- langfun/core/agentic/action_test.py +189 -24
- langfun/core/async_support.py +104 -5
- langfun/core/async_support_test.py +23 -0
- langfun/core/coding/python/correction.py +19 -9
- langfun/core/coding/python/execution.py +14 -12
- langfun/core/coding/python/generation.py +21 -16
- langfun/core/coding/python/sandboxing.py +23 -3
- langfun/core/component.py +42 -3
- langfun/core/concurrent.py +70 -6
- langfun/core/concurrent_test.py +9 -2
- langfun/core/console.py +1 -1
- langfun/core/data/conversion/anthropic.py +12 -3
- langfun/core/data/conversion/anthropic_test.py +8 -6
- langfun/core/data/conversion/gemini.py +11 -2
- langfun/core/data/conversion/gemini_test.py +48 -9
- langfun/core/data/conversion/openai.py +145 -31
- langfun/core/data/conversion/openai_test.py +161 -17
- langfun/core/eval/base.py +48 -44
- langfun/core/eval/base_test.py +5 -5
- langfun/core/eval/matching.py +5 -2
- langfun/core/eval/patching.py +3 -3
- langfun/core/eval/scoring.py +4 -3
- langfun/core/eval/v2/__init__.py +3 -0
- langfun/core/eval/v2/checkpointing.py +148 -46
- langfun/core/eval/v2/checkpointing_test.py +9 -2
- langfun/core/eval/v2/config_saver.py +37 -0
- langfun/core/eval/v2/config_saver_test.py +36 -0
- langfun/core/eval/v2/eval_test_helper.py +104 -3
- langfun/core/eval/v2/evaluation.py +102 -19
- langfun/core/eval/v2/evaluation_test.py +9 -3
- langfun/core/eval/v2/example.py +50 -40
- langfun/core/eval/v2/example_test.py +16 -8
- langfun/core/eval/v2/experiment.py +95 -20
- langfun/core/eval/v2/experiment_test.py +19 -0
- langfun/core/eval/v2/metric_values.py +31 -3
- langfun/core/eval/v2/metric_values_test.py +32 -0
- langfun/core/eval/v2/metrics.py +157 -44
- langfun/core/eval/v2/metrics_test.py +39 -18
- langfun/core/eval/v2/progress.py +31 -1
- langfun/core/eval/v2/progress_test.py +27 -0
- langfun/core/eval/v2/progress_tracking.py +13 -5
- langfun/core/eval/v2/progress_tracking_test.py +9 -1
- langfun/core/eval/v2/reporting.py +88 -71
- langfun/core/eval/v2/reporting_test.py +24 -6
- langfun/core/eval/v2/runners/__init__.py +30 -0
- langfun/core/eval/v2/{runners.py → runners/base.py} +73 -180
- langfun/core/eval/v2/runners/beam.py +354 -0
- langfun/core/eval/v2/runners/beam_test.py +153 -0
- langfun/core/eval/v2/runners/ckpt_monitor.py +350 -0
- langfun/core/eval/v2/runners/ckpt_monitor_test.py +213 -0
- langfun/core/eval/v2/runners/debug.py +40 -0
- langfun/core/eval/v2/runners/debug_test.py +76 -0
- langfun/core/eval/v2/runners/parallel.py +243 -0
- langfun/core/eval/v2/runners/parallel_test.py +182 -0
- langfun/core/eval/v2/runners/sequential.py +47 -0
- langfun/core/eval/v2/runners/sequential_test.py +169 -0
- langfun/core/langfunc.py +45 -130
- langfun/core/langfunc_test.py +7 -5
- langfun/core/language_model.py +189 -36
- langfun/core/language_model_test.py +54 -3
- langfun/core/llms/__init__.py +14 -1
- langfun/core/llms/anthropic.py +157 -2
- langfun/core/llms/azure_openai.py +29 -17
- langfun/core/llms/cache/base.py +25 -3
- langfun/core/llms/cache/in_memory.py +48 -7
- langfun/core/llms/cache/in_memory_test.py +14 -4
- langfun/core/llms/compositional.py +25 -1
- langfun/core/llms/deepseek.py +30 -2
- langfun/core/llms/fake.py +32 -1
- langfun/core/llms/gemini.py +90 -12
- langfun/core/llms/gemini_test.py +110 -0
- langfun/core/llms/google_genai.py +52 -1
- langfun/core/llms/groq.py +28 -3
- langfun/core/llms/llama_cpp.py +23 -4
- langfun/core/llms/openai.py +120 -3
- langfun/core/llms/openai_compatible.py +148 -27
- langfun/core/llms/openai_compatible_test.py +207 -20
- langfun/core/llms/openai_test.py +0 -2
- langfun/core/llms/rest.py +16 -1
- langfun/core/llms/vertexai.py +78 -8
- langfun/core/logging.py +1 -1
- langfun/core/mcp/__init__.py +10 -0
- langfun/core/mcp/client.py +177 -0
- langfun/core/mcp/client_test.py +71 -0
- langfun/core/mcp/session.py +241 -0
- langfun/core/mcp/session_test.py +54 -0
- langfun/core/mcp/testing/simple_mcp_client.py +33 -0
- langfun/core/mcp/testing/simple_mcp_server.py +33 -0
- langfun/core/mcp/tool.py +254 -0
- langfun/core/mcp/tool_test.py +197 -0
- langfun/core/memory.py +1 -0
- langfun/core/message.py +160 -55
- langfun/core/message_test.py +65 -81
- langfun/core/modalities/__init__.py +8 -0
- langfun/core/modalities/audio.py +21 -1
- langfun/core/modalities/image.py +73 -3
- langfun/core/modalities/image_test.py +116 -0
- langfun/core/modalities/mime.py +78 -4
- langfun/core/modalities/mime_test.py +59 -0
- langfun/core/modalities/pdf.py +19 -1
- langfun/core/modalities/video.py +21 -1
- langfun/core/modality.py +167 -29
- langfun/core/modality_test.py +42 -12
- langfun/core/natural_language.py +1 -1
- langfun/core/sampling.py +4 -4
- langfun/core/sampling_test.py +20 -4
- langfun/core/structured/__init__.py +2 -24
- langfun/core/structured/completion.py +34 -44
- langfun/core/structured/completion_test.py +23 -43
- langfun/core/structured/description.py +54 -50
- langfun/core/structured/function_generation.py +29 -12
- langfun/core/structured/mapping.py +81 -37
- langfun/core/structured/parsing.py +95 -79
- langfun/core/structured/parsing_test.py +0 -3
- langfun/core/structured/querying.py +230 -154
- langfun/core/structured/querying_test.py +69 -33
- langfun/core/structured/schema/__init__.py +49 -0
- langfun/core/structured/schema/base.py +664 -0
- langfun/core/structured/schema/base_test.py +531 -0
- langfun/core/structured/schema/json.py +174 -0
- langfun/core/structured/schema/json_test.py +121 -0
- langfun/core/structured/schema/python.py +316 -0
- langfun/core/structured/schema/python_test.py +410 -0
- langfun/core/structured/schema_generation.py +33 -14
- langfun/core/structured/scoring.py +47 -36
- langfun/core/structured/tokenization.py +26 -11
- langfun/core/subscription.py +2 -2
- langfun/core/template.py +175 -50
- langfun/core/template_test.py +123 -17
- langfun/env/__init__.py +43 -0
- langfun/env/base_environment.py +827 -0
- langfun/env/base_environment_test.py +473 -0
- langfun/env/base_feature.py +304 -0
- langfun/env/base_feature_test.py +228 -0
- langfun/env/base_sandbox.py +842 -0
- langfun/env/base_sandbox_test.py +1235 -0
- langfun/env/event_handlers/__init__.py +14 -0
- langfun/env/event_handlers/chain.py +233 -0
- langfun/env/event_handlers/chain_test.py +253 -0
- langfun/env/event_handlers/event_logger.py +472 -0
- langfun/env/event_handlers/event_logger_test.py +304 -0
- langfun/env/event_handlers/metric_writer.py +726 -0
- langfun/env/event_handlers/metric_writer_test.py +214 -0
- langfun/env/interface.py +1640 -0
- langfun/env/interface_test.py +153 -0
- langfun/env/load_balancers.py +59 -0
- langfun/env/load_balancers_test.py +141 -0
- langfun/env/test_utils.py +507 -0
- {langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/METADATA +7 -3
- langfun-0.1.2.dev202512150805.dist-info/RECORD +217 -0
- langfun/core/eval/v2/runners_test.py +0 -343
- langfun/core/structured/schema.py +0 -987
- langfun/core/structured/schema_test.py +0 -982
- langfun-0.1.2.dev202509120804.dist-info/RECORD +0 -172
- {langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/WHEEL +0 -0
- {langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/licenses/LICENSE +0 -0
- {langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
# Copyright 2025 The Langfun Authors
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Test utils for base environment."""
|
|
15
|
+
|
|
16
|
+
import contextlib
|
|
17
|
+
import time
|
|
18
|
+
from typing import Iterator, Type
|
|
19
|
+
|
|
20
|
+
from langfun.env import base_environment
|
|
21
|
+
from langfun.env import base_feature
|
|
22
|
+
from langfun.env import base_sandbox
|
|
23
|
+
from langfun.env import interface
|
|
24
|
+
import pyglove as pg
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TestingEnvironment(base_environment.BaseEnvironment):
|
|
28
|
+
"""Testing environment for unit tests."""
|
|
29
|
+
image_ids: list[str] = ['test_image']
|
|
30
|
+
housekeep_interval: float = 0.0
|
|
31
|
+
simulate_start_error: Type[BaseException] | None = None
|
|
32
|
+
simulate_shutdown_error: Type[BaseException] | None = None
|
|
33
|
+
simulate_ping_error: Type[BaseException] | None = None
|
|
34
|
+
offline: bool = False
|
|
35
|
+
|
|
36
|
+
__test__ = False
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def id(self) -> interface.Environment.Id:
|
|
40
|
+
return interface.Environment.Id('testing-env')
|
|
41
|
+
|
|
42
|
+
def wait_for_housekeeping(self):
|
|
43
|
+
housekeep_counter = self.housekeep_counter
|
|
44
|
+
while self.housekeep_counter == housekeep_counter:
|
|
45
|
+
time.sleep(0.01)
|
|
46
|
+
|
|
47
|
+
def _create_sandbox(
|
|
48
|
+
self,
|
|
49
|
+
image_id: str,
|
|
50
|
+
sandbox_id: str,
|
|
51
|
+
reusable: bool,
|
|
52
|
+
proactive_session_setup: bool,
|
|
53
|
+
keepalive_interval: float | None,
|
|
54
|
+
) -> base_sandbox.BaseSandbox:
|
|
55
|
+
return TestingSandbox(
|
|
56
|
+
environment=self,
|
|
57
|
+
id=interface.Sandbox.Id(
|
|
58
|
+
environment_id=self.id,
|
|
59
|
+
image_id=image_id,
|
|
60
|
+
sandbox_id=sandbox_id
|
|
61
|
+
),
|
|
62
|
+
image_id=image_id,
|
|
63
|
+
reusable=reusable,
|
|
64
|
+
proactive_session_setup=proactive_session_setup,
|
|
65
|
+
keepalive_interval=keepalive_interval,
|
|
66
|
+
simulate_start_error=self.simulate_start_error,
|
|
67
|
+
simulate_shutdown_error=self.simulate_shutdown_error,
|
|
68
|
+
simulate_ping_error=self.simulate_ping_error,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class TestingSandbox(base_sandbox.BaseSandbox):
|
|
73
|
+
"""Testing sandbox for unit tests."""
|
|
74
|
+
|
|
75
|
+
simulate_start_error: Type[BaseException] | None = None
|
|
76
|
+
simulate_shutdown_error: Type[BaseException] | None = None
|
|
77
|
+
simulate_ping_error: Type[BaseException] | None = None
|
|
78
|
+
|
|
79
|
+
__test__ = False
|
|
80
|
+
|
|
81
|
+
def _on_bound(self) -> None:
|
|
82
|
+
super()._on_bound()
|
|
83
|
+
self._shell_history = []
|
|
84
|
+
self._ping_history = []
|
|
85
|
+
|
|
86
|
+
def _raise_error(self, message, error_type: Type[BaseException], **kwargs):
|
|
87
|
+
if (error_type is interface.SandboxStateError or
|
|
88
|
+
issubclass(error_type, interface.SandboxStateError)):
|
|
89
|
+
kwargs['sandbox'] = self
|
|
90
|
+
raise error_type(message, **kwargs)
|
|
91
|
+
else:
|
|
92
|
+
raise error_type(message)
|
|
93
|
+
|
|
94
|
+
def wait_until_not(
|
|
95
|
+
self,
|
|
96
|
+
status: interface.Sandbox.Status | tuple[interface.Sandbox.Status, ...]
|
|
97
|
+
) -> None:
|
|
98
|
+
if not isinstance(status, tuple):
|
|
99
|
+
status = (status,)
|
|
100
|
+
while self.status in status:
|
|
101
|
+
time.sleep(0.01)
|
|
102
|
+
|
|
103
|
+
def wait_until_next_housekeep(self) -> None:
|
|
104
|
+
housekeep_counter = self.housekeep_counter
|
|
105
|
+
while self.housekeep_counter == housekeep_counter:
|
|
106
|
+
time.sleep(0.01)
|
|
107
|
+
|
|
108
|
+
def _start(self) -> None:
|
|
109
|
+
if self.simulate_start_error:
|
|
110
|
+
self._raise_error('Sandbox start error', self.simulate_start_error)
|
|
111
|
+
super()._start()
|
|
112
|
+
|
|
113
|
+
def _shutdown(self) -> None:
|
|
114
|
+
if self.simulate_shutdown_error:
|
|
115
|
+
self._raise_error('Sandbox shutdown error', self.simulate_shutdown_error)
|
|
116
|
+
super()._shutdown()
|
|
117
|
+
|
|
118
|
+
@interface.treat_as_sandbox_state_error(errors=(RuntimeError,))
|
|
119
|
+
@interface.log_activity()
|
|
120
|
+
def shell(
|
|
121
|
+
self,
|
|
122
|
+
code: str,
|
|
123
|
+
raise_error: Type[BaseException] | None = None,
|
|
124
|
+
) -> str:
|
|
125
|
+
self._shell_history.append(code)
|
|
126
|
+
if raise_error is not None:
|
|
127
|
+
self._raise_error(f'shell "{code}" failed', raise_error)
|
|
128
|
+
return f'shell "{code}" succeeded'
|
|
129
|
+
|
|
130
|
+
def _ping(self) -> None:
|
|
131
|
+
self._ping_history.append(not self.simulate_ping_error)
|
|
132
|
+
if self.simulate_ping_error:
|
|
133
|
+
self._raise_error('Ping error', self.simulate_ping_error, code='ping')
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class TestingFeature(base_feature.BaseFeature):
|
|
137
|
+
"""Testing feature for unit tests."""
|
|
138
|
+
|
|
139
|
+
housekeep_interval = 0
|
|
140
|
+
setup_session_delay: float = 0.0
|
|
141
|
+
simulate_housekeep_error: Type[BaseException] | None = None
|
|
142
|
+
simulate_setup_error: Type[BaseException] | None = None
|
|
143
|
+
simulate_teardown_error: Type[BaseException] | None = None
|
|
144
|
+
simulate_setup_session_error: Type[BaseException] | None = None
|
|
145
|
+
simulate_teardown_session_error: Type[BaseException] | None = None
|
|
146
|
+
call_end_session_on_teardown_session: bool = False
|
|
147
|
+
|
|
148
|
+
__test__ = False
|
|
149
|
+
|
|
150
|
+
class Service:
|
|
151
|
+
"""Sandbox."""
|
|
152
|
+
|
|
153
|
+
def __init__(self, sandbox: interface.Sandbox):
|
|
154
|
+
self._sandbox = sandbox
|
|
155
|
+
|
|
156
|
+
def do(self, code: str, raise_error: Type[BaseException] | None = None):
|
|
157
|
+
self._sandbox.shell(code, raise_error=raise_error)
|
|
158
|
+
|
|
159
|
+
def _raise_error(self, message, error_type: Type[BaseException], **kwargs):
|
|
160
|
+
self._sandbox._raise_error(message, error_type, **kwargs) # pylint: disable=protected-access
|
|
161
|
+
|
|
162
|
+
def _setup(self) -> None:
|
|
163
|
+
if self.simulate_setup_error:
|
|
164
|
+
self._raise_error(f'{self.name} setup error', self.simulate_setup_error)
|
|
165
|
+
self.sandbox.shell(f'"{self.name}" setup')
|
|
166
|
+
|
|
167
|
+
def _teardown(self) -> None:
|
|
168
|
+
if self.simulate_teardown_error:
|
|
169
|
+
self._raise_error(
|
|
170
|
+
f'{self.name} teardown error', self.simulate_teardown_error
|
|
171
|
+
)
|
|
172
|
+
self.sandbox.shell(f'"{self.name}" teardown')
|
|
173
|
+
|
|
174
|
+
def _setup_session(self) -> None:
|
|
175
|
+
if self.setup_session_delay > 0:
|
|
176
|
+
time.sleep(self.setup_session_delay)
|
|
177
|
+
|
|
178
|
+
if self.simulate_setup_session_error:
|
|
179
|
+
self._raise_error(
|
|
180
|
+
'Feature session setup error', self.simulate_setup_session_error
|
|
181
|
+
)
|
|
182
|
+
self.sandbox.shell(f'"{self.name}" setup session')
|
|
183
|
+
|
|
184
|
+
def _teardown_session(self) -> None:
|
|
185
|
+
if self.simulate_teardown_session_error:
|
|
186
|
+
self._raise_error(
|
|
187
|
+
'Feature session teardown error', self.simulate_teardown_session_error
|
|
188
|
+
)
|
|
189
|
+
self.sandbox.shell(f'"{self.name}" teardown session')
|
|
190
|
+
if self.call_end_session_on_teardown_session:
|
|
191
|
+
self.sandbox.end_session()
|
|
192
|
+
|
|
193
|
+
@interface.log_activity()
|
|
194
|
+
def num_shell_calls(self) -> int:
|
|
195
|
+
return len(self.sandbox._shell_history) # pylint: disable=protected-access
|
|
196
|
+
|
|
197
|
+
@interface.log_activity()
|
|
198
|
+
def bad_shell_call(self) -> None:
|
|
199
|
+
self.sandbox.shell('bad command', raise_error=RuntimeError)
|
|
200
|
+
|
|
201
|
+
@interface.log_activity()
|
|
202
|
+
def show_session_id(self):
|
|
203
|
+
return self.session_id
|
|
204
|
+
|
|
205
|
+
@interface.log_activity()
|
|
206
|
+
def call_with_varargs(self, code: str, *args, **kwargs):
|
|
207
|
+
del code, args, kwargs
|
|
208
|
+
return 0
|
|
209
|
+
|
|
210
|
+
def _on_bound(self) -> None:
|
|
211
|
+
super()._on_bound()
|
|
212
|
+
self._service = None
|
|
213
|
+
|
|
214
|
+
@contextlib.contextmanager
|
|
215
|
+
def my_service(self) -> Iterator[Service]:
|
|
216
|
+
try:
|
|
217
|
+
self._service = TestingFeature.Service(sandbox=self.sandbox)
|
|
218
|
+
yield self._service
|
|
219
|
+
finally:
|
|
220
|
+
self._service = None
|
|
221
|
+
|
|
222
|
+
def _housekeep(self) -> None:
|
|
223
|
+
if self.simulate_housekeep_error:
|
|
224
|
+
raise interface.SandboxStateError(
|
|
225
|
+
'House keeping error', sandbox=self.sandbox
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class TestingNonSandboxBasedFeature(base_feature.BaseFeature):
|
|
230
|
+
"""Testing non-sandbox based feature for unit tests."""
|
|
231
|
+
is_sandbox_based: bool = False
|
|
232
|
+
simulate_setup_error: Type[BaseException] | None = None
|
|
233
|
+
simulate_teardown_error: Type[BaseException] | None = None
|
|
234
|
+
simulate_setup_session_error: Type[BaseException] | None = None
|
|
235
|
+
simulate_teardown_session_error: Type[BaseException] | None = None
|
|
236
|
+
simulate_housekeep_error: Type[BaseException] | None = None
|
|
237
|
+
|
|
238
|
+
__test__ = False
|
|
239
|
+
|
|
240
|
+
def _setup(self) -> None:
|
|
241
|
+
if self.simulate_setup_error:
|
|
242
|
+
raise self.simulate_setup_error('Feature setup error')
|
|
243
|
+
|
|
244
|
+
def _teardown(self) -> None:
|
|
245
|
+
if self.simulate_teardown_error:
|
|
246
|
+
raise self.simulate_teardown_error('Feature teardown error')
|
|
247
|
+
|
|
248
|
+
def _setup_session(self) -> None:
|
|
249
|
+
if self.simulate_setup_session_error:
|
|
250
|
+
raise self.simulate_setup_session_error('Feature session setup error')
|
|
251
|
+
|
|
252
|
+
def _teardown_session(self) -> None:
|
|
253
|
+
if self.simulate_teardown_session_error:
|
|
254
|
+
raise self.simulate_teardown_session_error(
|
|
255
|
+
'Feature session teardown error'
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
def _housekeep(self) -> None:
|
|
259
|
+
if self.simulate_housekeep_error:
|
|
260
|
+
raise self.simulate_housekeep_error('Feature housekeeping error')
|
|
261
|
+
_ = self.foo(1)
|
|
262
|
+
|
|
263
|
+
@interface.log_activity()
|
|
264
|
+
def foo(self, x: int) -> int:
|
|
265
|
+
return x + 1
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class TestingEventHandler(pg.Object, interface.EventHandler):
|
|
269
|
+
"""Testing environment event handler for unit tests."""
|
|
270
|
+
|
|
271
|
+
log_sandbox_status: bool = False
|
|
272
|
+
log_feature_setup: bool = True
|
|
273
|
+
log_session_setup: bool = False
|
|
274
|
+
log_housekeep: bool = False
|
|
275
|
+
|
|
276
|
+
__test__ = False
|
|
277
|
+
|
|
278
|
+
def _on_bound(self) -> None:
|
|
279
|
+
super()._on_bound()
|
|
280
|
+
self._logs = []
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def logs(self) -> list[str]:
|
|
284
|
+
return self._logs
|
|
285
|
+
|
|
286
|
+
def _add_message(self, message: str, error: BaseException | None) -> None:
|
|
287
|
+
"""Adds a message to the history."""
|
|
288
|
+
if error is None:
|
|
289
|
+
self._logs.append(message)
|
|
290
|
+
else:
|
|
291
|
+
self._logs.append(f'{message} with {error.__class__.__name__}')
|
|
292
|
+
|
|
293
|
+
def on_environment_start(
|
|
294
|
+
self,
|
|
295
|
+
environment: interface.Environment,
|
|
296
|
+
duration: float,
|
|
297
|
+
error: BaseException | None
|
|
298
|
+
) -> None:
|
|
299
|
+
"""Called when the environment is started."""
|
|
300
|
+
assert duration > 0
|
|
301
|
+
self._add_message(f'[{environment.id}] environment started', error)
|
|
302
|
+
|
|
303
|
+
def on_environment_housekeep(
|
|
304
|
+
self,
|
|
305
|
+
environment: interface.Environment,
|
|
306
|
+
counter: int,
|
|
307
|
+
duration: float,
|
|
308
|
+
error: BaseException | None,
|
|
309
|
+
**kwargs
|
|
310
|
+
) -> None:
|
|
311
|
+
"""Called when the environment finishes a round of housekeeping."""
|
|
312
|
+
assert duration > 0
|
|
313
|
+
if self.log_housekeep:
|
|
314
|
+
self._add_message(
|
|
315
|
+
f'[{environment.id}] environment housekeeping {counter}', error
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
def on_environment_shutdown(
|
|
319
|
+
self,
|
|
320
|
+
environment: interface.Environment,
|
|
321
|
+
duration: float,
|
|
322
|
+
lifetime: float,
|
|
323
|
+
error: BaseException | None
|
|
324
|
+
) -> None:
|
|
325
|
+
"""Called when the environment is shutdown."""
|
|
326
|
+
assert duration > 0 and lifetime is not None
|
|
327
|
+
self._add_message(f'[{environment.id}] environment shutdown', error)
|
|
328
|
+
|
|
329
|
+
def on_sandbox_start(
|
|
330
|
+
self,
|
|
331
|
+
sandbox: interface.Sandbox,
|
|
332
|
+
duration: float,
|
|
333
|
+
error: BaseException | None
|
|
334
|
+
) -> None:
|
|
335
|
+
assert duration > 0
|
|
336
|
+
self._add_message(f'[{sandbox.id}] sandbox started', error)
|
|
337
|
+
|
|
338
|
+
def on_sandbox_status_change(
|
|
339
|
+
self,
|
|
340
|
+
sandbox: interface.Sandbox,
|
|
341
|
+
old_status: interface.Sandbox.Status,
|
|
342
|
+
new_status: interface.Sandbox.Status,
|
|
343
|
+
span: float
|
|
344
|
+
) -> None:
|
|
345
|
+
assert span > 0
|
|
346
|
+
if self.log_sandbox_status:
|
|
347
|
+
self._add_message(
|
|
348
|
+
f'[{sandbox.id}] {old_status.value} -> {new_status.value}',
|
|
349
|
+
None,
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
def on_sandbox_shutdown(
|
|
353
|
+
self,
|
|
354
|
+
sandbox: interface.Sandbox,
|
|
355
|
+
duration: float,
|
|
356
|
+
lifetime: float,
|
|
357
|
+
error: BaseException | None
|
|
358
|
+
) -> None:
|
|
359
|
+
assert duration > 0 and lifetime is not None
|
|
360
|
+
self._add_message(f'[{sandbox.id}] sandbox shutdown', error)
|
|
361
|
+
|
|
362
|
+
def on_sandbox_session_start(
|
|
363
|
+
self,
|
|
364
|
+
sandbox: interface.Sandbox,
|
|
365
|
+
session_id: str,
|
|
366
|
+
duration: float,
|
|
367
|
+
error: BaseException | None
|
|
368
|
+
) -> None:
|
|
369
|
+
"""Called when a sandbox session starts."""
|
|
370
|
+
assert duration > 0
|
|
371
|
+
self._add_message(
|
|
372
|
+
f'[{sandbox.id}] session {session_id!r} started', error
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
def on_sandbox_session_end(
|
|
376
|
+
self,
|
|
377
|
+
sandbox: interface.Sandbox,
|
|
378
|
+
session_id: str,
|
|
379
|
+
duration: float,
|
|
380
|
+
lifetime: float,
|
|
381
|
+
error: BaseException | None
|
|
382
|
+
) -> None:
|
|
383
|
+
"""Called when a sandbox session ends."""
|
|
384
|
+
assert duration > 0 and lifetime > 0
|
|
385
|
+
self._add_message(
|
|
386
|
+
f'[{sandbox.id}] session {session_id!r} ended', error
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
def on_sandbox_activity(
|
|
390
|
+
self,
|
|
391
|
+
name: str,
|
|
392
|
+
sandbox: interface.Sandbox,
|
|
393
|
+
session_id: str | None,
|
|
394
|
+
duration: float,
|
|
395
|
+
error: BaseException | None,
|
|
396
|
+
*,
|
|
397
|
+
code: str | None = None,
|
|
398
|
+
**kwargs
|
|
399
|
+
) -> None:
|
|
400
|
+
"""Called when a sandbox activity is performed."""
|
|
401
|
+
del kwargs
|
|
402
|
+
log_id = f'{sandbox.id}@{session_id or "<idle>"}'
|
|
403
|
+
self._add_message(
|
|
404
|
+
f'[{log_id}] {name}: {code}', error
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
def on_sandbox_housekeep(
|
|
408
|
+
self,
|
|
409
|
+
sandbox: interface.Sandbox,
|
|
410
|
+
counter: int,
|
|
411
|
+
duration: float,
|
|
412
|
+
error: BaseException | None,
|
|
413
|
+
**kwargs
|
|
414
|
+
) -> None:
|
|
415
|
+
assert duration > 0
|
|
416
|
+
if self.log_housekeep:
|
|
417
|
+
self._add_message(
|
|
418
|
+
f'[{sandbox.id}] sandbox housekeeping {counter}', error
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
def on_feature_setup(
|
|
422
|
+
self,
|
|
423
|
+
feature: interface.Feature,
|
|
424
|
+
duration: float,
|
|
425
|
+
error: BaseException | None
|
|
426
|
+
) -> None:
|
|
427
|
+
"""Called when a sandbox feature is setup."""
|
|
428
|
+
assert duration > 0
|
|
429
|
+
if self.log_feature_setup:
|
|
430
|
+
self._add_message(
|
|
431
|
+
f'[{feature.id}] feature setup', error
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
def on_feature_teardown(
|
|
435
|
+
self,
|
|
436
|
+
feature: interface.Feature,
|
|
437
|
+
duration: float,
|
|
438
|
+
error: BaseException | None
|
|
439
|
+
) -> None:
|
|
440
|
+
"""Called when a sandbox feature is teardown."""
|
|
441
|
+
assert duration > 0
|
|
442
|
+
if self.log_feature_setup:
|
|
443
|
+
self._add_message(
|
|
444
|
+
f'[{feature.id}] feature teardown', error
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
def on_feature_setup_session(
|
|
448
|
+
self,
|
|
449
|
+
feature: interface.Feature,
|
|
450
|
+
session_id: str | None,
|
|
451
|
+
duration: float,
|
|
452
|
+
error: BaseException | None
|
|
453
|
+
) -> None:
|
|
454
|
+
"""Called when a sandbox feature is setup."""
|
|
455
|
+
assert duration > 0
|
|
456
|
+
if self.log_session_setup:
|
|
457
|
+
self._add_message(
|
|
458
|
+
f'[{feature.id}@{session_id or "<idle>"}] feature setup session',
|
|
459
|
+
error
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
def on_feature_teardown_session(
|
|
463
|
+
self,
|
|
464
|
+
feature: interface.Feature,
|
|
465
|
+
session_id: str,
|
|
466
|
+
duration: float,
|
|
467
|
+
error: BaseException | None
|
|
468
|
+
) -> None:
|
|
469
|
+
"""Called when a sandbox feature is teardown."""
|
|
470
|
+
assert duration > 0
|
|
471
|
+
if self.log_session_setup:
|
|
472
|
+
self._add_message(
|
|
473
|
+
f'[{feature.id}@{session_id}] feature teardown session', error
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
def on_feature_activity(
|
|
477
|
+
self,
|
|
478
|
+
name: str,
|
|
479
|
+
feature: interface.Feature,
|
|
480
|
+
session_id: str | None,
|
|
481
|
+
duration: float,
|
|
482
|
+
error: BaseException | None,
|
|
483
|
+
*,
|
|
484
|
+
code: str | None = None,
|
|
485
|
+
**kwargs
|
|
486
|
+
) -> None:
|
|
487
|
+
"""Called when a sandbox activity is performed."""
|
|
488
|
+
del kwargs
|
|
489
|
+
log_id = f'{feature.id}@{session_id or "<idle>"}'
|
|
490
|
+
self._add_message(
|
|
491
|
+
f'[{log_id}] {name}: {code}', error
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
def on_feature_housekeep(
|
|
495
|
+
self,
|
|
496
|
+
feature: interface.Feature,
|
|
497
|
+
counter: int,
|
|
498
|
+
duration: float,
|
|
499
|
+
error: BaseException | None,
|
|
500
|
+
**kwargs
|
|
501
|
+
) -> None:
|
|
502
|
+
"""Called when a sandbox feature is housekeeping."""
|
|
503
|
+
assert duration > 0
|
|
504
|
+
if self.log_housekeep:
|
|
505
|
+
self._add_message(
|
|
506
|
+
f'[{feature.id}] feature housekeeping {counter}', error
|
|
507
|
+
)
|
{langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langfun
|
|
3
|
-
Version: 0.1.2.
|
|
3
|
+
Version: 0.1.2.dev202512150805
|
|
4
4
|
Summary: Langfun: Language as Functions.
|
|
5
5
|
Home-page: https://github.com/google/langfun
|
|
6
6
|
Author: Langfun Authors
|
|
@@ -21,14 +21,18 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
|
+
Requires-Dist: anyio>=4.7.0
|
|
24
25
|
Requires-Dist: jinja2>=3.1.2
|
|
26
|
+
Requires-Dist: mcp>=1.17.0
|
|
25
27
|
Requires-Dist: puremagic>=1.20
|
|
26
|
-
Requires-Dist: pyglove>=0.
|
|
28
|
+
Requires-Dist: pyglove>=0.5.0.dev202510170226
|
|
27
29
|
Requires-Dist: requests>=2.31.0
|
|
28
30
|
Provides-Extra: all
|
|
31
|
+
Requires-Dist: anyio>=4.7.0; extra == "all"
|
|
29
32
|
Requires-Dist: jinja2>=3.1.2; extra == "all"
|
|
33
|
+
Requires-Dist: mcp>=1.17.0; extra == "all"
|
|
30
34
|
Requires-Dist: puremagic>=1.20; extra == "all"
|
|
31
|
-
Requires-Dist: pyglove>=0.
|
|
35
|
+
Requires-Dist: pyglove>=0.5.0.dev202510170226; extra == "all"
|
|
32
36
|
Requires-Dist: requests>=2.31.0; extra == "all"
|
|
33
37
|
Requires-Dist: google-auth>=2.16.0; extra == "all"
|
|
34
38
|
Requires-Dist: pillow>=10.0.0; extra == "all"
|