graph-agents-cli 0.3.1__py3-none-any.whl
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.
- graph_agents_cli/__init__.py +26 -0
- graph_agents_cli/_api_policy.py +2145 -0
- graph_agents_cli/_approvals.py +400 -0
- graph_agents_cli/_build.py +186 -0
- graph_agents_cli/_build_info.json +7 -0
- graph_agents_cli/_chat_client.py +462 -0
- graph_agents_cli/_click.py +157 -0
- graph_agents_cli/_defaults.py +139 -0
- graph_agents_cli/_experiments.py +64 -0
- graph_agents_cli/_http.py +192 -0
- graph_agents_cli/_output.py +83 -0
- graph_agents_cli/_project.py +462 -0
- graph_agents_cli/_remote.py +220 -0
- graph_agents_cli/_response_schema.py +264 -0
- graph_agents_cli/_runner.py +319 -0
- graph_agents_cli/_skills_check.py +274 -0
- graph_agents_cli/_tools.py +189 -0
- graph_agents_cli/_trust.py +66 -0
- graph_agents_cli/api/__init__.py +15 -0
- graph_agents_cli/api/_changes.py +506 -0
- graph_agents_cli/api/_files.py +658 -0
- graph_agents_cli/api/cmd_api.py +2480 -0
- graph_agents_cli/deploy/__init__.py +15 -0
- graph_agents_cli/deploy/_config.py +171 -0
- graph_agents_cli/deploy/_image.py +128 -0
- graph_agents_cli/deploy/_kube.py +286 -0
- graph_agents_cli/deploy/_modes.py +234 -0
- graph_agents_cli/deploy/_preflight.py +370 -0
- graph_agents_cli/deploy/_values.py +168 -0
- graph_agents_cli/deploy/cmd_deploy.py +1866 -0
- graph_agents_cli/deploy/gitops.py +562 -0
- graph_agents_cli/deploy/local_load.py +273 -0
- graph_agents_cli/dev/__init__.py +13 -0
- graph_agents_cli/dev/cmd_build.py +131 -0
- graph_agents_cli/dev/cmd_install.py +78 -0
- graph_agents_cli/dev/cmd_lint.py +119 -0
- graph_agents_cli/dev/cmd_playground.py +297 -0
- graph_agents_cli/dev/policy_check.py +1287 -0
- graph_agents_cli/eval/__init__.py +22 -0
- graph_agents_cli/eval/_client.py +670 -0
- graph_agents_cli/eval/_common.py +177 -0
- graph_agents_cli/eval/_judge.py +168 -0
- graph_agents_cli/eval/_judge_runner.py +238 -0
- graph_agents_cli/eval/_paths.py +212 -0
- graph_agents_cli/eval/checks.py +581 -0
- graph_agents_cli/eval/cmd_analyze.py +278 -0
- graph_agents_cli/eval/cmd_compare.py +284 -0
- graph_agents_cli/eval/cmd_eval_group.py +80 -0
- graph_agents_cli/eval/cmd_generate.py +558 -0
- graph_agents_cli/eval/cmd_grade.py +466 -0
- graph_agents_cli/eval/cmd_metric.py +156 -0
- graph_agents_cli/eval/cmd_run.py +370 -0
- graph_agents_cli/eval/cmd_submit.py +400 -0
- graph_agents_cli/eval/config.py +435 -0
- graph_agents_cli/eval/dataset.py +350 -0
- graph_agents_cli/eval/gate.py +420 -0
- graph_agents_cli/eval/transcript.py +192 -0
- graph_agents_cli/extension/__init__.py +13 -0
- graph_agents_cli/extension/_compat.py +86 -0
- graph_agents_cli/extension/_loader.py +293 -0
- graph_agents_cli/extension/_manifest.py +135 -0
- graph_agents_cli/extension/_overrides.py +195 -0
- graph_agents_cli/extension/_paths.py +91 -0
- graph_agents_cli/extension/_refs.py +193 -0
- graph_agents_cli/extension/_resolver.py +453 -0
- graph_agents_cli/extension/_schema.py +106 -0
- graph_agents_cli/extension/_spec.py +253 -0
- graph_agents_cli/extension/_sync.py +102 -0
- graph_agents_cli/extension/_trust.py +58 -0
- graph_agents_cli/extension/cmd_extension_add.py +259 -0
- graph_agents_cli/extension/cmd_extension_group.py +57 -0
- graph_agents_cli/extension/cmd_extension_list.py +56 -0
- graph_agents_cli/extension/cmd_extension_remove.py +61 -0
- graph_agents_cli/extension/cmd_extension_update.py +195 -0
- graph_agents_cli/info/__init__.py +13 -0
- graph_agents_cli/info/cmd_info.py +222 -0
- graph_agents_cli/infra/__init__.py +15 -0
- graph_agents_cli/infra/checks.py +1169 -0
- graph_agents_cli/infra/cmd_infra.py +103 -0
- graph_agents_cli/main.py +591 -0
- graph_agents_cli/peer/__init__.py +15 -0
- graph_agents_cli/peer/_generate.py +254 -0
- graph_agents_cli/peer/cmd_peer.py +1151 -0
- graph_agents_cli/run/__init__.py +13 -0
- graph_agents_cli/run/_local_server.py +1157 -0
- graph_agents_cli/run/_signals.py +141 -0
- graph_agents_cli/run/cmd_approvals.py +530 -0
- graph_agents_cli/run/cmd_run.py +1421 -0
- graph_agents_cli/scaffold/__init__.py +19 -0
- graph_agents_cli/scaffold/agents/README.md +24 -0
- graph_agents_cli/scaffold/agents/empty_py/.template/templateconfig.yaml +22 -0
- graph_agents_cli/scaffold/agents/langgraph/.env.example +292 -0
- graph_agents_cli/scaffold/agents/langgraph/.template/templateconfig.yaml +28 -0
- graph_agents_cli/scaffold/agents/langgraph/Dockerfile +59 -0
- graph_agents_cli/scaffold/agents/langgraph/Dockerfile.langgraph-server +59 -0
- graph_agents_cli/scaffold/agents/langgraph/README.md +571 -0
- graph_agents_cli/scaffold/agents/langgraph/api-policy.yaml +60 -0
- graph_agents_cli/scaffold/agents/langgraph/app/__init__.py +20 -0
- graph_agents_cli/scaffold/agents/langgraph/app/agent.py +174 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/__init__.py +15 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/a2a.py +2162 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/a2a_client.py +1167 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/api_client.py +4220 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/approvals.py +1349 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/auth.py +1986 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/chat.py +2962 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/checkpointer.py +432 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/content.py +569 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/db.py +580 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/limits.py +203 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/metrics.py +231 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/middleware.py +361 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/model.py +611 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/playground.py +230 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/run_locks.py +459 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/structured.py +755 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/telemetry.py +681 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/threads.py +493 -0
- graph_agents_cli/scaffold/agents/langgraph/app/app_utils/token_exchange.py +959 -0
- graph_agents_cli/scaffold/agents/langgraph/app/fast_api_app.py +770 -0
- graph_agents_cli/scaffold/agents/langgraph/app/policies/__init__.py +55 -0
- graph_agents_cli/scaffold/agents/langgraph/app/policies/custom.py +97 -0
- graph_agents_cli/scaffold/agents/langgraph/app/tools/__init__.py +46 -0
- graph_agents_cli/scaffold/agents/langgraph/app/tools/example_api.py +92 -0
- graph_agents_cli/scaffold/agents/langgraph/app/tools/weather.py +33 -0
- graph_agents_cli/scaffold/agents/langgraph/langgraph.json +14 -0
- graph_agents_cli/scaffold/agents/langgraph/pyproject.toml +78 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/conftest.py +376 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/eval/datasets/basic-dataset.json +53 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/eval/eval_config.yaml +32 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/approval_graph.py +137 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/fake_issuer.py +216 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/fake_openai.py +357 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_a2a_outcomes.py +569 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_a2a_relay.py +479 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_api_surface.py +812 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_approvals.py +1367 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_approvals_server.py +794 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_cross_actor.py +497 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_cross_actor_server.py +247 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_history_repair.py +278 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_model_apis.py +242 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_postgres.py +637 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_resilience_postgres.py +770 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_runtime_guardrails.py +854 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_server_e2e.py +340 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_server_runtime.py +989 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_structured_answers.py +584 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_structured_server.py +222 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_token_exchange_issuer.py +650 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/load_test/.results/.placeholder +0 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/load_test/README.md +22 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/load_test/conftest.py +21 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/load_test/load_test.py +81 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_a2a_client.py +824 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_a2a_scoping.py +724 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_client.py +1214 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_client_hardening.py +716 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_policy_rpc.py +767 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_approval_ledger.py +1536 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_fake_model.py +115 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_jwt_policy.py +991 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_limits.py +310 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_logging.py +148 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_logging_hardening.py +271 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_policy.py +378 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_resilience.py +610 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_server_auth.py +702 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_structured.py +673 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_telemetry.py +404 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_thread_listing.py +255 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_threads.py +268 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_token_exchange.py +1320 -0
- graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_untrusted_content.py +393 -0
- graph_agents_cli/scaffold/agents/langgraph/uv-fastapi.lock +2084 -0
- graph_agents_cli/scaffold/agents/langgraph/uv-langgraph-server.lock +2106 -0
- graph_agents_cli/scaffold/agents/langgraph/{{cookiecutter.agent_guidance_filename}} +129 -0
- graph_agents_cli/scaffold/base_templates/_shared/graph-agents-cli-manifest.yaml +36 -0
- graph_agents_cli/scaffold/base_templates/python/.dockerignore +32 -0
- graph_agents_cli/scaffold/base_templates/python/.github/CODEOWNERS +30 -0
- graph_agents_cli/scaffold/base_templates/python/.github/agent.env +7 -0
- graph_agents_cli/scaffold/base_templates/python/.github/workflows/pr_checks.yaml +214 -0
- graph_agents_cli/scaffold/base_templates/python/.gitignore +209 -0
- graph_agents_cli/scaffold/base_templates/python/tests/unit/test_dummy.py +23 -0
- graph_agents_cli/scaffold/base_templates/python/{{cookiecutter.agent_guidance_filename}} +35 -0
- graph_agents_cli/scaffold/cmd_scaffold_group.py +49 -0
- graph_agents_cli/scaffold/commands/__init__.py +13 -0
- graph_agents_cli/scaffold/commands/create.py +1424 -0
- graph_agents_cli/scaffold/commands/enhance.py +1652 -0
- graph_agents_cli/scaffold/commands/upgrade.py +570 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/agent.env +12 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/workflows/promote-to-prod.yaml +371 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/workflows/staging.yaml +450 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-dev.yaml +43 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-prod.yaml +41 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-staging.yaml +43 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/.helmignore +14 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/Chart.yaml +21 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/examples/networkpolicy.yaml +103 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/NOTES.txt +48 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/_helpers.tpl +189 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/certificate.yaml +15 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/configmap.yaml +10 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/deployment.yaml +199 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/hpa.yaml +22 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/httproute.yaml +30 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/ingress.yaml +39 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/networkpolicy.yaml +48 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/pdb.yaml +13 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/postgresql-secret.yaml +37 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/service.yaml +15 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/serviceaccount.yaml +13 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/servicemonitor.yaml +42 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-dev.yaml +22 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-prod.yaml +45 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-staging.yaml +29 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values.yaml +396 -0
- graph_agents_cli/scaffold/deployment_targets/kubernetes/python/tests/integration/test_chart.py +269 -0
- graph_agents_cli/scaffold/deployment_targets/none/README.md +5 -0
- graph_agents_cli/scaffold/deployment_targets/none/python/README.md +6 -0
- graph_agents_cli/scaffold/utils/__init__.py +13 -0
- graph_agents_cli/scaffold/utils/backup.py +212 -0
- graph_agents_cli/scaffold/utils/build_record.py +257 -0
- graph_agents_cli/scaffold/utils/cli_options.py +184 -0
- graph_agents_cli/scaffold/utils/fs.py +83 -0
- graph_agents_cli/scaffold/utils/generate_locks.py +214 -0
- graph_agents_cli/scaffold/utils/generation_metadata.py +88 -0
- graph_agents_cli/scaffold/utils/keyedit.py +768 -0
- graph_agents_cli/scaffold/utils/keymerge.py +537 -0
- graph_agents_cli/scaffold/utils/language.py +138 -0
- graph_agents_cli/scaffold/utils/lock_utils.py +94 -0
- graph_agents_cli/scaffold/utils/logging.py +77 -0
- graph_agents_cli/scaffold/utils/manifest.py +292 -0
- graph_agents_cli/scaffold/utils/merge.py +970 -0
- graph_agents_cli/scaffold/utils/merge3.py +216 -0
- graph_agents_cli/scaffold/utils/openapi_seed.py +199 -0
- graph_agents_cli/scaffold/utils/remote_template.py +376 -0
- graph_agents_cli/scaffold/utils/template.py +1352 -0
- graph_agents_cli/scaffold/utils/upgrade.py +894 -0
- graph_agents_cli/scaffold/utils/version.py +438 -0
- graph_agents_cli/secrets/__init__.py +15 -0
- graph_agents_cli/secrets/_apply.py +954 -0
- graph_agents_cli/secrets/_required.py +188 -0
- graph_agents_cli/secrets/cmd_secrets.py +211 -0
- graph_agents_cli/setup/__init__.py +13 -0
- graph_agents_cli/setup/_antigravity.py +221 -0
- graph_agents_cli/setup/cmd_auth.py +1030 -0
- graph_agents_cli/setup/cmd_dev_token.py +513 -0
- graph_agents_cli/setup/cmd_setup.py +428 -0
- graph_agents_cli/setup/cmd_update.py +140 -0
- graph_agents_cli/skills/__init__.py +13 -0
- graph_agents_cli/skills/_bundle.py +65 -0
- graph_agents_cli/skills/data/README.md +19 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/SKILL.md +357 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/references/github-settings.md +113 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/references/gitops.md +137 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/references/kubernetes.md +315 -0
- graph_agents_cli/skills/data/graph-agents-cli-deploy/references/secrets.md +160 -0
- graph_agents_cli/skills/data/graph-agents-cli-eval/SKILL.md +303 -0
- graph_agents_cli/skills/data/graph-agents-cli-eval/references/dataset_schema.md +282 -0
- graph_agents_cli/skills/data/graph-agents-cli-eval/references/metrics-guide.md +143 -0
- graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/SKILL.md +659 -0
- graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/langchain-models.md +124 -0
- graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/langgraph.md +235 -0
- graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/template-contract.md +477 -0
- graph_agents_cli/skills/data/graph-agents-cli-observability/SKILL.md +231 -0
- graph_agents_cli/skills/data/graph-agents-cli-observability/references/langsmith.md +46 -0
- graph_agents_cli/skills/data/graph-agents-cli-observability/references/otel.md +59 -0
- graph_agents_cli/skills/data/graph-agents-cli-scaffold/SKILL.md +414 -0
- graph_agents_cli/skills/data/graph-agents-cli-scaffold/references/flags.md +134 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/SKILL.md +478 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/brainstorming.md +118 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/commands.md +419 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/extension.md +156 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/internals.md +67 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/spec-template.md +56 -0
- graph_agents_cli/skills/data/graph-agents-cli-workflow/references/terminology.md +119 -0
- graph_agents_cli/system/__init__.py +15 -0
- graph_agents_cli/system/_apply.py +519 -0
- graph_agents_cli/system/_checks.py +1023 -0
- graph_agents_cli/system/_deploy.py +215 -0
- graph_agents_cli/system/_model.py +363 -0
- graph_agents_cli/system/_system.py +664 -0
- graph_agents_cli/system/_views.py +208 -0
- graph_agents_cli/system/cmd_system.py +423 -0
- graph_agents_cli-0.3.1.dist-info/METADATA +162 -0
- graph_agents_cli-0.3.1.dist-info/RECORD +291 -0
- graph_agents_cli-0.3.1.dist-info/WHEEL +4 -0
- graph_agents_cli-0.3.1.dist-info/entry_points.txt +2 -0
- graph_agents_cli-0.3.1.dist-info/licenses/LICENSE +201 -0
- graph_agents_cli-0.3.1.dist-info/licenses/NOTICE +19 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# Copyright 2026 graph-agents-cli contributors
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""graph-agents-cli eval submit command: upload a dataset and results to LangSmith.
|
|
16
|
+
|
|
17
|
+
Optional and never required (nothing hosted is needed to evaluate): needs
|
|
18
|
+
``LANGSMITH_API_KEY`` and the ``langsmith`` extra (the error names the install
|
|
19
|
+
command when it is missing). The SDK is imported lazily so the CLI works
|
|
20
|
+
without it.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import uuid
|
|
26
|
+
from datetime import UTC, datetime, timedelta
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any
|
|
29
|
+
|
|
30
|
+
import click
|
|
31
|
+
|
|
32
|
+
from graph_agents_cli._output import Console
|
|
33
|
+
from graph_agents_cli._project import find_project_root
|
|
34
|
+
from graph_agents_cli.eval import _paths
|
|
35
|
+
from graph_agents_cli.eval._common import (
|
|
36
|
+
EvalConfigError,
|
|
37
|
+
load_json_file,
|
|
38
|
+
project_env,
|
|
39
|
+
project_meta,
|
|
40
|
+
)
|
|
41
|
+
from graph_agents_cli.eval.cmd_grade import load_traces
|
|
42
|
+
from graph_agents_cli.eval.dataset import Dataset, cases_from_raw, load_dataset
|
|
43
|
+
from graph_agents_cli.eval.gate import STATUS_PASSED
|
|
44
|
+
|
|
45
|
+
LANGSMITH_API_KEY = "LANGSMITH_API_KEY"
|
|
46
|
+
LANGSMITH_ENDPOINT = "LANGSMITH_ENDPOINT"
|
|
47
|
+
# The upload failed (network, auth, the service): a tool failure, not the gate.
|
|
48
|
+
EXIT_SUBMIT_FAILED = 2
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class SubmitFailedError(click.ClickException):
|
|
52
|
+
"""LangSmith rejected or never received the upload (exit 2)."""
|
|
53
|
+
|
|
54
|
+
exit_code = EXIT_SUBMIT_FAILED
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _describe_upload_failure(exc: Exception, endpoint: str | None) -> str:
|
|
58
|
+
endpoint = endpoint or "the default LangSmith endpoint"
|
|
59
|
+
first_line = (str(exc).strip().splitlines() or [""])[0][:300]
|
|
60
|
+
name = type(exc).__name__
|
|
61
|
+
lowered = name.lower()
|
|
62
|
+
if "connection" in lowered or "timeout" in lowered or isinstance(exc, OSError):
|
|
63
|
+
hint = (
|
|
64
|
+
f"could not reach {endpoint}; check --endpoint / {LANGSMITH_ENDPOINT} and the network"
|
|
65
|
+
)
|
|
66
|
+
elif "auth" in lowered or "forbidden" in lowered:
|
|
67
|
+
hint = f"LangSmith refused the credentials; check {LANGSMITH_API_KEY}"
|
|
68
|
+
else:
|
|
69
|
+
hint = "LangSmith refused the upload"
|
|
70
|
+
detail = f" ({name}: {first_line})" if first_line else f" ({name})"
|
|
71
|
+
return (
|
|
72
|
+
f"eval submit failed: {hint}{detail}.\n"
|
|
73
|
+
" The local results are unchanged; the eval gate never depends on this upload."
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _langsmith_client(api_key: str, endpoint: str | None) -> Any:
|
|
78
|
+
try:
|
|
79
|
+
import langsmith
|
|
80
|
+
except ImportError as exc:
|
|
81
|
+
from graph_agents_cli.scaffold.utils.version import get_current_version, install_command
|
|
82
|
+
|
|
83
|
+
raise EvalConfigError(
|
|
84
|
+
"the langsmith package is not installed; install the extra: "
|
|
85
|
+
+ install_command("langsmith", version=get_current_version())
|
|
86
|
+
) from exc
|
|
87
|
+
kwargs: dict[str, Any] = {"api_key": api_key}
|
|
88
|
+
if endpoint:
|
|
89
|
+
kwargs["api_url"] = endpoint
|
|
90
|
+
return langsmith.Client(**kwargs)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _resolve_results(project_root: Path | None, results: str | None) -> Path:
|
|
94
|
+
if results:
|
|
95
|
+
path = Path(results)
|
|
96
|
+
if not path.is_absolute() and project_root is not None and not path.exists():
|
|
97
|
+
path = project_root / path
|
|
98
|
+
if not path.is_file():
|
|
99
|
+
raise EvalConfigError(f"results file not found: {path}")
|
|
100
|
+
return path
|
|
101
|
+
if project_root is None:
|
|
102
|
+
raise EvalConfigError("not inside a graph-agents-cli project; pass --results PATH")
|
|
103
|
+
latest = _paths.latest_file(
|
|
104
|
+
_paths.default_grade_results_dir(project_root), _paths.RESULTS_FILE_PREFIX
|
|
105
|
+
)
|
|
106
|
+
if latest is None:
|
|
107
|
+
raise EvalConfigError(
|
|
108
|
+
"no results found; run `graph-agents-cli eval grade` first or pass --results PATH"
|
|
109
|
+
)
|
|
110
|
+
return latest
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _resolve_traces(
|
|
114
|
+
project_root: Path | None, traces: str | None, results: dict[str, Any]
|
|
115
|
+
) -> tuple[dict[str, Any], dict[str, dict[str, Any]]]:
|
|
116
|
+
candidates: list[Path] = []
|
|
117
|
+
if traces:
|
|
118
|
+
path = Path(traces)
|
|
119
|
+
if not path.is_absolute() and project_root is not None and not path.exists():
|
|
120
|
+
path = project_root / path
|
|
121
|
+
candidates = sorted(path.glob("*.json")) if path.is_dir() else [path]
|
|
122
|
+
else:
|
|
123
|
+
for recorded in results.get("traces_files") or []:
|
|
124
|
+
path = Path(recorded)
|
|
125
|
+
if not path.is_absolute() and project_root is not None:
|
|
126
|
+
path = project_root / path
|
|
127
|
+
if path.is_file():
|
|
128
|
+
candidates.append(path)
|
|
129
|
+
if not candidates:
|
|
130
|
+
return {}, {}
|
|
131
|
+
return load_traces(candidates)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _resolve_dataset(
|
|
135
|
+
project_root: Path | None,
|
|
136
|
+
dataset: str | None,
|
|
137
|
+
results: dict[str, Any],
|
|
138
|
+
trace_meta: dict[str, Any],
|
|
139
|
+
) -> Dataset:
|
|
140
|
+
root = project_root or Path.cwd()
|
|
141
|
+
if dataset:
|
|
142
|
+
files = _paths.resolve_input_datasets(root, dataset)
|
|
143
|
+
if not files:
|
|
144
|
+
raise EvalConfigError(f"dataset not found: {dataset}")
|
|
145
|
+
return load_dataset(files)
|
|
146
|
+
recorded = results.get("dataset_paths") or trace_meta.get("dataset_paths") or []
|
|
147
|
+
files = [root / p if not Path(p).is_absolute() else Path(p) for p in recorded]
|
|
148
|
+
if files and all(f.is_file() for f in files):
|
|
149
|
+
return load_dataset(files)
|
|
150
|
+
embedded = trace_meta.get("embedded_cases") or []
|
|
151
|
+
if embedded:
|
|
152
|
+
return cases_from_raw(embedded)
|
|
153
|
+
raise EvalConfigError("cannot locate the dataset for these results; pass --dataset PATH")
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def upload(
|
|
157
|
+
client: Any,
|
|
158
|
+
*,
|
|
159
|
+
dataset: Dataset,
|
|
160
|
+
results: dict[str, Any],
|
|
161
|
+
traces: dict[str, dict[str, Any]],
|
|
162
|
+
dataset_name: str,
|
|
163
|
+
experiment: str,
|
|
164
|
+
console: Console,
|
|
165
|
+
) -> dict[str, Any]:
|
|
166
|
+
"""Create/update the dataset and examples, then an experiment with runs and feedback."""
|
|
167
|
+
try:
|
|
168
|
+
ls_dataset = client.read_dataset(dataset_name=dataset_name)
|
|
169
|
+
console.print(f"Updating LangSmith dataset [cyan]{dataset_name}[/cyan]")
|
|
170
|
+
except Exception:
|
|
171
|
+
ls_dataset = client.create_dataset(
|
|
172
|
+
dataset_name=dataset_name,
|
|
173
|
+
description="graph-agents-cli eval dataset (tests/eval/datasets)",
|
|
174
|
+
)
|
|
175
|
+
console.print(f"Created LangSmith dataset [cyan]{dataset_name}[/cyan]")
|
|
176
|
+
|
|
177
|
+
existing: dict[str, Any] = {}
|
|
178
|
+
for example in client.list_examples(dataset_id=ls_dataset.id):
|
|
179
|
+
metadata = getattr(example, "metadata", None) or {}
|
|
180
|
+
case_id = metadata.get("case_id")
|
|
181
|
+
if case_id:
|
|
182
|
+
existing[str(case_id)] = example
|
|
183
|
+
|
|
184
|
+
example_ids: dict[str, Any] = {}
|
|
185
|
+
for case in dataset.cases:
|
|
186
|
+
inputs = {"messages": case.messages}
|
|
187
|
+
outputs: dict[str, Any] = {}
|
|
188
|
+
if case.reference is not None:
|
|
189
|
+
outputs["reference"] = case.reference
|
|
190
|
+
if case.context is not None:
|
|
191
|
+
outputs["context"] = case.context
|
|
192
|
+
metadata = {
|
|
193
|
+
"case_id": case.id,
|
|
194
|
+
"dataset_hash": dataset.hash,
|
|
195
|
+
"expect": case.expect,
|
|
196
|
+
"judge": case.judge,
|
|
197
|
+
**case.metadata,
|
|
198
|
+
}
|
|
199
|
+
if case.id in existing:
|
|
200
|
+
example = existing[case.id]
|
|
201
|
+
client.update_example(
|
|
202
|
+
example_id=example.id, inputs=inputs, outputs=outputs or None, metadata=metadata
|
|
203
|
+
)
|
|
204
|
+
example_ids[case.id] = example.id
|
|
205
|
+
else:
|
|
206
|
+
example = client.create_example(
|
|
207
|
+
inputs=inputs, outputs=outputs or None, dataset_id=ls_dataset.id, metadata=metadata
|
|
208
|
+
)
|
|
209
|
+
example_ids[case.id] = getattr(example, "id", None)
|
|
210
|
+
|
|
211
|
+
project = client.create_project(
|
|
212
|
+
project_name=experiment,
|
|
213
|
+
reference_dataset_id=ls_dataset.id,
|
|
214
|
+
metadata={
|
|
215
|
+
"dataset_hash": results.get("dataset_hash"),
|
|
216
|
+
"traces_dataset_hash": results.get("traces_dataset_hash"),
|
|
217
|
+
"graded_at": results.get("graded_at"),
|
|
218
|
+
"agent_version": results.get("agent_version"),
|
|
219
|
+
"model": results.get("model"),
|
|
220
|
+
"judge": results.get("judge"),
|
|
221
|
+
"summary": results.get("summary"),
|
|
222
|
+
"quality": results.get("quality"),
|
|
223
|
+
},
|
|
224
|
+
)
|
|
225
|
+
console.print(f"Created LangSmith experiment [cyan]{experiment}[/cyan]")
|
|
226
|
+
|
|
227
|
+
run_count = 0
|
|
228
|
+
feedback_count = 0
|
|
229
|
+
for case_result in results.get("cases", []):
|
|
230
|
+
case_id = case_result["id"]
|
|
231
|
+
trace = traces.get(case_id) or {}
|
|
232
|
+
case = dataset.by_id().get(case_id)
|
|
233
|
+
run_id = uuid.uuid4()
|
|
234
|
+
end = datetime.now(UTC)
|
|
235
|
+
latency = trace.get("latency_ms")
|
|
236
|
+
start = (
|
|
237
|
+
end - timedelta(milliseconds=float(latency))
|
|
238
|
+
if isinstance(latency, int | float)
|
|
239
|
+
else end
|
|
240
|
+
)
|
|
241
|
+
client.create_run(
|
|
242
|
+
id=run_id,
|
|
243
|
+
name=case_id,
|
|
244
|
+
run_type="chain",
|
|
245
|
+
inputs={"messages": case.messages} if case else {},
|
|
246
|
+
outputs={
|
|
247
|
+
"response": trace.get("response"),
|
|
248
|
+
"tool_calls": trace.get("tool_calls"),
|
|
249
|
+
"status": case_result.get("status"),
|
|
250
|
+
},
|
|
251
|
+
error=trace.get("error"),
|
|
252
|
+
start_time=start,
|
|
253
|
+
end_time=end,
|
|
254
|
+
project_name=experiment,
|
|
255
|
+
reference_example_id=example_ids.get(case_id),
|
|
256
|
+
extra={
|
|
257
|
+
"metadata": {
|
|
258
|
+
"case_id": case_id,
|
|
259
|
+
"thread_id": trace.get("thread_id"),
|
|
260
|
+
"run_id": trace.get("run_id"),
|
|
261
|
+
"usage": trace.get("usage"),
|
|
262
|
+
"latency_ms": latency,
|
|
263
|
+
"reasons": case_result.get("reasons"),
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
)
|
|
267
|
+
run_count += 1
|
|
268
|
+
client.create_feedback(
|
|
269
|
+
run_id,
|
|
270
|
+
key="gate",
|
|
271
|
+
score=1 if case_result.get("status") == STATUS_PASSED else 0,
|
|
272
|
+
value=case_result.get("status"),
|
|
273
|
+
comment="; ".join(case_result.get("reasons") or []) or None,
|
|
274
|
+
)
|
|
275
|
+
feedback_count += 1
|
|
276
|
+
for name, check in (case_result.get("checks") or {}).items():
|
|
277
|
+
client.create_feedback(
|
|
278
|
+
run_id,
|
|
279
|
+
key=f"check:{name}",
|
|
280
|
+
score=1 if check.get("passed") else 0,
|
|
281
|
+
comment=check.get("reason") or None,
|
|
282
|
+
)
|
|
283
|
+
feedback_count += 1
|
|
284
|
+
for name, entry in (case_result.get("judge_scores") or {}).items():
|
|
285
|
+
score = entry.get("score")
|
|
286
|
+
if isinstance(score, int | float):
|
|
287
|
+
client.create_feedback(
|
|
288
|
+
run_id, key=name, score=score, comment=entry.get("reasoning") or None
|
|
289
|
+
)
|
|
290
|
+
feedback_count += 1
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
"dataset_id": str(getattr(ls_dataset, "id", "")),
|
|
294
|
+
"dataset_url": getattr(ls_dataset, "url", None),
|
|
295
|
+
"project_id": str(getattr(project, "id", "")),
|
|
296
|
+
"project_url": getattr(project, "url", None),
|
|
297
|
+
"examples": len(example_ids),
|
|
298
|
+
"runs": run_count,
|
|
299
|
+
"feedback": feedback_count,
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
@click.command("submit")
|
|
304
|
+
@click.option(
|
|
305
|
+
"--results",
|
|
306
|
+
default=None,
|
|
307
|
+
help="Results file. Defaults to the newest artifacts/grade_results/results_<ts>.json.",
|
|
308
|
+
)
|
|
309
|
+
@click.option(
|
|
310
|
+
"--traces",
|
|
311
|
+
default=None,
|
|
312
|
+
help="Traces file or directory. Defaults to the traces recorded in the results.",
|
|
313
|
+
)
|
|
314
|
+
@click.option(
|
|
315
|
+
"--dataset",
|
|
316
|
+
default=None,
|
|
317
|
+
help="Dataset file or directory. Defaults to the dataset recorded in the results.",
|
|
318
|
+
)
|
|
319
|
+
@click.option(
|
|
320
|
+
"--dataset-name", default=None, help="LangSmith dataset name. Defaults to '<project>-eval'."
|
|
321
|
+
)
|
|
322
|
+
@click.option(
|
|
323
|
+
"--experiment",
|
|
324
|
+
default=None,
|
|
325
|
+
help="LangSmith experiment (project) name. Defaults to '<dataset-name>-<graded_at>'.",
|
|
326
|
+
)
|
|
327
|
+
@click.option("--endpoint", default=None, help="LangSmith API URL. Defaults to LANGSMITH_ENDPOINT.")
|
|
328
|
+
def cmd_submit(
|
|
329
|
+
*,
|
|
330
|
+
results: str | None,
|
|
331
|
+
traces: str | None,
|
|
332
|
+
dataset: str | None,
|
|
333
|
+
dataset_name: str | None,
|
|
334
|
+
experiment: str | None,
|
|
335
|
+
endpoint: str | None,
|
|
336
|
+
) -> None:
|
|
337
|
+
"""Upload the dataset and a results file to LangSmith as an experiment.
|
|
338
|
+
|
|
339
|
+
Creates or updates the dataset and its examples (one per case, keyed by
|
|
340
|
+
case id), then creates an experiment whose runs carry each case's
|
|
341
|
+
response, tool calls and status, with feedback scores for the gate, every
|
|
342
|
+
deterministic check and every judge metric. Requires LANGSMITH_API_KEY in
|
|
343
|
+
the environment or the project's .env, and the `langsmith` extra.
|
|
344
|
+
"""
|
|
345
|
+
console = Console()
|
|
346
|
+
project_root = find_project_root()
|
|
347
|
+
env = project_env(project_root)
|
|
348
|
+
api_key = env.get(LANGSMITH_API_KEY)
|
|
349
|
+
if not api_key:
|
|
350
|
+
raise EvalConfigError(
|
|
351
|
+
"LangSmith is not configured: set LANGSMITH_API_KEY in the environment or the "
|
|
352
|
+
"project's .env (optional; the local eval gate does not need it)"
|
|
353
|
+
)
|
|
354
|
+
results_path = _resolve_results(project_root, results)
|
|
355
|
+
results_doc = load_json_file(results_path, "results file")
|
|
356
|
+
if not isinstance(results_doc, dict) or not isinstance(results_doc.get("cases"), list):
|
|
357
|
+
raise EvalConfigError(f"results file {results_path} has no 'cases' list")
|
|
358
|
+
trace_meta, trace_map = _resolve_traces(project_root, traces, results_doc)
|
|
359
|
+
if not trace_map:
|
|
360
|
+
console.print("[yellow]Warning:[/yellow] no traces found; runs will carry statuses only.")
|
|
361
|
+
ds = _resolve_dataset(project_root, dataset, results_doc, trace_meta)
|
|
362
|
+
|
|
363
|
+
meta = project_meta(project_root)
|
|
364
|
+
name = dataset_name or f"{meta['name'] or 'graph-agents-cli'}-eval"
|
|
365
|
+
stamp = (
|
|
366
|
+
str(results_doc.get("graded_at") or _paths.timestamp())
|
|
367
|
+
.replace(":", "")
|
|
368
|
+
.replace("+0000", "Z")
|
|
369
|
+
)
|
|
370
|
+
experiment_name = experiment or f"{name}-{stamp}"
|
|
371
|
+
|
|
372
|
+
client = _langsmith_client(api_key, endpoint or env.get(LANGSMITH_ENDPOINT))
|
|
373
|
+
console.print(
|
|
374
|
+
f"Submitting [cyan]{results_path}[/cyan] ({len(results_doc['cases'])} case(s)) to LangSmith..."
|
|
375
|
+
)
|
|
376
|
+
try:
|
|
377
|
+
report = upload(
|
|
378
|
+
client,
|
|
379
|
+
dataset=ds,
|
|
380
|
+
results=results_doc,
|
|
381
|
+
traces=trace_map,
|
|
382
|
+
dataset_name=name,
|
|
383
|
+
experiment=experiment_name,
|
|
384
|
+
console=console,
|
|
385
|
+
)
|
|
386
|
+
except click.ClickException:
|
|
387
|
+
raise
|
|
388
|
+
except Exception as exc:
|
|
389
|
+
# The LangSmith SDK raises its own classes (connection, auth, rate
|
|
390
|
+
# limit, ...): one line naming what failed, not the SDK's traceback.
|
|
391
|
+
raise SubmitFailedError(
|
|
392
|
+
_describe_upload_failure(exc, endpoint or env.get(LANGSMITH_ENDPOINT))
|
|
393
|
+
) from exc
|
|
394
|
+
console.print(
|
|
395
|
+
f"[green]Uploaded[/green] {report['examples']} example(s), {report['runs']} run(s), "
|
|
396
|
+
f"{report['feedback']} feedback score(s)."
|
|
397
|
+
)
|
|
398
|
+
for label, key in (("Dataset", "dataset_url"), ("Experiment", "project_url")):
|
|
399
|
+
if report.get(key):
|
|
400
|
+
console.print(f"{label}: [cyan]{report[key]}[/cyan]")
|