steerable-sidecar 0.6.0__tar.gz

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 (73) hide show
  1. steerable_sidecar-0.6.0/PKG-INFO +56 -0
  2. steerable_sidecar-0.6.0/README.md +42 -0
  3. steerable_sidecar-0.6.0/pyproject.toml +55 -0
  4. steerable_sidecar-0.6.0/setup.cfg +4 -0
  5. steerable_sidecar-0.6.0/src/steerable_sidecar/__init__.py +28 -0
  6. steerable_sidecar-0.6.0/src/steerable_sidecar/__main__.py +84 -0
  7. steerable_sidecar-0.6.0/src/steerable_sidecar/acp_adapter.py +808 -0
  8. steerable_sidecar-0.6.0/src/steerable_sidecar/acp_fs.py +64 -0
  9. steerable_sidecar-0.6.0/src/steerable_sidecar/acp_terminal.py +147 -0
  10. steerable_sidecar-0.6.0/src/steerable_sidecar/ag_ui.py +223 -0
  11. steerable_sidecar-0.6.0/src/steerable_sidecar/delivery.py +2764 -0
  12. steerable_sidecar-0.6.0/src/steerable_sidecar/file_edit.py +251 -0
  13. steerable_sidecar-0.6.0/src/steerable_sidecar/headless.py +738 -0
  14. steerable_sidecar-0.6.0/src/steerable_sidecar/host_spawn.py +130 -0
  15. steerable_sidecar-0.6.0/src/steerable_sidecar/host_tools.py +221 -0
  16. steerable_sidecar-0.6.0/src/steerable_sidecar/jpeg_ascii.py +314 -0
  17. steerable_sidecar-0.6.0/src/steerable_sidecar/landlock.py +353 -0
  18. steerable_sidecar-0.6.0/src/steerable_sidecar/landlock_run.py +35 -0
  19. steerable_sidecar-0.6.0/src/steerable_sidecar/loop_limits.py +77 -0
  20. steerable_sidecar-0.6.0/src/steerable_sidecar/multi_file_edit.py +109 -0
  21. steerable_sidecar-0.6.0/src/steerable_sidecar/png_ascii.py +246 -0
  22. steerable_sidecar-0.6.0/src/steerable_sidecar/run_code.py +602 -0
  23. steerable_sidecar-0.6.0/src/steerable_sidecar/run_code_driver.py +229 -0
  24. steerable_sidecar-0.6.0/src/steerable_sidecar/sandbox.py +693 -0
  25. steerable_sidecar-0.6.0/src/steerable_sidecar/search_tools.py +173 -0
  26. steerable_sidecar-0.6.0/src/steerable_sidecar/shell_session.py +301 -0
  27. steerable_sidecar-0.6.0/src/steerable_sidecar/sidecar.py +2624 -0
  28. steerable_sidecar-0.6.0/src/steerable_sidecar/tool_contract.json +326 -0
  29. steerable_sidecar-0.6.0/src/steerable_sidecar/tool_contract.py +62 -0
  30. steerable_sidecar-0.6.0/src/steerable_sidecar/web_tools.py +964 -0
  31. steerable_sidecar-0.6.0/src/steerable_sidecar/workspace_fs.py +71 -0
  32. steerable_sidecar-0.6.0/src/steerable_sidecar/workspace_tools.py +1118 -0
  33. steerable_sidecar-0.6.0/src/steerable_sidecar.egg-info/PKG-INFO +56 -0
  34. steerable_sidecar-0.6.0/src/steerable_sidecar.egg-info/SOURCES.txt +71 -0
  35. steerable_sidecar-0.6.0/src/steerable_sidecar.egg-info/dependency_links.txt +1 -0
  36. steerable_sidecar-0.6.0/src/steerable_sidecar.egg-info/entry_points.txt +4 -0
  37. steerable_sidecar-0.6.0/src/steerable_sidecar.egg-info/requires.txt +7 -0
  38. steerable_sidecar-0.6.0/src/steerable_sidecar.egg-info/top_level.txt +1 -0
  39. steerable_sidecar-0.6.0/tests/test_acp_adapter.py +955 -0
  40. steerable_sidecar-0.6.0/tests/test_acp_e2e.py +88 -0
  41. steerable_sidecar-0.6.0/tests/test_ag_ui.py +223 -0
  42. steerable_sidecar-0.6.0/tests/test_delivery.py +3326 -0
  43. steerable_sidecar-0.6.0/tests/test_e2e_loop_limits.py +189 -0
  44. steerable_sidecar-0.6.0/tests/test_e2e_record_migration.py +198 -0
  45. steerable_sidecar-0.6.0/tests/test_e2e_run_code.py +237 -0
  46. steerable_sidecar-0.6.0/tests/test_e2e_tool_exposure.py +198 -0
  47. steerable_sidecar-0.6.0/tests/test_e2e_web_tools.py +216 -0
  48. steerable_sidecar-0.6.0/tests/test_file_edit.py +152 -0
  49. steerable_sidecar-0.6.0/tests/test_headless.py +968 -0
  50. steerable_sidecar-0.6.0/tests/test_host_spawn.py +153 -0
  51. steerable_sidecar-0.6.0/tests/test_host_tools.py +508 -0
  52. steerable_sidecar-0.6.0/tests/test_landlock.py +279 -0
  53. steerable_sidecar-0.6.0/tests/test_loop_limits.py +92 -0
  54. steerable_sidecar-0.6.0/tests/test_multi_file_edit.py +144 -0
  55. steerable_sidecar-0.6.0/tests/test_provider_factory.py +237 -0
  56. steerable_sidecar-0.6.0/tests/test_run_code.py +339 -0
  57. steerable_sidecar-0.6.0/tests/test_sandbox.py +658 -0
  58. steerable_sidecar-0.6.0/tests/test_search_tools.py +83 -0
  59. steerable_sidecar-0.6.0/tests/test_shell_session.py +183 -0
  60. steerable_sidecar-0.6.0/tests/test_sidecar_approval.py +436 -0
  61. steerable_sidecar-0.6.0/tests/test_sidecar_coreloop.py +2036 -0
  62. steerable_sidecar-0.6.0/tests/test_sidecar_exec_sandbox.py +355 -0
  63. steerable_sidecar-0.6.0/tests/test_sidecar_mcp.py +276 -0
  64. steerable_sidecar-0.6.0/tests/test_sidecar_methods.py +535 -0
  65. steerable_sidecar-0.6.0/tests/test_sidecar_parts.py +91 -0
  66. steerable_sidecar-0.6.0/tests/test_sidecar_reverse_channel.py +144 -0
  67. steerable_sidecar-0.6.0/tests/test_sidecar_skills.py +229 -0
  68. steerable_sidecar-0.6.0/tests/test_sidecar_subprocess.py +143 -0
  69. steerable_sidecar-0.6.0/tests/test_sidecar_world_state.py +134 -0
  70. steerable_sidecar-0.6.0/tests/test_tool_contract.py +141 -0
  71. steerable_sidecar-0.6.0/tests/test_web_tools.py +836 -0
  72. steerable_sidecar-0.6.0/tests/test_win32_stdio.py +109 -0
  73. steerable_sidecar-0.6.0/tests/test_workspace_tools.py +723 -0
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.4
2
+ Name: steerable-sidecar
3
+ Version: 0.6.0
4
+ Summary: Steerable agent runtime sidecar — JSON-RPC over stdio.
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: pydantic>=2.10.0
8
+ Requires-Dist: httpx[socks]>=0.27
9
+ Requires-Dist: steerable-agent-protocol<1.0.0,>=0.1.0
10
+ Requires-Dist: steerable-agent-harness<1.0.0,>=0.1.0
11
+ Requires-Dist: steerable-agent-runtime<1.0.0,>=0.1.0
12
+ Requires-Dist: ag-ui-protocol>=0.1.21
13
+ Requires-Dist: agent-client-protocol>=0.12.1
14
+
15
+ # steerable-sidecar
16
+
17
+ The portable Python entrypoint for the **steerable** framework. Designed to be
18
+ spawned by an Electron / desktop host (or directly from a CLI) and addressed
19
+ via stdio JSON-RPC 2.0.
20
+
21
+ ## Quick start
22
+
23
+ ```bash
24
+ pip install steerable-sidecar
25
+ python -m steerable_sidecar
26
+ ```
27
+
28
+ Or use the console script:
29
+
30
+ ```bash
31
+ steerable-sidecar
32
+ ```
33
+
34
+ The process:
35
+
36
+ 1. Initializes the in-memory storage and a default tool router.
37
+ 2. Prints the **ready signal** on **stderr** as a single line:
38
+ `__SIDECAR_READY__:<json>` matching `spec/sidecar/SidecarHealth`.
39
+ 3. Begins reading JSON-RPC frames from stdin (one frame per line).
40
+ 4. Writes responses and notifications to stdout.
41
+
42
+ See `spec/sidecar/README.md` for the full method/notification catalog.
43
+
44
+ ## Embedding
45
+
46
+ ```python
47
+ import asyncio
48
+ from steerable_sidecar import Sidecar
49
+
50
+ async def main() -> None:
51
+ sidecar = Sidecar()
52
+ sidecar.tools.register(my_tool)
53
+ await sidecar.serve()
54
+
55
+ asyncio.run(main())
56
+ ```
@@ -0,0 +1,42 @@
1
+ # steerable-sidecar
2
+
3
+ The portable Python entrypoint for the **steerable** framework. Designed to be
4
+ spawned by an Electron / desktop host (or directly from a CLI) and addressed
5
+ via stdio JSON-RPC 2.0.
6
+
7
+ ## Quick start
8
+
9
+ ```bash
10
+ pip install steerable-sidecar
11
+ python -m steerable_sidecar
12
+ ```
13
+
14
+ Or use the console script:
15
+
16
+ ```bash
17
+ steerable-sidecar
18
+ ```
19
+
20
+ The process:
21
+
22
+ 1. Initializes the in-memory storage and a default tool router.
23
+ 2. Prints the **ready signal** on **stderr** as a single line:
24
+ `__SIDECAR_READY__:<json>` matching `spec/sidecar/SidecarHealth`.
25
+ 3. Begins reading JSON-RPC frames from stdin (one frame per line).
26
+ 4. Writes responses and notifications to stdout.
27
+
28
+ See `spec/sidecar/README.md` for the full method/notification catalog.
29
+
30
+ ## Embedding
31
+
32
+ ```python
33
+ import asyncio
34
+ from steerable_sidecar import Sidecar
35
+
36
+ async def main() -> None:
37
+ sidecar = Sidecar()
38
+ sidecar.tools.register(my_tool)
39
+ await sidecar.serve()
40
+
41
+ asyncio.run(main())
42
+ ```
@@ -0,0 +1,55 @@
1
+ [project]
2
+ name = "steerable-sidecar"
3
+ version = "0.6.0"
4
+ description = "Steerable agent runtime sidecar — JSON-RPC over stdio."
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ # Pre-1.0 inter-package pins use `>=X,<1.0.0` ranges — flexible enough
8
+ # that any 0.x lockstep version installs cleanly. `bump_to.sh` keeps
9
+ # all 7 Steerable packages at the same X.Y.Z, enforced by the
10
+ # release.yml lockstep gate. Tighten to `~=1.0` post-GA.
11
+ # See packages/agent-harness/py/pyproject.toml for the rationale.
12
+ dependencies = [
13
+ "pydantic>=2.10.0",
14
+ # httpx backs OpenAICompatProvider — the default provider family for
15
+ # agent.chat.stream (openai_compat / ollama). Not optional here: the
16
+ # sidecar exists to talk to LLM endpoints. (anthropic stays a lazy
17
+ # import, only loaded when provider=anthropic.)
18
+ # The `socks` extra covers hosts exporting `all_proxy=socks5://…`: httpx
19
+ # builds a transport per declared proxy at client construction, so the scheme
20
+ # must be buildable or every provider call fails before reaching a URL.
21
+ "httpx[socks]>=0.27",
22
+ "steerable-agent-protocol>=0.1.0,<1.0.0",
23
+ "steerable-agent-harness>=0.1.0,<1.0.0",
24
+ "steerable-agent-runtime>=0.1.0,<1.0.0",
25
+ "ag-ui-protocol>=0.1.21",
26
+ "agent-client-protocol>=0.12.1",
27
+ ]
28
+
29
+ [project.scripts]
30
+ steerable-sidecar = "steerable_sidecar.__main__:main"
31
+ steerable-sidecar-acp = "steerable_sidecar.acp_adapter:main"
32
+ steerable-sidecar-headless = "steerable_sidecar.headless:main"
33
+
34
+ [build-system]
35
+ requires = ["setuptools>=68", "wheel"]
36
+ build-backend = "setuptools.build_meta"
37
+
38
+ [tool.setuptools]
39
+ package-dir = {"" = "src"}
40
+
41
+ [tool.setuptools.packages.find]
42
+ where = ["src"]
43
+
44
+ # tool_contract.json is loaded via __file__ by tool_contract.py; ship it so the
45
+ # canonical tool contract resolves from an installed wheel, not only from source.
46
+ [tool.setuptools.package-data]
47
+ steerable_sidecar = ["*.json"]
48
+
49
+ [tool.uv.sources]
50
+ steerable-agent-protocol = { workspace = true }
51
+ steerable-agent-harness = { workspace = true }
52
+ steerable-agent-runtime = { workspace = true }
53
+
54
+ [tool.pytest.ini_options]
55
+ asyncio_mode = "auto"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,28 @@
1
+ """steerable-sidecar — portable runtime entrypoint."""
2
+
3
+ from .landlock import LandlockExecBackend, landlock_available
4
+ from .sandbox import (
5
+ BwrapExecBackend,
6
+ SeatbeltExecBackend,
7
+ build_seatbelt_profile,
8
+ bwrap_available,
9
+ seatbelt_argv,
10
+ seatbelt_available,
11
+ select_exec_backend,
12
+ )
13
+ from .sidecar import Sidecar, SidecarConfig
14
+
15
+ __all__ = [
16
+ "BwrapExecBackend",
17
+ "LandlockExecBackend",
18
+ "SeatbeltExecBackend",
19
+ "Sidecar",
20
+ "SidecarConfig",
21
+ "build_seatbelt_profile",
22
+ "bwrap_available",
23
+ "landlock_available",
24
+ "seatbelt_argv",
25
+ "seatbelt_available",
26
+ "select_exec_backend",
27
+ ]
28
+ __version__ = "0.1.0"
@@ -0,0 +1,84 @@
1
+ """``python -m steerable_sidecar`` entrypoint."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import asyncio
7
+ import logging
8
+
9
+ from steerable_agent_runtime.errors import StoreAlreadyOwnedError
10
+
11
+ from .sidecar import Sidecar, SidecarConfig
12
+ from .web_tools import register_web_tools
13
+ from .run_code import register_run_code, run_code_enabled
14
+
15
+
16
+ def _build_parser() -> argparse.ArgumentParser:
17
+ parser = argparse.ArgumentParser(prog="steerable-sidecar")
18
+ parser.add_argument(
19
+ "--log-level",
20
+ default="INFO",
21
+ choices=["DEBUG", "INFO", "WARNING", "ERROR"],
22
+ help="Sidecar log level (logged on stderr).",
23
+ )
24
+ parser.add_argument(
25
+ "--quiet-ready",
26
+ action="store_true",
27
+ help="Skip the __SIDECAR_READY__ stderr marker.",
28
+ )
29
+ parser.add_argument(
30
+ "--storage-path",
31
+ default=None,
32
+ metavar="PATH",
33
+ help="Persist sessions/traces/history to a sqlite database at PATH "
34
+ "(W2.6.1). Default: in-memory, per-process only.",
35
+ )
36
+ return parser
37
+
38
+
39
+ def main() -> int:
40
+ parser = _build_parser()
41
+ args = parser.parse_args()
42
+ config = SidecarConfig(
43
+ log_level=args.log_level,
44
+ quiet_stderr=args.quiet_ready,
45
+ storage_path=args.storage_path,
46
+ )
47
+ try:
48
+ sidecar = Sidecar(config=config)
49
+ except StoreAlreadyOwnedError as exc:
50
+ logging.getLogger("steerable_sidecar").error("%s", exc)
51
+ return 1
52
+ # web_search / web_fetch on the RPC router: the desktop host delegates
53
+ # these calls here over forward `tool.invoke` (single implementation —
54
+ # the host carries schemas only). A malformed STEERABLE_WEB_* bound must
55
+ # not brick chat for an optional feature, so the misconfiguration logs
56
+ # loud and the sidecar serves without the web pair.
57
+ try:
58
+ register_web_tools(sidecar.tools)
59
+ except ValueError as exc:
60
+ logging.getLogger("steerable_sidecar").error(
61
+ "web tools disabled: %s", exc
62
+ )
63
+ if run_code_enabled():
64
+ register_run_code(sidecar.tools)
65
+ # Third-party tools: discover packages that registered the
66
+ # ``steerable.tools`` entry-point group and load their tools onto the
67
+ # router. A broken entry point fails the boot loud (PluginLoadError
68
+ # names the offender) rather than silently dropping an installed tool.
69
+ from steerable_agent_runtime import PluginLoadError, load_tool_entry_points
70
+
71
+ try:
72
+ load_tool_entry_points(sidecar.tools)
73
+ except PluginLoadError as exc:
74
+ logging.getLogger("steerable_sidecar").error("tool plugin: %s", exc)
75
+ return 1
76
+ try:
77
+ asyncio.run(sidecar.serve())
78
+ except KeyboardInterrupt:
79
+ logging.getLogger("steerable_sidecar").info("interrupted")
80
+ return 0
81
+
82
+
83
+ if __name__ == "__main__": # pragma: no cover
84
+ raise SystemExit(main())