devops-bot-sdk 1.4.147__tar.gz → 1.4.149__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 (95) hide show
  1. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/PKG-INFO +1 -1
  2. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
  3. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/__init__.py +2 -2
  4. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/local_exec.py +14 -6
  5. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/ip_allowlist.py +40 -4
  6. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/server.py +16 -0
  7. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/service.py +17 -4
  8. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/README.md +0 -0
  9. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/devops_bot_sdk.egg-info/SOURCES.txt +0 -0
  10. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
  11. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
  12. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/devops_bot_sdk.egg-info/requires.txt +0 -0
  13. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/devops_bot_sdk.egg-info/top_level.txt +0 -0
  14. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/pyproject.toml +0 -0
  15. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agentd.py +0 -0
  16. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/__init__.py +0 -0
  17. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/builder.py +0 -0
  18. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/chat.py +0 -0
  19. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/connectors.py +0 -0
  20. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/engines/__init__.py +0 -0
  21. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/engines/claude_code.py +0 -0
  22. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/engines/http.py +0 -0
  23. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/engines/mcp.py +0 -0
  24. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/engines/n8n.py +0 -0
  25. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/engines/shell.py +0 -0
  26. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/integrations.py +0 -0
  27. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/inventory.py +0 -0
  28. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/library/__init__.py +0 -0
  29. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/manifest.py +0 -0
  30. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/prompt_studio.py +0 -0
  31. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/prompt_template.py +0 -0
  32. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/prompt_vars.py +0 -0
  33. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/run_log.py +0 -0
  34. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/secrets.py +0 -0
  35. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/usage.py +0 -0
  36. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/agents/varstore.py +0 -0
  37. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/cli.py +0 -0
  38. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/client.py +0 -0
  39. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/collectors/__init__.py +0 -0
  40. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/collectors/files.py +0 -0
  41. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/collectors/process.py +0 -0
  42. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/collectors/screenshot.py +0 -0
  43. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/config.py +0 -0
  44. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/crucial.py +0 -0
  45. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/design_verify/__init__.py +0 -0
  46. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/design_verify/assets.py +0 -0
  47. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/design_verify/bootstrap.py +0 -0
  48. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/design_verify/browser.py +0 -0
  49. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/design_verify/compare.py +0 -0
  50. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/design_verify/loop.py +0 -0
  51. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/exceptions.py +0 -0
  52. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/git_ops.py +0 -0
  53. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/graphify.py +0 -0
  54. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/hooks/__init__.py +0 -0
  55. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/hooks/crucial_guard.py +0 -0
  56. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ipc/__init__.py +0 -0
  57. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ipc/electron_bridge.py +0 -0
  58. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ipc/handlers.py +0 -0
  59. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/models/__init__.py +0 -0
  60. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/models/envelope.py +0 -0
  61. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/models/requests.py +0 -0
  62. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/models/responses.py +0 -0
  63. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/models/snapshots.py +0 -0
  64. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/platform_compat.py +0 -0
  65. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/py.typed +0 -0
  66. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/run_auto.py +0 -0
  67. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/sse.py +0 -0
  68. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/test.py +0 -0
  69. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/test_pipeline.py +0 -0
  70. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/__init__.py +0 -0
  71. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/api.py +0 -0
  72. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/dashboard.py +0 -0
  73. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/health.py +0 -0
  74. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/jobs.py +0 -0
  75. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/models.py +0 -0
  76. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/runner.py +0 -0
  77. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/security.py +0 -0
  78. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/setup_manager.py +0 -0
  79. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/agents.html +0 -0
  80. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/app.js +0 -0
  81. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/custom-agents.html +0 -0
  82. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/default-agents.html +0 -0
  83. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/index.html +0 -0
  84. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/runs.html +0 -0
  85. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/setup.html +0 -0
  86. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/styles.css +0 -0
  87. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/ui/static/tickets.html +0 -0
  88. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/sdk/updater.py +0 -0
  89. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/setup.cfg +0 -0
  90. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/tests/test_agent_chat_features.py +0 -0
  91. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/tests/test_agent_prompt_models.py +0 -0
  92. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/tests/test_agents_connectors_builder.py +0 -0
  93. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/tests/test_git_action.py +0 -0
  94. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/tests/test_health.py +0 -0
  95. {devops_bot_sdk-1.4.147 → devops_bot_sdk-1.4.149}/tests/test_updater_extras.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.4.147
3
+ Version: 1.4.149
4
4
  Summary: DevOps Bot Desktop SDK — thin client for the AgentOS Electron desktop app
5
5
  Author: noumanaziz2128
6
6
  License-Expression: LicenseRef-Proprietary
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.4.147
3
+ Version: 1.4.149
4
4
  Summary: DevOps Bot Desktop SDK — thin client for the AgentOS Electron desktop app
5
5
  Author: noumanaziz2128
6
6
  License-Expression: LicenseRef-Proprietary
@@ -1,6 +1,6 @@
1
1
  """AgentOS Desktop SDK — thin HTTPS/SSE client for the Electron app.
2
2
 
3
- Version: 1.4.147
3
+ Version: 1.4.149
4
4
 
5
5
  Public surface:
6
6
  BackendClient.from_config() — create client from ~/.agentos/config.toml
@@ -30,7 +30,7 @@ Rules:
30
30
  - All data egress through submit_webhook only
31
31
  """
32
32
 
33
- __version__ = "1.4.147" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
33
+ __version__ = "1.4.149" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
34
34
  __author__ = "AgentOS" # sdk.client.SDK_VERSION and the UI server version all read this.
35
35
 
36
36
  from sdk.client import BackendClient
@@ -244,16 +244,24 @@ def claude_cli_path() -> str | None:
244
244
  """Absolute path to the `claude` CLI, or None if it isn't on PATH.
245
245
 
246
246
  Resolution order:
247
- 1. ``AGENTOS_CLAUDE_CLI`` env var — explicit path override (escape hatch for
248
- an install in a non-standard location).
247
+ 1. ``AGENTOS_CLAUDE_CLI`` — explicit path override, read from the process env
248
+ OR ``~/.agentos/.env`` (same file as the IP allowlist). Escape hatch for an
249
+ install in a location the service's PATH doesn't cover.
249
250
  2. ``PATH`` (``shutil.which``) — cross-platform, no guessing.
250
251
 
251
- The service must therefore RUN with a PATH that includes the CLI. The install
252
- step bakes that in (see ``sdk.ui.service`` — systemd ``Environment=PATH`` /
253
- launchd ``EnvironmentVariables``; Windows tasks inherit the user's PATH), so
254
- ``engine=claude_code`` works without anyone editing a unit file.
252
+ The service normally RUNs with a PATH that includes the CLI (the install step
253
+ bakes that in — see ``sdk.ui.service``: systemd ``Environment=PATH`` / launchd
254
+ ``EnvironmentVariables``; Windows tasks inherit the user's PATH). When a unit
255
+ predates that or the CLI lives somewhere unusual, setting ``AGENTOS_CLAUDE_CLI``
256
+ in ``~/.agentos/.env`` fixes it with no unit editing.
255
257
  """
256
258
  override = os.environ.get("AGENTOS_CLAUDE_CLI", "").strip()
259
+ if not override:
260
+ try:
261
+ from sdk.config import _dotenv_value
262
+ override = (_dotenv_value("AGENTOS_CLAUDE_CLI") or "").strip()
263
+ except Exception: # noqa: BLE001 — a config hiccup must never break resolution
264
+ override = ""
257
265
  if override and Path(override).exists():
258
266
  return override
259
267
  return shutil.which("claude")
@@ -20,16 +20,52 @@ import ipaddress
20
20
  import os
21
21
  import socket
22
22
 
23
+ _TRUE = ("1", "true", "yes", "on")
24
+
25
+
26
+ def _setting(name: str) -> str:
27
+ """Read an ``AGENTOS_UI_*`` toggle from the process env OR ``~/.agentos/.env``
28
+ (or a CWD ``.env``), so an operator can set it in the same file as the IP
29
+ allowlist without editing the service unit. Process env wins."""
30
+ val = os.environ.get(name, "").strip()
31
+ if val:
32
+ return val
33
+ try:
34
+ from sdk.config import _dotenv_value
35
+ return (_dotenv_value(name) or "").strip()
36
+ except Exception: # noqa: BLE001 — a config hiccup must never break the server
37
+ return ""
38
+
23
39
 
24
40
  def public_mode() -> bool:
25
41
  """Opt-in PUBLIC mode (``AGENTOS_UI_PUBLIC=1``).
26
42
 
27
43
  When set, the SDK is a public, token-authenticated server: the IP gate is
28
- lifted so Swagger (``/docs``) is browsable from any IP and every ``/api/ui/*``
29
- path relies SOLELY on the ``co_`` token (``require_token``) as its credential.
30
- Off by default — a plain launch stays locked to loopback + allowlisted IPs.
44
+ lifted so Swagger (``/docs``) is browsable from any IP over http and every
45
+ ``/api/ui/*`` path relies SOLELY on the ``co_`` token (``require_token``) as its
46
+ credential. Off by default — a plain launch stays locked to loopback +
47
+ allowlisted IPs. Read from the process env or ``~/.agentos/.env``.
48
+ """
49
+ return _setting("AGENTOS_UI_PUBLIC").lower() in _TRUE
50
+
51
+
52
+ def cors_origins() -> list[str] | None:
53
+ """Browser (CORS) origins to allow, or ``None`` to leave CORS disabled.
54
+
55
+ Enabled when the server is PUBLIC (``AGENTOS_UI_PUBLIC=1``) or explicitly via
56
+ ``AGENTOS_UI_CORS=1``. Origins come from ``AGENTOS_UI_CORS_ORIGINS`` (comma/space
57
+ separated); default ``["*"]`` (any origin). ``*`` is safe here because every
58
+ data route is guarded by the ``co_`` token in the ``Authorization`` header (no
59
+ cookies), so a permissive origin can't be abused via ambient credentials.
60
+
61
+ Needed so a browser (e.g. Swagger "Try it out" served from another origin) can
62
+ call the API — without it the browser blocks the response as a CORS error.
31
63
  """
32
- return os.environ.get("AGENTOS_UI_PUBLIC", "").strip().lower() in ("1", "true", "yes", "on")
64
+ enabled = public_mode() or _setting("AGENTOS_UI_CORS").lower() in _TRUE
65
+ if not enabled:
66
+ return None
67
+ raw = _setting("AGENTOS_UI_CORS_ORIGINS").replace(",", " ").split()
68
+ return raw or ["*"]
33
69
 
34
70
 
35
71
  def _loopback(ip: ipaddress._BaseAddress) -> bool:
@@ -41,6 +41,22 @@ def create_app():
41
41
  # this host's own IPs, and whitelisted IPs (the AI backend) may reach the server
42
42
  # AT ALL. Configure via AGENTOS_UI_ALLOWED_IPS or the config.toml `allowed_ips` key.
43
43
  app.add_middleware(IPAllowlistMiddleware)
44
+ # CORS (opt-in — on automatically in PUBLIC mode, or via AGENTOS_UI_CORS=1). Added
45
+ # AFTER the allowlist so it is the OUTERMOST layer: it answers browser preflight
46
+ # (OPTIONS) and attaches CORS headers to EVERY response — including a 403 from the
47
+ # allowlist — so the browser can read the real result instead of a bare "CORS
48
+ # error". Data routes stay guarded by the co_ token regardless.
49
+ from sdk.ui.ip_allowlist import cors_origins
50
+ _cors = cors_origins()
51
+ if _cors is not None:
52
+ from fastapi.middleware.cors import CORSMiddleware
53
+ app.add_middleware(
54
+ CORSMiddleware,
55
+ allow_origins=_cors,
56
+ allow_methods=["*"],
57
+ allow_headers=["*"],
58
+ allow_credentials=False, # token is in the Authorization header, not cookies
59
+ )
44
60
  app.include_router(api_router)
45
61
 
46
62
  @app.get("/")
@@ -31,11 +31,24 @@ WIN_TASK = "AgentOS Control Panel" # Windows scheduled-task name
31
31
 
32
32
 
33
33
  def _exe() -> str:
34
- """Absolute path to the ``agentos-ui`` console script in this venv."""
35
- bindir = Path(sys.executable).parent
34
+ """ABSOLUTE path to the ``agentos-ui`` console script.
35
+
36
+ Must be absolute: a service manager (systemd/launchd) does NOT search the
37
+ user's PATH for ExecStart, so a bare ``agentos-ui`` fails with 203/EXEC when
38
+ the script lives somewhere like ``~/.local/bin`` (a ``pip --user`` install) —
39
+ the common case on a VPS. Resolve, in order:
40
+ 1. next to the running interpreter (venv installs),
41
+ 2. on the current PATH (finds ``~/.local/bin`` at install time),
42
+ 3. bare name as a last resort (kept only so install never hard-fails).
43
+ """
36
44
  name = "agentos-ui.exe" if IS_WINDOWS else "agentos-ui"
37
- cand = bindir / name
38
- return str(cand if cand.exists() else name)
45
+ cand = Path(sys.executable).parent / name
46
+ if cand.exists():
47
+ return str(cand)
48
+ found = shutil.which(name)
49
+ if found:
50
+ return str(Path(found).resolve())
51
+ return name
39
52
 
40
53
 
41
54
  def _run(argv: list[str]) -> tuple[int, str]: