forgexa-cli 1.81.1__tar.gz → 1.82.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.81.1 → forgexa_cli-1.82.1}/PKG-INFO +1 -1
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/__init__.py +1 -1
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/daemon.py +29 -13
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli.egg-info/PKG-INFO +1 -1
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/pyproject.toml +1 -1
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/README.md +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/_build_config.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/_local_bind.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/agent_core.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/autoupgrade.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/aws_evidence.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/aws_logs_evidence.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/main.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/observability_contract.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/observability_evidence.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/py.typed +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/runtime_evidence.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli/zcode_protocol.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli.egg-info/SOURCES.txt +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli.egg-info/dependency_links.txt +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli.egg-info/entry_points.txt +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli.egg-info/requires.txt +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/forgexa_cli.egg-info/top_level.txt +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/setup.cfg +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_auth_and_runtime_commands.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_autoupgrade.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_check_command.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_expiry_warnings_and_revoke.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_local_bind_commands.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_runtime_credentials.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_session_credentials.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_silent_install.py +0 -0
- {forgexa_cli-1.81.1 → forgexa_cli-1.82.1}/tests/test_upgrade_observability.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""forgexa-cli — Forgexa command-line client."""
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.82.1"
|
|
@@ -1234,7 +1234,7 @@ except (ImportError, ModuleNotFoundError):
|
|
|
1234
1234
|
# DAEMON_VERSION is the protocol/logic version of the daemon code.
|
|
1235
1235
|
# Kept in sync with pyproject.toml version via bump-version.sh.
|
|
1236
1236
|
# CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
|
|
1237
|
-
DAEMON_VERSION = "1.
|
|
1237
|
+
DAEMON_VERSION = "1.82.1"
|
|
1238
1238
|
|
|
1239
1239
|
|
|
1240
1240
|
def _detect_client_type() -> str:
|
|
@@ -2212,6 +2212,7 @@ def _normalize_ai_job_output(
|
|
|
2212
2212
|
"qa_scenario_generate_prompt",
|
|
2213
2213
|
"qa_scenario_preview",
|
|
2214
2214
|
"qa_script_preview",
|
|
2215
|
+
"qa_recording_suggest",
|
|
2215
2216
|
"test_script_generate",
|
|
2216
2217
|
}:
|
|
2217
2218
|
return raw_output, None
|
|
@@ -9951,6 +9952,7 @@ class ServerConnection:
|
|
|
9951
9952
|
},
|
|
9952
9953
|
"implementation_audit": {"protocol_version": 3},
|
|
9953
9954
|
"task_delivery": {"protocol_version": 1},
|
|
9955
|
+
"recording_suggestions": {"protocol_version": 1, "isolated_workspace": True},
|
|
9954
9956
|
"task_attachment_staging": {"protocol_version": 1, "runtime_proxy": True, "image_agents": ["claude"]},
|
|
9955
9957
|
},
|
|
9956
9958
|
"server_url": self.server_url,
|
|
@@ -10376,6 +10378,7 @@ class ServerConnection:
|
|
|
10376
10378
|
},
|
|
10377
10379
|
"implementation_audit": {"protocol_version": 3},
|
|
10378
10380
|
"task_delivery": {"protocol_version": 1},
|
|
10381
|
+
"recording_suggestions": {"protocol_version": 1, "isolated_workspace": True},
|
|
10379
10382
|
"local_evidence": {"protocol_version": 1, "structured_summary": True},
|
|
10380
10383
|
"task_attachment_staging": {"protocol_version": 1, "runtime_proxy": True, "image_agents": ["claude"]},
|
|
10381
10384
|
},
|
|
@@ -15462,8 +15465,9 @@ class RuntimeDaemon:
|
|
|
15462
15465
|
if task_type == "deployment_merge":
|
|
15463
15466
|
await self._execute_deployment_merge_job(aj, conn)
|
|
15464
15467
|
return
|
|
15465
|
-
project_info =
|
|
15466
|
-
|
|
15468
|
+
project_info = ({"id": job_id, "project_key": f"recording-{job_id}", "name": "Recording suggestions", "repo_url": ""}
|
|
15469
|
+
if task_type == "qa_recording_suggest" else aj.get("project", {}))
|
|
15470
|
+
requirement_key = None if task_type == "qa_recording_suggest" else aj.get("requirement_key")
|
|
15467
15471
|
agent_override = aj.get("agent_override")
|
|
15468
15472
|
system_prompt = aj.get("system_prompt", "")
|
|
15469
15473
|
user_prompt = aj.get("user_prompt", "")
|
|
@@ -15491,6 +15495,7 @@ class RuntimeDaemon:
|
|
|
15491
15495
|
)
|
|
15492
15496
|
await project_lock.acquire()
|
|
15493
15497
|
workspace_execution_lock: _WorkspaceFileLock | None = None
|
|
15498
|
+
recording_workspace = None
|
|
15494
15499
|
|
|
15495
15500
|
try:
|
|
15496
15501
|
# Report progress: starting
|
|
@@ -15553,7 +15558,7 @@ class RuntimeDaemon:
|
|
|
15553
15558
|
# 2. Prepare workspace (using project info + requirement branch)
|
|
15554
15559
|
full_prompt = f"{system_prompt}\n\n{user_prompt}" if system_prompt else user_prompt
|
|
15555
15560
|
task_timeout = settings.AGENT_TIMEOUT
|
|
15556
|
-
if task_type in {"qa_scenario_preview", "qa_script_preview"}:
|
|
15561
|
+
if task_type in {"qa_scenario_preview", "qa_script_preview", "qa_recording_suggest"}:
|
|
15557
15562
|
try:
|
|
15558
15563
|
task_timeout = min(
|
|
15559
15564
|
max(int(input_ctx.get("timeout_seconds", settings.AGENT_TIMEOUT)), 30),
|
|
@@ -15583,13 +15588,19 @@ class RuntimeDaemon:
|
|
|
15583
15588
|
workspace_source_mode=qa_ws_source.get("mode"),
|
|
15584
15589
|
workspace_branch=qa_ws_source.get("branch"),
|
|
15585
15590
|
)
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
|
|
15590
|
-
|
|
15591
|
-
|
|
15592
|
-
|
|
15591
|
+
if task_type == "qa_recording_suggest":
|
|
15592
|
+
import tempfile as _recording_tempfile
|
|
15593
|
+
|
|
15594
|
+
recording_workspace = _recording_tempfile.TemporaryDirectory(prefix="forgexa-recording-suggest-")
|
|
15595
|
+
workspace_path = Path(recording_workspace.name)
|
|
15596
|
+
else:
|
|
15597
|
+
workspace_execution_lock = await self.workspace_manager.acquire_workspace_execution_lock(
|
|
15598
|
+
project_info,
|
|
15599
|
+
fake_task,
|
|
15600
|
+
)
|
|
15601
|
+
workspace_path = await self.workspace_manager.prepare_workspace(
|
|
15602
|
+
project_info, fake_task,
|
|
15603
|
+
)
|
|
15593
15604
|
|
|
15594
15605
|
if task_type == "qa_scenario_generate_prompt" and not input_ctx.get("project_context"):
|
|
15595
15606
|
local_project_context = _summarize_workspace_source(workspace_path)
|
|
@@ -15829,7 +15840,7 @@ class RuntimeDaemon:
|
|
|
15829
15840
|
# Pushing here is dangerous because it can propagate stale local branch
|
|
15830
15841
|
# state even when the AIJob produced no repo changes at all.
|
|
15831
15842
|
git_info = {}
|
|
15832
|
-
if result.status == "success":
|
|
15843
|
+
if result.status == "success" and task_type != "qa_recording_suggest":
|
|
15833
15844
|
git_info = await self._collect_workspace_git_info(workspace_path)
|
|
15834
15845
|
|
|
15835
15846
|
# 5. Report completion
|
|
@@ -15850,7 +15861,7 @@ class RuntimeDaemon:
|
|
|
15850
15861
|
scenario_ids=input_ctx.get("scenario_ids", []),
|
|
15851
15862
|
workspace_path=workspace_path,
|
|
15852
15863
|
)
|
|
15853
|
-
if task_type in {"qa_scenario_generate_prompt", "qa_scenario_preview", "qa_script_preview"}:
|
|
15864
|
+
if task_type in {"qa_scenario_generate_prompt", "qa_scenario_preview", "qa_script_preview", "qa_recording_suggest"}:
|
|
15854
15865
|
output_content, scenario_items = _prepare_ai_job_output(
|
|
15855
15866
|
task_type=task_type,
|
|
15856
15867
|
agent_id=agent.agent_id,
|
|
@@ -15913,6 +15924,11 @@ class RuntimeDaemon:
|
|
|
15913
15924
|
except Exception:
|
|
15914
15925
|
pass
|
|
15915
15926
|
finally:
|
|
15927
|
+
if recording_workspace is not None:
|
|
15928
|
+
try:
|
|
15929
|
+
recording_workspace.cleanup()
|
|
15930
|
+
except OSError:
|
|
15931
|
+
logger.warning("Recording suggestion temporary workspace cleanup failed")
|
|
15916
15932
|
if workspace_execution_lock is not None:
|
|
15917
15933
|
workspace_execution_lock.release()
|
|
15918
15934
|
project_lock.release()
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|