devops-bot-sdk 1.4.27__tar.gz → 1.4.29__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 (38) hide show
  1. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/PKG-INFO +1 -1
  2. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
  3. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/pyproject.toml +1 -1
  4. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/__init__.py +2 -2
  5. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/client.py +1 -1
  6. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/ipc/handlers.py +28 -14
  7. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/run_auto.py +8 -0
  8. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/README.md +0 -0
  9. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/devops_bot_sdk.egg-info/SOURCES.txt +0 -0
  10. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
  11. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
  12. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/devops_bot_sdk.egg-info/requires.txt +0 -0
  13. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/devops_bot_sdk.egg-info/top_level.txt +0 -0
  14. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/collectors/__init__.py +0 -0
  15. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/collectors/files.py +0 -0
  16. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/collectors/process.py +0 -0
  17. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/collectors/screenshot.py +0 -0
  18. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/config.py +0 -0
  19. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/crucial.py +0 -0
  20. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/exceptions.py +0 -0
  21. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/git_ops.py +0 -0
  22. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/graphify.py +0 -0
  23. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/hooks/__init__.py +0 -0
  24. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/hooks/crucial_guard.py +0 -0
  25. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/ipc/__init__.py +0 -0
  26. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/ipc/electron_bridge.py +0 -0
  27. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/local_exec.py +0 -0
  28. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/models/__init__.py +0 -0
  29. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/models/envelope.py +0 -0
  30. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/models/requests.py +0 -0
  31. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/models/responses.py +0 -0
  32. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/models/snapshots.py +0 -0
  33. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/py.typed +0 -0
  34. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/sse.py +0 -0
  35. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/test.py +0 -0
  36. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/test_pipeline.py +0 -0
  37. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/sdk/updater.py +0 -0
  38. {devops_bot_sdk-1.4.27 → devops_bot_sdk-1.4.29}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devops-bot-sdk
3
- Version: 1.4.27
3
+ Version: 1.4.29
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.27
3
+ Version: 1.4.29
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "devops-bot-sdk"
7
- version = "1.4.27"
7
+ version = "1.4.29"
8
8
  description = "DevOps Bot Desktop SDK — thin client for the AgentOS Electron desktop app"
9
9
  readme = "README.md"
10
10
  license = "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.27
3
+ Version: 1.4.29
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.27"
33
+ __version__ = "1.4.29"
34
34
  __author__ = "AgentOS"
35
35
 
36
36
  from sdk.client import BackendClient
@@ -36,7 +36,7 @@ from sdk.sse import _check_status, stream_with_reconnect
36
36
 
37
37
  logger = logging.getLogger(__name__)
38
38
 
39
- SDK_VERSION = "1.4.27"
39
+ SDK_VERSION = "1.4.29"
40
40
  _POLL_INTERVAL = 3.0
41
41
  _POLL_TIMEOUT = 600.0
42
42
  _ORCHESTRATE_TIMEOUT = 2700.0 # 45 min — covers approval wait + VPS execution time
@@ -1845,31 +1845,45 @@ async def handle_orchestrate_auto_local_run(
1845
1845
  "current_step": f"{jira_key}: awaiting approval"},
1846
1846
  ).model_dump())
1847
1847
 
1848
- # Safety net for the gate-1 WhatsApp. The backend sends it
1849
- # when planning opens the gate; if that send failed the
1850
- # approver would get nothing and the ticket would silently
1851
- # time out to Backlog. Re-send it ourselves once, only after
1852
- # the grace window, so a healthy backend doesn't duplicate.
1853
1848
  _wa_summary = task.get("summary") or jira_key or "task"
1854
1849
 
1855
- async def _first_gate_wa_fallback(
1850
+ async def _send_first_gate_wa(
1856
1851
  tid=tid, jira_key=jira_key, _wa_summary=_wa_summary,
1857
- ) -> None:
1858
- await send(Envelope(
1859
- type="step_update", thread_id=thread_id,
1860
- data={"current_step": f"{jira_key}: no approval reply yet "
1861
- "re-sending WhatsApp approval request"},
1862
- ).model_dump())
1863
- await client.notify_whatsapp(
1852
+ ) -> bool:
1853
+ # approver_role defaults to TEAM_LEAD (matches the ML
1854
+ # backend's /approvals-ml routing that is known to work).
1855
+ # Log the outcome to the daemon log + activity DB so a
1856
+ # failed send is visible instead of silently swallowed.
1857
+ ok = await client.notify_whatsapp(
1864
1858
  tid,
1865
1859
  f"Approval needed for {jira_key or tid}: {_wa_summary} — "
1866
1860
  "reply on WhatsApp to approve or reject so the work can start.",
1867
1861
  summary=_wa_summary,
1868
1862
  )
1863
+ note = ("WhatsApp approval request sent" if ok
1864
+ else "WhatsApp approval request FAILED to send "
1865
+ "(check /approvals-ml + approver phone on file)")
1866
+ await send(Envelope(
1867
+ type="step_update", thread_id=thread_id,
1868
+ data={"current_step": f"{jira_key}: {note}"},
1869
+ ).model_dump())
1870
+ try:
1871
+ await client.log_activity(f"Task {tid}: {note}")
1872
+ except Exception: # noqa: BLE001
1873
+ pass
1874
+ return ok
1875
+
1876
+ # Send the gate-1 WhatsApp NOW via /approvals-ml (the ML
1877
+ # backend actually delivers it). Owning the send here makes
1878
+ # it reliable regardless of whether the AI backend's own
1879
+ # M5.2 send fired — the previous "no WhatsApp at all" bug.
1880
+ await _send_first_gate_wa()
1869
1881
 
1882
+ # Re-send once, after the grace window, only if still unanswered
1883
+ # (covers a transient failure of the send above).
1870
1884
  decision = await _poll_approval(
1871
1885
  client, tid, should_stop,
1872
- fallback_notify=_first_gate_wa_fallback,
1886
+ fallback_notify=_send_first_gate_wa,
1873
1887
  fallback_after_s=_FIRST_GATE_WA_FALLBACK_S,
1874
1888
  )
1875
1889
 
@@ -134,6 +134,14 @@ def _daemonize() -> bool:
134
134
  os.close(devnull)
135
135
  os.close(logfd)
136
136
 
137
+ # CRITICAL: when stdout is a file (not a tty) Python block-buffers it, so
138
+ # progress printed via _send() would sit in the buffer and never reach the
139
+ # log until the process exits — making the daemon look idle. Replace the
140
+ # streams with line-buffered writers so every progress line is flushed live,
141
+ # exactly like the foreground run.
142
+ sys.stdout = open(_LOG_FILE, "a", buffering=1, encoding="utf-8")
143
+ sys.stderr = sys.stdout
144
+
137
145
  _PID_FILE.write_text(str(os.getpid()))
138
146
  return True
139
147