evalgate-sdk 3.5.0__tar.gz → 3.5.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.
Files changed (122) hide show
  1. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/CHANGELOG.md +9 -0
  2. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/PKG-INFO +32 -2
  3. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/README.md +29 -1
  4. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/pyproject.toml +5 -1
  5. evalgate_sdk-3.5.1/src/evalgate_sdk/_version.py +3 -0
  6. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/__init__.py +29 -0
  7. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/commands.py +280 -35
  8. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/config.py +31 -0
  9. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/new_commands.py +23 -1
  10. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/regression_gate.py +20 -5
  11. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/client.py +354 -24
  12. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/executor.py +2 -2
  13. evalgate_sdk-3.5.1/tests/test_cli_hardening_351.py +321 -0
  14. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_client.py +195 -0
  15. evalgate_sdk-3.5.0/src/evalgate_sdk/_version.py +0 -3
  16. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/.gitignore +0 -0
  17. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/__init__.py +0 -0
  18. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/assertions.py +0 -0
  19. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/auto.py +0 -0
  20. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/auto_experiment_runner.py +0 -0
  21. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/auto_failure_analyzer.py +0 -0
  22. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/auto_mutation_engine.py +0 -0
  23. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/batch.py +0 -0
  24. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cache.py +0 -0
  25. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/ci_context.py +0 -0
  26. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/api.py +0 -0
  27. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/api_command_config.py +0 -0
  28. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/cli_constants.py +0 -0
  29. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/env.py +0 -0
  30. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/formatters/types.py +0 -0
  31. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/golden_commands.py +0 -0
  32. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/judge_commands.py +0 -0
  33. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/manifest.py +0 -0
  34. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/policy_packs.py +0 -0
  35. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/profiles.py +0 -0
  36. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/render/__init__.py +0 -0
  37. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/render/snippet.py +0 -0
  38. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/render/sort.py +0 -0
  39. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/report/__init__.py +0 -0
  40. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/report/build_check_report.py +0 -0
  41. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/traces.py +0 -0
  42. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/workflow_commands.py +0 -0
  43. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cli/workspace.py +0 -0
  44. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/cluster.py +0 -0
  45. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/collector.py +0 -0
  46. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/constants.py +0 -0
  47. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/context.py +0 -0
  48. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/errors.py +0 -0
  49. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/export.py +0 -0
  50. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/formatters/__init__.py +0 -0
  51. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/formatters/github.py +0 -0
  52. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/formatters/human.py +0 -0
  53. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/formatters/json_fmt.py +0 -0
  54. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/formatters/pr_comment.py +0 -0
  55. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/golden.py +0 -0
  56. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/integrations/__init__.py +0 -0
  57. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/integrations/anthropic.py +0 -0
  58. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/integrations/autogen.py +0 -0
  59. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/integrations/crewai.py +0 -0
  60. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/integrations/langchain.py +0 -0
  61. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/integrations/openai.py +0 -0
  62. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/integrations/openai_eval.py +0 -0
  63. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/knowledge.py +0 -0
  64. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/local.py +0 -0
  65. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/logger.py +0 -0
  66. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/matchers.py +0 -0
  67. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/otel.py +0 -0
  68. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/pagination.py +0 -0
  69. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/py.typed +0 -0
  70. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/pytest_plugin.py +0 -0
  71. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/reason_codes.py +0 -0
  72. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/regression.py +0 -0
  73. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/replay_decision.py +0 -0
  74. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/__init__.py +0 -0
  75. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/adapters/__init__.py +0 -0
  76. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/adapters/config_to_dsl.py +0 -0
  77. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/adapters/testsuite_to_dsl.py +0 -0
  78. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/context.py +0 -0
  79. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/eval.py +0 -0
  80. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/execution_mode.py +0 -0
  81. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/registry.py +0 -0
  82. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/run_report.py +0 -0
  83. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/runtime/types.py +0 -0
  84. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/snapshot.py +0 -0
  85. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/streaming.py +0 -0
  86. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/synthesize.py +0 -0
  87. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/testing.py +0 -0
  88. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/types.py +0 -0
  89. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/utils/__init__.py +0 -0
  90. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/utils/input_hash.py +0 -0
  91. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/src/evalgate_sdk/workflows.py +0 -0
  92. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/__init__.py +0 -0
  93. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_assertions.py +0 -0
  94. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_assertions_async.py +0 -0
  95. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_auto_mutation_engine_parity.py +0 -0
  96. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_auto_session_methods.py +0 -0
  97. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_batch_collector.py +0 -0
  98. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_ci_context.py +0 -0
  99. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_cli_golden_commands.py +0 -0
  100. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_cli_new_commands.py +0 -0
  101. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_collector.py +0 -0
  102. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_contract_payloads.py +0 -0
  103. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_decorators_and_integrations.py +0 -0
  104. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_errors.py +0 -0
  105. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_execution_mode.py +0 -0
  106. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_formatters.py +0 -0
  107. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_knowledge_methods.py +0 -0
  108. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_local_storage.py +0 -0
  109. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_new_modules.py +0 -0
  110. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_openapi_contracts.py +0 -0
  111. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_otel.py +0 -0
  112. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_parity_gap_modules.py +0 -0
  113. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_parity_gaps.py +0 -0
  114. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_prod_hardening.py +0 -0
  115. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_pytest_plugin.py +0 -0
  116. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_run_report.py +0 -0
  117. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_runtime_dsl.py +0 -0
  118. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_sdk_contract_scaffold.py +0 -0
  119. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_testing.py +0 -0
  120. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_types.py +0 -0
  121. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_workflows.py +0 -0
  122. {evalgate_sdk-3.5.0 → evalgate_sdk-3.5.1}/tests/test_workflows_parity.py +0 -0
@@ -9,6 +9,15 @@ Version numbering is aligned with the TypeScript SDK (`@evalgate/sdk`) and the p
9
9
 
10
10
  **Version history note:** The Python SDK jumped from 1.0.0 → 1.9.x → 2.0.0 to stay in sync with the TypeScript SDK. The TypeScript SDK had many releases (1.1–1.9) before the Python SDK existed. We now align both SDKs on the same major.minor version.
11
11
 
12
+ ## [3.5.1] - 2026-06-26
13
+
14
+ ### Fixed
15
+ - **CLI JSON contracts** — `check --format json` now emits one parseable JSON document.
16
+ - **Zero-config scaffolds** — `start --template` writes config that `run` and `doctor` discover consistently.
17
+ - **Runtime scoring defaults** — boolean/dict executor fallbacks now use the SDK's 0-100 score scale.
18
+ - **Sync safety** — missing labeled datasets surface an explicit error, and prompt pulls write UTF-8 content on Windows.
19
+ - **Default CLI install** — `pip install evalgate-sdk` now includes the runtime dependencies needed for the `evalgate` command.
20
+
12
21
  ## [3.5.0] - 2026-04-09
13
22
 
14
23
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evalgate-sdk
3
- Version: 3.5.0
3
+ Version: 3.5.1
4
4
  Summary: EvalGate Python SDK — CI for AI behavior. Traces, evaluations, assertions, and regression gates for LLM apps.
5
5
  Project-URL: Homepage, https://evalgate.com
6
6
  Project-URL: Documentation, https://github.com/evalgate/ai-evaluation-platform#readme
@@ -24,6 +24,8 @@ Classifier: Typing :: Typed
24
24
  Requires-Python: >=3.10
25
25
  Requires-Dist: httpx<1,>=0.27
26
26
  Requires-Dist: pydantic<3,>=2.0
27
+ Requires-Dist: rich>=13
28
+ Requires-Dist: typer>=0.12
27
29
  Provides-Extra: all
28
30
  Requires-Dist: anthropic>=0.20; extra == 'all'
29
31
  Requires-Dist: langchain-core>=0.2; extra == 'all'
@@ -65,7 +67,6 @@ Use it to run assertions, trace agent workflows, inspect platform runs, orchestr
65
67
 
66
68
  ```bash
67
69
  pip install evalgate-sdk
68
- pip install "evalgate-sdk[cli]"
69
70
  ```
70
71
 
71
72
  Optional extras:
@@ -125,6 +126,35 @@ evalgate judge registry
125
126
  evalgate judge presets
126
127
  ```
127
128
 
129
+ ## Web App Sync
130
+
131
+ The Python CLI uses the same sync contracts as the TypeScript SDK. Local labeled
132
+ JSONL can be pushed into the web app, web-labeled cases can be merged back into
133
+ the same file, and prompt files can round-trip with stale active-version
134
+ protection.
135
+
136
+ ```bash
137
+ # Push local labels into the web app and pull web labels back into JSONL
138
+ evalgate sync \
139
+ --project-key support-agent \
140
+ --labeled-dataset .evalgate/golden/labeled.jsonl \
141
+ --pull-labels
142
+
143
+ # Pull the active web prompt into a local file
144
+ evalgate sync \
145
+ --project-key support-agent \
146
+ --prompt-id prompt_support \
147
+ --target-path prompts/support.md \
148
+ --pull-prompt
149
+
150
+ # Push an edited local prompt as a new web prompt version
151
+ evalgate sync \
152
+ --project-key support-agent \
153
+ --prompt-id prompt_support \
154
+ --target-path prompts/support.md \
155
+ --push-prompt
156
+ ```
157
+
128
158
  ## Judge Orchestration
129
159
 
130
160
  The Python SDK supports the same core judge model as the platform:
@@ -13,7 +13,6 @@ Use it to run assertions, trace agent workflows, inspect platform runs, orchestr
13
13
 
14
14
  ```bash
15
15
  pip install evalgate-sdk
16
- pip install "evalgate-sdk[cli]"
17
16
  ```
18
17
 
19
18
  Optional extras:
@@ -73,6 +72,35 @@ evalgate judge registry
73
72
  evalgate judge presets
74
73
  ```
75
74
 
75
+ ## Web App Sync
76
+
77
+ The Python CLI uses the same sync contracts as the TypeScript SDK. Local labeled
78
+ JSONL can be pushed into the web app, web-labeled cases can be merged back into
79
+ the same file, and prompt files can round-trip with stale active-version
80
+ protection.
81
+
82
+ ```bash
83
+ # Push local labels into the web app and pull web labels back into JSONL
84
+ evalgate sync \
85
+ --project-key support-agent \
86
+ --labeled-dataset .evalgate/golden/labeled.jsonl \
87
+ --pull-labels
88
+
89
+ # Pull the active web prompt into a local file
90
+ evalgate sync \
91
+ --project-key support-agent \
92
+ --prompt-id prompt_support \
93
+ --target-path prompts/support.md \
94
+ --pull-prompt
95
+
96
+ # Push an edited local prompt as a new web prompt version
97
+ evalgate sync \
98
+ --project-key support-agent \
99
+ --prompt-id prompt_support \
100
+ --target-path prompts/support.md \
101
+ --push-prompt
102
+ ```
103
+
76
104
  ## Judge Orchestration
77
105
 
78
106
  The Python SDK supports the same core judge model as the platform:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "evalgate-sdk"
7
- version = "3.5.0"
7
+ version = "3.5.1"
8
8
  description = "EvalGate Python SDK — CI for AI behavior. Traces, evaluations, assertions, and regression gates for LLM apps."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -31,6 +31,8 @@ classifiers = [
31
31
  dependencies = [
32
32
  "httpx>=0.27,<1",
33
33
  "pydantic>=2.0,<3",
34
+ "rich>=13",
35
+ "typer>=0.12",
34
36
  ]
35
37
 
36
38
  [project.optional-dependencies]
@@ -66,6 +68,8 @@ packages = ["src/evalgate_sdk"]
66
68
  [tool.pytest.ini_options]
67
69
  testpaths = ["tests"]
68
70
  asyncio_mode = "auto"
71
+ asyncio_default_fixture_loop_scope = "function"
72
+ pythonpath = ["src"]
69
73
 
70
74
  [tool.ruff]
71
75
  target-version = "py310"
@@ -0,0 +1,3 @@
1
+ __version__ = "3.5.1"
2
+ SDK_VERSION = __version__
3
+ SPEC_VERSION = "3.5.1"
@@ -6,10 +6,34 @@ Submodules like config.py, api.py, etc. can be imported without typer.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
+ import sys
10
+
9
11
  # Lazy initialization - only set up CLI when typer is available
10
12
  app = None # Will be initialized on first access via get_app()
11
13
 
12
14
 
15
+ def _stream_needs_replacement_errors(stream: object) -> bool:
16
+ """Return whether the stream encoding cannot represent common CLI glyphs."""
17
+ encoding = getattr(stream, "encoding", None)
18
+ if not encoding:
19
+ return False
20
+ try:
21
+ "✓ → ─".encode(encoding)
22
+ return False
23
+ except (LookupError, UnicodeEncodeError):
24
+ return True
25
+
26
+
27
+ def _make_output_streams_encoding_safe() -> None:
28
+ """Prevent Windows legacy code pages from crashing Rich/Typer help output."""
29
+ for stream in (sys.stdout, sys.stderr):
30
+ if not _stream_needs_replacement_errors(stream):
31
+ continue
32
+ reconfigure = getattr(stream, "reconfigure", None)
33
+ if reconfigure is not None:
34
+ reconfigure(errors="replace")
35
+
36
+
13
37
  def _ensure_typer() -> None:
14
38
  """Check that typer is installed, raise helpful error if not."""
15
39
  try:
@@ -50,7 +74,9 @@ def get_app():
50
74
  print_config,
51
75
  run,
52
76
  share,
77
+ sync,
53
78
  upgrade,
79
+ version,
54
80
  )
55
81
  from evalgate_sdk.cli.judge_commands import judge
56
82
  from evalgate_sdk.cli.workflow_commands import controls, integrity, knowledge, plan, trace, workflow
@@ -74,8 +100,10 @@ def get_app():
74
100
  app.command("baseline")(baseline)
75
101
  app.command("print-config")(print_config)
76
102
  app.command("share")(share)
103
+ app.command("sync")(sync)
77
104
  app.command("configure")(configure)
78
105
  app.command("upgrade")(upgrade)
106
+ app.command("version")(version)
79
107
  app.command("impact-analysis")(impact_analysis)
80
108
  app.command("migrate")(migrate)
81
109
 
@@ -116,5 +144,6 @@ def __getattr__(name: str):
116
144
 
117
145
  def main() -> None:
118
146
  """CLI entry point."""
147
+ _make_output_streams_encoding_safe()
119
148
  cli_app = get_app()
120
149
  cli_app()