forgexa-cli 1.54.2__tar.gz → 1.55.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.54.2 → forgexa_cli-1.55.1}/PKG-INFO +2 -2
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/README.md +1 -1
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/__init__.py +1 -1
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/agent_core.py +33 -2
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/daemon.py +25 -1
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/main.py +55 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli.egg-info/PKG-INFO +2 -2
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/pyproject.toml +1 -1
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/_build_config.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/_local_bind.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/autoupgrade.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/py.typed +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/runtime_evidence.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli/zcode_protocol.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli.egg-info/SOURCES.txt +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli.egg-info/dependency_links.txt +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli.egg-info/entry_points.txt +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli.egg-info/requires.txt +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/forgexa_cli.egg-info/top_level.txt +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/setup.cfg +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/tests/test_auth_and_runtime_commands.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/tests/test_autoupgrade.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/tests/test_check_command.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/tests/test_expiry_warnings_and_revoke.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/tests/test_local_bind_commands.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/tests/test_runtime_credentials.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/tests/test_session_credentials.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/tests/test_silent_install.py +0 -0
- {forgexa_cli-1.54.2 → forgexa_cli-1.55.1}/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.
|
|
3
|
+
Version: 1.55.1
|
|
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
|
|
@@ -35,7 +35,7 @@ Requires-Dist: socksio>=1.0.0; extra == "daemon"
|
|
|
35
35
|
Command-line client and agent runtime for the [Forgexa](https://forgexa.net) platform.
|
|
36
36
|
|
|
37
37
|
Communicates with the Forgexa server via REST API.
|
|
38
|
-
Includes a built-in **daemon** that discovers
|
|
38
|
+
Includes a built-in **daemon** that discovers twelve local AI agent integrations (Claude Code, Codex, GitHub Copilot, Gemini CLI, OpenCode, Kimi Code, MiMo Code, Qwen Code, CodeBuddy, Qoder CLI, TraeCode CLI, and ZCode) and executes tasks on behalf of the server. MiMo Code (`mimo`, v0.1.14+), Qwen Code (`qwen`, v0.24.1+), CodeBuddy (`codebuddy`, v2.156.0+), Qoder CLI (`qoder`, v1.1.59+), TraeCode CLI (`trae`), and ZCode (`zcode`) are selected explicitly; automatic routing and generated default fallback chains exclude all six. CodeBuddy and Qoder completed their local AgentHost start/resume acceptance gates. Authentication, endpoint, and model selection remain in each local CLI profile; Forgexa never stores or overrides them.
|
|
39
39
|
|
|
40
40
|
## Installation
|
|
41
41
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Command-line client and agent runtime for the [Forgexa](https://forgexa.net) platform.
|
|
4
4
|
|
|
5
5
|
Communicates with the Forgexa server via REST API.
|
|
6
|
-
Includes a built-in **daemon** that discovers
|
|
6
|
+
Includes a built-in **daemon** that discovers twelve local AI agent integrations (Claude Code, Codex, GitHub Copilot, Gemini CLI, OpenCode, Kimi Code, MiMo Code, Qwen Code, CodeBuddy, Qoder CLI, TraeCode CLI, and ZCode) and executes tasks on behalf of the server. MiMo Code (`mimo`, v0.1.14+), Qwen Code (`qwen`, v0.24.1+), CodeBuddy (`codebuddy`, v2.156.0+), Qoder CLI (`qoder`, v1.1.59+), TraeCode CLI (`trae`), and ZCode (`zcode`) are selected explicitly; automatic routing and generated default fallback chains exclude all six. CodeBuddy and Qoder completed their local AgentHost start/resume acceptance gates. Authentication, endpoint, and model selection remain in each local CLI profile; Forgexa never stores or overrides them.
|
|
7
7
|
|
|
8
8
|
## Installation
|
|
9
9
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""forgexa-cli — Forgexa command-line client."""
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.55.1"
|
|
@@ -2311,15 +2311,46 @@ def zcode_binary_fingerprint(binary: str | Path) -> str:
|
|
|
2311
2311
|
return digest.hexdigest()
|
|
2312
2312
|
|
|
2313
2313
|
|
|
2314
|
-
|
|
2315
|
-
|
|
2314
|
+
ZCODE_ALLOWED_SHA256_FILE = Path.home() / ".forgexa" / "zcode-allowed-sha256"
|
|
2315
|
+
|
|
2316
|
+
|
|
2317
|
+
def zcode_allowed_fingerprints(env: dict[str, str] | None = None) -> set[str]:
|
|
2318
|
+
"""Union of the env allowlist and the persistent approval file.
|
|
2319
|
+
|
|
2320
|
+
GUI-launched daemons (macOS Dock/Finder) never inherit shell exports, so
|
|
2321
|
+
an explicit `forgexa zcode approve-build` writes the approval here where
|
|
2322
|
+
every runtime can read it regardless of how it was launched.
|
|
2323
|
+
"""
|
|
2316
2324
|
source_env = os.environ if env is None else env
|
|
2317
2325
|
allowed = {
|
|
2318
2326
|
value.strip().lower()
|
|
2319
2327
|
for value in source_env.get("FORGEXA_ZCODE_ALLOWED_SHA256", "").split(",")
|
|
2320
2328
|
if value.strip()
|
|
2321
2329
|
}
|
|
2330
|
+
try:
|
|
2331
|
+
lines = ZCODE_ALLOWED_SHA256_FILE.read_text(encoding="utf-8").splitlines()
|
|
2332
|
+
except OSError:
|
|
2333
|
+
lines = []
|
|
2334
|
+
for line in lines:
|
|
2335
|
+
value = line.split("#", 1)[0].strip()
|
|
2336
|
+
if value:
|
|
2337
|
+
allowed.add(value.lower())
|
|
2338
|
+
return allowed
|
|
2339
|
+
|
|
2340
|
+
|
|
2341
|
+
def zcode_build_verification_issue(binary: str | Path, env: dict[str, str] | None = None) -> str | None:
|
|
2342
|
+
"""Return a fail-closed reason unless the binary fingerprint is allowlisted."""
|
|
2343
|
+
allowed = zcode_allowed_fingerprints(env)
|
|
2322
2344
|
if not allowed:
|
|
2345
|
+
try:
|
|
2346
|
+
actual = zcode_binary_fingerprint(binary)
|
|
2347
|
+
except OSError:
|
|
2348
|
+
actual = ""
|
|
2349
|
+
if actual:
|
|
2350
|
+
return (
|
|
2351
|
+
"ZCode build is not approved; run `forgexa zcode approve-build` or set "
|
|
2352
|
+
f"FORGEXA_ZCODE_ALLOWED_SHA256={actual}"
|
|
2353
|
+
)
|
|
2323
2354
|
return "ZCode build is not approved; configure FORGEXA_ZCODE_ALLOWED_SHA256"
|
|
2324
2355
|
try:
|
|
2325
2356
|
actual = zcode_binary_fingerprint(binary)
|
|
@@ -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.
|
|
1153
|
+
DAEMON_VERSION = "1.55.1"
|
|
1154
1154
|
|
|
1155
1155
|
|
|
1156
1156
|
def _detect_client_type() -> str:
|
|
@@ -13150,6 +13150,30 @@ class RuntimeDaemon:
|
|
|
13150
13150
|
f"E2E test case {_tc_id} script_path "
|
|
13151
13151
|
f"'{_sp}' does not exist on disk."
|
|
13152
13152
|
)
|
|
13153
|
+
# Contract lint on the script content
|
|
13154
|
+
# (same deterministic rules as
|
|
13155
|
+
# app.services.test_asset_validator):
|
|
13156
|
+
# root-relative APIRequestContext
|
|
13157
|
+
# paths and hardcoded admin route
|
|
13158
|
+
# literals encode deployment-specific
|
|
13159
|
+
# assumptions that only surface when
|
|
13160
|
+
# the script runs outside the sandbox
|
|
13161
|
+
# or gets externally reviewed. Feed
|
|
13162
|
+
# them into the fix-retry loop here so
|
|
13163
|
+
# they are repaired before push.
|
|
13164
|
+
try:
|
|
13165
|
+
from app.services.test_asset_validator import (
|
|
13166
|
+
lint_e2e_script_contract,
|
|
13167
|
+
)
|
|
13168
|
+
# Messages already carry the
|
|
13169
|
+
# "{case_id}: " prefix.
|
|
13170
|
+
issues.extend(
|
|
13171
|
+
lint_e2e_script_contract(
|
|
13172
|
+
_script, str(_tc_id)
|
|
13173
|
+
)
|
|
13174
|
+
)
|
|
13175
|
+
except Exception:
|
|
13176
|
+
pass # standalone vendored daemon
|
|
13153
13177
|
except (_json.JSONDecodeError, UnicodeDecodeError) as e:
|
|
13154
13178
|
issues.append(f"test-cases.json is not valid JSON: {e}")
|
|
13155
13179
|
elif _requires_structured_artifacts or _requires_e2e_artifacts:
|
|
@@ -3573,6 +3573,45 @@ def cmd_upgrade(args: argparse.Namespace) -> None:
|
|
|
3573
3573
|
# ── Argument parser ──
|
|
3574
3574
|
|
|
3575
3575
|
|
|
3576
|
+
def cmd_zcode_approve_build(args: argparse.Namespace) -> None:
|
|
3577
|
+
from . import agent_core
|
|
3578
|
+
|
|
3579
|
+
binary = os.environ.get("FACTORY_ZCODE_PATH") or args.binary or shutil.which("zcode")
|
|
3580
|
+
if not binary:
|
|
3581
|
+
print("error: zcode binary not found; install it or pass --binary PATH", file=sys.stderr)
|
|
3582
|
+
return
|
|
3583
|
+
try:
|
|
3584
|
+
fingerprint = agent_core.zcode_binary_fingerprint(binary)
|
|
3585
|
+
except OSError as exc:
|
|
3586
|
+
print(f"error: could not fingerprint {binary}: {exc}", file=sys.stderr)
|
|
3587
|
+
return
|
|
3588
|
+
path = agent_core.ZCODE_ALLOWED_SHA256_FILE
|
|
3589
|
+
existing = ""
|
|
3590
|
+
try:
|
|
3591
|
+
existing = path.read_text(encoding="utf-8")
|
|
3592
|
+
except OSError:
|
|
3593
|
+
pass
|
|
3594
|
+
approved = {
|
|
3595
|
+
line.split("#", 1)[0].strip().lower()
|
|
3596
|
+
for line in existing.splitlines() if line.split("#", 1)[0].strip()
|
|
3597
|
+
}
|
|
3598
|
+
if fingerprint.lower() in approved:
|
|
3599
|
+
print(f"already approved: {fingerprint}")
|
|
3600
|
+
print(f"allowlist file: {path}")
|
|
3601
|
+
return
|
|
3602
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
3603
|
+
suffix = "" if (not existing or existing.endswith("\n")) else "\n"
|
|
3604
|
+
path.write_text(
|
|
3605
|
+
existing + suffix
|
|
3606
|
+
+ f"{fingerprint} # {binary} approved by `forgexa zcode approve-build`\n",
|
|
3607
|
+
encoding="utf-8",
|
|
3608
|
+
)
|
|
3609
|
+
print(f"approved ZCode build: {fingerprint}")
|
|
3610
|
+
print(f"binary: {binary}")
|
|
3611
|
+
print(f"written to: {path}")
|
|
3612
|
+
print("running daemons and desktop sidecars pick this up on their next probe (no restart needed)")
|
|
3613
|
+
|
|
3614
|
+
|
|
3576
3615
|
def main() -> None:
|
|
3577
3616
|
global _SERVER_URL_OVERRIDE, _output_format
|
|
3578
3617
|
|
|
@@ -3789,6 +3828,19 @@ def main() -> None:
|
|
|
3789
3828
|
help="Per-agent timeout for the live execution test (default: 90)",
|
|
3790
3829
|
)
|
|
3791
3830
|
|
|
3831
|
+
# zcode
|
|
3832
|
+
zcode_p = sub.add_parser("zcode", help="ZCode integration helpers")
|
|
3833
|
+
zcode_sub = zcode_p.add_subparsers(dest="zcode_cmd")
|
|
3834
|
+
zcode_approve_p = zcode_sub.add_parser(
|
|
3835
|
+
"approve-build",
|
|
3836
|
+
help="Persistently approve the installed ZCode binary fingerprint "
|
|
3837
|
+
"(works for GUI-launched daemons that never see shell exports)",
|
|
3838
|
+
)
|
|
3839
|
+
zcode_approve_p.add_argument(
|
|
3840
|
+
"--binary", default=None, metavar="PATH",
|
|
3841
|
+
help="Path to the zcode binary (default: $FACTORY_ZCODE_PATH or `zcode` on PATH)",
|
|
3842
|
+
)
|
|
3843
|
+
|
|
3792
3844
|
# runtimes
|
|
3793
3845
|
rt_p = sub.add_parser("runtimes", help="Runtime management")
|
|
3794
3846
|
rt_sub = rt_p.add_subparsers(dest="rt_cmd")
|
|
@@ -3918,6 +3970,9 @@ def main() -> None:
|
|
|
3918
3970
|
"logs": cmd_daemon_logs,
|
|
3919
3971
|
"agents": cmd_daemon_agents,
|
|
3920
3972
|
"check": cmd_check,
|
|
3973
|
+
"zcode": lambda a: {
|
|
3974
|
+
"approve-build": cmd_zcode_approve_build,
|
|
3975
|
+
}.get(a.zcode_cmd, lambda _: zcode_p.print_help())(a),
|
|
3921
3976
|
"runtimes": lambda a: {
|
|
3922
3977
|
"list": cmd_runtimes_list,
|
|
3923
3978
|
}.get(a.rt_cmd, lambda _: rt_p.print_help())(a),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: forgexa-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.55.1
|
|
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
|
|
@@ -35,7 +35,7 @@ Requires-Dist: socksio>=1.0.0; extra == "daemon"
|
|
|
35
35
|
Command-line client and agent runtime for the [Forgexa](https://forgexa.net) platform.
|
|
36
36
|
|
|
37
37
|
Communicates with the Forgexa server via REST API.
|
|
38
|
-
Includes a built-in **daemon** that discovers
|
|
38
|
+
Includes a built-in **daemon** that discovers twelve local AI agent integrations (Claude Code, Codex, GitHub Copilot, Gemini CLI, OpenCode, Kimi Code, MiMo Code, Qwen Code, CodeBuddy, Qoder CLI, TraeCode CLI, and ZCode) and executes tasks on behalf of the server. MiMo Code (`mimo`, v0.1.14+), Qwen Code (`qwen`, v0.24.1+), CodeBuddy (`codebuddy`, v2.156.0+), Qoder CLI (`qoder`, v1.1.59+), TraeCode CLI (`trae`), and ZCode (`zcode`) are selected explicitly; automatic routing and generated default fallback chains exclude all six. CodeBuddy and Qoder completed their local AgentHost start/resume acceptance gates. Authentication, endpoint, and model selection remain in each local CLI profile; Forgexa never stores or overrides them.
|
|
39
39
|
|
|
40
40
|
## Installation
|
|
41
41
|
|
|
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
|