tau-coding-agent 0.1.0__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 (283) hide show
  1. tau/__init__.py +0 -0
  2. tau/agent/__init__.py +11 -0
  3. tau/agent/prompt/__init__.py +10 -0
  4. tau/agent/prompt/builder.py +302 -0
  5. tau/agent/prompt/types.py +33 -0
  6. tau/agent/service.py +369 -0
  7. tau/agent/types.py +61 -0
  8. tau/auth/manager.py +247 -0
  9. tau/auth/storage.py +82 -0
  10. tau/auth/types.py +41 -0
  11. tau/builtins/__init__.py +4 -0
  12. tau/builtins/__pycache__/__init__.cpython-313.pyc +0 -0
  13. tau/builtins/__pycache__/__init__.cpython-314.pyc +0 -0
  14. tau/builtins/commands/__init__.py +41 -0
  15. tau/builtins/commands/__pycache__/__init__.cpython-313.pyc +0 -0
  16. tau/builtins/commands/__pycache__/__init__.cpython-314.pyc +0 -0
  17. tau/builtins/commands/__pycache__/clear.cpython-313.pyc +0 -0
  18. tau/builtins/commands/__pycache__/clear.cpython-314.pyc +0 -0
  19. tau/builtins/commands/__pycache__/compact.cpython-313.pyc +0 -0
  20. tau/builtins/commands/__pycache__/compact.cpython-314.pyc +0 -0
  21. tau/builtins/commands/__pycache__/reload.cpython-313.pyc +0 -0
  22. tau/builtins/commands/__pycache__/reload.cpython-314.pyc +0 -0
  23. tau/builtins/commands/__pycache__/session.cpython-313.pyc +0 -0
  24. tau/builtins/commands/__pycache__/session.cpython-314.pyc +0 -0
  25. tau/builtins/commands/clear.py +16 -0
  26. tau/builtins/commands/compact.py +28 -0
  27. tau/builtins/commands/reload.py +27 -0
  28. tau/builtins/commands/session.py +19 -0
  29. tau/builtins/extensions/footer/__init__.py +76 -0
  30. tau/builtins/extensions/footer/__pycache__/__init__.cpython-313.pyc +0 -0
  31. tau/builtins/extensions/footer/__pycache__/git.cpython-313.pyc +0 -0
  32. tau/builtins/extensions/footer/__pycache__/model.cpython-313.pyc +0 -0
  33. tau/builtins/extensions/footer/__pycache__/utils.cpython-313.pyc +0 -0
  34. tau/builtins/extensions/footer/git.py +26 -0
  35. tau/builtins/extensions/footer/model.py +69 -0
  36. tau/builtins/extensions/footer/utils.py +44 -0
  37. tau/builtins/extensions/header/__init__.py +18 -0
  38. tau/builtins/extensions/header/__pycache__/__init__.cpython-313.pyc +0 -0
  39. tau/builtins/models/__init__.py +0 -0
  40. tau/builtins/models/__pycache__/__init__.cpython-313.pyc +0 -0
  41. tau/builtins/models/__pycache__/text.cpython-313.pyc +0 -0
  42. tau/builtins/models/audio.py +43 -0
  43. tau/builtins/models/image.py +43 -0
  44. tau/builtins/models/text.py +482 -0
  45. tau/builtins/models/video.py +40 -0
  46. tau/builtins/prompts/commit.md +7 -0
  47. tau/builtins/prompts/docs.md +7 -0
  48. tau/builtins/prompts/explain.md +7 -0
  49. tau/builtins/prompts/fix.md +7 -0
  50. tau/builtins/prompts/refactor.md +7 -0
  51. tau/builtins/prompts/review.md +7 -0
  52. tau/builtins/prompts/test.md +7 -0
  53. tau/builtins/providers/__init__.py +0 -0
  54. tau/builtins/providers/__pycache__/__init__.cpython-313.pyc +0 -0
  55. tau/builtins/providers/__pycache__/text.cpython-313.pyc +0 -0
  56. tau/builtins/providers/audio.py +10 -0
  57. tau/builtins/providers/image.py +9 -0
  58. tau/builtins/providers/text.py +33 -0
  59. tau/builtins/providers/video.py +6 -0
  60. tau/builtins/skills/code-review/SKILL.md +4 -0
  61. tau/builtins/skills/debug/SKILL.md +4 -0
  62. tau/builtins/skills/git-commit/SKILL.md +4 -0
  63. tau/builtins/themes/dark.yaml +1 -0
  64. tau/builtins/themes/light.yaml +46 -0
  65. tau/builtins/tools/__init__.py +73 -0
  66. tau/builtins/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  67. tau/builtins/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  68. tau/builtins/tools/__pycache__/bash.cpython-313.pyc +0 -0
  69. tau/builtins/tools/__pycache__/bash.cpython-314.pyc +0 -0
  70. tau/builtins/tools/__pycache__/edit.cpython-313.pyc +0 -0
  71. tau/builtins/tools/__pycache__/edit.cpython-314.pyc +0 -0
  72. tau/builtins/tools/__pycache__/glob.cpython-313.pyc +0 -0
  73. tau/builtins/tools/__pycache__/glob.cpython-314.pyc +0 -0
  74. tau/builtins/tools/__pycache__/grep.cpython-313.pyc +0 -0
  75. tau/builtins/tools/__pycache__/grep.cpython-314.pyc +0 -0
  76. tau/builtins/tools/__pycache__/ls.cpython-313.pyc +0 -0
  77. tau/builtins/tools/__pycache__/ls.cpython-314.pyc +0 -0
  78. tau/builtins/tools/__pycache__/read.cpython-313.pyc +0 -0
  79. tau/builtins/tools/__pycache__/read.cpython-314.pyc +0 -0
  80. tau/builtins/tools/__pycache__/terminal.cpython-313.pyc +0 -0
  81. tau/builtins/tools/__pycache__/terminal.cpython-314.pyc +0 -0
  82. tau/builtins/tools/__pycache__/write.cpython-313.pyc +0 -0
  83. tau/builtins/tools/__pycache__/write.cpython-314.pyc +0 -0
  84. tau/builtins/tools/edit.py +215 -0
  85. tau/builtins/tools/glob.py +112 -0
  86. tau/builtins/tools/grep.py +146 -0
  87. tau/builtins/tools/ls.py +135 -0
  88. tau/builtins/tools/read.py +122 -0
  89. tau/builtins/tools/terminal.py +150 -0
  90. tau/builtins/tools/write.py +105 -0
  91. tau/commands/__init__.py +10 -0
  92. tau/commands/registry.py +71 -0
  93. tau/commands/types.py +33 -0
  94. tau/console/__init__.py +0 -0
  95. tau/console/cli.py +266 -0
  96. tau/console/commands/__init__.py +0 -0
  97. tau/console/commands/auth.py +193 -0
  98. tau/console/commands/packages.py +104 -0
  99. tau/console/commands/update.py +76 -0
  100. tau/core/__init__.py +0 -0
  101. tau/core/registry.py +102 -0
  102. tau/engine/__init__.py +47 -0
  103. tau/engine/service.py +768 -0
  104. tau/engine/types.py +163 -0
  105. tau/extensions/__init__.py +28 -0
  106. tau/extensions/api.py +928 -0
  107. tau/extensions/context.py +462 -0
  108. tau/extensions/events.py +70 -0
  109. tau/extensions/loader.py +386 -0
  110. tau/extensions/runtime.py +184 -0
  111. tau/extensions/settings.py +137 -0
  112. tau/hooks/__init__.py +112 -0
  113. tau/hooks/engine.py +237 -0
  114. tau/hooks/inference.py +21 -0
  115. tau/hooks/runtime.py +126 -0
  116. tau/hooks/service.py +121 -0
  117. tau/hooks/session.py +117 -0
  118. tau/hooks/tui.py +61 -0
  119. tau/hooks/types.py +72 -0
  120. tau/inference/__init__.py +180 -0
  121. tau/inference/api/__init__.py +0 -0
  122. tau/inference/api/audio/__init__.py +0 -0
  123. tau/inference/api/audio/base.py +29 -0
  124. tau/inference/api/audio/builtins.py +15 -0
  125. tau/inference/api/audio/elevenlabs_audio.py +183 -0
  126. tau/inference/api/audio/gemini_audio.py +95 -0
  127. tau/inference/api/audio/openai_audio.py +159 -0
  128. tau/inference/api/audio/registry.py +15 -0
  129. tau/inference/api/audio/sarvam_audio.py +163 -0
  130. tau/inference/api/audio/service.py +103 -0
  131. tau/inference/api/audio/utils.py +47 -0
  132. tau/inference/api/image/__init__.py +0 -0
  133. tau/inference/api/image/base.py +17 -0
  134. tau/inference/api/image/builtins.py +8 -0
  135. tau/inference/api/image/gemini_image.py +77 -0
  136. tau/inference/api/image/openai_image.py +103 -0
  137. tau/inference/api/image/openrouter.py +144 -0
  138. tau/inference/api/image/registry.py +15 -0
  139. tau/inference/api/image/service.py +71 -0
  140. tau/inference/api/registry.py +82 -0
  141. tau/inference/api/text/__init__.py +0 -0
  142. tau/inference/api/text/anthropic_claude_code.py +222 -0
  143. tau/inference/api/text/anthropic_messages.py +196 -0
  144. tau/inference/api/text/base.py +40 -0
  145. tau/inference/api/text/builtins.py +19 -0
  146. tau/inference/api/text/gemini_generate.py +234 -0
  147. tau/inference/api/text/github_copilot_chat.py +172 -0
  148. tau/inference/api/text/google_antigravity.py +522 -0
  149. tau/inference/api/text/mistral_chat.py +284 -0
  150. tau/inference/api/text/ollama_chat.py +200 -0
  151. tau/inference/api/text/openai_codex_responses.py +497 -0
  152. tau/inference/api/text/openai_completions.py +227 -0
  153. tau/inference/api/text/openai_responses.py +235 -0
  154. tau/inference/api/text/registry.py +50 -0
  155. tau/inference/api/text/service.py +297 -0
  156. tau/inference/api/text/types.py +7 -0
  157. tau/inference/api/text/utils.py +228 -0
  158. tau/inference/api/video/__init__.py +0 -0
  159. tau/inference/api/video/base.py +26 -0
  160. tau/inference/api/video/builtins.py +7 -0
  161. tau/inference/api/video/fal_video.py +119 -0
  162. tau/inference/api/video/openrouter_video.py +142 -0
  163. tau/inference/api/video/registry.py +15 -0
  164. tau/inference/api/video/service.py +72 -0
  165. tau/inference/model/__init__.py +0 -0
  166. tau/inference/model/registry.py +102 -0
  167. tau/inference/model/types.py +65 -0
  168. tau/inference/provider/__init__.py +0 -0
  169. tau/inference/provider/oauth/__init__.py +35 -0
  170. tau/inference/provider/oauth/anthropic_claude_code.py +286 -0
  171. tau/inference/provider/oauth/github_copilot.py +333 -0
  172. tau/inference/provider/oauth/google_antigravity.py +258 -0
  173. tau/inference/provider/oauth/openai_codex.py +309 -0
  174. tau/inference/provider/oauth/pkce.py +14 -0
  175. tau/inference/provider/oauth/types.py +46 -0
  176. tau/inference/provider/oauth/utils.py +154 -0
  177. tau/inference/provider/registry.py +141 -0
  178. tau/inference/provider/types.py +114 -0
  179. tau/inference/types.py +549 -0
  180. tau/inference/utils.py +219 -0
  181. tau/message/__init__.py +0 -0
  182. tau/message/types.py +482 -0
  183. tau/message/utils.py +178 -0
  184. tau/packages/__init__.py +11 -0
  185. tau/packages/manager.py +190 -0
  186. tau/packages/types.py +20 -0
  187. tau/packages/utils.py +67 -0
  188. tau/prompts/expand.py +58 -0
  189. tau/prompts/loader.py +69 -0
  190. tau/prompts/registry.py +45 -0
  191. tau/prompts/types.py +24 -0
  192. tau/rpc/__init__.py +8 -0
  193. tau/rpc/mode.py +783 -0
  194. tau/rpc/types.py +252 -0
  195. tau/runtime/service.py +759 -0
  196. tau/runtime/types.py +303 -0
  197. tau/session/branch_summarization.py +312 -0
  198. tau/session/compaction.py +646 -0
  199. tau/session/manager.py +652 -0
  200. tau/session/types.py +188 -0
  201. tau/session/utils.py +233 -0
  202. tau/settings/manager.py +1077 -0
  203. tau/settings/paths.py +150 -0
  204. tau/settings/storage.py +63 -0
  205. tau/settings/types.py +173 -0
  206. tau/settings/utils.py +25 -0
  207. tau/skills/loader.py +91 -0
  208. tau/skills/registry.py +70 -0
  209. tau/skills/types.py +25 -0
  210. tau/themes/loader.py +238 -0
  211. tau/themes/registry.py +108 -0
  212. tau/themes/types.py +19 -0
  213. tau/tool/__init__.py +3 -0
  214. tau/tool/registry.py +117 -0
  215. tau/tool/render.py +21 -0
  216. tau/tool/types.py +244 -0
  217. tau/trust/__init__.py +13 -0
  218. tau/trust/manager.py +80 -0
  219. tau/trust/types.py +14 -0
  220. tau/trust/utils.py +72 -0
  221. tau/tui/__init__.py +54 -0
  222. tau/tui/agent_hooks.py +346 -0
  223. tau/tui/ansi.py +330 -0
  224. tau/tui/app.py +540 -0
  225. tau/tui/autocomplete.py +33 -0
  226. tau/tui/capabilities.py +119 -0
  227. tau/tui/commands/__init__.py +3 -0
  228. tau/tui/commands/appearance.py +498 -0
  229. tau/tui/commands/auth.py +232 -0
  230. tau/tui/commands/context.py +38 -0
  231. tau/tui/commands/misc.py +82 -0
  232. tau/tui/commands/model.py +118 -0
  233. tau/tui/commands/session.py +464 -0
  234. tau/tui/component.py +268 -0
  235. tau/tui/components/__init__.py +0 -0
  236. tau/tui/components/autocomplete_manager.py +267 -0
  237. tau/tui/components/autocomplete_picker.py +143 -0
  238. tau/tui/components/box.py +90 -0
  239. tau/tui/components/command_palette.py +144 -0
  240. tau/tui/components/dynamic_border.py +19 -0
  241. tau/tui/components/file_picker.py +233 -0
  242. tau/tui/components/image.py +181 -0
  243. tau/tui/components/inline_selector.py +71 -0
  244. tau/tui/components/layout.py +1194 -0
  245. tau/tui/components/message_list.py +692 -0
  246. tau/tui/components/modal.py +97 -0
  247. tau/tui/components/model_palette.py +204 -0
  248. tau/tui/components/picker_overlay.py +174 -0
  249. tau/tui/components/prompt_overlay.py +236 -0
  250. tau/tui/components/resume_modal.py +372 -0
  251. tau/tui/components/select_list.py +222 -0
  252. tau/tui/components/settings_modal.py +274 -0
  253. tau/tui/components/settings_schema.py +203 -0
  254. tau/tui/components/spinner.py +119 -0
  255. tau/tui/components/text_input.py +396 -0
  256. tau/tui/components/text_prompt.py +82 -0
  257. tau/tui/components/tree_select_list.py +580 -0
  258. tau/tui/components/trust_screen.py +97 -0
  259. tau/tui/diff.py +114 -0
  260. tau/tui/fuzzy.py +99 -0
  261. tau/tui/input.py +496 -0
  262. tau/tui/input_handler.py +716 -0
  263. tau/tui/keybindings.py +87 -0
  264. tau/tui/markdown.py +286 -0
  265. tau/tui/message_renderers.py +31 -0
  266. tau/tui/overlay.py +326 -0
  267. tau/tui/renderer.py +378 -0
  268. tau/tui/terminal.py +499 -0
  269. tau/tui/theme.py +148 -0
  270. tau/tui/tui.py +544 -0
  271. tau/tui/ui_context.py +768 -0
  272. tau/tui/utils.py +20 -0
  273. tau/utils/__init__.py +0 -0
  274. tau/utils/http_proxy.py +221 -0
  275. tau/utils/image_processing.py +172 -0
  276. tau/utils/secrets.py +59 -0
  277. tau/utils/version_check.py +60 -0
  278. tau_coding_agent-0.1.0.dist-info/METADATA +177 -0
  279. tau_coding_agent-0.1.0.dist-info/RECORD +283 -0
  280. tau_coding_agent-0.1.0.dist-info/WHEEL +5 -0
  281. tau_coding_agent-0.1.0.dist-info/entry_points.txt +2 -0
  282. tau_coding_agent-0.1.0.dist-info/licenses/LICENSE +21 -0
  283. tau_coding_agent-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,104 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+
6
+ import click
7
+
8
+
9
+ @click.command("install")
10
+ @click.argument("source")
11
+ @click.option("--local", is_flag=True, default=False,
12
+ help="Install to project scope (.tau/venv/) instead of global (~/.tau/venv/).")
13
+ def install(source: str, local: bool) -> None:
14
+ """Install a package as a tau extension source.
15
+
16
+ SOURCE formats:
17
+ pypi:name install latest from PyPI
18
+ pypi:name@1.2.3 install pinned version
19
+ git+https://... install from a git URL
20
+ ./path or /path install from a local directory
21
+ """
22
+ from tau.packages.manager import PackageManager
23
+ from tau.settings.manager import SettingsManager
24
+ from tau.settings.paths import get_packages_venv
25
+
26
+ cwd = Path.cwd()
27
+ venv_dir = get_packages_venv(cwd) if local else get_packages_venv()
28
+ pkg_manager = PackageManager(venv_dir)
29
+
30
+ click.echo(f"Installing {source}…")
31
+ try:
32
+ entry = pkg_manager.install(source)
33
+ except Exception as e:
34
+ raise click.ClickException(str(e))
35
+
36
+ settings = SettingsManager.create(cwd)
37
+ settings.add_package(entry, local=local)
38
+ asyncio.run(settings.flush())
39
+
40
+ v = f"@{entry.version}" if entry.version else ""
41
+ scope = "project" if local else "global"
42
+ click.echo(click.style(f"✓ Installed {entry.name}{v} ({scope})", fg="green"))
43
+
44
+
45
+ @click.command("remove")
46
+ @click.argument("name")
47
+ @click.option("--local", is_flag=True, default=False,
48
+ help="Remove from project scope instead of global.")
49
+ def remove(name: str, local: bool) -> None:
50
+ """Remove an installed package by NAME."""
51
+ from tau.packages.manager import PackageManager
52
+ from tau.settings.manager import SettingsManager
53
+ from tau.settings.paths import get_packages_venv
54
+
55
+ cwd = Path.cwd()
56
+ venv_dir = get_packages_venv(cwd) if local else get_packages_venv()
57
+ pkg_manager = PackageManager(venv_dir)
58
+
59
+ click.echo(f"Removing {name}…")
60
+ try:
61
+ pkg_manager.remove(name)
62
+ except Exception as e:
63
+ raise click.ClickException(str(e))
64
+
65
+ settings = SettingsManager.create(cwd)
66
+ settings.remove_package(name, local=local)
67
+ asyncio.run(settings.flush())
68
+
69
+ click.echo(click.style(f"✓ Removed {name}", fg="green"))
70
+
71
+
72
+
73
+ @click.command("list")
74
+ @click.option("--local", is_flag=True, default=False,
75
+ help="Show project-scoped packages only.")
76
+ @click.option("--all", "show_all", is_flag=True, default=False,
77
+ help="Show both global and project packages.")
78
+ def list_packages(local: bool, show_all: bool) -> None:
79
+ """List installed packages."""
80
+ from tau.settings.manager import SettingsManager
81
+
82
+ cwd = Path.cwd()
83
+ settings = SettingsManager.create(cwd)
84
+
85
+ if show_all:
86
+ packages = settings.get_all_packages()
87
+ header = "Installed packages (global + project)"
88
+ elif local:
89
+ packages = settings.get_packages(local=True)
90
+ header = "Installed packages (project)"
91
+ else:
92
+ packages = settings.get_packages(local=False)
93
+ header = "Installed packages (global)"
94
+
95
+ if not packages:
96
+ click.echo("No packages installed.")
97
+ return
98
+
99
+ click.echo(f"{header}:\n")
100
+ for pkg in packages:
101
+ v = f" {pkg.version}" if pkg.version else ""
102
+ status = click.style(" [disabled]", fg="bright_black") if not pkg.enabled else ""
103
+ source = click.style(f" ({pkg.source})", fg="bright_black")
104
+ click.echo(f" {pkg.name}{v}{status}{source}")
@@ -0,0 +1,76 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ import click
8
+
9
+
10
+ @click.command("update")
11
+ @click.argument("name", required=False, default=None)
12
+ @click.option("--local", is_flag=True, default=False,
13
+ help="Update in project scope instead of global.")
14
+ def update(name: str | None, local: bool) -> None:
15
+ """Update tau itself, or update an extension package by NAME."""
16
+ if name is None:
17
+ _update_tau()
18
+ return
19
+
20
+ from tau.packages.manager import PackageManager
21
+ from tau.settings.manager import SettingsManager
22
+ from tau.settings.paths import get_packages_venv
23
+
24
+ cwd = Path.cwd()
25
+ venv_dir = get_packages_venv(cwd) if local else get_packages_venv()
26
+ pkg_manager = PackageManager(venv_dir)
27
+ settings = SettingsManager.create(cwd)
28
+
29
+ packages = settings.get_packages(local=local)
30
+ targets = [p for p in packages if p.name == name]
31
+
32
+ if not targets:
33
+ raise click.ClickException(f"Package '{name}' not found.")
34
+
35
+ for pkg in targets:
36
+ click.echo(f"Updating {pkg.name}…")
37
+ try:
38
+ new_version = pkg_manager.update(pkg.name)
39
+ settings.update_package_version(pkg.name, new_version, local=local)
40
+ arrow = f" → {new_version}" if new_version else ""
41
+ click.echo(click.style(f"✓ Updated {pkg.name}{arrow}", fg="green"))
42
+ except Exception as e:
43
+ click.echo(click.style(f"✗ {pkg.name}: {e}", fg="red"))
44
+
45
+ asyncio.run(settings.flush())
46
+
47
+
48
+ def _update_tau() -> None:
49
+ """Upgrade tau itself using whichever installer manages this install."""
50
+ import os
51
+ import shutil
52
+ import subprocess
53
+ from tau.settings.paths import get_app_name, get_package_name
54
+
55
+ app = get_package_name()
56
+ click.echo(f"Updating {get_app_name()}…")
57
+
58
+ # Pick the upgrade tool that matches how this copy was installed, inferred
59
+ # from the venv it runs in, so we upgrade the right managed environment.
60
+ prefix = sys.prefix.replace(os.sep, "/")
61
+ if "/pipx/" in prefix and shutil.which("pipx"):
62
+ cmd = ["pipx", "upgrade", app]
63
+ elif "/uv/tools/" in prefix and shutil.which("uv"):
64
+ cmd = ["uv", "tool", "upgrade", app]
65
+ elif shutil.which("uv"):
66
+ cmd = ["uv", "tool", "upgrade", app]
67
+ elif shutil.which("pipx"):
68
+ cmd = ["pipx", "upgrade", app]
69
+ else:
70
+ cmd = [sys.executable, "-m", "pip", "install", "--upgrade", app]
71
+
72
+ result = subprocess.run(cmd, capture_output=True, text=True)
73
+ if result.returncode == 0:
74
+ click.echo(click.style(f"✓ {get_app_name()} updated successfully", fg="green"))
75
+ else:
76
+ raise click.ClickException(result.stderr.strip() or "Update failed.")
tau/core/__init__.py ADDED
File without changes
tau/core/registry.py ADDED
@@ -0,0 +1,102 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from pathlib import Path
5
+ from typing import Any, Generic, TypeVar
6
+
7
+ T = TypeVar("T")
8
+ E = TypeVar("E")
9
+
10
+
11
+ class Registry(ABC, Generic[T, E]):
12
+ """
13
+ Base for lazy-loaded 3-tier content registries (prompts, skills).
14
+
15
+ Load priority (highest wins): project → global → builtin.
16
+ Subclasses supply the loader, dir resolver, and result accessors.
17
+ """
18
+
19
+ def __init__(self) -> None:
20
+ self._registry: dict[str, T] = {}
21
+ self._builtins_loaded = False
22
+
23
+ # ── Abstract interface ────────────────────────────────────────────────────
24
+
25
+ @abstractmethod
26
+ def _load_from_dir(self, path: Path) -> Any:
27
+ """Load items from *path*; returns a result object with errors and items."""
28
+
29
+ @abstractmethod
30
+ def _get_dir(self, cwd: Path | None = None) -> Path:
31
+ """Return the global (or *cwd*-scoped) config directory for this type."""
32
+
33
+ @abstractmethod
34
+ def _builtins_subdir(self) -> str:
35
+ """Subdirectory name under the builtins root (e.g. 'prompts', 'skills')."""
36
+
37
+ @abstractmethod
38
+ def _extract_items(self, result: Any) -> dict[str, T]:
39
+ """Pull the name→item mapping out of a load result."""
40
+
41
+ @abstractmethod
42
+ def _extract_errors(self, result: Any) -> list[E]:
43
+ """Pull the error list out of a load result."""
44
+
45
+ def _item_key(self, item: T) -> str:
46
+ return getattr(item, "name").lower()
47
+
48
+ # ── Shared implementation ─────────────────────────────────────────────────
49
+
50
+ def _ensure_builtins(self) -> None:
51
+ if self._builtins_loaded:
52
+ return
53
+ from tau.settings.paths import get_builtins_dir
54
+ _dir = get_builtins_dir() / self._builtins_subdir()
55
+ for item in self._extract_items(self._load_from_dir(_dir)).values():
56
+ self._registry[self._item_key(item)] = item
57
+ self._builtins_loaded = True
58
+
59
+ def reload(
60
+ self,
61
+ cwd: Path | None = None,
62
+ extra_paths: list[str] | None = None,
63
+ ) -> list[E]:
64
+ """Clear and reload builtins + external from scratch."""
65
+ self._registry.clear()
66
+ self._builtins_loaded = False
67
+ errors = self.load_external(cwd)
68
+ for p in (extra_paths or []):
69
+ r = self._load_from_dir(Path(p))
70
+ errors.extend(self._extract_errors(r))
71
+ self._registry.update(self._extract_items(r))
72
+ return errors
73
+
74
+ def load_external(self, cwd: Path | None = None) -> list[E]:
75
+ """Load from global and optional project-specific directories."""
76
+ self._ensure_builtins()
77
+ errors: list[E] = []
78
+ g = self._load_from_dir(self._get_dir())
79
+ errors.extend(self._extract_errors(g))
80
+ self._registry.update(self._extract_items(g))
81
+ if cwd is not None:
82
+ p = self._load_from_dir(self._get_dir(cwd))
83
+ errors.extend(self._extract_errors(p))
84
+ self._registry.update(self._extract_items(p))
85
+ return errors
86
+
87
+ def get(self, name: str) -> T | None:
88
+ self._ensure_builtins()
89
+ return self._registry.get(name.lower())
90
+
91
+ def list(self) -> list[T]:
92
+ self._ensure_builtins()
93
+ return list(self._registry.values())
94
+
95
+ def register(self, item: T) -> None:
96
+ self._registry[self._item_key(item)] = item
97
+
98
+ def unregister(self, name: str) -> None:
99
+ key = name.lower()
100
+ if key not in self._registry:
101
+ raise ValueError(f"{name!r} is not registered.")
102
+ del self._registry[key]
tau/engine/__init__.py ADDED
@@ -0,0 +1,47 @@
1
+ from tau.engine.types import (
2
+ EngineState as AgentState,
3
+ EngineOptions as Options,
4
+ AgentEvent,
5
+ AgentEventType,
6
+ AgentStartEvent,
7
+ AgentEndEvent,
8
+ TurnStartEvent,
9
+ TurnEndEvent,
10
+ MessageStartEvent,
11
+ MessageUpdateEvent,
12
+ MessageEndEvent,
13
+ ToolExecutionStartEvent,
14
+ ToolExecutionUpdateEvent,
15
+ ToolExecutionEndEvent,
16
+ AgentErrorEvent,
17
+ SteeringMode,
18
+ FollowupMode,
19
+ FollowupQueue,
20
+ SteeringQueue,
21
+ )
22
+ from tau.tool.types import ToolExecutionMode
23
+ from tau.engine.service import Engine as Agent
24
+
25
+ __all__ = [
26
+ "Agent",
27
+ "AgentState",
28
+ "Options",
29
+ "AgentEvent",
30
+ "AgentEventType",
31
+ "AgentStartEvent",
32
+ "AgentEndEvent",
33
+ "TurnStartEvent",
34
+ "TurnEndEvent",
35
+ "MessageStartEvent",
36
+ "MessageUpdateEvent",
37
+ "MessageEndEvent",
38
+ "ToolExecutionStartEvent",
39
+ "ToolExecutionUpdateEvent",
40
+ "ToolExecutionEndEvent",
41
+ "AgentErrorEvent",
42
+ "ToolExecutionMode",
43
+ "SteeringMode",
44
+ "FollowupMode",
45
+ "FollowupQueue",
46
+ "SteeringQueue",
47
+ ]