forgexa-cli 1.57.3__tar.gz → 1.57.5__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 (29) hide show
  1. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/PKG-INFO +1 -1
  2. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/__init__.py +1 -1
  3. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/daemon.py +27 -16
  4. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli.egg-info/PKG-INFO +1 -1
  5. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/pyproject.toml +1 -1
  6. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/README.md +0 -0
  7. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/_build_config.py +0 -0
  8. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/_local_bind.py +0 -0
  9. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/agent_core.py +0 -0
  10. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/autoupgrade.py +0 -0
  11. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/main.py +0 -0
  12. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/py.typed +0 -0
  13. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/runtime_evidence.py +0 -0
  14. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli/zcode_protocol.py +0 -0
  15. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli.egg-info/SOURCES.txt +0 -0
  16. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli.egg-info/dependency_links.txt +0 -0
  17. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli.egg-info/entry_points.txt +0 -0
  18. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli.egg-info/requires.txt +0 -0
  19. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/forgexa_cli.egg-info/top_level.txt +0 -0
  20. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/setup.cfg +0 -0
  21. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_auth_and_runtime_commands.py +0 -0
  22. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_autoupgrade.py +0 -0
  23. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_check_command.py +0 -0
  24. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_expiry_warnings_and_revoke.py +0 -0
  25. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_local_bind_commands.py +0 -0
  26. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_runtime_credentials.py +0 -0
  27. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_session_credentials.py +0 -0
  28. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_silent_install.py +0 -0
  29. {forgexa_cli-1.57.3 → forgexa_cli-1.57.5}/tests/test_upgrade_observability.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forgexa-cli
3
- Version: 1.57.3
3
+ Version: 1.57.5
4
4
  Summary: Forgexa CLI — command-line client and AI agent runtime for the Forgexa platform
5
5
  Author-email: Jason Sun <dev.winds@gmail.com>
6
6
  License-Expression: MIT
@@ -1,2 +1,2 @@
1
1
  """forgexa-cli — Forgexa command-line client."""
2
- __version__ = "1.57.3"
2
+ __version__ = "1.57.5"
@@ -1150,7 +1150,7 @@ except (ImportError, ModuleNotFoundError):
1150
1150
  # DAEMON_VERSION is the protocol/logic version of the daemon code.
1151
1151
  # Kept in sync with pyproject.toml version via bump-version.sh.
1152
1152
  # CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
1153
- DAEMON_VERSION = "1.57.3"
1153
+ DAEMON_VERSION = "1.57.5"
1154
1154
 
1155
1155
 
1156
1156
  def _detect_client_type() -> str:
@@ -9520,7 +9520,7 @@ class ServerConnection:
9520
9520
  self._publish_local_runtime_registration()
9521
9521
  self._warn_runtime_credential_expiring()
9522
9522
  except Exception as e:
9523
- logger.error("[%s] Failed to register with server: %s", self.label, e)
9523
+ logger.error("[%s] Failed to register with server: %s", self.label, _format_exc(e))
9524
9524
  raise
9525
9525
 
9526
9526
  def start_services(
@@ -11089,10 +11089,11 @@ class RuntimeDaemon:
11089
11089
  # initial heartbeat already carries a real status snapshot).
11090
11090
  await self.preflight_monitor.start()
11091
11091
 
11092
- # 2. Register with all servers
11093
11092
  # 2. Register with all servers (with retry on transient failures)
11094
- max_registration_attempts = 5
11095
- for attempt in range(max_registration_attempts):
11093
+ attempt = 0
11094
+ while not self._shutdown:
11095
+ attempt += 1
11096
+ rejected_explicit_tokens = 0
11096
11097
  for url in self.server_urls:
11097
11098
  if any(c.server_url == url.rstrip("/") for c in self.connections):
11098
11099
  continue # Already connected to this server
@@ -11136,24 +11137,34 @@ class RuntimeDaemon:
11136
11137
  )
11137
11138
  raise SystemExit(1)
11138
11139
  except Exception as e:
11139
- logger.error("[%s] Failed to connect: %s — skipping this server", conn.label, e)
11140
+ logger.error("[%s] Failed to connect: %s — skipping this server", conn.label, _format_exc(e))
11140
11141
  await conn.client.aclose()
11142
+ if (
11143
+ self._has_explicit_api_token
11144
+ and isinstance(e, httpx.HTTPStatusError)
11145
+ and e.response.status_code in (401, 403)
11146
+ ):
11147
+ rejected_explicit_tokens += 1
11141
11148
 
11142
11149
  if self.connections:
11143
11150
  break # At least one server connected
11151
+ if rejected_explicit_tokens == len(self.server_urls):
11152
+ logger.error("Explicit daemon API token rejected by all servers; update DAEMON_API_TOKEN or FORGEXA_TOKEN")
11153
+ raise SystemExit(1)
11144
11154
 
11145
- if attempt < max_registration_attempts - 1:
11146
- wait = (attempt + 1) * 5 # 5s, 10s, 15s, 20s
11147
- logger.warning(
11148
- "No servers reachable (attempt %d/%d). Retrying in %ds...",
11149
- attempt + 1, max_registration_attempts, wait,
11150
- )
11151
- await asyncio.sleep(wait)
11155
+ wait = min(attempt * 5, 60)
11156
+ logger.warning(
11157
+ "No servers reachable (attempt %d). Retrying in %ds...",
11158
+ attempt, wait,
11159
+ )
11160
+ try:
11161
+ await asyncio.wait_for(self._shutdown_event.wait(), timeout=wait)
11162
+ except asyncio.TimeoutError:
11163
+ pass
11152
11164
 
11153
11165
  if not self.connections:
11154
- logger.error("Failed to connect to any server after %d attempts. Exiting.",
11155
- max_registration_attempts)
11156
- raise SystemExit(1)
11166
+ await self._shutdown_gracefully()
11167
+ return
11157
11168
 
11158
11169
  logger.info("Daemon ready. Connected to %d server(s). Polling for tasks...",
11159
11170
  len(self.connections))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forgexa-cli
3
- Version: 1.57.3
3
+ Version: 1.57.5
4
4
  Summary: Forgexa CLI — command-line client and AI agent runtime for the Forgexa platform
5
5
  Author-email: Jason Sun <dev.winds@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "forgexa-cli"
3
- version = "1.57.3"
3
+ version = "1.57.5"
4
4
  description = "Forgexa CLI — command-line client and AI agent runtime for the Forgexa platform"
5
5
  requires-python = ">=3.9"
6
6
  license = "MIT"
File without changes
File without changes