forgexa-cli 1.48.3__tar.gz → 1.48.4__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.
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/PKG-INFO +1 -1
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/__init__.py +1 -1
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/daemon.py +21 -6
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli.egg-info/PKG-INFO +1 -1
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/pyproject.toml +1 -1
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/README.md +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/_build_config.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/_local_bind.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/agent_core.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/autoupgrade.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/main.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/py.typed +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli/runtime_evidence.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli.egg-info/SOURCES.txt +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli.egg-info/dependency_links.txt +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli.egg-info/entry_points.txt +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli.egg-info/requires.txt +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/forgexa_cli.egg-info/top_level.txt +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/setup.cfg +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_auth_and_runtime_commands.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_autoupgrade.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_check_command.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_expiry_warnings_and_revoke.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_local_bind_commands.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_runtime_credentials.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_session_credentials.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_silent_install.py +0 -0
- {forgexa_cli-1.48.3 → forgexa_cli-1.48.4}/tests/test_upgrade_observability.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""forgexa-cli — Forgexa command-line client."""
|
|
2
|
-
__version__ = "1.48.
|
|
2
|
+
__version__ = "1.48.4"
|
|
@@ -1120,7 +1120,7 @@ except (ImportError, ModuleNotFoundError):
|
|
|
1120
1120
|
# DAEMON_VERSION is the protocol/logic version of the daemon code.
|
|
1121
1121
|
# Kept in sync with pyproject.toml version via bump-version.sh.
|
|
1122
1122
|
# CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
|
|
1123
|
-
DAEMON_VERSION = "1.48.
|
|
1123
|
+
DAEMON_VERSION = "1.48.4"
|
|
1124
1124
|
|
|
1125
1125
|
|
|
1126
1126
|
def _detect_client_type() -> str:
|
|
@@ -9493,6 +9493,11 @@ class RuntimeDaemon:
|
|
|
9493
9493
|
for field, value in attachment.items():
|
|
9494
9494
|
if value and not existing.get(field):
|
|
9495
9495
|
existing[field] = value
|
|
9496
|
+
if download_url and download_url != existing.get("download_url"):
|
|
9497
|
+
aliases = list(existing.get("_download_url_aliases") or [])
|
|
9498
|
+
if download_url not in aliases:
|
|
9499
|
+
aliases.append(download_url)
|
|
9500
|
+
existing["_download_url_aliases"] = aliases
|
|
9496
9501
|
existing_artifact_id = str(
|
|
9497
9502
|
existing.get("artifact_id") or existing.get("id") or ""
|
|
9498
9503
|
).strip()
|
|
@@ -9537,6 +9542,12 @@ class RuntimeDaemon:
|
|
|
9537
9542
|
for field, value in attachment.items():
|
|
9538
9543
|
if value and not identified.get(field):
|
|
9539
9544
|
identified[field] = value
|
|
9545
|
+
legacy_url = attachment.get("download_url")
|
|
9546
|
+
if isinstance(legacy_url, str) and legacy_url and legacy_url != identified.get("download_url"):
|
|
9547
|
+
aliases = list(identified.get("_download_url_aliases") or [])
|
|
9548
|
+
if legacy_url not in aliases:
|
|
9549
|
+
aliases.append(legacy_url)
|
|
9550
|
+
identified["_download_url_aliases"] = aliases
|
|
9540
9551
|
return deduplicated
|
|
9541
9552
|
|
|
9542
9553
|
@staticmethod
|
|
@@ -9551,14 +9562,14 @@ class RuntimeDaemon:
|
|
|
9551
9562
|
@staticmethod
|
|
9552
9563
|
def _rewrite_staged_attachment_references(
|
|
9553
9564
|
prompt: str,
|
|
9554
|
-
staged: list[tuple[str, str, str]],
|
|
9565
|
+
staged: list[tuple[str, list[str], str]],
|
|
9555
9566
|
) -> str:
|
|
9556
9567
|
if not staged:
|
|
9557
9568
|
return prompt
|
|
9558
9569
|
|
|
9559
9570
|
local_files = []
|
|
9560
|
-
for file_name,
|
|
9561
|
-
|
|
9571
|
+
for file_name, download_urls, local_path in staged:
|
|
9572
|
+
for download_url in download_urls:
|
|
9562
9573
|
command_pattern = r"`curl -L '" + re.escape(download_url) + r"' -o /tmp/[^`]+`"
|
|
9563
9574
|
prompt = re.sub(command_pattern, lambda _match, path=local_path: f"`{path}`", prompt)
|
|
9564
9575
|
prompt = prompt.replace(f"Download: {download_url}", f"Staged local file: `{local_path}`")
|
|
@@ -9685,7 +9696,7 @@ class RuntimeDaemon:
|
|
|
9685
9696
|
)
|
|
9686
9697
|
|
|
9687
9698
|
staging_dir = Path(tempfile.mkdtemp(prefix=f"forgexa-attachments-{task.task_id[:8]}-"))
|
|
9688
|
-
staged: list[tuple[str, str, str]] = []
|
|
9699
|
+
staged: list[tuple[str, list[str], str]] = []
|
|
9689
9700
|
deadline = time.monotonic() + self._TASK_ATTACHMENT_DOWNLOAD_TIMEOUT_SECONDS
|
|
9690
9701
|
remaining_bytes = self._TASK_ATTACHMENT_MAX_TOTAL_BYTES
|
|
9691
9702
|
try:
|
|
@@ -9694,6 +9705,10 @@ class RuntimeDaemon:
|
|
|
9694
9705
|
attachment.get("file_path") or attachment.get("file_name") or "attachment"
|
|
9695
9706
|
)
|
|
9696
9707
|
download_url = str(attachment.get("download_url") or "")
|
|
9708
|
+
download_url_aliases = [download_url] if download_url else []
|
|
9709
|
+
for alias in attachment.get("_download_url_aliases") or []:
|
|
9710
|
+
if isinstance(alias, str) and alias and alias not in download_url_aliases:
|
|
9711
|
+
download_url_aliases.append(alias)
|
|
9697
9712
|
destination = staging_dir / self._task_attachment_filename(attachment, position)
|
|
9698
9713
|
try:
|
|
9699
9714
|
expected_size = int(attachment.get("size_bytes") or 0)
|
|
@@ -9735,7 +9750,7 @@ class RuntimeDaemon:
|
|
|
9735
9750
|
timeout_seconds=remaining_seconds,
|
|
9736
9751
|
)
|
|
9737
9752
|
remaining_bytes -= destination.stat().st_size
|
|
9738
|
-
staged.append((file_name,
|
|
9753
|
+
staged.append((file_name, download_url_aliases, str(destination)))
|
|
9739
9754
|
except Exception:
|
|
9740
9755
|
shutil.rmtree(staging_dir, ignore_errors=True)
|
|
9741
9756
|
raise
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|