zrb 1.5.7__py3-none-any.whl → 1.5.8__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.
zrb/task/llm_task.py CHANGED
@@ -1,7 +1,5 @@
1
- import inspect
2
1
  import json
3
2
  from collections.abc import Callable
4
- from textwrap import dedent
5
3
  from typing import Any
6
4
 
7
5
  from pydantic_ai import Agent, Tool
@@ -14,22 +12,31 @@ from zrb.context.any_context import AnyContext
14
12
  from zrb.context.any_shared_context import AnySharedContext
15
13
  from zrb.env.any_env import AnyEnv
16
14
  from zrb.input.any_input import AnyInput
17
- from zrb.llm_config import LLMConfig
18
- from zrb.llm_config import llm_config as default_llm_config
19
15
  from zrb.task.any_task import AnyTask
20
16
  from zrb.task.base_task import BaseTask
21
- from zrb.task.llm.agent_runner import run_agent_iteration
22
- from zrb.task.llm.context_enricher import EnrichmentConfig, enrich_context
23
- from zrb.task.llm.default_context import get_default_context
24
- from zrb.task.llm.history import ConversationHistoryData, ListOfDict
25
- from zrb.task.llm.history_summarizer import SummarizationConfig, summarize_history
26
- from zrb.task.llm.tool_wrapper import wrap_tool
27
- from zrb.util.attr import get_attr, get_bool_attr, get_int_attr, get_str_attr
28
- from zrb.util.file import write_file
29
- from zrb.util.run import run_async
17
+ from zrb.task.llm.agent import get_agent, run_agent_iteration
18
+ from zrb.task.llm.config import (
19
+ get_model,
20
+ get_model_settings,
21
+ )
22
+ from zrb.task.llm.context import get_conversation_context
23
+ from zrb.task.llm.context_enrichment import maybe_enrich_context
24
+ from zrb.task.llm.history import (
25
+ ConversationHistoryData,
26
+ ListOfDict,
27
+ prepare_initial_state,
28
+ write_conversation_history,
29
+ )
30
+ from zrb.task.llm.history_summarization import maybe_summarize_history
31
+ from zrb.task.llm.prompt import (
32
+ build_user_prompt,
33
+ get_context_enrichment_prompt,
34
+ get_summarization_prompt,
35
+ get_system_prompt,
36
+ )
37
+ from zrb.util.cli.style import stylize_faint
38
+ from zrb.xcom.xcom import Xcom
30
39
 
31
- # ListOfDict moved to history.py
32
- # Removed old ConversationHistoryData type alias
33
40
  ToolOrCallable = Tool | Callable
34
41
 
35
42
 
@@ -183,323 +190,131 @@ class LLMTask(BaseTask):
183
190
  self._history_summarization_threshold = summarization_threshold
184
191
 
185
192
  async def _exec_action(self, ctx: AnyContext) -> Any:
186
- history_data: ConversationHistoryData = await self._read_conversation_history(
187
- ctx
188
- )
189
- # Extract history list and conversation context
190
- history_list = history_data.history
191
- conversation_context = self._get_conversation_context(ctx)
192
- # Merge history context without overwriting existing keys
193
- for key, value in history_data.context.items():
194
- if key not in conversation_context:
195
- conversation_context[key] = value
196
- # Enrich context based on history (if enabled)
197
- if self._get_should_enrich_context(ctx, history_list):
198
- conversation_context = await enrich_context(
199
- ctx=ctx,
200
- config=EnrichmentConfig(
201
- model=self._get_model(ctx),
202
- settings=self._get_model_settings(ctx),
203
- prompt=self._get_context_enrichment_prompt(ctx),
204
- ),
205
- conversation_context=conversation_context,
206
- history_list=history_list,
207
- )
208
- # Get history handling parameters
209
- if self._get_should_summarize_history(ctx, history_list):
210
- ctx.log_info("Summarize previous conversation")
211
- # Summarize the part to be removed and update context
212
- conversation_context = await summarize_history(
213
- ctx=ctx,
214
- config=SummarizationConfig(
215
- model=self._get_model(ctx),
216
- settings=self._get_model_settings(ctx),
217
- prompt=self._get_summarization_prompt(ctx),
218
- ),
219
- conversation_context=conversation_context,
220
- history_list=history_list, # Pass the full list for context
221
- )
222
- # Truncate the history list after summarization
223
- history_list = []
224
- # Construct user prompt
225
- user_prompt = self._get_user_prompt(ctx, conversation_context)
226
- # Create and run agent
227
- agent = self._get_agent(ctx)
228
- try:
229
- agent_run = await run_agent_iteration(
230
- ctx=ctx,
231
- agent=agent,
232
- user_prompt=user_prompt,
233
- history_list=history_list,
234
- )
235
- if agent_run:
236
- new_history_list = json.loads(agent_run.result.all_messages_json())
237
- data_to_write = ConversationHistoryData(
238
- context=conversation_context,
239
- history=new_history_list,
240
- )
241
- await self._write_conversation_history(
242
- ctx, data_to_write
243
- ) # Pass the model instance
244
- return agent_run.result.data
245
- except Exception as e:
246
- ctx.log_error(f"Error in agent execution: {str(e)}")
247
- raise
248
-
249
- async def _write_conversation_history(
250
- self, ctx: AnyContext, history_data: ConversationHistoryData
251
- ):
252
- # Expects the model instance
253
- if self._conversation_history_writer is not None:
254
- # Pass the model instance directly to the writer
255
- await run_async(self._conversation_history_writer(ctx, history_data))
256
- history_file = self._get_history_file(ctx)
257
- if history_file != "":
258
- # Use model_dump_json for serialization
259
- write_file(history_file, history_data.model_dump_json(indent=2))
260
-
261
- def _get_model_settings(self, ctx: AnyContext) -> ModelSettings | None:
262
- if callable(self._model_settings):
263
- return self._model_settings(ctx)
264
- return self._model_settings
265
-
266
- def _get_agent(self, ctx: AnyContext) -> Agent:
267
- if isinstance(self._agent, Agent):
268
- return self._agent
269
- if callable(self._agent):
270
- return self._agent(ctx)
271
- tools_or_callables = list(
272
- self._tools(ctx) if callable(self._tools) else self._tools
273
- )
274
- tools_or_callables.extend(self._additional_tools)
275
- tools = []
276
- for tool_or_callable in tools_or_callables:
277
- if isinstance(tool_or_callable, Tool):
278
- tools.append(tool_or_callable)
279
- else:
280
- # Inspect original callable for 'ctx' parameter
281
- # This ctx refer to pydantic AI's ctx, not task ctx.
282
- original_sig = inspect.signature(tool_or_callable)
283
- takes_ctx = "ctx" in original_sig.parameters
284
- wrapped_tool = wrap_tool(tool_or_callable)
285
- tools.append(Tool(wrapped_tool, takes_ctx=takes_ctx))
286
- mcp_servers = list(
287
- self._mcp_servers(ctx) if callable(self._mcp_servers) else self._mcp_servers
288
- )
289
- mcp_servers.extend(self._additional_mcp_servers)
290
- return Agent(
291
- self._get_model(ctx),
292
- system_prompt=self._get_system_prompt(ctx),
293
- tools=tools,
294
- mcp_servers=mcp_servers,
295
- model_settings=self._get_model_settings(ctx),
296
- retries=3,
297
- )
298
-
299
- def _get_model(self, ctx: AnyContext) -> str | Model | None:
300
- model = get_attr(ctx, self._model, None, auto_render=self._render_model)
301
- if model is None:
302
- return default_llm_config.get_default_model()
303
- if isinstance(model, str):
304
- model_base_url = self._get_model_base_url(ctx)
305
- model_api_key = self._get_model_api_key(ctx)
306
- llm_config = LLMConfig(
307
- default_model_name=model,
308
- default_base_url=model_base_url,
309
- default_api_key=model_api_key,
310
- )
311
- if model_base_url is None and model_api_key is None:
312
- default_model_provider = default_llm_config.get_default_model_provider()
313
- if default_model_provider is not None:
314
- llm_config.set_default_provider(default_model_provider)
315
- return llm_config.get_default_model()
316
- raise ValueError(f"Invalid model: {model}")
317
-
318
- def _get_model_base_url(self, ctx: AnyContext) -> str | None:
319
- base_url = get_attr(
320
- ctx, self._model_base_url, None, auto_render=self._render_model_base_url
193
+ # Get dependent configurations first
194
+ model_settings = get_model_settings(ctx, self._model_settings)
195
+ model = get_model(
196
+ ctx=ctx,
197
+ model_attr=self._model,
198
+ render_model=self._render_model,
199
+ model_base_url_attr=self._model_base_url,
200
+ render_model_base_url=self._render_model_base_url,
201
+ model_api_key_attr=self._model_api_key,
202
+ render_model_api_key=self._render_model_api_key,
321
203
  )
322
- if isinstance(base_url, str) or base_url is None:
323
- return base_url
324
- raise ValueError(f"Invalid model base URL: {base_url}")
325
-
326
- def _get_model_api_key(self, ctx: AnyContext) -> str | None:
327
- api_key = get_attr(
328
- ctx, self._model_api_key, None, auto_render=self._render_model_api_key
204
+ context_enrichment_prompt = get_context_enrichment_prompt(
205
+ ctx=ctx,
206
+ context_enrichment_prompt_attr=self._context_enrichment_prompt,
207
+ render_context_enrichment_prompt=self._render_context_enrichment_prompt,
329
208
  )
330
- if isinstance(api_key, str) or api_key is None:
331
- return api_key
332
- raise ValueError(f"Invalid model API key: {api_key}")
333
-
334
- def _get_system_prompt(self, ctx: AnyContext) -> str:
335
- system_prompt = get_attr(
336
- ctx,
337
- self._system_prompt,
338
- None,
339
- auto_render=self._render_system_prompt,
209
+ summarization_prompt = get_summarization_prompt(
210
+ ctx=ctx,
211
+ summarization_prompt_attr=self._summarization_prompt,
212
+ render_summarization_prompt=self._render_summarization_prompt,
340
213
  )
341
- if system_prompt is not None:
342
- return system_prompt
343
- return default_llm_config.get_default_system_prompt()
344
-
345
- def _get_user_prompt(
346
- self, ctx: AnyContext, conversation_context: dict[str, Any]
347
- ) -> str:
348
- user_message = self._get_user_message(ctx)
349
- enriched_context = {**get_default_context(user_message), **conversation_context}
350
- return dedent(
351
- f"""
352
- # Context
353
- {json.dumps(enriched_context)}
354
- # User Message
355
- {user_message}
356
- """.strip()
214
+ system_prompt = get_system_prompt(
215
+ ctx=ctx,
216
+ system_prompt_attr=self._system_prompt,
217
+ render_system_prompt=self._render_system_prompt,
357
218
  )
358
-
359
- def _get_user_message(self, ctx: AnyContext) -> str:
360
- return get_str_attr(ctx, self._message, "How are you?", auto_render=True)
361
-
362
- def _get_summarization_prompt(self, ctx: AnyContext) -> str:
363
- summarization_prompt = get_attr(
364
- ctx,
365
- self._summarization_prompt,
366
- None,
367
- auto_render=self._render_summarization_prompt,
219
+ # 1. Prepare initial state (read history, get initial context)
220
+ history_list, conversation_context = await prepare_initial_state(
221
+ ctx=ctx,
222
+ conversation_history_reader=self._conversation_history_reader,
223
+ conversation_history_file_attr=self._conversation_history_file,
224
+ render_history_file=self._render_history_file,
225
+ conversation_history_attr=self._conversation_history,
226
+ conversation_context_getter=lambda c: get_conversation_context(
227
+ c, self._conversation_context
228
+ ),
368
229
  )
369
- if summarization_prompt is not None:
370
- return summarization_prompt
371
- return default_llm_config.get_default_summarization_prompt()
372
-
373
- def _get_should_enrich_context(
374
- self, ctx: AnyContext, history_list: ListOfDict
375
- ) -> bool:
376
- if len(history_list) == 0:
377
- return False
378
- return get_bool_attr(
379
- ctx,
380
- self._should_enrich_context,
381
- True, # Default to True if not specified
382
- auto_render=self._render_enrich_context,
230
+ # 2. Enrich context (optional)
231
+ conversation_context = await maybe_enrich_context(
232
+ ctx=ctx,
233
+ history_list=history_list,
234
+ conversation_context=conversation_context,
235
+ should_enrich_context_attr=self._should_enrich_context,
236
+ render_enrich_context=self._render_enrich_context,
237
+ model=model,
238
+ model_settings=model_settings,
239
+ context_enrichment_prompt=context_enrichment_prompt,
383
240
  )
384
-
385
- def _get_context_enrichment_prompt(self, ctx: AnyContext) -> str:
386
- context_enrichment_prompt = get_attr(
387
- ctx,
388
- self._context_enrichment_prompt,
389
- None,
390
- auto_render=self._render_context_enrichment_prompt,
241
+ # 3. Summarize history (optional, modifies history_list and context)
242
+ history_list, conversation_context = await maybe_summarize_history(
243
+ ctx=ctx,
244
+ history_list=history_list,
245
+ conversation_context=conversation_context,
246
+ should_summarize_history_attr=self._should_summarize_history,
247
+ render_summarize_history=self._render_summarize_history,
248
+ history_summarization_threshold_attr=self._history_summarization_threshold,
249
+ render_history_summarization_threshold=(
250
+ self._render_history_summarization_threshold
251
+ ),
252
+ model=model,
253
+ model_settings=model_settings,
254
+ summarization_prompt=summarization_prompt,
391
255
  )
392
- if context_enrichment_prompt is not None:
393
- return context_enrichment_prompt
394
- return default_llm_config.get_default_context_enrichment_prompt()
395
-
396
- async def _read_conversation_history(
397
- self, ctx: AnyContext
398
- ) -> ConversationHistoryData: # Returns the model instance
399
- """Reads conversation history from reader, file, or attribute, with validation."""
400
- history_file = self._get_history_file(ctx)
401
- # Priority 1 & 2: Reader and File (handled by ConversationHistoryData)
402
- history_data = await ConversationHistoryData.read_from_sources(
256
+ # 4. Build the final user prompt
257
+ user_prompt = build_user_prompt(
403
258
  ctx=ctx,
404
- reader=self._conversation_history_reader,
405
- file_path=history_file,
259
+ message_attr=self._message,
260
+ conversation_context=conversation_context,
406
261
  )
407
- if history_data:
408
- return history_data
409
- # Priority 3: Callable or direct conversation_history attribute
410
- raw_data_attr: Any = None
411
- if callable(self._conversation_history):
412
- try:
413
- raw_data_attr = await run_async(self._conversation_history(ctx))
414
- except Exception as e:
415
- ctx.log_warning(
416
- f"Error executing callable conversation_history attribute: {e}. "
417
- "Ignoring."
418
- )
419
- if raw_data_attr is None:
420
- raw_data_attr = self._conversation_history
421
- if raw_data_attr:
422
- history_data = ConversationHistoryData.parse_and_validate(
423
- ctx, raw_data_attr, "attribute"
424
- )
425
- if history_data:
426
- return history_data
427
- # Fallback: Return default value
428
- return ConversationHistoryData()
429
-
430
- def _get_history_file(self, ctx: AnyContext) -> str:
431
- return get_str_attr(
432
- ctx,
433
- self._conversation_history_file,
434
- "",
435
- auto_render=self._render_history_file,
262
+ # 5. Get the agent instance
263
+ agent = get_agent(
264
+ ctx=ctx,
265
+ agent_attr=self._agent,
266
+ model=model,
267
+ system_prompt=system_prompt,
268
+ model_settings=model_settings,
269
+ tools_attr=self._tools,
270
+ additional_tools=self._additional_tools,
271
+ mcp_servers_attr=self._mcp_servers,
272
+ additional_mcp_servers=self._additional_mcp_servers,
436
273
  )
437
-
438
- def _get_should_summarize_history(
439
- self, ctx: AnyContext, history_list: ListOfDict
440
- ) -> bool:
441
- history_len = len(history_list)
442
- if history_len == 0:
443
- return False
444
- summarization_threshold = self._get_history_summarization_threshold(ctx)
445
- if summarization_threshold == -1:
446
- return False
447
- if summarization_threshold > history_len:
448
- return False
449
- return get_bool_attr(
450
- ctx,
451
- self._should_summarize_history,
452
- False,
453
- auto_render=self._render_summarize_history,
274
+ # 6. Run the agent iteration and save the results/history
275
+ return await self._run_agent_and_save_history(
276
+ ctx, agent, user_prompt, history_list, conversation_context
454
277
  )
455
278
 
456
- def _get_history_summarization_threshold(self, ctx: AnyContext) -> int:
457
- # Use get_int_attr with -1 as default (no limit)
279
+ async def _run_agent_and_save_history(
280
+ self,
281
+ ctx: AnyContext,
282
+ agent: Agent,
283
+ user_prompt: str,
284
+ history_list: ListOfDict,
285
+ conversation_context: dict[str, Any],
286
+ ) -> Any:
287
+ """Executes the agent, processes results, and saves history."""
458
288
  try:
459
- return get_int_attr(
460
- ctx,
461
- self._history_summarization_threshold,
462
- -1,
463
- auto_render=self._render_history_summarization_threshold,
464
- )
465
- except ValueError as e:
466
- ctx.log_warning(
467
- f"Could not convert history_summarization_threshold to int: {e}. "
468
- "Defaulting to -1 (no threshold)."
469
- )
470
- return -1
471
-
472
- def _get_conversation_context(self, ctx: AnyContext) -> dict[str, Any]:
473
- """
474
- Retrieves the conversation context.
475
- If a value in the context dict is callable, it executes it with ctx.
476
- """
477
- raw_context = get_attr(
478
- ctx, self._conversation_context, {}, auto_render=False
479
- ) # Context usually shouldn't be rendered
480
- if not isinstance(raw_context, dict):
481
- ctx.log_warning(
482
- f"Conversation context resolved to type {type(raw_context)}, "
483
- "expected dict. Returning empty context."
289
+ agent_run = await run_agent_iteration(
290
+ ctx=ctx,
291
+ agent=agent,
292
+ user_prompt=user_prompt,
293
+ history_list=history_list,
484
294
  )
485
- return {}
486
- # If conversation_context contains callable value, execute them.
487
- processed_context: dict[str, Any] = {}
488
- for key, value in raw_context.items():
489
- if callable(value):
490
- try:
491
- # Check if the callable expects 'ctx'
492
- sig = inspect.signature(value)
493
- if "ctx" in sig.parameters:
494
- processed_context[key] = value(ctx)
495
- else:
496
- processed_context[key] = value()
497
- except Exception as e:
498
- ctx.log_warning(
499
- f"Error executing callable for context key '{key}': {e}. "
500
- "Skipping."
501
- )
502
- processed_context[key] = None
295
+ if agent_run:
296
+ new_history_list = json.loads(agent_run.result.all_messages_json())
297
+ data_to_write = ConversationHistoryData(
298
+ context=conversation_context, # Save the final context state
299
+ history=new_history_list,
300
+ )
301
+ await write_conversation_history(
302
+ ctx=ctx,
303
+ history_data=data_to_write,
304
+ conversation_history_writer=self._conversation_history_writer,
305
+ conversation_history_file_attr=self._conversation_history_file,
306
+ render_history_file=self._render_history_file,
307
+ )
308
+ xcom_usage_key = f"{self.name}-usage"
309
+ if xcom_usage_key not in ctx.xcom:
310
+ ctx.xcom[xcom_usage_key] = Xcom([])
311
+ usage = agent_run.result.usage()
312
+ ctx.xcom.get(xcom_usage_key).push(usage)
313
+ ctx.print(stylize_faint(f"[USAGE] {usage}"))
314
+ return agent_run.result.data
503
315
  else:
504
- processed_context[key] = value
505
- return processed_context
316
+ ctx.log_warning("Agent run did not produce a result.")
317
+ return None # Or handle as appropriate
318
+ except Exception as e:
319
+ ctx.log_error(f"Error during agent execution or history saving: {str(e)}")
320
+ raise # Re-raise the exception after logging
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zrb
3
- Version: 1.5.7
3
+ Version: 1.5.8
4
4
  Summary: Your Automation Powerhouse
5
5
  Home-page: https://github.com/state-alchemists/zrb
6
6
  License: AGPL-3.0-or-later
@@ -14,7 +14,7 @@ zrb/builtin/llm/previous-session.js,sha256=xMKZvJoAbrwiyHS0OoPrWuaKxWYLoyR5sgueP
14
14
  zrb/builtin/llm/tool/api.py,sha256=yR9I0ZsI96OeQl9pgwORMASVuXsAL0a89D_iPS4C8Dc,1699
15
15
  zrb/builtin/llm/tool/cli.py,sha256=_CNEmEc6K2Z0i9ppYeM7jGpqaEdT3uxaWQatmxP3jKE,858
16
16
  zrb/builtin/llm/tool/file.py,sha256=ecFBmbMaqCIfqNGTmvd-Yt3vLtKuQ15KbjXlnIMWdho,19269
17
- zrb/builtin/llm/tool/rag.py,sha256=tw4MW5VW_3hezGufS0nICHe28eg5hPLMO4SsiDp4srQ,7500
17
+ zrb/builtin/llm/tool/rag.py,sha256=45t0o88l7F62oq2P61NnC1hsZJ4h72dZsVQfcsOIUc8,7521
18
18
  zrb/builtin/llm/tool/web.py,sha256=4qzom9xX-JxztIaTWneNfyTRlgweHIxzC1uSEAxJ00A,5507
19
19
  zrb/builtin/md5.py,sha256=0pNlrfZA0wlZlHvFHLgyqN0JZJWGKQIF5oXxO44_OJk,949
20
20
  zrb/builtin/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -300,18 +300,21 @@ zrb/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
300
300
  zrb/task/any_task.py,sha256=9rCdKe-Sayr34Han9AsbhRxFpkbk6Rteg1DOyETulwQ,4917
301
301
  zrb/task/base_task.py,sha256=H1D2KyJ9qK0GIPJ4kYyvfRe7fseJibmLVGjj8iRuLs4,21320
302
302
  zrb/task/base_trigger.py,sha256=jC722rDvodaBLeNaFghkTyv1u0QXrK6BLZUUqcmBJ7Q,4581
303
- zrb/task/cmd_task.py,sha256=pUKRSR4DZKjbmluB6vi7cxqyhxOLfJ2czSpYeQbiDvo,10705
303
+ zrb/task/cmd_task.py,sha256=f1OWajOBmdtx2QcXBr_8s6o82Fp4UTLqCXJqp2gxwzU,10750
304
304
  zrb/task/http_check.py,sha256=Gf5rOB2Se2EdizuN9rp65HpGmfZkGc-clIAlHmPVehs,2565
305
305
  zrb/task/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
306
- zrb/task/llm/agent_runner.py,sha256=-6i351_AViek2xXpqPHa0LdwhhRDPLpcnKeyr-pAGyI,1848
307
- zrb/task/llm/context_enricher.py,sha256=eNjyHkL2g5X1jMtYR711-N_x7EtkoP6d577uT3anOYA,3016
308
- zrb/task/llm/default_context.py,sha256=IgHpmlGsBXILJcWC4Fn9dr52UG-puMXlQ-AHoXd6Oh0,1460
306
+ zrb/task/llm/agent.py,sha256=2u1zlX41oBzMKozXWXD3gDEOzOsHNsFpedRcJXbUNHI,5105
307
+ zrb/task/llm/config.py,sha256=fXasnGb_DVTJIeY--HZ8bf1jd7iCUNttfUDJB5PvHRk,3071
308
+ zrb/task/llm/context.py,sha256=JAI1DqqiXlDkyL4aEXVyeutU8K5YfdSsWMbzx1rxMZU,3281
309
+ zrb/task/llm/context_enrichment.py,sha256=nnALfQ_jnRpQZJad0pgOY8JkOb9Au4LoH_NNhw4rTMQ,4442
309
310
  zrb/task/llm/error.py,sha256=YOwnEdFMtqOlaiA83tDHpC6uh2_9r5NeS-inrlb5a8E,3622
310
- zrb/task/llm/history.py,sha256=qQtp-8a71sYL0A9YWo94KRy9o9J5ZCCJlMk4jM-t_rI,3572
311
- zrb/task/llm/history_summarizer.py,sha256=WZRyVRh1eGOmZKHypaxEidzruDYEM-Gcmdy2Z_XJ4Ro,2572
311
+ zrb/task/llm/history.py,sha256=LnrJdXLyo2qz-bNCwLorhoqGmgSiPTUU0bzY63w67-E,9257
312
+ zrb/task/llm/history_summarization.py,sha256=MW9wg6m0y2Vjcdyvh-NCOCyYWUZeqamlL3z3LCkn1J0,5996
312
313
  zrb/task/llm/print_node.py,sha256=Dkb0xFyEXpNRKFRCM4Md0lfg6K3nI0t8yH3Abh20PjE,4430
314
+ zrb/task/llm/prompt.py,sha256=PmzeSeUBoqZqqHox1Kq8FkikvmB2lNA3hus-pybXAQg,2719
313
315
  zrb/task/llm/tool_wrapper.py,sha256=gZgoxcuOCgAVDPnLqfJ3ps57ZCVQi7q68z_KnS5Mx1U,3350
314
- zrb/task/llm_task.py,sha256=VH96eDL51MnMiYq91jPA4ONTXTuL5hYH_Uas0Fd_608,21211
316
+ zrb/task/llm/typing.py,sha256=c8VAuPBw_4A3DxfYdydkgedaP-LU61W9_wj3m3CAX1E,58
317
+ zrb/task/llm_task.py,sha256=mrv7AVZd2LEz_z6CqC2gN6iqg27riUyrpTH99HdqpX0,13731
315
318
  zrb/task/make_task.py,sha256=PD3b_aYazthS8LHeJsLAhwKDEgdurQZpymJDKeN60u0,2265
316
319
  zrb/task/rsync_task.py,sha256=GSL9144bmp6F0EckT6m-2a1xG25AzrrWYzH4k3SVUKM,6370
317
320
  zrb/task/scaffolder.py,sha256=rME18w1HJUHXgi9eTYXx_T2G4JdqDYzBoNOkdOOo5-o,6806
@@ -352,7 +355,7 @@ zrb/util/string/name.py,sha256=8picJfUBXNpdh64GNaHv3om23QHhUZux7DguFLrXHp8,1163
352
355
  zrb/util/todo.py,sha256=1nDdwPc22oFoK_1ZTXyf3638Bg6sqE2yp_U4_-frHoc,16015
353
356
  zrb/xcom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
354
357
  zrb/xcom/xcom.py,sha256=o79rxR9wphnShrcIushA0Qt71d_p3ZTxjNf7x9hJB78,1571
355
- zrb-1.5.7.dist-info/METADATA,sha256=jnJmD2uvg38nJvh5kYyMM77rWT4HEIEjnOCIgI8IhJY,8470
356
- zrb-1.5.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
357
- zrb-1.5.7.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
358
- zrb-1.5.7.dist-info/RECORD,,
358
+ zrb-1.5.8.dist-info/METADATA,sha256=Av7ZK7PbcYfMR6KUZ0IjN39HKabpxoWNUdAxP7yli_E,8470
359
+ zrb-1.5.8.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
360
+ zrb-1.5.8.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
361
+ zrb-1.5.8.dist-info/RECORD,,
@@ -1,53 +0,0 @@
1
- from typing import Any
2
-
3
- from openai import APIError
4
- from pydantic_ai import Agent
5
- from pydantic_ai.messages import ModelMessagesTypeAdapter
6
-
7
- from zrb.context.any_context import AnyContext
8
- from zrb.task.llm.error import extract_api_error_details
9
- from zrb.task.llm.history import ListOfDict
10
- from zrb.task.llm.print_node import print_node
11
-
12
-
13
- async def run_agent_iteration(
14
- ctx: AnyContext,
15
- agent: Agent,
16
- user_prompt: str,
17
- history_list: ListOfDict,
18
- ) -> Any:
19
- """
20
- Runs a single iteration of the agent execution loop.
21
-
22
- Args:
23
- ctx: The task context.
24
- agent: The Pydantic AI agent instance.
25
- user_prompt: The user's input prompt.
26
- history_list: The current conversation history.
27
-
28
- Returns:
29
- The agent run result object.
30
-
31
- Raises:
32
- Exception: If any error occurs during agent execution.
33
- """
34
- async with agent.run_mcp_servers():
35
- async with agent.iter(
36
- user_prompt=user_prompt,
37
- message_history=ModelMessagesTypeAdapter.validate_python(history_list),
38
- ) as agent_run:
39
- async for node in agent_run:
40
- # Each node represents a step in the agent's execution
41
- # Reference: https://ai.pydantic.dev/agents/#streaming
42
- try:
43
- await print_node(ctx.print, agent_run, node)
44
- except APIError as e:
45
- # Extract detailed error information from the response
46
- error_details = extract_api_error_details(e)
47
- ctx.log_error(f"API Error: {error_details}")
48
- raise
49
- except Exception as e:
50
- ctx.log_error(f"Error processing node: {str(e)}")
51
- ctx.log_error(f"Error type: {type(e).__name__}")
52
- raise
53
- return agent_run
@@ -1,45 +0,0 @@
1
- import datetime
2
- import os
3
- import platform
4
- import re
5
- from typing import Any
6
-
7
- from zrb.util.file import read_dir, read_file_with_line_numbers
8
-
9
-
10
- def get_default_context(user_message: str) -> dict[str, Any]:
11
- references = re.findall(r"@(\S+)", user_message)
12
- current_references = []
13
-
14
- for ref in references:
15
- resource_path = os.path.abspath(os.path.expanduser(ref))
16
- if os.path.isfile(resource_path):
17
- content = read_file_with_line_numbers(resource_path)
18
- current_references.append(
19
- {
20
- "reference": ref,
21
- "name": resource_path,
22
- "type": "file",
23
- "note": "line numbers are included in the content",
24
- "content": content,
25
- }
26
- )
27
- elif os.path.isdir(resource_path):
28
- content = read_dir(resource_path)
29
- current_references.append(
30
- {
31
- "reference": ref,
32
- "name": resource_path,
33
- "type": "directory",
34
- "content": content,
35
- }
36
- )
37
-
38
- return {
39
- "current_time": datetime.datetime.now().isoformat(),
40
- "current_working_directory": os.getcwd(),
41
- "current_os": platform.system(),
42
- "os_version": platform.version(),
43
- "python_version": platform.python_version(),
44
- "current_references": current_references,
45
- }