zrb 1.8.1__py3-none-any.whl → 1.8.3__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/__main__.py +2 -1
- zrb/builtin/setup/asdf/asdf.py +1 -0
- zrb/builtin/setup/tmux/tmux.py +1 -0
- zrb/builtin/setup/ubuntu.py +11 -2
- zrb/builtin/setup/zsh/zsh.py +1 -0
- zrb/config.py +1 -5
- zrb/llm_config.py +7 -18
- zrb/session/session.py +14 -7
- zrb/task/base/execution.py +1 -2
- zrb/task/base/lifecycle.py +22 -18
- zrb/task/cmd_task.py +3 -0
- zrb/task/llm/prompt.py +1 -13
- zrb/util/cmd/command.py +101 -50
- {zrb-1.8.1.dist-info → zrb-1.8.3.dist-info}/METADATA +32 -2
- {zrb-1.8.1.dist-info → zrb-1.8.3.dist-info}/RECORD +17 -17
- {zrb-1.8.1.dist-info → zrb-1.8.3.dist-info}/WHEEL +0 -0
- {zrb-1.8.1.dist-info → zrb-1.8.3.dist-info}/entry_points.txt +0 -0
zrb/__main__.py
CHANGED
@@ -60,8 +60,9 @@ def serve_cli():
|
|
60
60
|
# run the CLI
|
61
61
|
cli.run(sys.argv[1:])
|
62
62
|
except KeyboardInterrupt:
|
63
|
+
# The exception is handled by the task runner
|
63
64
|
print(stylize_warning("\nStopped"), file=sys.stderr)
|
64
|
-
|
65
|
+
pass
|
65
66
|
except RuntimeError as e:
|
66
67
|
if f"{e}".lower() != "event loop is closed":
|
67
68
|
raise e
|
zrb/builtin/setup/asdf/asdf.py
CHANGED
zrb/builtin/setup/tmux/tmux.py
CHANGED
zrb/builtin/setup/ubuntu.py
CHANGED
@@ -1,10 +1,18 @@
|
|
1
1
|
from zrb.builtin.group import setup_group
|
2
2
|
from zrb.task.cmd_task import CmdTask
|
3
3
|
|
4
|
-
update_ubuntu = CmdTask(
|
4
|
+
update_ubuntu = CmdTask(
|
5
|
+
name="update-ubuntu",
|
6
|
+
cmd="sudo apt update",
|
7
|
+
render_cmd=False,
|
8
|
+
is_interactive=True,
|
9
|
+
)
|
5
10
|
|
6
11
|
upgrade_todo = CmdTask(
|
7
|
-
name="upgrade-ubuntu",
|
12
|
+
name="upgrade-ubuntu",
|
13
|
+
cmd="sudo apt upgrade -y",
|
14
|
+
render_cmd=False,
|
15
|
+
is_interactive=True,
|
8
16
|
)
|
9
17
|
update_ubuntu >> upgrade_todo
|
10
18
|
|
@@ -22,6 +30,7 @@ setup_ubuntu = setup_group.add_task(
|
|
22
30
|
"cmake make tree tmux zsh neovim xdotool xsel",
|
23
31
|
],
|
24
32
|
render_cmd=False,
|
33
|
+
is_interactive=True,
|
25
34
|
),
|
26
35
|
alias="ubuntu",
|
27
36
|
)
|
zrb/builtin/setup/zsh/zsh.py
CHANGED
zrb/config.py
CHANGED
@@ -14,7 +14,7 @@ _DEFAULT_BANNER = """
|
|
14
14
|
zzzzz rr bbbbbb {VERSION} Janggala
|
15
15
|
_ _ . . . _ . _ . . .
|
16
16
|
Your Automation Powerhouse
|
17
|
-
☕ Donate at: https://stalchmst.com
|
17
|
+
☕ Donate at: https://stalchmst.com
|
18
18
|
🐙 Submit issues/PR at: https://github.com/state-alchemists/zrb
|
19
19
|
🐤 Follow us at: https://twitter.com/zarubastalchmst
|
20
20
|
"""
|
@@ -229,10 +229,6 @@ class Config:
|
|
229
229
|
def LLM_PERSONA(self) -> str | None:
|
230
230
|
return os.getenv("ZRB_LLM_PERSONA", None)
|
231
231
|
|
232
|
-
@property
|
233
|
-
def LLM_CODE_REVIEW_INSTRUCTION_PROMPT(self) -> str | None:
|
234
|
-
return os.getenv("ZRB_LLM_CODE_REVIEW_INSTRUCTION_PROMPT", None)
|
235
|
-
|
236
232
|
@property
|
237
233
|
def LLM_SPECIAL_INSTRUCTION_PROMPT(self) -> str | None:
|
238
234
|
return os.getenv("ZRB_LLM_SPECIAL_INSTRUCTION_PROMPT", None)
|
zrb/llm_config.py
CHANGED
@@ -51,9 +51,9 @@ another JSON object with these details (i.e., {"response": {"context_name": "val
|
|
51
51
|
If no context can be extracted, return {"response": {}}.
|
52
52
|
""".strip()
|
53
53
|
|
54
|
-
DEFAULT_SPECIAL_INSTRUCTION_PROMPT = ""
|
55
|
-
|
56
|
-
|
54
|
+
DEFAULT_SPECIAL_INSTRUCTION_PROMPT = """
|
55
|
+
# Coding and Code Review
|
56
|
+
When asked to do coding/code review related task, you prioritize correctness, readability,
|
57
57
|
performance, security, and maintainability.
|
58
58
|
Follow these principles:
|
59
59
|
1. **Correctness** Check whether the code performs the intended logic,
|
@@ -66,9 +66,10 @@ Follow these principles:
|
|
66
66
|
that could lead to security issues.
|
67
67
|
5. **Consistency** Ensure the code adheres to common language idioms,
|
68
68
|
style guides, and project conventions.
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
|
70
|
+
## Code Review
|
71
|
+
When asked to do code review, you provide clear, concise, and actionable feedback.
|
72
|
+
Use inline code examples when helpful. Do not restate the code unnecessarily.
|
72
73
|
Focus on meaningful insights that help the user improve the code quality.
|
73
74
|
Avoid excessive nitpicking unless requested.
|
74
75
|
""".strip()
|
@@ -84,7 +85,6 @@ class LLMConfig:
|
|
84
85
|
default_persona: str | None = None,
|
85
86
|
default_system_prompt: str | None = None,
|
86
87
|
default_special_instruction_prompt: str | None = None,
|
87
|
-
default_code_review_instruction_prompt: str | None = None,
|
88
88
|
default_summarization_prompt: str | None = None,
|
89
89
|
default_context_enrichment_prompt: str | None = None,
|
90
90
|
default_summarize_history: bool | None = None,
|
@@ -101,9 +101,6 @@ class LLMConfig:
|
|
101
101
|
self._default_persona = default_persona
|
102
102
|
self._default_system_prompt = default_system_prompt
|
103
103
|
self._default_special_instruction_prompt = default_special_instruction_prompt
|
104
|
-
self._default_code_review_instruction_prompt = (
|
105
|
-
default_code_review_instruction_prompt
|
106
|
-
)
|
107
104
|
self._default_summarization_prompt = default_summarization_prompt
|
108
105
|
self._default_context_enrichment_prompt = default_context_enrichment_prompt
|
109
106
|
self._default_summarize_history = default_summarize_history
|
@@ -175,14 +172,6 @@ class LLMConfig:
|
|
175
172
|
return CFG.LLM_PERSONA
|
176
173
|
return DEFAULT_PERSONA
|
177
174
|
|
178
|
-
@property
|
179
|
-
def default_code_review_instruction_prompt(self) -> str:
|
180
|
-
if self._default_code_review_instruction_prompt is not None:
|
181
|
-
return self._default_code_review_instruction_prompt
|
182
|
-
if CFG.LLM_CODE_REVIEW_INSTRUCTION_PROMPT is not None:
|
183
|
-
return CFG.LLM_CODE_REVIEW_INSTRUCTION_PROMPT
|
184
|
-
return DEFAULT_CODE_REVIEW_INSTRUCTION_PROMPT
|
185
|
-
|
186
175
|
@property
|
187
176
|
def default_special_instruction_prompt(self) -> str:
|
188
177
|
if self._default_special_instruction_prompt is not None:
|
zrb/session/session.py
CHANGED
@@ -51,9 +51,9 @@ class Session(AnySession):
|
|
51
51
|
self._shared_ctx = shared_ctx
|
52
52
|
self._shared_ctx.set_session(self)
|
53
53
|
self._parent = parent
|
54
|
-
self._action_coros: dict[AnyTask,
|
55
|
-
self._monitoring_coros: dict[AnyTask,
|
56
|
-
self._coros: list[
|
54
|
+
self._action_coros: dict[AnyTask, asyncio.Task] = {}
|
55
|
+
self._monitoring_coros: dict[AnyTask, asyncio.Task] = {}
|
56
|
+
self._coros: list[asyncio.Task] = []
|
57
57
|
self._colors = [
|
58
58
|
GREEN,
|
59
59
|
YELLOW,
|
@@ -100,6 +100,12 @@ class Session(AnySession):
|
|
100
100
|
self._is_terminated = True
|
101
101
|
for task_status in self._task_status.values():
|
102
102
|
task_status.mark_as_terminated()
|
103
|
+
for task in self._action_coros.values():
|
104
|
+
task.cancel()
|
105
|
+
for task in self._monitoring_coros.values():
|
106
|
+
task.cancel()
|
107
|
+
for task in self._coros:
|
108
|
+
task.cancel()
|
103
109
|
|
104
110
|
@property
|
105
111
|
def is_terminated(self) -> bool:
|
@@ -180,16 +186,17 @@ class Session(AnySession):
|
|
180
186
|
|
181
187
|
def defer_monitoring(self, task: AnyTask, coro: Coroutine):
|
182
188
|
self._register_single_task(task)
|
183
|
-
self._monitoring_coros[task] = coro
|
189
|
+
self._monitoring_coros[task] = asyncio.create_task(coro)
|
184
190
|
|
185
191
|
def defer_action(self, task: AnyTask, coro: Coroutine):
|
186
192
|
self._register_single_task(task)
|
187
|
-
self._action_coros[task] = coro
|
193
|
+
self._action_coros[task] = asyncio.create_task(coro)
|
188
194
|
|
189
195
|
def defer_coro(self, coro: Coroutine):
|
190
|
-
|
196
|
+
task = asyncio.create_task(coro)
|
197
|
+
self._coros.append(task)
|
191
198
|
self._coros = [
|
192
|
-
|
199
|
+
existing_task for existing_task in self._coros if not existing_task.done()
|
193
200
|
]
|
194
201
|
|
195
202
|
async def wait_deferred(self):
|
zrb/task/base/execution.py
CHANGED
@@ -175,8 +175,7 @@ async def execute_action_with_retry(task: "BaseTask", session: AnySession) -> An
|
|
175
175
|
ctx.log_warning("Task cancelled or interrupted")
|
176
176
|
session.get_task_status(task).mark_as_failed() # Mark as failed on cancel
|
177
177
|
# Do not trigger fallbacks/successors on cancellation
|
178
|
-
|
179
|
-
|
178
|
+
raise
|
180
179
|
except BaseException as e:
|
181
180
|
ctx.log_error(f"Attempt {attempt + 1}/{max_attempt} failed: {e}")
|
182
181
|
session.get_task_status(
|
zrb/task/base/lifecycle.py
CHANGED
@@ -38,26 +38,30 @@ async def run_and_cleanup(
|
|
38
38
|
ctx = task.get_ctx(session) # Get context for logging
|
39
39
|
ctx.log_info("Terminating session after run completion/error.")
|
40
40
|
session.terminate()
|
41
|
-
|
42
41
|
# Clean up other potentially running asyncio tasks (excluding the main one)
|
43
42
|
# Be cautious with blanket cancellation if other background tasks are expected
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
43
|
+
try:
|
44
|
+
pending = [
|
45
|
+
t
|
46
|
+
for t in asyncio.all_tasks()
|
47
|
+
if t is not main_task_coro and not t.done()
|
48
|
+
]
|
49
|
+
if pending:
|
50
|
+
ctx = task.get_ctx(session) # Get context for logging
|
51
|
+
ctx.log_debug(f"Cleaning up {len(pending)} pending asyncio tasks...")
|
52
|
+
for t in pending:
|
53
|
+
t.cancel()
|
54
|
+
try:
|
55
|
+
# Give cancelled tasks a moment to process cancellation
|
56
|
+
await asyncio.wait(pending, timeout=1.0)
|
57
|
+
except asyncio.CancelledError:
|
58
|
+
# Expected if tasks handle cancellation promptly
|
59
|
+
pass
|
60
|
+
except Exception as cleanup_exc:
|
61
|
+
# Log errors during cleanup if necessary
|
62
|
+
ctx.log_warning(f"Error during task cleanup: {cleanup_exc}")
|
63
|
+
except RuntimeError as cleanup_exc:
|
64
|
+
ctx.log_warning(f"Error during task cleanup: {cleanup_exc}")
|
61
65
|
|
62
66
|
|
63
67
|
async def run_task_async(
|
zrb/task/cmd_task.py
CHANGED
@@ -48,6 +48,7 @@ class CmdTask(BaseTask):
|
|
48
48
|
warn_unrecommended_command: bool | None = None,
|
49
49
|
max_output_line: int = 1000,
|
50
50
|
max_error_line: int = 1000,
|
51
|
+
is_interactive: bool = False,
|
51
52
|
execute_condition: BoolAttr = True,
|
52
53
|
retries: int = 2,
|
53
54
|
retry_period: float = 0,
|
@@ -104,6 +105,7 @@ class CmdTask(BaseTask):
|
|
104
105
|
self._max_error_line = max_error_line
|
105
106
|
self._should_plain_print = plain_print
|
106
107
|
self._should_warn_unrecommended_command = warn_unrecommended_command
|
108
|
+
self._is_interactive = is_interactive
|
107
109
|
|
108
110
|
async def _exec_action(self, ctx: AnyContext) -> CmdResult:
|
109
111
|
"""Turn _cmd attribute into subprocess.Popen and execute it as task's action.
|
@@ -140,6 +142,7 @@ class CmdTask(BaseTask):
|
|
140
142
|
register_pid_method=lambda pid: ctx.xcom.get(xcom_pid_key).push(pid),
|
141
143
|
max_output_line=self._max_output_line,
|
142
144
|
max_error_line=self._max_error_line,
|
145
|
+
is_interactive=self._is_interactive,
|
143
146
|
)
|
144
147
|
# Check for errors
|
145
148
|
if return_code > 0:
|
zrb/task/llm/prompt.py
CHANGED
@@ -52,19 +52,7 @@ def get_special_instruction_prompt(
|
|
52
52
|
)
|
53
53
|
if special_instruction is not None:
|
54
54
|
return special_instruction
|
55
|
-
|
56
|
-
if llm_config.default_code_review_instruction_prompt:
|
57
|
-
aggregated_special_instruction += "\n".join(
|
58
|
-
[
|
59
|
-
"# Code review instruction",
|
60
|
-
llm_config.default_code_review_instruction_prompt,
|
61
|
-
]
|
62
|
-
)
|
63
|
-
if llm_config.default_special_instruction_prompt:
|
64
|
-
aggregated_special_instruction += "\n" + "\n".join(
|
65
|
-
["# Code review instruction", llm_config.default_special_instruction_prompt]
|
66
|
-
)
|
67
|
-
return aggregated_special_instruction or ""
|
55
|
+
return llm_config.default_special_instruction_prompt
|
68
56
|
|
69
57
|
|
70
58
|
def get_combined_system_prompt(
|
zrb/util/cmd/command.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
import asyncio
|
2
2
|
import os
|
3
3
|
import re
|
4
|
+
import signal
|
4
5
|
import sys
|
6
|
+
from collections import deque
|
5
7
|
from collections.abc import Callable
|
8
|
+
from typing import TextIO
|
6
9
|
|
7
10
|
import psutil
|
8
11
|
|
@@ -59,67 +62,112 @@ async def run_command(
|
|
59
62
|
register_pid_method: Callable[[int], None] | None = None,
|
60
63
|
max_output_line: int = 1000,
|
61
64
|
max_error_line: int = 1000,
|
65
|
+
is_interactive: bool = False,
|
62
66
|
) -> tuple[CmdResult, int]:
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
line = await stream.readline()
|
74
|
-
except asyncio.exceptions.CancelledError:
|
75
|
-
pass
|
76
|
-
except asyncio.exceptions.LimitOverrunError as e:
|
77
|
-
# Recover by reading a limited chunk instead
|
78
|
-
await stream.read(e.consumed)
|
79
|
-
line = "<output line too long>"
|
80
|
-
except BaseException as e:
|
81
|
-
line = f"Error while reading stream {type(e)} {e}"
|
82
|
-
pass
|
83
|
-
if not line:
|
84
|
-
break
|
85
|
-
try:
|
86
|
-
line = line.decode("utf-8").rstrip()
|
87
|
-
except Exception:
|
88
|
-
pass
|
89
|
-
lines.append(line)
|
90
|
-
if len(lines) > max_lines:
|
91
|
-
lines.pop(0) # Keep only the last max_lines
|
92
|
-
print_method(line)
|
93
|
-
return "\n".join(lines)
|
94
|
-
|
67
|
+
"""
|
68
|
+
Executes a command using the robust `readline` strategy with a memory
|
69
|
+
limit, and correctly handles terminal control characters in the output.
|
70
|
+
Please note that `interactive` execution is generally not recommended and thus
|
71
|
+
disabled by default.
|
72
|
+
When using `interactive execution, the command will not be started in new session
|
73
|
+
and will share the same stdin as the main process, which might trigger race condition.
|
74
|
+
You can use interactive execution for a limited usecase when the command
|
75
|
+
require user input.
|
76
|
+
"""
|
95
77
|
actual_print_method = print_method if print_method is not None else print
|
96
|
-
cmd_process = None
|
97
78
|
if cwd is None:
|
98
79
|
cwd = os.getcwd()
|
99
|
-
|
100
|
-
|
80
|
+
# While environment variables alone weren't the fix, they are still
|
81
|
+
# good practice for encouraging simpler output from tools.
|
82
|
+
child_env = (env_map or os.environ).copy()
|
83
|
+
child_env["TERM"] = "xterm-256color" # A capable but standard terminal
|
84
|
+
child_env["NO_COLOR"] = "0" # Explicitly allow color
|
101
85
|
cmd_process = await asyncio.create_subprocess_exec(
|
102
86
|
*cmd,
|
103
87
|
cwd=cwd,
|
104
|
-
|
88
|
+
env=child_env,
|
89
|
+
start_new_session=not is_interactive,
|
90
|
+
stdin=__get_cmd_stdin(is_interactive),
|
105
91
|
stdout=asyncio.subprocess.PIPE,
|
106
92
|
stderr=asyncio.subprocess.PIPE,
|
107
|
-
|
108
|
-
bufsize=0,
|
93
|
+
limit=10 * 10 * 1024, # Buffer memory limit
|
109
94
|
)
|
110
95
|
if register_pid_method is not None:
|
111
96
|
register_pid_method(cmd_process.pid)
|
97
|
+
# Use the new, simple, and correct stream reader.
|
112
98
|
stdout_task = asyncio.create_task(
|
113
99
|
__read_stream(cmd_process.stdout, actual_print_method, max_output_line)
|
114
100
|
)
|
115
101
|
stderr_task = asyncio.create_task(
|
116
102
|
__read_stream(cmd_process.stderr, actual_print_method, max_error_line)
|
117
103
|
)
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
104
|
+
try:
|
105
|
+
return_code = await cmd_process.wait()
|
106
|
+
stdout, stderr = await asyncio.gather(stdout_task, stderr_task)
|
107
|
+
return CmdResult(stdout, stderr), return_code
|
108
|
+
except (KeyboardInterrupt, asyncio.CancelledError):
|
109
|
+
try:
|
110
|
+
os.killpg(cmd_process.pid, signal.SIGINT)
|
111
|
+
await asyncio.wait_for(cmd_process.wait(), timeout=2.0)
|
112
|
+
except asyncio.TimeoutError:
|
113
|
+
# If it doesn't terminate, kill it forcefully
|
114
|
+
actual_print_method(
|
115
|
+
f"Process {cmd_process.pid} did not terminate gracefully, killing."
|
116
|
+
)
|
117
|
+
kill_pid(cmd_process.pid, print_method=actual_print_method)
|
118
|
+
except Exception:
|
119
|
+
pass
|
120
|
+
# Final cleanup
|
121
|
+
stdout_task.cancel()
|
122
|
+
stderr_task.cancel()
|
123
|
+
await asyncio.gather(stdout_task, stderr_task, return_exceptions=True)
|
124
|
+
raise
|
125
|
+
|
126
|
+
|
127
|
+
def __get_cmd_stdin(is_interactive: bool) -> int | TextIO:
|
128
|
+
if is_interactive and sys.stdin.isatty():
|
129
|
+
return sys.stdin
|
130
|
+
return asyncio.subprocess.DEVNULL
|
131
|
+
|
132
|
+
|
133
|
+
async def __read_stream(
|
134
|
+
stream: asyncio.StreamReader,
|
135
|
+
print_method: Callable[..., None],
|
136
|
+
max_lines: int,
|
137
|
+
) -> str:
|
138
|
+
"""
|
139
|
+
Reads from the stream using the robust `readline()` and correctly
|
140
|
+
interprets carriage returns (`\r`) as distinct print events.
|
141
|
+
"""
|
142
|
+
captured_lines = deque(maxlen=max_lines if max_lines > 0 else 0)
|
143
|
+
while True:
|
144
|
+
try:
|
145
|
+
line_bytes = await stream.readline()
|
146
|
+
if not line_bytes:
|
147
|
+
break
|
148
|
+
except ValueError:
|
149
|
+
# Safety valve for the memory limit.
|
150
|
+
error_msg = "[ERROR] A single line of output was too long to process."
|
151
|
+
print_method(error_msg)
|
152
|
+
if max_lines > 0:
|
153
|
+
captured_lines.append(error_msg)
|
154
|
+
break
|
155
|
+
except (KeyboardInterrupt, asyncio.CancelledError):
|
156
|
+
raise
|
157
|
+
except Exception:
|
158
|
+
break
|
159
|
+
decoded_line = line_bytes.decode("utf-8", errors="replace")
|
160
|
+
parts = decoded_line.replace("\r", "\n").splitlines()
|
161
|
+
for part in parts:
|
162
|
+
clean_part = part.rstrip()
|
163
|
+
if clean_part:
|
164
|
+
try:
|
165
|
+
print_method(clean_part, end="\r\n")
|
166
|
+
except Exception:
|
167
|
+
print_method(clean_part)
|
168
|
+
if max_lines > 0:
|
169
|
+
captured_lines.append(clean_part)
|
170
|
+
return "\r\n".join(captured_lines)
|
123
171
|
|
124
172
|
|
125
173
|
def kill_pid(pid: int, print_method: Callable[..., None] | None = None):
|
@@ -132,10 +180,13 @@ def kill_pid(pid: int, print_method: Callable[..., None] | None = None):
|
|
132
180
|
Defaults to the built-in print function.
|
133
181
|
"""
|
134
182
|
actual_print_method = print_method if print_method is not None else print
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
183
|
+
try:
|
184
|
+
parent = psutil.Process(pid)
|
185
|
+
children = parent.children(recursive=True)
|
186
|
+
for child in children:
|
187
|
+
actual_print_method(f"Killing child process {child.pid}")
|
188
|
+
child.kill()
|
189
|
+
actual_print_method(f"Killing process {pid}")
|
190
|
+
parent.kill()
|
191
|
+
except psutil.NoSuchProcess:
|
192
|
+
actual_print_method(f"Process with pid: {pid} already terminated")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: zrb
|
3
|
-
Version: 1.8.
|
3
|
+
Version: 1.8.3
|
4
4
|
Summary: Your Automation Powerhouse
|
5
5
|
Home-page: https://github.com/state-alchemists/zrb
|
6
6
|
License: AGPL-3.0-or-later
|
@@ -194,6 +194,36 @@ Then open your browser and visit `http://localhost:21213`
|
|
194
194
|

|
195
195
|
|
196
196
|
|
197
|
+
# 🐋 Running Zrb as a Container
|
198
|
+
|
199
|
+
Zrb can be run in a containerized environment, offering two distinct versions to suit different needs:
|
200
|
+
|
201
|
+
- **Standard Version**: Ideal for general use cases where Docker CLI access is not required.
|
202
|
+
- **Dind (Docker in Docker) Version**: Includes built-in Docker commands, perfect for scenarios where you need to access the host's Docker CLI.
|
203
|
+
|
204
|
+
### Standard Version
|
205
|
+
|
206
|
+
The standard version of the Zrb container is suitable for most automation tasks. To run this version, execute the following command:
|
207
|
+
|
208
|
+
```bash
|
209
|
+
# Replace <host-path> and <container-path> with your desired paths
|
210
|
+
docker run -v ${HOME}:/zrb-home -it --rm stalchmst/zrb:1.8.1 zrb
|
211
|
+
```
|
212
|
+
|
213
|
+
### Dind Version
|
214
|
+
|
215
|
+
The Dind version is tailored for advanced use cases where Docker commands need to be executed within the container. This version allows the container to interact with the host's Docker daemon. To run the Dind version, use the command below:
|
216
|
+
|
217
|
+
```bash
|
218
|
+
# Replace <host-path> and <container-path> with your desired paths
|
219
|
+
docker run \
|
220
|
+
-v ${HOME}:/zrb-home \
|
221
|
+
-v /var/run/docker.sock:/var/run/docker.sock \
|
222
|
+
-it --rm stalchmst/zrb:1.8.1-dind docker ps
|
223
|
+
```
|
224
|
+
|
225
|
+
> **Note:** The Dind (Docker in Docker) version of the container is larger in size compared to the standard version due to the inclusion of Docker CLI tools. Consider this when choosing the appropriate version for your needs.
|
226
|
+
|
197
227
|
# 🎥 Demo & Documentation
|
198
228
|
|
199
229
|
- **Full documentation:** [Zrb Documentation](https://github.com/state-alchemists/zrb/blob/main/docs/README.md)
|
@@ -214,7 +244,7 @@ Then open your browser and visit `http://localhost:21213`
|
|
214
244
|
|
215
245
|
If you find Zrb valuable, please consider donating:
|
216
246
|
|
217
|
-
[](https://stalchmst.com
|
247
|
+
[](https://stalchmst.com)
|
218
248
|
|
219
249
|
# 🎉 Fun Fact
|
220
250
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
zrb/__init__.py,sha256=e0fZglzFsjO-jz0HhHaBV5Vm0e3MZJBtXcrgDOPESB0,3103
|
2
|
-
zrb/__main__.py,sha256=
|
2
|
+
zrb/__main__.py,sha256=aeIpBjlLef8bfdp0CYumnn5jVkHDPS5bwAxfuCJVUNI,2650
|
3
3
|
zrb/attr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
zrb/attr/type.py,sha256=4TV5gPYMMrKh5V-yB6iRYKCbsXAH_AvGXMsjxKLHcUs,568
|
5
5
|
zrb/builtin/__init__.py,sha256=N-h-BoXWv0jYOldixXwgk6ekiWtrGZsGv57iqonsYdc,2657
|
@@ -192,15 +192,15 @@ zrb/builtin/project/create/project-template/zrb_init.py,sha256=kY0x5MrkIVl3l1GtN
|
|
192
192
|
zrb/builtin/project/create/project_task.py,sha256=az-yd2FRDmGZ_7qxslmW11ryTeI3yttRmXtlFnZhF00,1132
|
193
193
|
zrb/builtin/python.py,sha256=e-yyVWovwlxCBLyXGsd9Ek3IAL_X-Q_hpNNOPoRjOgk,349
|
194
194
|
zrb/builtin/random.py,sha256=p9kCvosSiSJyuGQrlrXuIQT8TRDGxXhfiUbsm3GFPd0,1793
|
195
|
-
zrb/builtin/setup/asdf/asdf.py,sha256=
|
195
|
+
zrb/builtin/setup/asdf/asdf.py,sha256=_k60yiRiKbRPh_eJVI4Nx_ZmmClOlOb9G0b0KhSGo1M,2444
|
196
196
|
zrb/builtin/setup/asdf/asdf_helper.py,sha256=6jARtyIAE1H82HKVQ84D25RrMAsAip_gD28X9ZlaTCk,1205
|
197
197
|
zrb/builtin/setup/common_input.py,sha256=zIVVsZsNlSoV2Fw8kyt7g5B8XAU8cWBsT865NPoddwo,848
|
198
198
|
zrb/builtin/setup/latex/ubuntu.py,sha256=er9wJAT4CpmghIaiIPFb3FvgqAn1aqU5UgX7GHL3FjA,577
|
199
|
-
zrb/builtin/setup/tmux/tmux.py,sha256=
|
199
|
+
zrb/builtin/setup/tmux/tmux.py,sha256=cV-azDzLtNYtwxucmYqpPqoeSVz3lxP2GOc1-I1yhKs,1428
|
200
200
|
zrb/builtin/setup/tmux/tmux_config.sh,sha256=wQCb4Q-mNkxIPOcvpN84X9RUWkGY16u3Vd-pOhVidgg,416
|
201
201
|
zrb/builtin/setup/tmux/tmux_helper.py,sha256=M03l0wfL25TzGGp6lnVfX40ayT_x7N2lz-nz2chO7PU,396
|
202
|
-
zrb/builtin/setup/ubuntu.py,sha256=
|
203
|
-
zrb/builtin/setup/zsh/zsh.py,sha256=
|
202
|
+
zrb/builtin/setup/ubuntu.py,sha256=N4F55xzWKy0Hm115Qr19BADO29thDN7HB5myUaHZDBQ,1122
|
203
|
+
zrb/builtin/setup/zsh/zsh.py,sha256=wy7WSYIie6GprCqH4J2ygcTjWdOeRnxmOZcz8fRykcg,1845
|
204
204
|
zrb/builtin/setup/zsh/zsh_config.sh,sha256=SRkcXvVT3tdfS1UDT0-dSj2PKXPLohhyakY6tUEQPjc,4764
|
205
205
|
zrb/builtin/setup/zsh/zsh_helper.py,sha256=1zF1FH0oEPVAVhMA20tsdk1H0RPMCkLusYX8twsTbGI,393
|
206
206
|
zrb/builtin/shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -216,7 +216,7 @@ zrb/callback/callback.py,sha256=mk_RIHuWi-oP5b81jfhzU6fruhsIjhRtKpwh2yYmsiM,3876
|
|
216
216
|
zrb/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
217
217
|
zrb/cmd/cmd_result.py,sha256=L8bQJzWCpcYexIxHBNsXj2pT3BtLmWex0iJSMkvimOA,597
|
218
218
|
zrb/cmd/cmd_val.py,sha256=7Doowyg6BK3ISSGBLt-PmlhzaEkBjWWm51cED6fAUOQ,1014
|
219
|
-
zrb/config.py,sha256=
|
219
|
+
zrb/config.py,sha256=lpJJv5ns-bNntEpScSLptPHv9gQYvEl4M8LP6rE7zfk,9423
|
220
220
|
zrb/content_transformer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
221
221
|
zrb/content_transformer/any_content_transformer.py,sha256=v8ZUbcix1GGeDQwB6OKX_1TjpY__ksxWVeqibwa_iZA,850
|
222
222
|
zrb/content_transformer/content_transformer.py,sha256=STl77wW-I69QaGzCXjvkppngYFLufow8ybPLSyAvlHs,2404
|
@@ -245,7 +245,7 @@ zrb/input/option_input.py,sha256=TQB82ko5odgzkULEizBZi0e9TIHEbIgvdP0AR3RhA74,213
|
|
245
245
|
zrb/input/password_input.py,sha256=szBojWxSP9QJecgsgA87OIYwQrY2AQ3USIKdDZY6snU,1465
|
246
246
|
zrb/input/str_input.py,sha256=NevZHX9rf1g8eMatPyy-kUX3DglrVAQpzvVpKAzf7bA,81
|
247
247
|
zrb/input/text_input.py,sha256=6T3MngWdUs0u0ZVs5Dl11w5KS7nN1RkgrIR_zKumzPM,3695
|
248
|
-
zrb/llm_config.py,sha256=
|
248
|
+
zrb/llm_config.py,sha256=w_GSyQiJ_Q2jupej8xvQULScqPaSYICdNcH9J54W1lE,11696
|
249
249
|
zrb/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
250
250
|
zrb/runner/cli.py,sha256=AbLTNqFy5FuyGQOWOjHZGaBC8e2yuE_Dx1sBdnisR18,6984
|
251
251
|
zrb/runner/common_util.py,sha256=JDMcwvQ8cxnv9kQrAoKVLA40Q1omfv-u5_d5MvvwHeE,1373
|
@@ -315,7 +315,7 @@ zrb/runner/web_util/token.py,sha256=6Yqp6mQJJMAOsSkAN-6dvtdiQbAv5xtll9jOmNYzbUY,
|
|
315
315
|
zrb/runner/web_util/user.py,sha256=vE61pDjHoaHw9K0YAv1Gu2zWX2WkM2aWG-8776_aAiM,2061
|
316
316
|
zrb/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
317
317
|
zrb/session/any_session.py,sha256=x57mS15E-AfUjdVxwOWEzCBjW32zjer7WoeBw0guoDc,5266
|
318
|
-
zrb/session/session.py,sha256=
|
318
|
+
zrb/session/session.py,sha256=wkWwueMotpbXaMew1JKil4QMR3UbcBbx4IAZWKSFYjY,10272
|
319
319
|
zrb/session_state_log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
320
320
|
zrb/session_state_log/session_state_log.py,sha256=VVghDMU72PbrvnzQ7MJuc-KTJ5P5fX0FYuCh3Rlwd9M,709
|
321
321
|
zrb/session_state_logger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -326,13 +326,13 @@ zrb/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
326
326
|
zrb/task/any_task.py,sha256=zklUjkLRQ62TEvfnOUUYfXChj8Zk4igee3w8V3_rN08,5846
|
327
327
|
zrb/task/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
328
328
|
zrb/task/base/context.py,sha256=73k3fKwup0AJwTTLpay0f_-axJextaxgbTem4w4Bmas,3670
|
329
|
-
zrb/task/base/execution.py,sha256=
|
330
|
-
zrb/task/base/lifecycle.py,sha256=
|
329
|
+
zrb/task/base/execution.py,sha256=scDLfNYBe8Bc8Ct1LCIKmFtjpPxm7FjqZ2bJXIQAzv8,11042
|
330
|
+
zrb/task/base/lifecycle.py,sha256=4tGeN9yE5sQt1lHYq-1_vOFSGk1z8JneNCbVUWFVm-Q,7507
|
331
331
|
zrb/task/base/monitoring.py,sha256=UAOEcPiYNtZR4FFxzWCosuOEFE_P3c4GT5vAhQmohqI,5663
|
332
332
|
zrb/task/base/operators.py,sha256=uAMFqpZJsPnCrojgOl1FUDXTS15mtOa_IqiAXltyYRU,1576
|
333
333
|
zrb/task/base_task.py,sha256=Y5JNzU6Y1E8RKGdj16HTlhny0v8N2I98GCA4D8h6Kmw,10962
|
334
334
|
zrb/task/base_trigger.py,sha256=WSGcmBcGAZw8EzUXfmCjqJQkz8GEmi1RzogpF6A1V4s,6902
|
335
|
-
zrb/task/cmd_task.py,sha256=
|
335
|
+
zrb/task/cmd_task.py,sha256=irGi0txTcsvGhxjfem4_radR4csNXhgtfcxruSF1LFI,10853
|
336
336
|
zrb/task/http_check.py,sha256=Gf5rOB2Se2EdizuN9rp65HpGmfZkGc-clIAlHmPVehs,2565
|
337
337
|
zrb/task/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
338
338
|
zrb/task/llm/agent.py,sha256=6wGSsw03GdY_fj12CsJh7wxB6BnE13N8RYXaWfbiUsk,5451
|
@@ -343,7 +343,7 @@ zrb/task/llm/error.py,sha256=27DQXSG8SH1-XuvXFdZQKzP39wZDWmd_YnSTz6DJKKI,3690
|
|
343
343
|
zrb/task/llm/history.py,sha256=3WMXoi7RquxosXQf3iv2_BCeF8iKtY1f407pR71xERs,7745
|
344
344
|
zrb/task/llm/history_summarization.py,sha256=n3GbgwXlDIkgpJppMGfpqF_8Wpi9yAoZYh46O1pFQeU,6432
|
345
345
|
zrb/task/llm/print_node.py,sha256=bpISOUxSH_JBLR-4Nq6-iLrzNWFagrKFX6u8ogYYMw8,4395
|
346
|
-
zrb/task/llm/prompt.py,sha256=
|
346
|
+
zrb/task/llm/prompt.py,sha256=zBo3xT3YPX_A4_t8Cd-QjNqQZl9dsoWMTt-NdytI2f4,3827
|
347
347
|
zrb/task/llm/tool_wrapper.py,sha256=Xygd4VCY3ykjVv63pqlTI16ZG41ySkp683_5VTnL-Zo,6481
|
348
348
|
zrb/task/llm/typing.py,sha256=c8VAuPBw_4A3DxfYdydkgedaP-LU61W9_wj3m3CAX1E,58
|
349
349
|
zrb/task/llm_task.py,sha256=Yav1pmV26Eh4h9xTh16dN-DbTvhfYINI0EDp_ptJHLg,15643
|
@@ -361,7 +361,7 @@ zrb/util/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
361
361
|
zrb/util/cli/style.py,sha256=D_548KG1gXEirQGdkAVTc81vBdCeInXtnG1gV1yabBA,6655
|
362
362
|
zrb/util/cli/subcommand.py,sha256=umTZIlrL-9g-qc_eRRgdaQgK-whvXK1roFfvnbuY7NQ,1753
|
363
363
|
zrb/util/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
364
|
-
zrb/util/cmd/command.py,sha256=
|
364
|
+
zrb/util/cmd/command.py,sha256=WpEMWVL9hBsxptvDHmRR93_cJ2zP05BJ2h9-tP93M1Y,7473
|
365
365
|
zrb/util/cmd/remote.py,sha256=NGQq2_IrUMDoZz3qmcgtnNYVGjMHaBKQpZxImf0yfXA,1296
|
366
366
|
zrb/util/codemod/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
367
367
|
zrb/util/codemod/modification_mode.py,sha256=z_4U2gjskEHkFm6UtBe_Wbm-erufYaXgPbdCQ6CZMlw,128
|
@@ -388,7 +388,7 @@ zrb/util/string/name.py,sha256=SXEfxJ1-tDOzHqmSV8kvepRVyMqs2XdV_vyoh_9XUu0,1584
|
|
388
388
|
zrb/util/todo.py,sha256=VGISej2KQZERpornK-8X7bysp4JydMrMUTnG8B0-liI,20708
|
389
389
|
zrb/xcom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
390
390
|
zrb/xcom/xcom.py,sha256=o79rxR9wphnShrcIushA0Qt71d_p3ZTxjNf7x9hJB78,1571
|
391
|
-
zrb-1.8.
|
392
|
-
zrb-1.8.
|
393
|
-
zrb-1.8.
|
394
|
-
zrb-1.8.
|
391
|
+
zrb-1.8.3.dist-info/METADATA,sha256=VMBmGEImGJOvME1Jr6IrdYEWexUsmYcmgh8kmhE-kT4,9760
|
392
|
+
zrb-1.8.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
393
|
+
zrb-1.8.3.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
|
394
|
+
zrb-1.8.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|