indusagi 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 (295) hide show
  1. indusagi/__init__.py +34 -0
  2. indusagi/_internal/__init__.py +5 -0
  3. indusagi/_internal/cancel.py +96 -0
  4. indusagi/_internal/env.py +41 -0
  5. indusagi/agent/__init__.py +249 -0
  6. indusagi/agent/agent.py +1456 -0
  7. indusagi/agent/registry.py +440 -0
  8. indusagi/agent/sessions.py +1328 -0
  9. indusagi/agent/tools.py +518 -0
  10. indusagi/ai/__init__.py +288 -0
  11. indusagi/ai/env_keys.py +275 -0
  12. indusagi/ai/events.py +401 -0
  13. indusagi/ai/registry.py +647 -0
  14. indusagi/ai/stream.py +1057 -0
  15. indusagi/ai/types.py +866 -0
  16. indusagi/capabilities/__init__.py +127 -0
  17. indusagi/capabilities/backends/__init__.py +22 -0
  18. indusagi/capabilities/backends/local.py +658 -0
  19. indusagi/capabilities/files/__init__.py +32 -0
  20. indusagi/capabilities/files/diff.py +292 -0
  21. indusagi/capabilities/files/edit.py +292 -0
  22. indusagi/capabilities/files/ls.py +284 -0
  23. indusagi/capabilities/files/read.py +266 -0
  24. indusagi/capabilities/files/write.py +129 -0
  25. indusagi/capabilities/kernel/__init__.py +87 -0
  26. indusagi/capabilities/kernel/backends.py +180 -0
  27. indusagi/capabilities/kernel/context.py +94 -0
  28. indusagi/capabilities/kernel/output.py +131 -0
  29. indusagi/capabilities/kernel/registry.py +163 -0
  30. indusagi/capabilities/kernel/spec.py +299 -0
  31. indusagi/capabilities/planning/__init__.py +30 -0
  32. indusagi/capabilities/planning/todo.py +302 -0
  33. indusagi/capabilities/registry.py +134 -0
  34. indusagi/capabilities/search/__init__.py +16 -0
  35. indusagi/capabilities/search/find.py +301 -0
  36. indusagi/capabilities/search/grep.py +360 -0
  37. indusagi/capabilities/shell/__init__.py +23 -0
  38. indusagi/capabilities/shell/bash.py +212 -0
  39. indusagi/capabilities/shell/process.py +543 -0
  40. indusagi/capabilities/web/__init__.py +16 -0
  41. indusagi/capabilities/web/webfetch.py +477 -0
  42. indusagi/capabilities/web/websearch.py +371 -0
  43. indusagi/connectors/__init__.py +76 -0
  44. indusagi/connectors/adapter/__init__.py +20 -0
  45. indusagi/connectors/adapter/composio_backend.py +407 -0
  46. indusagi/connectors/control/__init__.py +60 -0
  47. indusagi/connectors/control/connect.py +269 -0
  48. indusagi/connectors/control/tools.py +343 -0
  49. indusagi/connectors/core/__init__.py +78 -0
  50. indusagi/connectors/core/builder.py +346 -0
  51. indusagi/connectors/core/cache.py +129 -0
  52. indusagi/connectors/core/port.py +210 -0
  53. indusagi/connectors/core/scope_planner.py +130 -0
  54. indusagi/connectors/gateway.py +477 -0
  55. indusagi/connectors/render/__init__.py +50 -0
  56. indusagi/connectors/render/format.py +135 -0
  57. indusagi/connectors/render/summarizers.py +229 -0
  58. indusagi/interop/__init__.py +95 -0
  59. indusagi/interop/protocol_bridge/__init__.py +81 -0
  60. indusagi/interop/protocol_bridge/bridge.py +248 -0
  61. indusagi/interop/protocol_bridge/contract.py +378 -0
  62. indusagi/interop/protocol_bridge/endpoint.py +486 -0
  63. indusagi/interop/protocol_bridge/fleet.py +166 -0
  64. indusagi/interop/protocol_bridge/host.py +205 -0
  65. indusagi/interop/protocol_bridge/schema.py +218 -0
  66. indusagi/llmgateway/__init__.py +137 -0
  67. indusagi/llmgateway/catalog/__init__.py +41 -0
  68. indusagi/llmgateway/catalog/bridge.py +163 -0
  69. indusagi/llmgateway/catalog/cards.py +463 -0
  70. indusagi/llmgateway/catalog/cost.py +35 -0
  71. indusagi/llmgateway/catalog/fallback.py +265 -0
  72. indusagi/llmgateway/catalog/full.py +254 -0
  73. indusagi/llmgateway/catalog/models_data.json +16806 -0
  74. indusagi/llmgateway/catalog/query.py +101 -0
  75. indusagi/llmgateway/connectors/__init__.py +72 -0
  76. indusagi/llmgateway/connectors/anthropic.py +454 -0
  77. indusagi/llmgateway/connectors/azure_openai.py +206 -0
  78. indusagi/llmgateway/connectors/bedrock.py +577 -0
  79. indusagi/llmgateway/connectors/google.py +444 -0
  80. indusagi/llmgateway/connectors/google_vertex.py +541 -0
  81. indusagi/llmgateway/connectors/kimi.py +165 -0
  82. indusagi/llmgateway/connectors/mock.py +212 -0
  83. indusagi/llmgateway/connectors/nvidia.py +175 -0
  84. indusagi/llmgateway/connectors/ollama.py +447 -0
  85. indusagi/llmgateway/connectors/openai_chat.py +164 -0
  86. indusagi/llmgateway/connectors/openai_responses.py +500 -0
  87. indusagi/llmgateway/contract/__init__.py +91 -0
  88. indusagi/llmgateway/contract/connector.py +62 -0
  89. indusagi/llmgateway/contract/conversation.py +138 -0
  90. indusagi/llmgateway/contract/emission.py +99 -0
  91. indusagi/llmgateway/contract/errors.py +85 -0
  92. indusagi/llmgateway/contract/model_card.py +95 -0
  93. indusagi/llmgateway/contract/options.py +40 -0
  94. indusagi/llmgateway/contract/reply.py +51 -0
  95. indusagi/llmgateway/conversion/mappers.py +515 -0
  96. indusagi/llmgateway/conversion/openai_compatible.py +386 -0
  97. indusagi/llmgateway/conversion/reduce.py +144 -0
  98. indusagi/llmgateway/credentials/__init__.py +67 -0
  99. indusagi/llmgateway/credentials/oauth.py +226 -0
  100. indusagi/llmgateway/credentials/pkce.py +95 -0
  101. indusagi/llmgateway/credentials/secrets.py +206 -0
  102. indusagi/llmgateway/gateway.py +93 -0
  103. indusagi/llmgateway/streaming/__init__.py +19 -0
  104. indusagi/llmgateway/streaming/channel.py +77 -0
  105. indusagi/llmgateway/streaming/ndjson.py +144 -0
  106. indusagi/llmgateway/streaming/sse.py +229 -0
  107. indusagi/mcp/__init__.py +174 -0
  108. indusagi/mcp/client.py +2135 -0
  109. indusagi/memory.py +17 -0
  110. indusagi/py.typed +0 -0
  111. indusagi/react_host/__init__.py +199 -0
  112. indusagi/react_ink/__init__.py +617 -0
  113. indusagi/react_ink/components/__init__.py +56 -0
  114. indusagi/react_ink/components/changelog.py +187 -0
  115. indusagi/react_ink/components/dialogs/__init__.py +103 -0
  116. indusagi/react_ink/components/dialogs/frame.py +159 -0
  117. indusagi/react_ink/components/dialogs/login.py +285 -0
  118. indusagi/react_ink/components/dialogs/model.py +100 -0
  119. indusagi/react_ink/components/dialogs/oauth.py +320 -0
  120. indusagi/react_ink/components/dialogs/scoped_models.py +312 -0
  121. indusagi/react_ink/components/dialogs/selectable.py +370 -0
  122. indusagi/react_ink/components/dialogs/session.py +543 -0
  123. indusagi/react_ink/components/dialogs/settings.py +212 -0
  124. indusagi/react_ink/components/dialogs/startup_picker.py +302 -0
  125. indusagi/react_ink/components/dialogs/theme.py +130 -0
  126. indusagi/react_ink/components/dialogs/tree.py +153 -0
  127. indusagi/react_ink/components/dialogs/user_message.py +193 -0
  128. indusagi/react_ink/components/display_block.py +119 -0
  129. indusagi/react_ink/components/editor.py +722 -0
  130. indusagi/react_ink/components/footer.py +325 -0
  131. indusagi/react_ink/components/messages/__init__.py +44 -0
  132. indusagi/react_ink/components/messages/assistant.py +218 -0
  133. indusagi/react_ink/components/messages/bash.py +109 -0
  134. indusagi/react_ink/components/messages/branch_summary.py +74 -0
  135. indusagi/react_ink/components/messages/compaction.py +75 -0
  136. indusagi/react_ink/components/messages/custom.py +92 -0
  137. indusagi/react_ink/components/messages/list.py +329 -0
  138. indusagi/react_ink/components/messages/row.py +117 -0
  139. indusagi/react_ink/components/messages/skill_invocation.py +105 -0
  140. indusagi/react_ink/components/messages/tool_call.py +56 -0
  141. indusagi/react_ink/components/messages/tool_result.py +142 -0
  142. indusagi/react_ink/components/messages/user.py +90 -0
  143. indusagi/react_ink/components/status_line.py +129 -0
  144. indusagi/react_ink/components/task_panel.py +344 -0
  145. indusagi/react_ink/components/tool_event.py +284 -0
  146. indusagi/react_ink/diff/__init__.py +28 -0
  147. indusagi/react_ink/diff/structured.py +333 -0
  148. indusagi/react_ink/diff/view.py +203 -0
  149. indusagi/react_ink/diff/word_diff.py +157 -0
  150. indusagi/react_ink/markdown/__init__.py +75 -0
  151. indusagi/react_ink/markdown/format_token.py +236 -0
  152. indusagi/react_ink/markdown/highlight.py +263 -0
  153. indusagi/react_ink/markdown/streaming.py +130 -0
  154. indusagi/react_ink/markdown/table.py +127 -0
  155. indusagi/react_ink/markdown/view.py +137 -0
  156. indusagi/react_ink/theme_adapter.py +496 -0
  157. indusagi/react_ink/types.py +291 -0
  158. indusagi/react_ink/utils/__init__.py +92 -0
  159. indusagi/react_ink/utils/message_groups.py +436 -0
  160. indusagi/react_ink/utils/selection_dialog.py +40 -0
  161. indusagi/react_ink/utils/session_browser.py +322 -0
  162. indusagi/react_ink/utils/tool_display.py +679 -0
  163. indusagi/runtime/__init__.py +74 -0
  164. indusagi/runtime/cadence/__init__.py +36 -0
  165. indusagi/runtime/cadence/fold.py +192 -0
  166. indusagi/runtime/cadence/reducer.py +439 -0
  167. indusagi/runtime/conductor/__init__.py +17 -0
  168. indusagi/runtime/conductor/agent.py +696 -0
  169. indusagi/runtime/contract/__init__.py +94 -0
  170. indusagi/runtime/contract/config.py +51 -0
  171. indusagi/runtime/contract/effect.py +69 -0
  172. indusagi/runtime/contract/errors.py +45 -0
  173. indusagi/runtime/contract/events.py +100 -0
  174. indusagi/runtime/contract/run_state.py +75 -0
  175. indusagi/runtime/contract/session.py +58 -0
  176. indusagi/runtime/contract/signal.py +88 -0
  177. indusagi/runtime/contract/tools.py +65 -0
  178. indusagi/runtime/dispatch/__init__.py +11 -0
  179. indusagi/runtime/dispatch/scheduler.py +295 -0
  180. indusagi/runtime/ledger/__init__.py +19 -0
  181. indusagi/runtime/ledger/accumulator.py +85 -0
  182. indusagi/runtime/ledger/bus.py +84 -0
  183. indusagi/runtime/memory/__init__.py +23 -0
  184. indusagi/runtime/memory/compactor.py +229 -0
  185. indusagi/runtime/memory/estimate.py +91 -0
  186. indusagi/runtime/store/__init__.py +18 -0
  187. indusagi/runtime/store/dag.py +141 -0
  188. indusagi/runtime/store/hash.py +281 -0
  189. indusagi/runtime/store/persist.py +193 -0
  190. indusagi/runtime/turn/__init__.py +10 -0
  191. indusagi/runtime/turn/driver.py +76 -0
  192. indusagi/runtime/wire/__init__.py +18 -0
  193. indusagi/runtime/wire/projectors.py +119 -0
  194. indusagi/shell_app/__init__.py +115 -0
  195. indusagi/shell_app/auth_cli/__init__.py +16 -0
  196. indusagi/shell_app/auth_cli/oauth_cli.py +723 -0
  197. indusagi/shell_app/boot/__init__.py +34 -0
  198. indusagi/shell_app/boot/context.py +172 -0
  199. indusagi/shell_app/boot/pipeline.py +94 -0
  200. indusagi/shell_app/boot/stages.py +613 -0
  201. indusagi/shell_app/cli.py +404 -0
  202. indusagi/shell_app/config/__init__.py +47 -0
  203. indusagi/shell_app/config/settings.py +327 -0
  204. indusagi/shell_app/invocation/__init__.py +48 -0
  205. indusagi/shell_app/invocation/flags.py +209 -0
  206. indusagi/shell_app/invocation/parse.py +389 -0
  207. indusagi/shell_app/locate/__init__.py +24 -0
  208. indusagi/shell_app/locate/brand.py +130 -0
  209. indusagi/shell_app/locate/locator.py +270 -0
  210. indusagi/shell_app/runners/__init__.py +56 -0
  211. indusagi/shell_app/runners/contract.py +197 -0
  212. indusagi/shell_app/runners/one_shot.py +90 -0
  213. indusagi/shell_app/runners/registry.py +54 -0
  214. indusagi/shell_app/runners/repl.py +240 -0
  215. indusagi/shell_app/runners/wire.py +480 -0
  216. indusagi/shell_app/upgrade/__init__.py +10 -0
  217. indusagi/shell_app/upgrade/upgrades.py +162 -0
  218. indusagi/smithy/__init__.py +165 -0
  219. indusagi/smithy/config/__init__.py +27 -0
  220. indusagi/smithy/config/flag_reader.py +265 -0
  221. indusagi/smithy/forge.py +350 -0
  222. indusagi/smithy/knowledge/__init__.py +25 -0
  223. indusagi/smithy/knowledge/guides/authoring-an-agent.md +53 -0
  224. indusagi/smithy/knowledge/guides/choosing-tools.md +49 -0
  225. indusagi/smithy/knowledge/guides/model-selection.md +51 -0
  226. indusagi/smithy/knowledge/guides/writing-system-prompts.md +53 -0
  227. indusagi/smithy/knowledge/loader.py +227 -0
  228. indusagi/smithy/knowledge/manifest.json +29 -0
  229. indusagi/smithy/persona/__init__.py +52 -0
  230. indusagi/smithy/persona/blueprint.py +265 -0
  231. indusagi/smithy/persona/define_agent.py +178 -0
  232. indusagi/smithy/persona/profiles.py +148 -0
  233. indusagi/smithy/runtime/__init__.py +22 -0
  234. indusagi/smithy/runtime/tool_ledger.py +222 -0
  235. indusagi/smithy/ui/__init__.py +45 -0
  236. indusagi/smithy/ui/transcript.py +578 -0
  237. indusagi/swarm/__init__.py +150 -0
  238. indusagi/swarm/coordinator.py +512 -0
  239. indusagi/swarm/isolation/__init__.py +32 -0
  240. indusagi/swarm/isolation/runner.py +115 -0
  241. indusagi/swarm/isolation/worktree.py +296 -0
  242. indusagi/swarm/kernel/__init__.py +36 -0
  243. indusagi/swarm/kernel/faults.py +91 -0
  244. indusagi/swarm/kernel/ids.py +34 -0
  245. indusagi/swarm/kernel/json_cell.py +378 -0
  246. indusagi/swarm/kernel/jsonl_log.py +197 -0
  247. indusagi/swarm/postbox/__init__.py +38 -0
  248. indusagi/swarm/postbox/channel.py +220 -0
  249. indusagi/swarm/postbox/codecs.py +328 -0
  250. indusagi/swarm/roster/__init__.py +34 -0
  251. indusagi/swarm/roster/manifest.py +370 -0
  252. indusagi/swarm/telemetry/__init__.py +29 -0
  253. indusagi/swarm/telemetry/activity.py +283 -0
  254. indusagi/swarm/workboard/__init__.py +31 -0
  255. indusagi/swarm/workboard/board.py +464 -0
  256. indusagi/swarm/workboard/dep_graph.py +160 -0
  257. indusagi/tracing/__init__.py +46 -0
  258. indusagi/tracing/adapter/__init__.py +11 -0
  259. indusagi/tracing/adapter/runtime_trace.py +196 -0
  260. indusagi/tracing/channel/__init__.py +22 -0
  261. indusagi/tracing/channel/signal.py +145 -0
  262. indusagi/tracing/recorder/__init__.py +19 -0
  263. indusagi/tracing/recorder/recorder.py +137 -0
  264. indusagi/tracing/recorder/sampling.py +112 -0
  265. indusagi/tracing/redaction/__init__.py +20 -0
  266. indusagi/tracing/redaction/secret_scrubber.py +228 -0
  267. indusagi/tracing/registry/__init__.py +9 -0
  268. indusagi/tracing/registry/hub.py +100 -0
  269. indusagi/tracing/signal/__init__.py +50 -0
  270. indusagi/tracing/signal/handle.py +219 -0
  271. indusagi/tracing/signal/segment.py +182 -0
  272. indusagi/tracing/sinks/__init__.py +23 -0
  273. indusagi/tracing/sinks/base.py +89 -0
  274. indusagi/tracing/sinks/console.py +95 -0
  275. indusagi/tracing/sinks/file.py +87 -0
  276. indusagi/tracing/sinks/stream.py +99 -0
  277. indusagi/tui/__init__.py +99 -0
  278. indusagi/tui/autocomplete.py +657 -0
  279. indusagi/tui/contracts.py +140 -0
  280. indusagi/tui/editor.py +1630 -0
  281. indusagi/tui/fuzzy.py +282 -0
  282. indusagi/tui/keybindings.py +412 -0
  283. indusagi/tui/keys.py +1437 -0
  284. indusagi/tui/theme_types.py +75 -0
  285. indusagi/tui/utils.py +1174 -0
  286. indusagi/ui_bridge/__init__.py +118 -0
  287. indusagi/ui_bridge/adapter.py +558 -0
  288. indusagi/ui_bridge/app.py +788 -0
  289. indusagi/ui_bridge/facade_types.py +51 -0
  290. indusagi-0.1.0.dist-info/METADATA +158 -0
  291. indusagi-0.1.0.dist-info/RECORD +295 -0
  292. indusagi-0.1.0.dist-info/WHEEL +4 -0
  293. indusagi-0.1.0.dist-info/entry_points.txt +3 -0
  294. indusagi-0.1.0.dist-info/licenses/CREDITS.md +23 -0
  295. indusagi-0.1.0.dist-info/licenses/NOTICE +17 -0
indusagi/__init__.py ADDED
@@ -0,0 +1,34 @@
1
+ """indusagi — terminal-first AI coding agent framework (Python rebuild)."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version as _version
4
+
5
+ try:
6
+ __version__ = _version("indusagi")
7
+ except PackageNotFoundError: # running from a source tree without install
8
+ __version__ = "0.0.0.dev0"
9
+
10
+ VERSION = __version__
11
+
12
+ _SUBSYSTEMS = {
13
+ "gateway": "llmgateway",
14
+ "runtime": "runtime",
15
+ "capabilities": "capabilities",
16
+ "interop": "interop",
17
+ "saas": "connectors",
18
+ "swarm": "swarm",
19
+ "smithy": "smithy",
20
+ "tracing": "tracing",
21
+ "shell": "shell_app",
22
+ }
23
+
24
+
25
+ def __getattr__(name: str): # PEP 562 lazy namespace re-exports
26
+ if name in _SUBSYSTEMS:
27
+ import importlib
28
+
29
+ return importlib.import_module(f"indusagi.{_SUBSYSTEMS[name]}")
30
+ raise AttributeError(f"module 'indusagi' has no attribute {name!r}")
31
+
32
+
33
+ def __dir__() -> list[str]:
34
+ return sorted([*globals(), *_SUBSYSTEMS])
@@ -0,0 +1,5 @@
1
+ """Framework-internal shared utilities (not part of the public API)."""
2
+
3
+ from indusagi._internal.cancel import CancelledByToken, CancelToken
4
+
5
+ __all__ = ["CancelToken", "CancelledByToken"]
@@ -0,0 +1,96 @@
1
+ """Cooperative cancellation for the indusagi framework.
2
+
3
+ Replaces the Web ``AbortSignal``/``AbortController`` pair from the TypeScript
4
+ implementation: queryable, multi-listener, and chainable. Cancellation is
5
+ cooperative — holders poll :attr:`CancelToken.cancelled` or register
6
+ callbacks; nothing is forcibly killed. This is deliberately NOT raw asyncio
7
+ task cancellation: tools must be able to observe cancellation and still
8
+ return typed ``is_error`` results.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import threading
14
+ from typing import Callable
15
+
16
+ Callback = Callable[[], None]
17
+
18
+
19
+ class CancelledByToken(Exception):
20
+ """Raised by :meth:`CancelToken.raise_if_cancelled`.
21
+
22
+ Distinct from :class:`asyncio.CancelledError` on purpose — framework code
23
+ never swallows ``asyncio.CancelledError``.
24
+ """
25
+
26
+ def __init__(self, reason: str | None = None) -> None:
27
+ super().__init__(reason or "cancelled")
28
+ self.reason = reason
29
+
30
+
31
+ class CancelToken:
32
+ """One-shot cancellation token shared across all subsystems."""
33
+
34
+ __slots__ = ("_cancelled", "_reason", "_callbacks", "_lock")
35
+
36
+ def __init__(self) -> None:
37
+ self._cancelled = False
38
+ self._reason: str | None = None
39
+ self._callbacks: list[Callback] = []
40
+ self._lock = threading.Lock()
41
+
42
+ @property
43
+ def cancelled(self) -> bool:
44
+ return self._cancelled
45
+
46
+ @property
47
+ def reason(self) -> str | None:
48
+ return self._reason
49
+
50
+ def cancel(self, reason: str | None = None) -> None:
51
+ with self._lock:
52
+ if self._cancelled:
53
+ return
54
+ self._cancelled = True
55
+ self._reason = reason
56
+ callbacks = list(self._callbacks)
57
+ self._callbacks.clear()
58
+ for callback in callbacks:
59
+ try:
60
+ callback()
61
+ except Exception:
62
+ pass # listener errors never break cancellation fan-out
63
+
64
+ def add_callback(self, callback: Callback) -> Callable[[], None]:
65
+ """Register ``callback`` to fire on cancellation; returns unsubscribe.
66
+
67
+ Mirrors ``AbortSignal.addEventListener("abort", ...)``: registering on
68
+ an already-cancelled token fires the callback immediately.
69
+ """
70
+ with self._lock:
71
+ if not self._cancelled:
72
+ self._callbacks.append(callback)
73
+
74
+ def unsubscribe() -> None:
75
+ with self._lock:
76
+ try:
77
+ self._callbacks.remove(callback)
78
+ except ValueError:
79
+ pass
80
+
81
+ return unsubscribe
82
+ callback()
83
+ return lambda: None
84
+
85
+ def child(self) -> "CancelToken":
86
+ """A token cancelled when this one is (but not vice versa)."""
87
+ token = CancelToken()
88
+ if self._cancelled:
89
+ token.cancel(self._reason)
90
+ else:
91
+ self.add_callback(lambda: token.cancel(self._reason))
92
+ return token
93
+
94
+ def raise_if_cancelled(self) -> None:
95
+ if self._cancelled:
96
+ raise CancelledByToken(self._reason)
@@ -0,0 +1,41 @@
1
+ """Single environment-variable registry for the framework.
2
+
3
+ Every env var the framework reads is declared and resolved here — subsystems
4
+ must not probe ``os.environ`` directly. (The TS codebase had two competing
5
+ resolution tables; the port has one.)
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import os
11
+ from pathlib import Path
12
+
13
+ ENV_PREFIX = "INDUSAGI"
14
+
15
+
16
+ def env_name(suffix: str) -> str:
17
+ """Compose a branded env-var name: ``env_name("home") -> "INDUSAGI_HOME"``."""
18
+ return f"{ENV_PREFIX}_{suffix.upper().replace('-', '_')}"
19
+
20
+
21
+ def read_env(suffix: str) -> str | None:
22
+ return os.environ.get(env_name(suffix))
23
+
24
+
25
+ def read_raw(name: str) -> str | None:
26
+ """Escape hatch for non-branded variables (e.g. ``AWS_REGION``)."""
27
+ return os.environ.get(name)
28
+
29
+
30
+ def indusagi_home() -> Path:
31
+ """State directory: ``$INDUSAGI_HOME`` or ``~/.pindusagi``.
32
+
33
+ Deliberately separate from the TypeScript builds' state directory
34
+ (owner decision, 2026-06-10): the Python build owns ``~/.pindusagi``
35
+ and never reads or writes the TS installs' state. The auth.json *format*
36
+ remains byte-compatible, but the store is no longer shared.
37
+ """
38
+ override = read_env("HOME")
39
+ if override:
40
+ return Path(override).expanduser()
41
+ return Path.home() / ".pindusagi"
@@ -0,0 +1,249 @@
1
+ """``indusagi.agent`` — the high-level Agent facade (old vocabulary).
2
+
3
+ Mirrors the public surface of ``indus-rebuild/src/facade/agent.ts``
4
+ (→ ``facade/bot/index.ts``) as thin shims over the green core:
5
+
6
+ * :class:`Agent` — prompt / steer / follow_up / wait_for_idle / abort over
7
+ :func:`indusagi.runtime.create_agent`, with events in the facade
8
+ vocabulary (``message_start`` / ``message_update`` / ``message_end``,
9
+ ``tool_execution_*``, ``turn_*``, ``agent_*``).
10
+ * ``create_*_tool`` factories — the facade names over the
11
+ :mod:`indusagi.capabilities` built-ins.
12
+ * :class:`SessionManager` — append-only JSONL session trees, read-compatible
13
+ with real TS v3 session files.
14
+ * :func:`register_message_type` — the explicit registry replacing the TS
15
+ ``CustomAgentMessages`` declaration merging, plus the built-in
16
+ session-only message kinds.
17
+
18
+ The message/content models themselves (``UserMessage``, ``AssistantMessage``,
19
+ ``TextContent``, ...) live in :mod:`indusagi.ai`; this package consumes them
20
+ without re-exporting (matching the TS module layout, where ``bot/`` imports
21
+ from ``ml/`` but ``facade/agent.ts`` re-exports only the bot surface).
22
+
23
+ Usage::
24
+
25
+ from indusagi.agent import Agent, create_coding_tools
26
+
27
+ agent = Agent()
28
+ agent.set_tools(create_coding_tools("/path/to/project"))
29
+ await agent.prompt("explain this repository")
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ # --- agent.ts / types.ts -----------------------------------------------------
35
+ from .agent import (
36
+ AGENT_EVENT_GROUPS,
37
+ Agent,
38
+ AgentContext,
39
+ AgentEndEvent,
40
+ AgentEvent,
41
+ AgentOptions,
42
+ AgentStartEvent,
43
+ AgentState,
44
+ AgentTool,
45
+ AgentToolResult,
46
+ AgentToolUpdateCallback,
47
+ MessageEndEvent,
48
+ MessageStartEvent,
49
+ MessageUpdateEvent,
50
+ QueueMode,
51
+ StreamFn,
52
+ ThinkingBudgets,
53
+ ThinkingLevel,
54
+ ToolExecutionEndEvent,
55
+ ToolExecutionStartEvent,
56
+ ToolExecutionUpdateEvent,
57
+ TurnEndEvent,
58
+ TurnStartEvent,
59
+ is_thinking,
60
+ is_tool_call,
61
+ is_user_message,
62
+ validate_message,
63
+ )
64
+
65
+ # --- messages.ts + the CustomAgentMessages replacement ------------------------
66
+ from .registry import (
67
+ BRANCH_SUMMARY_PREFIX,
68
+ BRANCH_SUMMARY_SUFFIX,
69
+ COMPACTION_SUMMARY_PREFIX,
70
+ COMPACTION_SUMMARY_SUFFIX,
71
+ BashExecutionMessage,
72
+ BranchSummaryMessage,
73
+ CompactionSummaryMessage,
74
+ CustomMessage,
75
+ bash_execution_to_text,
76
+ convert_to_llm,
77
+ create_branch_summary_message,
78
+ create_compaction_summary_message,
79
+ create_custom_message,
80
+ get_message_type,
81
+ register_message_type,
82
+ registered_message_types,
83
+ unregister_message_type,
84
+ )
85
+
86
+ # --- session-manager.ts --------------------------------------------------------
87
+ from .sessions import (
88
+ CURRENT_SESSION_VERSION,
89
+ FileEntry,
90
+ SessionContext,
91
+ SessionEntry,
92
+ SessionHeader,
93
+ SessionInfo,
94
+ SessionListProgress,
95
+ SessionManager,
96
+ SessionTreeNode,
97
+ build_session_context,
98
+ find_most_recent_session,
99
+ get_latest_compaction_entry,
100
+ load_entries_from_file,
101
+ migrate_session_entries,
102
+ parse_session_entries,
103
+ )
104
+
105
+ # --- actions/index.ts (the tool factories + collections) -------------------------
106
+ from .tools import (
107
+ TOOL_METADATA,
108
+ FacadeAgentTool,
109
+ TodoStore,
110
+ ToolCategory,
111
+ ToolMetadata,
112
+ ToolName,
113
+ ToolRegistry,
114
+ all_tools,
115
+ bash_tool,
116
+ coding_tools,
117
+ create_all_tools,
118
+ create_bash_tool,
119
+ create_coding_tools,
120
+ create_edit_tool,
121
+ create_find_tool,
122
+ create_grep_tool,
123
+ create_ls_tool,
124
+ create_process_tool,
125
+ create_read_only_tools,
126
+ create_read_tool,
127
+ create_todo_read_tool,
128
+ create_todo_write_tool,
129
+ create_tool_registry,
130
+ create_web_fetch_tool,
131
+ create_web_search_tool,
132
+ create_write_tool,
133
+ edit_tool,
134
+ find_tool,
135
+ grep_tool,
136
+ ls_tool,
137
+ process_tool,
138
+ read_only_tools,
139
+ read_tool,
140
+ todo_read_tool,
141
+ todo_write_tool,
142
+ web_fetch_tool,
143
+ web_search_tool,
144
+ write_tool,
145
+ )
146
+
147
+ __all__ = [
148
+ # agent.ts / types.ts
149
+ "AGENT_EVENT_GROUPS",
150
+ "Agent",
151
+ "AgentContext",
152
+ "AgentEndEvent",
153
+ "AgentEvent",
154
+ "AgentOptions",
155
+ "AgentStartEvent",
156
+ "AgentState",
157
+ "AgentTool",
158
+ "AgentToolResult",
159
+ "AgentToolUpdateCallback",
160
+ "MessageEndEvent",
161
+ "MessageStartEvent",
162
+ "MessageUpdateEvent",
163
+ "QueueMode",
164
+ "StreamFn",
165
+ "ThinkingBudgets",
166
+ "ThinkingLevel",
167
+ "ToolExecutionEndEvent",
168
+ "ToolExecutionStartEvent",
169
+ "ToolExecutionUpdateEvent",
170
+ "TurnEndEvent",
171
+ "TurnStartEvent",
172
+ "is_thinking",
173
+ "is_tool_call",
174
+ "is_user_message",
175
+ "validate_message",
176
+ # messages.ts / registry
177
+ "BRANCH_SUMMARY_PREFIX",
178
+ "BRANCH_SUMMARY_SUFFIX",
179
+ "COMPACTION_SUMMARY_PREFIX",
180
+ "COMPACTION_SUMMARY_SUFFIX",
181
+ "BashExecutionMessage",
182
+ "BranchSummaryMessage",
183
+ "CompactionSummaryMessage",
184
+ "CustomMessage",
185
+ "bash_execution_to_text",
186
+ "convert_to_llm",
187
+ "create_branch_summary_message",
188
+ "create_compaction_summary_message",
189
+ "create_custom_message",
190
+ "get_message_type",
191
+ "register_message_type",
192
+ "registered_message_types",
193
+ "unregister_message_type",
194
+ # session-manager.ts
195
+ "CURRENT_SESSION_VERSION",
196
+ "FileEntry",
197
+ "SessionContext",
198
+ "SessionEntry",
199
+ "SessionHeader",
200
+ "SessionInfo",
201
+ "SessionListProgress",
202
+ "SessionManager",
203
+ "SessionTreeNode",
204
+ "build_session_context",
205
+ "find_most_recent_session",
206
+ "get_latest_compaction_entry",
207
+ "load_entries_from_file",
208
+ "migrate_session_entries",
209
+ "parse_session_entries",
210
+ # actions/index.ts
211
+ "TOOL_METADATA",
212
+ "FacadeAgentTool",
213
+ "TodoStore",
214
+ "ToolCategory",
215
+ "ToolMetadata",
216
+ "ToolName",
217
+ "ToolRegistry",
218
+ "all_tools",
219
+ "bash_tool",
220
+ "coding_tools",
221
+ "create_all_tools",
222
+ "create_bash_tool",
223
+ "create_coding_tools",
224
+ "create_edit_tool",
225
+ "create_find_tool",
226
+ "create_grep_tool",
227
+ "create_ls_tool",
228
+ "create_process_tool",
229
+ "create_read_only_tools",
230
+ "create_read_tool",
231
+ "create_todo_read_tool",
232
+ "create_todo_write_tool",
233
+ "create_tool_registry",
234
+ "create_web_fetch_tool",
235
+ "create_web_search_tool",
236
+ "create_write_tool",
237
+ "edit_tool",
238
+ "find_tool",
239
+ "grep_tool",
240
+ "ls_tool",
241
+ "process_tool",
242
+ "read_only_tools",
243
+ "read_tool",
244
+ "todo_read_tool",
245
+ "todo_write_tool",
246
+ "web_fetch_tool",
247
+ "web_search_tool",
248
+ "write_tool",
249
+ ]