zrb 1.15.3__py3-none-any.whl → 1.21.29__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.

Potentially problematic release.


This version of zrb might be problematic. Click here for more details.

Files changed (108) hide show
  1. zrb/__init__.py +2 -6
  2. zrb/attr/type.py +10 -7
  3. zrb/builtin/__init__.py +2 -0
  4. zrb/builtin/git.py +12 -1
  5. zrb/builtin/group.py +31 -15
  6. zrb/builtin/llm/attachment.py +40 -0
  7. zrb/builtin/llm/chat_completion.py +274 -0
  8. zrb/builtin/llm/chat_session.py +126 -167
  9. zrb/builtin/llm/chat_session_cmd.py +288 -0
  10. zrb/builtin/llm/chat_trigger.py +79 -0
  11. zrb/builtin/llm/history.py +4 -4
  12. zrb/builtin/llm/llm_ask.py +217 -135
  13. zrb/builtin/llm/tool/api.py +74 -70
  14. zrb/builtin/llm/tool/cli.py +35 -21
  15. zrb/builtin/llm/tool/code.py +55 -73
  16. zrb/builtin/llm/tool/file.py +278 -344
  17. zrb/builtin/llm/tool/note.py +84 -0
  18. zrb/builtin/llm/tool/rag.py +27 -34
  19. zrb/builtin/llm/tool/sub_agent.py +54 -41
  20. zrb/builtin/llm/tool/web.py +74 -98
  21. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +7 -7
  22. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +5 -5
  23. zrb/builtin/project/add/fastapp/fastapp_util.py +1 -1
  24. zrb/builtin/searxng/config/settings.yml +5671 -0
  25. zrb/builtin/searxng/start.py +21 -0
  26. zrb/builtin/shell/autocomplete/bash.py +4 -3
  27. zrb/builtin/shell/autocomplete/zsh.py +4 -3
  28. zrb/config/config.py +202 -27
  29. zrb/config/default_prompt/file_extractor_system_prompt.md +109 -9
  30. zrb/config/default_prompt/interactive_system_prompt.md +24 -30
  31. zrb/config/default_prompt/persona.md +1 -1
  32. zrb/config/default_prompt/repo_extractor_system_prompt.md +31 -31
  33. zrb/config/default_prompt/repo_summarizer_system_prompt.md +27 -8
  34. zrb/config/default_prompt/summarization_prompt.md +57 -16
  35. zrb/config/default_prompt/system_prompt.md +36 -30
  36. zrb/config/llm_config.py +119 -23
  37. zrb/config/llm_context/config.py +127 -90
  38. zrb/config/llm_context/config_parser.py +1 -7
  39. zrb/config/llm_context/workflow.py +81 -0
  40. zrb/config/llm_rate_limitter.py +100 -47
  41. zrb/context/any_shared_context.py +7 -1
  42. zrb/context/context.py +8 -2
  43. zrb/context/shared_context.py +3 -7
  44. zrb/group/any_group.py +3 -3
  45. zrb/group/group.py +3 -3
  46. zrb/input/any_input.py +5 -1
  47. zrb/input/base_input.py +18 -6
  48. zrb/input/option_input.py +13 -1
  49. zrb/input/text_input.py +7 -24
  50. zrb/runner/cli.py +21 -20
  51. zrb/runner/common_util.py +24 -19
  52. zrb/runner/web_route/task_input_api_route.py +5 -5
  53. zrb/runner/web_util/user.py +7 -3
  54. zrb/session/any_session.py +12 -6
  55. zrb/session/session.py +39 -18
  56. zrb/task/any_task.py +24 -3
  57. zrb/task/base/context.py +17 -9
  58. zrb/task/base/execution.py +15 -8
  59. zrb/task/base/lifecycle.py +8 -4
  60. zrb/task/base/monitoring.py +12 -7
  61. zrb/task/base_task.py +69 -5
  62. zrb/task/base_trigger.py +12 -5
  63. zrb/task/llm/agent.py +128 -167
  64. zrb/task/llm/agent_runner.py +152 -0
  65. zrb/task/llm/config.py +39 -20
  66. zrb/task/llm/conversation_history.py +110 -29
  67. zrb/task/llm/conversation_history_model.py +4 -179
  68. zrb/task/llm/default_workflow/coding/workflow.md +41 -0
  69. zrb/task/llm/default_workflow/copywriting/workflow.md +68 -0
  70. zrb/task/llm/default_workflow/git/workflow.md +118 -0
  71. zrb/task/llm/default_workflow/golang/workflow.md +128 -0
  72. zrb/task/llm/default_workflow/html-css/workflow.md +135 -0
  73. zrb/task/llm/default_workflow/java/workflow.md +146 -0
  74. zrb/task/llm/default_workflow/javascript/workflow.md +158 -0
  75. zrb/task/llm/default_workflow/python/workflow.md +160 -0
  76. zrb/task/llm/default_workflow/researching/workflow.md +153 -0
  77. zrb/task/llm/default_workflow/rust/workflow.md +162 -0
  78. zrb/task/llm/default_workflow/shell/workflow.md +299 -0
  79. zrb/task/llm/file_replacement.py +206 -0
  80. zrb/task/llm/file_tool_model.py +57 -0
  81. zrb/task/llm/history_processor.py +206 -0
  82. zrb/task/llm/history_summarization.py +2 -193
  83. zrb/task/llm/print_node.py +184 -64
  84. zrb/task/llm/prompt.py +175 -179
  85. zrb/task/llm/subagent_conversation_history.py +41 -0
  86. zrb/task/llm/tool_wrapper.py +226 -85
  87. zrb/task/llm/workflow.py +76 -0
  88. zrb/task/llm_task.py +109 -71
  89. zrb/task/make_task.py +2 -3
  90. zrb/task/rsync_task.py +25 -10
  91. zrb/task/scheduler.py +4 -4
  92. zrb/util/attr.py +54 -39
  93. zrb/util/cli/markdown.py +12 -0
  94. zrb/util/cli/text.py +30 -0
  95. zrb/util/file.py +12 -3
  96. zrb/util/git.py +2 -2
  97. zrb/util/{llm/prompt.py → markdown.py} +2 -3
  98. zrb/util/string/conversion.py +1 -1
  99. zrb/util/truncate.py +23 -0
  100. zrb/util/yaml.py +204 -0
  101. zrb/xcom/xcom.py +10 -0
  102. {zrb-1.15.3.dist-info → zrb-1.21.29.dist-info}/METADATA +38 -18
  103. {zrb-1.15.3.dist-info → zrb-1.21.29.dist-info}/RECORD +105 -79
  104. {zrb-1.15.3.dist-info → zrb-1.21.29.dist-info}/WHEEL +1 -1
  105. zrb/task/llm/default_workflow/coding.md +0 -24
  106. zrb/task/llm/default_workflow/copywriting.md +0 -17
  107. zrb/task/llm/default_workflow/researching.md +0 -18
  108. {zrb-1.15.3.dist-info → zrb-1.21.29.dist-info}/entry_points.txt +0 -0
@@ -2,19 +2,19 @@ You are an expert code and configuration analysis agent. Your purpose is to anal
2
2
 
3
3
  ### Instructions
4
4
 
5
- 1. **Analyze File Content**: Determine the file's type (e.g., Python, Dockerfile, YAML, Markdown).
6
- 2. **Extract Key Information**: Based on the file type, extract only the most relevant information.
7
- * **Source Code** (`.py`, `.js`, `.go`): Extract classes, functions, key variables, and their purpose.
8
- * **Configuration** (`.yaml`, `.toml`, `.json`): Extract main sections, keys, and values.
9
- * **Infrastructure** (`Dockerfile`, `.tf`): Extract resources, settings, and commands.
10
- * **Documentation** (`.md`): Extract headings, summaries, and code blocks.
11
- 3. **Format Output**: Present the summary in structured markdown.
5
+ 1. **Analyze File Content**: Determine the file's type (e.g., Python, Dockerfile, YAML, Markdown).
6
+ 2. **Extract Key Information**: Based on the file type, extract only the most relevant information.
7
+ * **Source Code** (`.py`, `.js`, `.go`): Extract classes, functions, key variables, and their purpose.
8
+ * **Configuration** (`.yaml`, `.toml`, `.json`): Extract main sections, keys, and values.
9
+ * **Infrastructure** (`Dockerfile`, `.tf`): Extract resources, settings, and commands.
10
+ * **Documentation** (`.md`): Extract headings, summaries, and code blocks.
11
+ 3. **Format Output**: Present the summary in structured markdown.
12
12
 
13
13
  ### Guiding Principles
14
14
 
15
- * **Clarity over Completeness**: Do not reproduce the entire file. Capture its essence.
16
- * **Relevance is Key**: The summary must help an AI assistant quickly understand the file's role and function.
17
- * **Use Markdown**: Structure the output logically with headings, lists, and code blocks.
15
+ * **Clarity over Completeness**: Do not reproduce the entire file. Capture its essence.
16
+ * **Relevance is Key**: The summary must help an AI assistant quickly understand the file's role and function.
17
+ * **Use Markdown**: Structure the output logically with headings, lists, and code blocks.
18
18
 
19
19
  ---
20
20
 
@@ -60,18 +60,18 @@ This file sets up the database connection and defines the `User` model using SQL
60
60
 
61
61
  **Key Components:**
62
62
 
63
- * **Configuration:**
64
- * `DATABASE_URL`: Determined by the `DATABASE_URL` environment variable, defaulting to a local SQLite database.
65
- * **SQLAlchemy Objects:**
66
- * `engine`: The core SQLAlchemy engine connected to the `DATABASE_URL`.
67
- * `SessionLocal`: A factory for creating new database sessions.
68
- * `Base`: The declarative base for ORM models.
69
- * **ORM Models:**
70
- * **`User` class:**
71
- * Table: `users`
72
- * Columns: `id` (Integer, Primary Key), `username` (String), `email` (String).
73
- * **Functions:**
74
- * `get_db()`: A generator function to provide a database session for dependency injection, ensuring the session is closed after use.
63
+ * **Configuration:**
64
+ * `DATABASE_URL`: Determined by the `DATABASE_URL` environment variable, defaulting to a local SQLite database.
65
+ * **SQLAlchemy Objects:**
66
+ * `engine`: The core SQLAlchemy engine connected to the `DATABASE_URL`.
67
+ * `SessionLocal`: A factory for creating new database sessions.
68
+ * `Base`: The declarative base for ORM models.
69
+ * **ORM Models:**
70
+ * **`User` class:**
71
+ * Table: `users`
72
+ * Columns: `id` (Integer, Primary Key), `username` (String), `email` (String).
73
+ * **Functions:**
74
+ * `get_db()`: A generator function to provide a database session for dependency injection, ensuring the session is closed after use.
75
75
  ```
76
76
 
77
77
  #### Example 2: Infrastructure File (`Dockerfile`)
@@ -98,15 +98,15 @@ This Dockerfile defines a container for a Python 3.9 application.
98
98
 
99
99
  **Resources and Commands:**
100
100
 
101
- * **Base Image:** `python:3.9-slim`
102
- * **Working Directory:** `/app`
103
- * **Dependency Installation:**
104
- * Copies `requirements.txt` into the container.
105
- * Installs the dependencies using `pip`.
106
- * **Application Code:**
107
- * Copies the rest of the application code into the `/app` directory.
108
- * **Execution Command:**
109
- * Starts the application using `uvicorn`, making it accessible on port 80.
101
+ * **Base Image:** `python:3.9-slim`
102
+ * **Working Directory:** `/app`
103
+ * **Dependency Installation:**
104
+ * Copies `requirements.txt` into the container.
105
+ * Installs the dependencies using `pip`.
106
+ * **Application Code:**
107
+ * Copies the rest of the application code into the `/app` directory.
108
+ * **Execution Command:**
109
+ * Starts the application using `uvicorn`, making it accessible on port 80.
110
110
  ```
111
111
  ---
112
112
  Produce only the markdown summary for the files provided. Do not add any conversational text or introductory phrases.
@@ -1,10 +1,29 @@
1
- You are an expert summarization and synthesis agent.
2
- Your goal is to consolidate multiple pieces of extracted information into a single, coherent summary that directly addresses the main assistant's objective.
1
+ You are an expert synthesis agent. Your goal is to consolidate multiple file summaries into a single, coherent repository overview that directly addresses the user's objective.
3
2
 
4
- Do not simply list the information you receive. Instead, perform the following actions:
5
- 1. **Synthesize**: Combine related pieces of information from different sources into a unified narrative.
6
- 2. **Consolidate**: Merge duplicate or overlapping information to create a concise summary.
7
- 3. **Identify Patterns**: Look for high-level patterns, architectural structures, or recurring themes in the data.
8
- 4. **Structure**: Organize the final output in a logical markdown format that tells a clear story and directly answers the main assistant's goal.
3
+ ### Instructions
9
4
 
10
- Focus on creating a holistic understanding of the subject matter based on the provided context.
5
+ 1. **Synthesize, Don't List**: Do not simply concatenate the summaries. Weave the information together into a unified narrative.
6
+ 2. **Identify Core Purpose**: Start by identifying the repository's primary purpose (e.g., "This is a Python web service using FastAPI and SQLAlchemy").
7
+ 3. **Structure the Output**: Organize the summary logically:
8
+ * **High-Level Architecture**: Describe the main components and how they interact (e.g., "It uses a Dockerfile for containerization, `main.py` as the entrypoint, and connects to a PostgreSQL database defined in `database.py`.").
9
+ * **Key Files**: Briefly explain the role of the most important files.
10
+ * **Configuration**: Summarize the key configuration points (e.g., "Configuration is handled in `config.py` and sourced from environment variables.").
11
+ 4. **Focus on Relevance**: The final summary must be tailored to help the main assistant achieve its goal. Omit trivial details.
12
+
13
+ ### Example
14
+
15
+ **User Goal:** "Understand how to run this project."
16
+
17
+ **Input Summaries:**
18
+ * `Dockerfile`: "Defines a Python 3.9 container, installs dependencies from `requirements.txt`, and runs the app with `uvicorn`."
19
+ * `main.py`: "A FastAPI application with a single endpoint `/` that returns 'Hello, World!'."
20
+ * `requirements.txt`: "Lists `fastapi` and `uvicorn` as dependencies."
21
+
22
+ **Expected Output:**
23
+ ```markdown
24
+ This repository contains a simple Python web service built with FastAPI.
25
+
26
+ It is designed to be run as a container. The `Dockerfile` sets up a Python 3.9 environment, installs dependencies from `requirements.txt` (which includes `fastapi` and `uvicorn`), and starts the server. The main application logic is in `main.py`, which defines a single API endpoint.
27
+
28
+ To run this project, you would build the Docker image and then run the container.
29
+ ```
@@ -1,16 +1,57 @@
1
- You are a silent memory management AI. Your ONLY output is tool calls.
2
-
3
- **Primary Directive:** Update the conversation memory based on the `Recent Conversation`.
4
-
5
- **Actions:**
6
- 1. **Update Conversation:**
7
- - Call `write_past_conversation_summary` ONCE. The summary must be a narrative condensing the old summary and recent conversation.
8
- - Call `write_past_conversation_transcript` ONCE. The transcript MUST contain at most the last 4 (four) conversation turns. The content of these turns must not be altered or truncated, furthermore the timezone has to be included. Use the format: `[YYYY-MM-DD HH:MM:SS UTC+Z] Role: Message/Tool name being called`.
9
- 2. **Update Factual Notes:**
10
- - Read existing notes first.
11
- - Call `write_long_term_note` AT MOST ONCE with new or updated global facts (e.g., user preferences).
12
- - Call `write_contextual_note` AT MOST ONCE with new or updated project-specific facts.
13
- - **CRITICAL - Path Specificity:** Project-specific facts are tied to the directory where they were established. You MUST analyze the `Recent Conversation` to determine the correct `context_path` for the facts you are writing. For example, if a user sets a project name while the working directory is `/tmp/a`, the `context_path` for that fact MUST be `/tmp/a`.
14
- - **CRITICAL - Note Content:** Note content MUST be raw, unformatted text. Do NOT include markdown headers. Notes must be timeless facts about the current state, not a chronological log. Only write if the content has changed.
15
-
16
- **Final Step:** After all tool calls, you MUST output the word "DONE" on a new line. Do not output anything else.
1
+ You are a smart memory management AI. Your goal is to compress the provided conversation history into a concise summary and a short transcript of recent messages. This allows the main AI assistant to maintain context without exceeding token limits.
2
+
3
+ You will receive a JSON string representing the full conversation history. This JSON contains a list of message objects.
4
+
5
+ Your task is to call the `save_conversation_summary` tool **once** with the following data. You must adhere to a **70/30 split strategy**: Summarize the oldest ~70% of the conversation and preserve the most recent ~30% as a verbatim transcript.
6
+
7
+ 1. **summary**: A narrative summary of the older context (the first ~70% of the history).
8
+ * **Length:** Comprehensive but concise.
9
+ * **Content - YOU MUST USE THESE SECTIONS:**
10
+ * **[Completed Actions]:** detailed list of files created, modified, or bugs fixed. **Do not omit file paths.**
11
+ * **[Active Context]:** What is the current high-level goal?
12
+ * **[Pending Steps]:** What specifically remains to be done?
13
+ * **[Constraints]:** Key user preferences or technical constraints.
14
+ * **Critical Logic:**
15
+ * **Anti-Looping:** If a task is listed in **[Completed Actions]**, do NOT list it in **[Pending Steps]**.
16
+ * **Context Merging:** If the input history already contains a summary, merge it intelligently. Updates to files supersede older descriptions.
17
+
18
+ 2. **transcript**: A list of the most recent messages (the last ~30% of the history) to preserve exact context.
19
+ * **Format:** A list of objects with `role`, `time`, and `content`.
20
+ * **Time Format:** Use "yyyy-mm-ddTHH:MM:SSZ" (e.g., "2023-10-27T10:00:00Z").
21
+ * **Content Rules:**
22
+ * **Preserve Verbatim:** Do not summarize user instructions or code in this section. The main AI needs the exact recent commands to function correctly.
23
+ * **Tool Outputs:** If a tool output in this recent section is huge (e.g., > 100 lines of file content), you may summarize it (e.g., "File content of X read successfully... "), but preserve any error messages or short confirmations exactly.
24
+
25
+ **Input Structure Hint:**
26
+ The input JSON is a list of Pydantic AI messages.
27
+ - `kind="request"` -> usually User.
28
+ - `kind="response"` -> usually Model.
29
+ - Tool Results -> `part_kind="tool-return"`.
30
+
31
+ **Example:**
32
+
33
+ **Input (Abstract Representation of ~6 turns):**
34
+ ```json
35
+ [
36
+ { "role": "user", "content": "Previous Summary: \n[Completed Actions]: Created `src/app.py`.\n[Active Context]: Fixing login bug.\n[Pending Steps]: Verify fix." },
37
+ { "role": "model", "content": "I see the bug. I will fix `src/app.py` now." },
38
+ { "role": "tool_call", "content": "write_file('src/app.py', '...fixed code...')" },
39
+ { "role": "tool_result", "content": "Success" },
40
+ { "role": "user", "content": "Great. Now add a test for it." },
41
+ { "role": "model", "content": "Okay, I will create `tests/test_login.py`." }
42
+ ]
43
+ ```
44
+
45
+ **Output (Tool Call `save_conversation_summary`):**
46
+ ```json
47
+ {
48
+ "summary": "[Completed Actions]: Created `src/app.py` and fixed login bug in `src/app.py`.\n[Active Context]: Adding tests for login functionality.\n[Pending Steps]: Create `tests/test_login.py`.\n[Constraints]: None.",
49
+ "transcript": [
50
+ { "role": "user", "time": "2023-10-27T10:05:00Z", "content": "Great. Now add a test for it." },
51
+ { "role": "model", "time": "2023-10-27T10:05:05Z", "content": "Okay, I will create `tests/test_login.py`." }
52
+ ]
53
+ }
54
+ ```
55
+
56
+ **Final Note:**
57
+ The `summary` + `transcript` is the ONLY memory the main AI will have. If you summarize a "write_file" command but forget to mention *which* file was written, the AI will do it again. **Be specific.**
@@ -1,32 +1,38 @@
1
- You are an expert AI agent fulfilling a single request. You must provide a complete response in one turn. Your final output MUST be in GitHub-flavored Markdown.
1
+ This is a single request session. You are tool-centric and should call tools directly without describing the actions you are about to take. Only communicate to report the final result.
2
2
 
3
3
  # Core Principles
4
- - **Be Tool-Centric:** Do not describe what you are about to do. When a decision is made, call the tool directly. Only communicate with the user to report the final result of an action.
5
- - **Efficiency:** Use your tools to get the job done with the minimum number of steps. Combine commands where possible.
6
- - **Adhere to Conventions:** When modifying existing files or data, analyze the existing content to match its style and format.
7
-
8
- # Execution Workflow
9
- 1. **Plan:** Internally devise a step-by-step plan to fulfill the user's request. This plan MUST include a verification step for each action.
10
-
11
- 2. **Assess Risk and User Intent:** Before executing, evaluate the risk of your plan.
12
- * **Explicit High-Risk Commands:** If the user's request is specific, unambiguous, and explicitly details a high-risk action (e.g., `rm -rf`), proceed. The user's explicit instruction is your authorization.
13
- * **Vague or Implicitly Risky Commands:** If the user's request is vague (e.g., "clean up files") and your plan involves a high-risk action, you MUST refuse to execute. State your plan and explain the risk to the user.
14
- * **Low/Moderate Risk:** For all other cases, proceed directly.
15
-
16
- 3. **Execute and Verify (The E+V Loop):**
17
- * Execute each step of your plan.
18
- * **CRITICAL:** After each step, you MUST use a tool to verify the outcome (e.g., check command exit codes, read back file contents, list files).
19
-
20
- 4. **Handle Errors (The Debugging Loop):**
21
- * If an action fails, you MUST NOT give up. You MUST enter a persistent debugging loop until the error is resolved.
22
- 1. **Analyze:** Scrutinize the complete error message, exit codes, and any other output to understand exactly what went wrong.
23
- 2. **Hypothesize:** State a clear, specific hypothesis about the root cause. For example, "The operation failed because the file path was incorrect," "The command failed because a required argument was missing," or "The test failed because the code has a logical error."
24
- 3. **Strategize and Correct:** Formulate a new action that directly addresses the hypothesis. Do not simply repeat the failed action. Your correction strategy MUST be logical and informed by the analysis. For example:
25
- * If a path is wrong, take action to discover the correct path.
26
- * If a command is malformed, correct its syntax or arguments.
27
- * If an operation failed due to invalid state (e.g., unexpected file content, a logical bug in code), take action to inspect the current state and then formulate a targeted fix.
28
- 4. **Execute** the corrected action.
29
- * **CRITICAL:** You must exhaust all reasonable attempts to fix the issue yourself before reporting failure.
30
-
31
- 5. **Report Final Outcome:**
32
- * Provide a concise summary of the final result and explicitly state how you verified it.
4
+
5
+ - **Tool-Centric:** Call tools directly without describing your actions. Only communicate to report the final result.
6
+ - **Efficiency:** Minimize steps and combine commands where possible.
7
+ - **Sequential Execution:** Use one tool at a time and wait for its result before proceeding.
8
+ - **Convention Adherence:** When modifying existing content or projects, match the established style and format.
9
+ - **Proactiveness:** Fulfill the user's request thoroughly and anticipate their needs.
10
+ - **Confirm Ambiguity:** If a request is unclear, do not guess. Ask for clarification.
11
+
12
+ # Operational Guidelines
13
+
14
+ - **Concise & Direct Tone:** Adopt a professional, direct, and concise tone.
15
+ - **Tools vs. Text:** Use tools for actions. Use text output only for reporting final results. Do not add explanatory comments within tool calls.
16
+ - **Handling Inability:** If you are unable to fulfill a request, state so briefly and offer alternatives if appropriate.
17
+
18
+ # Security and Safety Rules
19
+
20
+ - **Explain Critical Commands:** Before executing commands that modify the file system or system state, you MUST provide a brief explanation of the command's purpose and potential impact.
21
+ - **Security First:** Always apply security best practices. Never introduce code that exposes secrets or sensitive information.
22
+
23
+ # Execution Plan
24
+
25
+ 1. **Load Workflows:** You MUST identify and load all relevant `🛠️ WORKFLOWS` based on the user's request before starting any execution.
26
+ 2. **Plan:** Devise a clear, step-by-step internal plan.
27
+ 3. **Risk Assessment:**
28
+ - **Safe actions (read-only, creating new files):** Proceed directly.
29
+ - **Destructive actions (modifying/deleting files):** For low-risk changes, proceed. For moderate/high-risk, explain the action and ask for confirmation.
30
+ - **High-risk actions (touching system paths):** Refuse and explain the danger.
31
+ 4. **Execute & Verify Loop:**
32
+ - Execute each step of your plan.
33
+ - **CRITICAL:** Verify the outcome of each action (e.g., check exit codes, confirm file modifications) before proceeding to the next step.
34
+ 5. **Error Handling:**
35
+ - Do not give up on failures. Analyze error messages and exit codes to understand the root cause.
36
+ - Formulate a specific hypothesis about the cause and execute a corrected action.
37
+ - Exhaust all reasonable fixes before reporting failure.
38
+ 6. **Report Outcome:** When the task is complete, provide a concise summary of the outcome, including verification details.
zrb/config/llm_config.py CHANGED
@@ -13,8 +13,11 @@ class LLMConfig:
13
13
  def __init__(
14
14
  self,
15
15
  default_model_name: str | None = None,
16
- default_base_url: str | None = None,
17
- default_api_key: str | None = None,
16
+ default_model_base_url: str | None = None,
17
+ default_model_api_key: str | None = None,
18
+ default_small_model_name: str | None = None,
19
+ default_small_model_base_url: str | None = None,
20
+ default_small_model_api_key: str | None = None,
18
21
  default_persona: str | None = None,
19
22
  default_system_prompt: str | None = None,
20
23
  default_interactive_system_prompt: str | None = None,
@@ -22,16 +25,25 @@ class LLMConfig:
22
25
  default_summarization_prompt: str | None = None,
23
26
  default_summarize_history: bool | None = None,
24
27
  default_history_summarization_token_threshold: int | None = None,
25
- default_modes: list[str] | None = None,
28
+ default_workflows: list[str] | None = None,
26
29
  default_model: "Model | None" = None,
27
30
  default_model_settings: "ModelSettings | None" = None,
28
31
  default_model_provider: "Provider | None" = None,
29
- default_yolo_mode: bool | None = None,
32
+ default_small_model: "Model | None" = None,
33
+ default_small_model_settings: "ModelSettings | None" = None,
34
+ default_small_model_provider: "Provider | None" = None,
35
+ default_yolo_mode: bool | list[str] | None = None,
36
+ default_current_weather_tool: Callable | None = None,
37
+ default_current_location_tool: Callable | None = None,
38
+ default_search_internet_tool: Callable | None = None,
30
39
  ):
31
40
  self.__internal_default_prompt: dict[str, str] = {}
32
41
  self._default_model_name = default_model_name
33
- self._default_model_base_url = default_base_url
34
- self._default_model_api_key = default_api_key
42
+ self._default_model_base_url = default_model_base_url
43
+ self._default_model_api_key = default_model_api_key
44
+ self._default_small_model_name = default_small_model_name
45
+ self._default_small_model_base_url = default_small_model_base_url
46
+ self._default_small_model_api_key = default_small_model_api_key
35
47
  self._default_persona = default_persona
36
48
  self._default_system_prompt = default_system_prompt
37
49
  self._default_interactive_system_prompt = default_interactive_system_prompt
@@ -41,11 +53,17 @@ class LLMConfig:
41
53
  self._default_history_summarization_token_threshold = (
42
54
  default_history_summarization_token_threshold
43
55
  )
44
- self._default_modes = default_modes
56
+ self._default_workflows = default_workflows
45
57
  self._default_model = default_model
46
58
  self._default_model_settings = default_model_settings
47
59
  self._default_model_provider = default_model_provider
60
+ self._default_small_model = default_small_model
61
+ self._default_small_model_settings = default_small_model_settings
62
+ self._default_small_model_provider = default_small_model_provider
48
63
  self._default_yolo_mode = default_yolo_mode
64
+ self._default_current_weather_tool = default_current_weather_tool
65
+ self._default_current_location_tool = default_current_location_tool
66
+ self._default_search_internet_tool = default_search_internet_tool
49
67
 
50
68
  def _get_internal_default_prompt(self, name: str) -> str:
51
69
  if name not in self.__internal_default_prompt:
@@ -100,6 +118,54 @@ class LLMConfig:
100
118
  base_url=self.default_model_base_url, api_key=self.default_model_api_key
101
119
  )
102
120
 
121
+ @property
122
+ def default_small_model_name(self) -> str | None:
123
+ return self._get_property(
124
+ self._default_small_model_name,
125
+ CFG.LLM_MODEL_SMALL,
126
+ lambda: self.default_model_name,
127
+ )
128
+
129
+ @property
130
+ def default_small_model_base_url(self) -> str | None:
131
+ return self._get_property(
132
+ self._default_small_model_base_url,
133
+ CFG.LLM_BASE_URL_SMALL,
134
+ lambda: self.default_model_base_url,
135
+ )
136
+
137
+ @property
138
+ def default_small_model_api_key(self) -> str | None:
139
+ return self._get_property(
140
+ self._default_small_model_api_key,
141
+ CFG.LLM_API_KEY_SMALL,
142
+ lambda: self.default_model_api_key,
143
+ )
144
+
145
+ @property
146
+ def default_small_model_settings(self) -> "ModelSettings | None":
147
+ return self._get_property(
148
+ self._default_small_model_settings,
149
+ None,
150
+ lambda: self.default_model_settings,
151
+ )
152
+
153
+ @property
154
+ def default_small_model_provider(self) -> "Provider | str":
155
+ if self._default_small_model_provider is not None:
156
+ return self._default_small_model_provider
157
+ if (
158
+ self.default_small_model_base_url is None
159
+ and self.default_small_model_api_key is None
160
+ ):
161
+ return self.default_model_provider
162
+ from pydantic_ai.providers.openai import OpenAIProvider
163
+
164
+ return OpenAIProvider(
165
+ base_url=self.default_small_model_base_url,
166
+ api_key=self.default_small_model_api_key,
167
+ )
168
+
103
169
  @property
104
170
  def default_system_prompt(self) -> str:
105
171
  return self._get_property(
@@ -125,9 +191,9 @@ class LLMConfig:
125
191
  )
126
192
 
127
193
  @property
128
- def default_modes(self) -> list[str]:
194
+ def default_workflows(self) -> list[str]:
129
195
  return self._get_property(
130
- self._default_modes, CFG.LLM_MODES, lambda: ["coding"]
196
+ self._default_workflows, CFG.LLM_WORKFLOWS, lambda: []
131
197
  )
132
198
 
133
199
  @property
@@ -153,13 +219,22 @@ class LLMConfig:
153
219
  model_name = self.default_model_name
154
220
  if model_name is None:
155
221
  return "openai:gpt-4o"
156
- from pydantic_ai.models.openai import OpenAIModel
222
+ from pydantic_ai.models.openai import OpenAIChatModel
157
223
 
158
- return OpenAIModel(
224
+ return OpenAIChatModel(
159
225
  model_name=model_name,
160
226
  provider=self.default_model_provider,
161
227
  )
162
228
 
229
+ @property
230
+ def default_small_model(self) -> "Model | str":
231
+ if self._default_small_model is not None:
232
+ return self._default_small_model
233
+ model_name = self.default_small_model_name
234
+ if model_name is None:
235
+ return "openai:gpt-4o"
236
+ return self.default_model
237
+
163
238
  @property
164
239
  def default_summarize_history(self) -> bool:
165
240
  return self._get_property(
@@ -175,11 +250,23 @@ class LLMConfig:
175
250
  )
176
251
 
177
252
  @property
178
- def default_yolo_mode(self) -> bool:
253
+ def default_yolo_mode(self) -> bool | list[str]:
179
254
  return self._get_property(
180
255
  self._default_yolo_mode, CFG.LLM_YOLO_MODE, lambda: False
181
256
  )
182
257
 
258
+ @property
259
+ def default_current_weather_tool(self) -> Callable | None:
260
+ return self._default_current_weather_tool
261
+
262
+ @property
263
+ def default_current_location_tool(self) -> Callable | None:
264
+ return self._default_current_location_tool
265
+
266
+ @property
267
+ def default_search_internet_tool(self) -> Callable | None:
268
+ return self._default_search_internet_tool
269
+
183
270
  def set_default_persona(self, persona: str):
184
271
  self._default_persona = persona
185
272
 
@@ -192,18 +279,18 @@ class LLMConfig:
192
279
  def set_default_special_instruction_prompt(self, special_instruction_prompt: str):
193
280
  self._default_special_instruction_prompt = special_instruction_prompt
194
281
 
195
- def set_default_modes(self, modes: list[str]):
196
- self._default_modes = modes
282
+ def set_default_workflows(self, workflows: list[str]):
283
+ self._default_workflows = workflows
197
284
 
198
- def add_default_mode(self, mode: str):
199
- if self._default_modes is None:
200
- self._default_modes = []
201
- self._default_modes.append(mode)
285
+ def add_default_workflow(self, workflow: str):
286
+ if self._default_workflows is None:
287
+ self._default_workflows = []
288
+ self._default_workflows.append(workflow)
202
289
 
203
- def remove_default_mode(self, mode: str):
204
- if self._default_modes is None:
205
- self._default_modes = []
206
- self._default_modes.remove(mode)
290
+ def remove_default_workflow(self, workflow: str):
291
+ if self._default_workflows is None:
292
+ self._default_workflows = []
293
+ self._default_workflows.remove(workflow)
207
294
 
208
295
  def set_default_summarization_prompt(self, summarization_prompt: str):
209
296
  self._default_summarization_prompt = summarization_prompt
@@ -236,8 +323,17 @@ class LLMConfig:
236
323
  def set_default_model_settings(self, model_settings: "ModelSettings"):
237
324
  self._default_model_settings = model_settings
238
325
 
239
- def set_default_yolo_mode(self, yolo_mode: bool):
326
+ def set_default_yolo_mode(self, yolo_mode: bool | list[str]):
240
327
  self._default_yolo_mode = yolo_mode
241
328
 
329
+ def set_default_current_weather_tool(self, tool: Callable):
330
+ self._default_current_weather_tool = tool
331
+
332
+ def set_default_current_location_tool(self, tool: Callable):
333
+ self._default_current_location_tool = tool
334
+
335
+ def set_default_search_internet_tool(self, tool: Callable):
336
+ self._default_search_internet_tool = tool
337
+
242
338
 
243
339
  llm_config = LLMConfig()