zrb 1.0.0a2__py3-none-any.whl → 1.0.0a4__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.
Files changed (174) hide show
  1. zrb/__init__.py +49 -40
  2. zrb/__main__.py +5 -3
  3. zrb/attr/type.py +2 -1
  4. zrb/builtin/__init__.py +42 -2
  5. zrb/builtin/base64.py +34 -0
  6. zrb/builtin/git.py +156 -0
  7. zrb/builtin/git_subtree.py +88 -0
  8. zrb/builtin/group.py +34 -0
  9. zrb/builtin/llm/llm_chat.py +47 -0
  10. zrb/builtin/llm/tool/cli.py +9 -0
  11. zrb/builtin/llm/tool/rag.py +189 -0
  12. zrb/builtin/llm/tool/web.py +74 -0
  13. zrb/builtin/md5.py +36 -0
  14. zrb/builtin/project/add/fastapp.py +72 -0
  15. zrb/builtin/project/add/fastapp_template/.gitignore +4 -0
  16. zrb/builtin/project/add/fastapp_template/README.md +7 -0
  17. zrb/builtin/project/add/fastapp_template/_zrb/config.py +17 -0
  18. zrb/builtin/project/add/fastapp_template/_zrb/group.py +16 -0
  19. zrb/builtin/project/add/fastapp_template/_zrb/helper.py +97 -0
  20. zrb/builtin/project/add/fastapp_template/_zrb/main.py +132 -0
  21. zrb/builtin/project/add/fastapp_template/_zrb/venv_task.py +22 -0
  22. zrb/builtin/project/add/fastapp_template/common/app.py +18 -0
  23. zrb/builtin/project/add/fastapp_template/common/db_engine.py +5 -0
  24. zrb/builtin/project/add/fastapp_template/common/db_repository.py +134 -0
  25. zrb/builtin/project/add/fastapp_template/common/error.py +8 -0
  26. zrb/builtin/project/add/fastapp_template/common/schema.py +5 -0
  27. zrb/builtin/project/add/fastapp_template/common/usecase.py +232 -0
  28. zrb/builtin/project/add/fastapp_template/config.py +29 -0
  29. zrb/builtin/project/add/fastapp_template/main.py +7 -0
  30. zrb/builtin/project/add/fastapp_template/migrate.py +3 -0
  31. zrb/builtin/project/add/fastapp_template/module/__init__.py +0 -0
  32. zrb/builtin/project/add/fastapp_template/module/auth/alembic.ini +117 -0
  33. zrb/builtin/project/add/fastapp_template/module/auth/client/api_client.py +7 -0
  34. zrb/builtin/project/add/fastapp_template/module/auth/client/base_client.py +27 -0
  35. zrb/builtin/project/add/fastapp_template/module/auth/client/direct_client.py +6 -0
  36. zrb/builtin/project/add/fastapp_template/module/auth/client/factory.py +9 -0
  37. zrb/builtin/project/add/fastapp_template/module/auth/migration/README +1 -0
  38. zrb/builtin/project/add/fastapp_template/module/auth/migration/env.py +108 -0
  39. zrb/builtin/project/add/fastapp_template/module/auth/migration/script.py.mako +26 -0
  40. zrb/builtin/project/add/fastapp_template/module/auth/migration/versions/3093c7336477_add_user_table.py +37 -0
  41. zrb/builtin/project/add/fastapp_template/module/auth/migration_metadata.py +6 -0
  42. zrb/builtin/project/add/fastapp_template/module/auth/route.py +22 -0
  43. zrb/builtin/project/add/fastapp_template/module/auth/service/__init__.py +0 -0
  44. zrb/builtin/project/add/fastapp_template/module/auth/service/user/__init__.py +0 -0
  45. zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/__init__.py +0 -0
  46. zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/db_repository.py +39 -0
  47. zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/factory.py +13 -0
  48. zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/repository.py +34 -0
  49. zrb/builtin/project/add/fastapp_template/module/auth/service/user/usecase.py +45 -0
  50. zrb/builtin/project/add/fastapp_template/module/gateway/alembic.ini +117 -0
  51. zrb/builtin/project/add/fastapp_template/module/gateway/migration/README +1 -0
  52. zrb/builtin/project/add/fastapp_template/module/gateway/migration/env.py +108 -0
  53. zrb/builtin/project/add/fastapp_template/module/gateway/migration/script.py.mako +26 -0
  54. zrb/builtin/project/add/fastapp_template/module/gateway/migration/versions/.gitkeep +0 -0
  55. zrb/builtin/project/add/fastapp_template/module/gateway/migration_metadata.py +3 -0
  56. zrb/builtin/project/add/fastapp_template/module/gateway/route.py +27 -0
  57. zrb/builtin/project/add/fastapp_template/requirements.txt +6 -0
  58. zrb/builtin/project/add/fastapp_template/schema/__init__.py +0 -0
  59. zrb/builtin/project/add/fastapp_template/schema/role.py +31 -0
  60. zrb/builtin/project/add/fastapp_template/schema/user.py +31 -0
  61. zrb/builtin/project/add/fastapp_template/template.env +2 -0
  62. zrb/builtin/project/create/__init__.py +0 -0
  63. zrb/builtin/project/create/create.py +41 -0
  64. zrb/builtin/project/create/project-template/README.md +3 -0
  65. zrb/builtin/project/create/project-template/zrb_init.py +7 -0
  66. zrb/builtin/python.py +11 -0
  67. zrb/builtin/shell/__init__.py +0 -5
  68. zrb/builtin/shell/autocomplete/__init__.py +0 -9
  69. zrb/builtin/shell/autocomplete/bash.py +5 -6
  70. zrb/builtin/shell/autocomplete/subcmd.py +7 -8
  71. zrb/builtin/shell/autocomplete/zsh.py +5 -6
  72. zrb/builtin/todo.py +219 -0
  73. zrb/callback/any_callback.py +1 -1
  74. zrb/callback/callback.py +5 -5
  75. zrb/cmd/cmd_val.py +2 -2
  76. zrb/config.py +16 -3
  77. zrb/content_transformer/any_content_transformer.py +1 -1
  78. zrb/content_transformer/content_transformer.py +2 -2
  79. zrb/context/any_context.py +1 -1
  80. zrb/context/any_shared_context.py +3 -3
  81. zrb/context/context.py +10 -8
  82. zrb/context/shared_context.py +9 -8
  83. zrb/env/__init__.py +0 -3
  84. zrb/env/any_env.py +1 -1
  85. zrb/env/env.py +3 -4
  86. zrb/env/env_file.py +4 -4
  87. zrb/env/env_map.py +2 -2
  88. zrb/group/__init__.py +0 -3
  89. zrb/group/any_group.py +3 -3
  90. zrb/group/group.py +7 -6
  91. zrb/input/any_input.py +1 -1
  92. zrb/input/base_input.py +4 -4
  93. zrb/input/bool_input.py +5 -5
  94. zrb/input/float_input.py +3 -3
  95. zrb/input/int_input.py +3 -3
  96. zrb/input/option_input.py +51 -0
  97. zrb/input/password_input.py +2 -2
  98. zrb/input/str_input.py +1 -1
  99. zrb/input/text_input.py +12 -10
  100. zrb/runner/cli.py +80 -45
  101. zrb/runner/web_app.py +150 -0
  102. zrb/runner/web_controller/__init__.py +0 -0
  103. zrb/runner/web_controller/group_info_ui/__init__.py +0 -0
  104. zrb/runner/{web_app → web_controller}/group_info_ui/controller.py +7 -8
  105. zrb/runner/{web_app → web_controller}/group_info_ui/view.html +2 -2
  106. zrb/runner/web_controller/home_page/__init__.py +0 -0
  107. zrb/runner/{web_app → web_controller}/home_page/controller.py +7 -6
  108. zrb/runner/{web_app → web_controller}/home_page/view.html +2 -2
  109. zrb/runner/web_controller/task_ui/__init__.py +0 -0
  110. zrb/runner/{web_app → web_controller}/task_ui/controller.py +8 -12
  111. zrb/runner/{web_app → web_controller}/task_ui/view.html +2 -2
  112. zrb/runner/web_util.py +5 -35
  113. zrb/session/any_session.py +13 -7
  114. zrb/session/session.py +78 -40
  115. zrb/session_state_log/session_state_log.py +7 -5
  116. zrb/session_state_logger/any_session_state_logger.py +1 -1
  117. zrb/session_state_logger/default_session_state_logger.py +2 -2
  118. zrb/session_state_logger/file_session_state_logger.py +19 -27
  119. zrb/task/any_task.py +4 -4
  120. zrb/task/base_task.py +33 -23
  121. zrb/task/base_trigger.py +11 -12
  122. zrb/task/cmd_task.py +72 -65
  123. zrb/task/http_check.py +13 -13
  124. zrb/task/llm_task.py +215 -0
  125. zrb/task/make_task.py +9 -9
  126. zrb/task/rsync_task.py +25 -25
  127. zrb/task/scaffolder.py +18 -15
  128. zrb/task/scheduler.py +6 -7
  129. zrb/task/task.py +1 -1
  130. zrb/task/tcp_check.py +11 -13
  131. zrb/util/attr.py +19 -3
  132. zrb/util/cli/style.py +71 -2
  133. zrb/util/cli/subcommand.py +2 -2
  134. zrb/util/codemod/__init__.py +0 -0
  135. zrb/util/codemod/add_code_to_class.py +35 -0
  136. zrb/util/codemod/add_code_to_function.py +36 -0
  137. zrb/util/codemod/add_code_to_method.py +55 -0
  138. zrb/util/codemod/add_key_to_dict.py +51 -0
  139. zrb/util/codemod/add_param_to_function_call.py +39 -0
  140. zrb/util/codemod/add_property_to_class.py +55 -0
  141. zrb/util/git.py +156 -0
  142. zrb/util/git_subtree.py +94 -0
  143. zrb/util/group.py +2 -2
  144. zrb/util/llm/tool.py +63 -0
  145. zrb/util/string/conversion.py +7 -0
  146. zrb/util/todo.py +259 -0
  147. {zrb-1.0.0a2.dist-info → zrb-1.0.0a4.dist-info}/METADATA +13 -5
  148. zrb-1.0.0a4.dist-info/RECORD +197 -0
  149. zrb/builtin/shell/_group.py +0 -9
  150. zrb/builtin/shell/autocomplete/_group.py +0 -6
  151. zrb/runner/web_app/any_request_handler.py +0 -24
  152. zrb/runner/web_server.py +0 -224
  153. zrb-1.0.0a2.dist-info/RECORD +0 -120
  154. /zrb/{runner/web_app → builtin/project}/__init__.py +0 -0
  155. /zrb/{runner/web_app/group_info_ui → builtin/project/add}/__init__.py +0 -0
  156. /zrb/{runner/web_app/home_page → builtin/project/add/fastapp_template}/__init__.py +0 -0
  157. /zrb/{runner/web_app/task_ui → builtin/project/add/fastapp_template/common}/__init__.py +0 -0
  158. /zrb/runner/{web_app → web_controller}/group_info_ui/partial/group_info.html +0 -0
  159. /zrb/runner/{web_app → web_controller}/group_info_ui/partial/group_li.html +0 -0
  160. /zrb/runner/{web_app → web_controller}/group_info_ui/partial/task_info.html +0 -0
  161. /zrb/runner/{web_app → web_controller}/group_info_ui/partial/task_li.html +0 -0
  162. /zrb/runner/{web_app → web_controller}/home_page/partial/group_info.html +0 -0
  163. /zrb/runner/{web_app → web_controller}/home_page/partial/group_li.html +0 -0
  164. /zrb/runner/{web_app → web_controller}/home_page/partial/task_info.html +0 -0
  165. /zrb/runner/{web_app → web_controller}/home_page/partial/task_li.html +0 -0
  166. /zrb/runner/{web_app → web_controller}/static/favicon-32x32.png +0 -0
  167. /zrb/runner/{web_app → web_controller}/static/pico.min.css +0 -0
  168. /zrb/runner/{web_app → web_controller}/task_ui/partial/common-util.js +0 -0
  169. /zrb/runner/{web_app → web_controller}/task_ui/partial/input.html +0 -0
  170. /zrb/runner/{web_app → web_controller}/task_ui/partial/main.js +0 -0
  171. /zrb/runner/{web_app → web_controller}/task_ui/partial/show-existing-session.js +0 -0
  172. /zrb/runner/{web_app → web_controller}/task_ui/partial/visualize-history.js +0 -0
  173. {zrb-1.0.0a2.dist-info → zrb-1.0.0a4.dist-info}/WHEEL +0 -0
  174. {zrb-1.0.0a2.dist-info → zrb-1.0.0a4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,31 @@
1
+ import datetime
2
+
3
+ import ulid
4
+ from sqlmodel import Field, SQLModel
5
+
6
+
7
+ class UserBase(SQLModel):
8
+ username: str
9
+
10
+
11
+ class UserCreate(UserBase):
12
+ password: str
13
+
14
+
15
+ class UserUpdate(SQLModel):
16
+ username: str | None = None
17
+ password: str | None = None
18
+
19
+
20
+ class UserResponse(UserBase):
21
+ id: str
22
+
23
+
24
+ class User(SQLModel, table=True):
25
+ id: str = Field(default_factory=lambda: ulid.new().str, primary_key=True)
26
+ created_at: datetime.datetime
27
+ created_by: str
28
+ updated_at: datetime.datetime
29
+ updated_by: str
30
+ username: str
31
+ password: str
@@ -0,0 +1,2 @@
1
+ export APP_NAME_MODE=monolith
2
+ export APP_NAME_PORT=3000
File without changes
@@ -0,0 +1,41 @@
1
+ import os
2
+
3
+ from zrb.builtin.group import project_group
4
+ from zrb.input.str_input import StrInput
5
+ from zrb.task.scaffolder import Scaffolder
6
+ from zrb.task.task import Task
7
+
8
+ _DIR = os.path.dirname(__file__)
9
+
10
+ scaffold_project = Scaffolder(
11
+ name="scaffold-project",
12
+ description="🌟 Create project",
13
+ input=[
14
+ StrInput(
15
+ name="project-dir",
16
+ description="Project directory",
17
+ prompt="Project directory",
18
+ default_str=lambda _: os.getcwd(),
19
+ ),
20
+ StrInput(
21
+ name="project-name",
22
+ description="Project name",
23
+ prompt="Project name",
24
+ default_str=lambda ctx: os.path.basename(ctx.input["project-dir"]),
25
+ ),
26
+ ],
27
+ source_path=os.path.join(_DIR, "project-template"),
28
+ render_source_path=False,
29
+ destination_path="{ctx.input['project-dir']}",
30
+ transform_content={"Project Name": "{ctx.input['project-name'].title()}"},
31
+ retries=0,
32
+ )
33
+
34
+ create_project = project_group.add_task(
35
+ Task(
36
+ name="create-project",
37
+ description="🌟 Create project",
38
+ ),
39
+ alias="create",
40
+ )
41
+ scaffold_project >> create_project
@@ -0,0 +1,3 @@
1
+ # Project Name
2
+
3
+ Welcome to Project Name
@@ -0,0 +1,7 @@
1
+ import os
2
+
3
+ from zrb import load_file
4
+
5
+ _DIR = os.path.dirname(__file__)
6
+
7
+ assert load_file
zrb/builtin/python.py ADDED
@@ -0,0 +1,11 @@
1
+ from zrb.builtin.group import python_group
2
+ from zrb.task.cmd_task import CmdTask
3
+
4
+ format_python_code = python_group.add_task(
5
+ CmdTask(
6
+ name="format-code",
7
+ description="✏️ Format Python code",
8
+ cmd=["isort .", "black ."],
9
+ ),
10
+ alias="format",
11
+ )
@@ -1,5 +0,0 @@
1
- from . import autocomplete
2
- from ._group import shell_group
3
-
4
- assert autocomplete
5
- assert shell_group
@@ -1,9 +0,0 @@
1
- from ._group import shell_autocomplete_group
2
- from .bash import make_bash_autocomplete
3
- from .subcmd import get_shell_subcommands
4
- from .zsh import make_zsh_autocomplete
5
-
6
- assert shell_autocomplete_group
7
- assert make_bash_autocomplete
8
- assert make_zsh_autocomplete
9
- assert get_shell_subcommands
@@ -1,6 +1,6 @@
1
- from ....context.context import Context
2
- from ....task.make_task import make_task
3
- from ._group import shell_autocomplete_group
1
+ from zrb.builtin.group import shell_autocomplete_group
2
+ from zrb.context.context import Context
3
+ from zrb.task.make_task import make_task
4
4
 
5
5
  _COMPLETION_SCRIPT = """
6
6
  # Bash dynamic completion script
@@ -33,9 +33,8 @@ complete -F _zrb_complete zrb
33
33
  @make_task(
34
34
  name="make-bash-autocomplete",
35
35
  description="Create Zrb autocomplete script for bash",
36
+ group=shell_autocomplete_group,
37
+ alias="bash",
36
38
  )
37
39
  def make_bash_autocomplete(ctx: Context):
38
40
  return _COMPLETION_SCRIPT
39
-
40
-
41
- shell_autocomplete_group.add_task(make_bash_autocomplete, "bash")
@@ -1,13 +1,15 @@
1
- from ....context.context import Context
2
- from ....runner.cli import cli
3
- from ....task.make_task import make_task
4
- from ....util.cli.subcommand import get_group_subcommands
5
- from ._group import shell_autocomplete_group
1
+ from zrb.builtin.group import shell_autocomplete_group
2
+ from zrb.context.context import Context
3
+ from zrb.runner.cli import cli
4
+ from zrb.task.make_task import make_task
5
+ from zrb.util.cli.subcommand import get_group_subcommands
6
6
 
7
7
 
8
8
  @make_task(
9
9
  name="get-shell-subcommands",
10
10
  description="Get subcommand of any Zrb command",
11
+ group=shell_autocomplete_group,
12
+ alias="subcmd",
11
13
  )
12
14
  def get_shell_subcommands(ctx: Context):
13
15
  subcommands = get_group_subcommands(cli)
@@ -15,6 +17,3 @@ def get_shell_subcommands(ctx: Context):
15
17
  if subcommand.paths == ctx.args:
16
18
  return " ".join(subcommand.nexts)
17
19
  return ""
18
-
19
-
20
- shell_autocomplete_group.add_task(get_shell_subcommands, "subcmd")
@@ -1,6 +1,6 @@
1
- from ....context.context import Context
2
- from ....task.make_task import make_task
3
- from ._group import shell_autocomplete_group
1
+ from zrb.builtin.group import shell_autocomplete_group
2
+ from zrb.context.context import Context
3
+ from zrb.task.make_task import make_task
4
4
 
5
5
  _COMPLETION_SCRIPT = """
6
6
  # Zsh dynamic completion script
@@ -30,9 +30,8 @@ compdef _zrb_complete zrb
30
30
  @make_task(
31
31
  name="make-zsh-autocomplete",
32
32
  description="Create Zrb autocomplete script for zsh",
33
+ group=shell_autocomplete_group,
34
+ alias="zsh",
33
35
  )
34
36
  def make_zsh_autocomplete(ctx: Context):
35
37
  return _COMPLETION_SCRIPT
36
-
37
-
38
- shell_autocomplete_group.add_task(make_zsh_autocomplete, "zsh")
zrb/builtin/todo.py ADDED
@@ -0,0 +1,219 @@
1
+ import datetime
2
+ import json
3
+ import os
4
+ from typing import Any
5
+
6
+ from zrb.builtin.group import todo_group
7
+ from zrb.config import TODO_DIR
8
+ from zrb.context.any_context import AnyContext
9
+ from zrb.input.str_input import StrInput
10
+ from zrb.input.text_input import TextInput
11
+ from zrb.task.make_task import make_task
12
+ from zrb.util.todo import (
13
+ TodoTaskModel,
14
+ add_durations,
15
+ cascade_todo_task,
16
+ get_visual_todo_list,
17
+ line_to_todo_task,
18
+ load_todo_list,
19
+ save_todo_list,
20
+ select_todo_task,
21
+ todo_task_to_line,
22
+ )
23
+
24
+
25
+ @make_task(
26
+ name="todo-add",
27
+ input=[
28
+ StrInput(
29
+ name="description",
30
+ description="Task description",
31
+ prompt="Task description",
32
+ ),
33
+ StrInput(
34
+ name="priority",
35
+ description="Task priority",
36
+ prompt="Task priority",
37
+ default_str="E",
38
+ ),
39
+ StrInput(
40
+ name="project",
41
+ description="Task project",
42
+ prompt="Task project (space separated)",
43
+ ),
44
+ StrInput(
45
+ name="context",
46
+ description="Task context",
47
+ prompt="Task context (space separated)",
48
+ ),
49
+ ],
50
+ description="➕ Add todo",
51
+ group=todo_group,
52
+ alias="add",
53
+ )
54
+ def todo_add(ctx: AnyContext):
55
+ todo_file_path = os.path.join(TODO_DIR, "todo.txt")
56
+ todo_list: list[TodoTaskModel] = []
57
+ if os.path.isfile(todo_file_path):
58
+ todo_list = load_todo_list(todo_file_path)
59
+ else:
60
+ os.makedirs(TODO_DIR, exist_ok=True)
61
+ todo_list.append(
62
+ cascade_todo_task(
63
+ TodoTaskModel(
64
+ priority=ctx.input.priority.upper(),
65
+ description=ctx.input.description,
66
+ contexts=[
67
+ context.strip()
68
+ for context in ctx.input.context.split(" ")
69
+ if context.strip() != ""
70
+ ],
71
+ projects=[
72
+ project.strip()
73
+ for project in ctx.input.project.split(" ")
74
+ if project.strip() != ""
75
+ ],
76
+ )
77
+ )
78
+ )
79
+ save_todo_list(todo_file_path, todo_list)
80
+ return get_visual_todo_list(todo_list)
81
+
82
+
83
+ @make_task(name="todo-list", description="📋 List todo", group=todo_group, alias="list")
84
+ def todo_list(ctx: AnyContext):
85
+ todo_file_path = os.path.join(TODO_DIR, "todo.txt")
86
+ todo_tasks: list[TodoTaskModel] = []
87
+ if os.path.isfile(todo_file_path):
88
+ todo_tasks = load_todo_list(todo_file_path)
89
+ return get_visual_todo_list(todo_tasks)
90
+
91
+
92
+ @make_task(
93
+ name="todo-complete",
94
+ input=StrInput(name="keyword", prompt="Task keyword", description="Task Keyword"),
95
+ description="✅ Complete todo",
96
+ group=todo_group,
97
+ alias="complete",
98
+ )
99
+ def todo_complete(ctx: AnyContext):
100
+ todo_file_path = os.path.join(TODO_DIR, "todo.txt")
101
+ todo_list: list[TodoTaskModel] = []
102
+ if os.path.isfile(todo_file_path):
103
+ todo_list = load_todo_list(todo_file_path)
104
+ # Get todo task
105
+ todo_task = select_todo_task(todo_list, ctx.input.keyword)
106
+ if todo_task is None:
107
+ ctx.log_error("Task not found")
108
+ return get_visual_todo_list(todo_list)
109
+ # Update todo task
110
+ todo_task = cascade_todo_task(todo_task)
111
+ if todo_task.creation_date is not None:
112
+ todo_task.completion_date = datetime.date.today()
113
+ todo_task.completed = True
114
+ # Save todo list
115
+ save_todo_list(todo_file_path, todo_list)
116
+ return get_visual_todo_list(todo_list)
117
+
118
+
119
+ @make_task(
120
+ name="todo-log",
121
+ input=[
122
+ StrInput(name="keyword", prompt="Task keyword", description="Task Keyword"),
123
+ StrInput(
124
+ name="start",
125
+ prompt="Working start time (%Y-%m-%d %H:%M:%S)",
126
+ description="Working start time",
127
+ default_str=lambda _: _get_default_start(),
128
+ ),
129
+ StrInput(
130
+ name="duration",
131
+ prompt="Working duration",
132
+ description="Working duration",
133
+ default_str="30m",
134
+ ),
135
+ StrInput(
136
+ name="log",
137
+ prompt="Working log",
138
+ description="Working log",
139
+ ),
140
+ ],
141
+ description="🕒 Log work todo",
142
+ group=todo_group,
143
+ alias="log",
144
+ )
145
+ def todo_log(ctx: AnyContext):
146
+ todo_file_path = os.path.join(TODO_DIR, "todo.txt")
147
+ todo_list: list[TodoTaskModel] = []
148
+ if os.path.isfile(todo_file_path):
149
+ todo_list = load_todo_list(todo_file_path)
150
+ # Get todo task
151
+ todo_task = select_todo_task(todo_list, ctx.input.keyword)
152
+ if todo_task is None:
153
+ ctx.log_error("Task not found")
154
+ return get_visual_todo_list(todo_list)
155
+ # Update todo task
156
+ todo_task = cascade_todo_task(todo_task)
157
+ current_duration = todo_task.keyval.get("duration", "0")
158
+ todo_task.keyval["duration"] = add_durations(current_duration, ctx.input.duration)
159
+ print(current_duration, todo_task.keyval)
160
+ # Save todo list
161
+ save_todo_list(todo_file_path, todo_list)
162
+ # Add log work
163
+ log_work_dir = os.path.join(TODO_DIR, "log-work")
164
+ os.makedirs(log_work_dir, exist_ok=True)
165
+ log_work_file_path = os.path.join(
166
+ log_work_dir, f"{todo_task.keyval.get('id')}.json"
167
+ )
168
+ if os.path.isfile(log_work_file_path):
169
+ with open(log_work_file_path, "r") as f:
170
+ log_work_json = f.read()
171
+ else:
172
+ log_work_json = "[]"
173
+ log_work: list[dict[str, Any]] = json.loads(log_work_json)
174
+ log_work.append(
175
+ {"log": ctx.input.log, "duration": ctx.input.duration, "start": ctx.input.start}
176
+ )
177
+ with open(log_work_file_path, "w") as f:
178
+ f.write(json.dumps(log_work, indent=2))
179
+ return get_visual_todo_list(todo_list)
180
+
181
+
182
+ def _get_default_start() -> str:
183
+ return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
184
+
185
+
186
+ @make_task(
187
+ name="todo-edit",
188
+ input=[
189
+ TextInput(
190
+ name="text",
191
+ description="Todo.txt content",
192
+ prompt="Todo.txt content (will override existing)",
193
+ default_str=lambda _: _get_todo_txt_content(),
194
+ ),
195
+ ],
196
+ description="📝 Edit todo",
197
+ group=todo_group,
198
+ alias="edit",
199
+ )
200
+ def todo_edit(ctx: AnyContext):
201
+ todo_list = [
202
+ cascade_todo_task(line_to_todo_task(line))
203
+ for line in ctx.input.text.split("\n")
204
+ if line.strip() != ""
205
+ ]
206
+ new_content = "\n".join(todo_task_to_line(todo_task) for todo_task in todo_list)
207
+ todo_file_path = os.path.join(TODO_DIR, "todo.txt")
208
+ with open(todo_file_path, "w") as f:
209
+ f.write(new_content)
210
+ todo_list = load_todo_list(todo_file_path)
211
+ return get_visual_todo_list(todo_list)
212
+
213
+
214
+ def _get_todo_txt_content() -> str:
215
+ todo_file_path = os.path.join(TODO_DIR, "todo.txt")
216
+ if not os.path.isfile(todo_file_path):
217
+ return ""
218
+ with open(todo_file_path, "r") as f:
219
+ return f.read()
@@ -1,7 +1,7 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from typing import Any
3
3
 
4
- from ..context.any_shared_context import AnySharedContext
4
+ from zrb.context.any_shared_context import AnySharedContext
5
5
 
6
6
 
7
7
  class AnyCallback(ABC):
zrb/callback/callback.py CHANGED
@@ -1,10 +1,10 @@
1
1
  from typing import Any
2
2
 
3
- from ..attr.type import StrDictAttr
4
- from ..session.any_session import AnySession
5
- from ..task.any_task import AnyTask
6
- from ..util.attr import get_str_dict_attr
7
- from .any_callback import AnyCallback
3
+ from zrb.attr.type import StrDictAttr
4
+ from zrb.callback.any_callback import AnyCallback
5
+ from zrb.session.any_session import AnySession
6
+ from zrb.task.any_task import AnyTask
7
+ from zrb.util.attr import get_str_dict_attr
8
8
 
9
9
 
10
10
  class Callback(AnyCallback):
zrb/cmd/cmd_val.py CHANGED
@@ -1,8 +1,8 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from collections.abc import Callable
3
3
 
4
- from ..attr.type import fstring
5
- from ..context.context import Context
4
+ from zrb.attr.type import fstring
5
+ from zrb.context.context import Context
6
6
 
7
7
 
8
8
  class AnyCmdVal(ABC):
zrb/config.py CHANGED
@@ -3,7 +3,7 @@ import logging
3
3
  import os
4
4
  import platform
5
5
 
6
- from .util.string.conversion import to_boolean
6
+ from zrb.util.string.conversion import to_boolean
7
7
 
8
8
 
9
9
  def _get_current_shell() -> str:
@@ -46,15 +46,28 @@ INIT_SCRIPTS = (
46
46
  else []
47
47
  )
48
48
  LOGGING_LEVEL = _get_log_level(os.getenv("ZRB_LOGGING_LEVEL", "WARNING"))
49
- SHOULD_LOAD_BUILTIN = to_boolean(os.getenv("ZRB_SHOULD_LOAD_BUILTIN", "1"))
49
+ LOAD_BUILTIN = to_boolean(os.getenv("ZRB_LOAD_BUILTIN", "1"))
50
50
  ENV_PREFIX = os.getenv("ZRB_ENV", "")
51
- SHOW_ADVERTISEMENT = to_boolean(os.getenv("ZRB_SHOW_ADVERTISEMENT", "1"))
52
51
  SHOW_PROMPT = to_boolean(os.getenv("ZRB_SHOW_PROMPT", "1"))
53
52
  SESSION_LOG_DIR = os.getenv(
54
53
  "ZRB_SESSION_LOG_DIR", os.path.expanduser(os.path.join("~", ".zrb-session"))
55
54
  )
55
+ TODO_DIR = os.getenv("ZRB_TODO_DIR", os.path.expanduser(os.path.join("~", "todo")))
56
56
  VERSION = metadata.version("zrb")
57
57
  WEB_HTTP_PORT = int(os.getenv("ZRB_WEB_HTTP_PORT", "21213"))
58
+ LLM_MODEL = os.getenv("ZRB_LLM_MODEL", "ollama_chat/llama3.1")
59
+ LLM_SYSTEM_PROMPT = os.getenv("ZRB_LLM_SYSTEM_PROMPT", "You are a helpful assistant")
60
+ LLM_HISTORY_FILE = os.getenv(
61
+ "ZRB_LLM_HISTORY_FILE",
62
+ os.path.expanduser(os.path.join("~", ".zrb-llm-history.json")),
63
+ )
64
+ LLM_ALLOW_ACCESS_SHELL = to_boolean(os.getenv("ZRB_LLM_ACCESS_FILE", "1"))
65
+ LLM_ALLOW_ACCESS_WEB = to_boolean(os.getenv("ZRB_LLM_ACCESS_WEB", "1"))
66
+ RAG_EMBEDDING_MODEL = os.getenv("ZRB_RAG_EMBEDDING_MODEL", "ollama/nomic-embed-text")
67
+ RAG_CHUNK_SIZE = int(os.getenv("ZRB_RAG_CHUNK_SIZE", "1024"))
68
+ RAG_OVERLAP = int(os.getenv("ZRB_RAG_OVERLAP", "128"))
69
+ RAG_MAX_RESULT_COUNT = int(os.getenv("ZRB_RAG_MAX_RESULT_COUNT", "5"))
70
+
58
71
 
59
72
  BANNER = f"""
60
73
  bb
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
 
3
- from ..context.any_context import AnyContext
3
+ from zrb.context.any_context import AnyContext
4
4
 
5
5
 
6
6
  class AnyContentTransformer(ABC):
@@ -2,8 +2,8 @@ import fnmatch
2
2
  import re
3
3
  from collections.abc import Callable
4
4
 
5
- from ..context.any_context import AnyContext
6
- from .any_content_transformer import AnyContentTransformer
5
+ from zrb.content_transformer.any_content_transformer import AnyContentTransformer
6
+ from zrb.context.any_context import AnyContext
7
7
 
8
8
 
9
9
  class ContentTransformer(AnyContentTransformer):
@@ -2,7 +2,7 @@ import sys
2
2
  from abc import abstractmethod
3
3
  from typing import TextIO
4
4
 
5
- from .any_shared_context import AnySharedContext
5
+ from zrb.context.any_shared_context import AnySharedContext
6
6
 
7
7
 
8
8
  class AnyContext(AnySharedContext):
@@ -3,11 +3,11 @@ from __future__ import annotations # Enables forward references
3
3
  from abc import ABC, abstractmethod
4
4
  from typing import TYPE_CHECKING, Any
5
5
 
6
- from ..dot_dict.dot_dict import DotDict
7
- from ..xcom.xcom import Xcom
6
+ from zrb.dot_dict.dot_dict import DotDict
7
+ from zrb.xcom.xcom import Xcom
8
8
 
9
9
  if TYPE_CHECKING:
10
- from ..session import any_session
10
+ from zrb.session import any_session
11
11
 
12
12
 
13
13
  class AnySharedContext(ABC):
zrb/context/context.py CHANGED
@@ -4,12 +4,12 @@ import re
4
4
  import sys
5
5
  from typing import Any, TextIO
6
6
 
7
- from ..dot_dict.dot_dict import DotDict
8
- from ..session.any_session import AnySession
9
- from ..util.cli.style import stylize, stylize_error, stylize_log, stylize_warning
10
- from ..util.string.conversion import to_boolean
11
- from .any_context import AnyContext
12
- from .any_shared_context import AnySharedContext
7
+ from zrb.context.any_context import AnyContext
8
+ from zrb.context.any_shared_context import AnySharedContext
9
+ from zrb.dot_dict.dot_dict import DotDict
10
+ from zrb.session.any_session import AnySession
11
+ from zrb.util.cli.style import stylize, stylize_error, stylize_log, stylize_warning
12
+ from zrb.util.string.conversion import to_boolean
13
13
 
14
14
 
15
15
  def _remove_ansi_escape_sequences(text):
@@ -103,14 +103,16 @@ class Context(AnyContext):
103
103
  ):
104
104
  color = self._color
105
105
  icon = self._icon
106
- task_name = self._task_name.rjust(15)
106
+ max_name_length = max(len(name) + len(icon) for name in self.session.task_names)
107
+ styled_task_name = f"{icon} {self._task_name}"
108
+ padded_styled_task_name = styled_task_name.rjust(max_name_length + 1)
107
109
  if self._attempt == 0:
108
110
  attempt_status = "".ljust(5)
109
111
  else:
110
112
  attempt_status = f"{self._attempt}/{self._max_attempt}".ljust(5)
111
113
  now = datetime.datetime.now()
112
114
  formatted_time = now.strftime("%y%m%d %H:%M:%S.%f")[:19]
113
- prefix = f"{formatted_time} {attempt_status} {icon} {task_name} ⬤ "
115
+ prefix = f"{formatted_time} {attempt_status} {padded_styled_task_name} ⬤ "
114
116
  message = sep.join([f"{value}" for value in values])
115
117
  self.append_to_shared_log(_remove_ansi_escape_sequences(f"{prefix} {message}"))
116
118
  stylized_prefix = stylize(prefix, color=color)
@@ -1,10 +1,12 @@
1
1
  import datetime
2
2
  from typing import Any
3
3
 
4
- from ..config import LOGGING_LEVEL
5
- from ..dot_dict.dot_dict import DotDict
6
- from ..session.any_session import AnySession
7
- from ..util.string.conversion import (
4
+ from zrb.config import LOGGING_LEVEL
5
+ from zrb.context.any_shared_context import AnySharedContext
6
+ from zrb.dot_dict.dot_dict import DotDict
7
+ from zrb.session.any_session import AnySession
8
+ from zrb.util.string.conversion import (
9
+ double_quote,
8
10
  to_boolean,
9
11
  to_camel_case,
10
12
  to_human_case,
@@ -12,9 +14,8 @@ from ..util.string.conversion import (
12
14
  to_pascal_case,
13
15
  to_snake_case,
14
16
  )
15
- from ..util.string.format import fstring_format
16
- from ..xcom.xcom import Xcom
17
- from .any_shared_context import AnySharedContext
17
+ from zrb.util.string.format import fstring_format
18
+ from zrb.xcom.xcom import Xcom
18
19
 
19
20
 
20
21
  class SharedContext(AnySharedContext):
@@ -86,12 +87,12 @@ class SharedContext(AnySharedContext):
86
87
  data={
87
88
  "ctx": self,
88
89
  "datetime": datetime,
89
- "Xcom": Xcom,
90
90
  "to_boolean": to_boolean,
91
91
  "to_camel_case": to_camel_case,
92
92
  "to_human_case": to_human_case,
93
93
  "to_kebab_case": to_kebab_case,
94
94
  "to_pascal_case": to_pascal_case,
95
95
  "to_snake_case": to_snake_case,
96
+ "double_quote": double_quote,
96
97
  },
97
98
  )
zrb/env/__init__.py CHANGED
@@ -1,3 +0,0 @@
1
- from .env import Env
2
-
3
- assert Env
zrb/env/any_env.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
 
3
- from ..context.any_shared_context import AnySharedContext
3
+ from zrb.context.any_shared_context import AnySharedContext
4
4
 
5
5
 
6
6
  class AnyEnv(ABC):
zrb/env/env.py CHANGED
@@ -1,10 +1,9 @@
1
1
  import os
2
2
 
3
+ from zrb.attr.type import StrAttr
3
4
  from zrb.context.any_shared_context import AnySharedContext
4
-
5
- from ..attr.type import StrAttr
6
- from ..util.attr import get_str_attr
7
- from .any_env import AnyEnv
5
+ from zrb.env.any_env import AnyEnv
6
+ from zrb.util.attr import get_str_attr
8
7
 
9
8
 
10
9
  class Env(AnyEnv):
zrb/env/env_file.py CHANGED
@@ -1,9 +1,9 @@
1
1
  from dotenv import dotenv_values
2
2
 
3
- from ..attr.type import StrAttr
4
- from ..context.shared_context import SharedContext
5
- from ..util.attr import get_str_attr
6
- from .env_map import EnvMap
3
+ from zrb.attr.type import StrAttr
4
+ from zrb.context.shared_context import SharedContext
5
+ from zrb.env.env_map import EnvMap
6
+ from zrb.util.attr import get_str_attr
7
7
 
8
8
 
9
9
  class EnvFile(EnvMap):