forgexa-cli 1.21.0__tar.gz → 1.21.1__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.21.0 → forgexa_cli-1.21.1}/PKG-INFO +1 -1
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli/__init__.py +1 -1
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli/daemon.py +56 -5
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli.egg-info/PKG-INFO +1 -1
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/pyproject.toml +1 -1
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/README.md +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli/_build_config.py +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli/autoupgrade.py +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli/main.py +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli/py.typed +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli.egg-info/SOURCES.txt +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli.egg-info/dependency_links.txt +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli.egg-info/entry_points.txt +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli.egg-info/requires.txt +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/forgexa_cli.egg-info/top_level.txt +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/setup.cfg +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/tests/test_auth_and_runtime_commands.py +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/tests/test_autoupgrade.py +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/tests/test_check_command.py +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/tests/test_silent_install.py +0 -0
- {forgexa_cli-1.21.0 → forgexa_cli-1.21.1}/tests/test_upgrade_observability.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""forgexa-cli — Forgexa command-line client."""
|
|
2
|
-
__version__ = "1.21.
|
|
2
|
+
__version__ = "1.21.1"
|
|
@@ -555,7 +555,7 @@ except (ImportError, ModuleNotFoundError):
|
|
|
555
555
|
# DAEMON_VERSION is the protocol/logic version of the daemon code.
|
|
556
556
|
# Kept in sync with pyproject.toml version via bump-version.sh.
|
|
557
557
|
# CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
|
|
558
|
-
DAEMON_VERSION = "1.21.
|
|
558
|
+
DAEMON_VERSION = "1.21.1"
|
|
559
559
|
|
|
560
560
|
|
|
561
561
|
def _detect_client_type() -> str:
|
|
@@ -780,8 +780,19 @@ def _prepare_agent_command(command: list[str]) -> list[str]:
|
|
|
780
780
|
|
|
781
781
|
suffix = Path(command[0]).suffix.lower()
|
|
782
782
|
if suffix in {".cmd", ".bat"}:
|
|
783
|
+
comspec = os.environ.get("COMSPEC", "")
|
|
784
|
+
if comspec and Path(comspec).is_file():
|
|
785
|
+
command_processor = comspec
|
|
786
|
+
else:
|
|
787
|
+
system_root = os.environ.get("SystemRoot") or os.environ.get("WINDIR", "")
|
|
788
|
+
system_cmd = Path(system_root) / "System32" / "cmd.exe" if system_root else None
|
|
789
|
+
command_processor = (
|
|
790
|
+
str(system_cmd)
|
|
791
|
+
if system_cmd and system_cmd.is_file()
|
|
792
|
+
else shutil.which("cmd.exe") or comspec or "cmd.exe"
|
|
793
|
+
)
|
|
783
794
|
return [
|
|
784
|
-
|
|
795
|
+
command_processor,
|
|
785
796
|
"/d",
|
|
786
797
|
"/s",
|
|
787
798
|
"/c",
|
|
@@ -800,6 +811,13 @@ def _prepare_agent_command(command: list[str]) -> list[str]:
|
|
|
800
811
|
return command
|
|
801
812
|
|
|
802
813
|
|
|
814
|
+
def _agent_process_group_kwargs() -> dict[str, bool]:
|
|
815
|
+
"""Isolate agent process groups where the platform supports POSIX sessions."""
|
|
816
|
+
# Windows cleanup uses taskkill /T, and starting cmd.exe with a new session
|
|
817
|
+
# differs from the command path proven during agent discovery.
|
|
818
|
+
return {"start_new_session": True} if sys.platform != "win32" else {}
|
|
819
|
+
|
|
820
|
+
|
|
803
821
|
@dataclass
|
|
804
822
|
class TaskInfo:
|
|
805
823
|
task_id: str
|
|
@@ -4502,7 +4520,7 @@ class ProcessManager:
|
|
|
4502
4520
|
cwd=str(cwd),
|
|
4503
4521
|
env=env,
|
|
4504
4522
|
limit=100 * 1024 * 1024, # 100MB line buffer for large JSON output from long sessions
|
|
4505
|
-
|
|
4523
|
+
**_agent_process_group_kwargs(),
|
|
4506
4524
|
)
|
|
4507
4525
|
self.active_processes[task_id] = proc
|
|
4508
4526
|
stdout, stderr, returncode = await self._stream_process(
|
|
@@ -4559,6 +4577,16 @@ class ProcessManager:
|
|
|
4559
4577
|
error=f"Claude exited with code {returncode}: {stderr[-500:]}",
|
|
4560
4578
|
metrics=metrics,
|
|
4561
4579
|
)
|
|
4580
|
+
except FileNotFoundError as exc:
|
|
4581
|
+
logger.exception("Claude executable was not found for task %s", task_id)
|
|
4582
|
+
return TaskResult(
|
|
4583
|
+
status="failed",
|
|
4584
|
+
exit_code=-1,
|
|
4585
|
+
stdout="",
|
|
4586
|
+
stderr="",
|
|
4587
|
+
error=f"Claude launch failed: executable not found: {cmd[0]!r} ({exc})",
|
|
4588
|
+
failure_code="agent_launch_not_found",
|
|
4589
|
+
)
|
|
4562
4590
|
except asyncio.TimeoutError as exc:
|
|
4563
4591
|
_kill_proc(self.active_processes.pop(task_id, None) or proc)
|
|
4564
4592
|
_err = (
|
|
@@ -5237,7 +5265,7 @@ class ProcessManager:
|
|
|
5237
5265
|
cwd=str(cwd),
|
|
5238
5266
|
env=env,
|
|
5239
5267
|
limit=100 * 1024 * 1024,
|
|
5240
|
-
|
|
5268
|
+
**_agent_process_group_kwargs(),
|
|
5241
5269
|
**_win_flags,
|
|
5242
5270
|
)
|
|
5243
5271
|
self.active_processes[task_id] = proc
|
|
@@ -5367,6 +5395,19 @@ class ProcessManager:
|
|
|
5367
5395
|
error=failure_error,
|
|
5368
5396
|
metrics=metrics,
|
|
5369
5397
|
)
|
|
5398
|
+
except FileNotFoundError as exc:
|
|
5399
|
+
logger.exception("Copilot executable was not found for task %s", task_id)
|
|
5400
|
+
return TaskResult(
|
|
5401
|
+
status="failed",
|
|
5402
|
+
exit_code=-1,
|
|
5403
|
+
stdout="",
|
|
5404
|
+
stderr="",
|
|
5405
|
+
error=(
|
|
5406
|
+
f"Copilot launch failed: executable not found: {cmd[0]!r}; "
|
|
5407
|
+
f"configured agent path: {agent.command!r} ({exc})"
|
|
5408
|
+
),
|
|
5409
|
+
failure_code="agent_launch_not_found",
|
|
5410
|
+
)
|
|
5370
5411
|
except asyncio.TimeoutError as exc:
|
|
5371
5412
|
_kill_proc(self.active_processes.pop(task_id, None) or proc)
|
|
5372
5413
|
_err = (
|
|
@@ -5428,7 +5469,7 @@ class ProcessManager:
|
|
|
5428
5469
|
cwd=str(cwd),
|
|
5429
5470
|
env=env,
|
|
5430
5471
|
limit=100 * 1024 * 1024, # 100MB line buffer for large agent output
|
|
5431
|
-
|
|
5472
|
+
**_agent_process_group_kwargs(),
|
|
5432
5473
|
)
|
|
5433
5474
|
self.active_processes[task_id] = proc
|
|
5434
5475
|
stdin_bytes = stdin_input.encode() if stdin_input else None
|
|
@@ -5445,6 +5486,16 @@ class ProcessManager:
|
|
|
5445
5486
|
stderr=stderr[-10000:],
|
|
5446
5487
|
error="" if status == "success" else f"Exited with code {returncode}",
|
|
5447
5488
|
)
|
|
5489
|
+
except FileNotFoundError as exc:
|
|
5490
|
+
logger.exception("Agent executable was not found for task %s", task_id)
|
|
5491
|
+
return TaskResult(
|
|
5492
|
+
status="failed",
|
|
5493
|
+
exit_code=-1,
|
|
5494
|
+
stdout="",
|
|
5495
|
+
stderr="",
|
|
5496
|
+
error=f"Agent launch failed: executable not found: {cmd[0]!r} ({exc})",
|
|
5497
|
+
failure_code="agent_launch_not_found",
|
|
5498
|
+
)
|
|
5448
5499
|
except asyncio.TimeoutError as exc:
|
|
5449
5500
|
_kill_proc(self.active_processes.pop(task_id, None) or proc)
|
|
5450
5501
|
_err = (
|
|
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
|