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,242 @@
|
|
|
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
|
+
"""The model settings against an OpenAI API over HTTP: Chat Completions and the Responses API.
|
|
16
|
+
|
|
17
|
+
The agent runs on `MODEL_PROVIDER=openai-compatible` with `OPENAI_BASE_URL`
|
|
18
|
+
naming a fake OpenAI server (`fake_openai.py`, loopback), through `/chat`, with
|
|
19
|
+
a test tool: the model calls it, reads its result and answers.
|
|
20
|
+
|
|
21
|
+
* `MODEL_USE_RESPONSES_API=true`: every request goes to `/v1/responses`, the
|
|
22
|
+
reasoning effort as `reasoning.effort`, the tool as a function tool, its
|
|
23
|
+
result as a `function_call_output`; the run records the usage the Responses
|
|
24
|
+
API reports.
|
|
25
|
+
* `false` (and unset, for a model langchain-openai does not know to need the
|
|
26
|
+
Responses API): `/v1/chat/completions`, the effort as `reasoning_effort`.
|
|
27
|
+
* A model that refuses function tools with a reasoning effort on Chat
|
|
28
|
+
Completions (Track C's F15) fails there, naming `/v1/responses`, and works
|
|
29
|
+
with the switch on or with `MODEL_REASONING_EFFORT=none`.
|
|
30
|
+
* The judge takes its own settings, or the agent's.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import json
|
|
36
|
+
import os
|
|
37
|
+
import uuid
|
|
38
|
+
from collections.abc import AsyncIterator, Iterator
|
|
39
|
+
from typing import Any
|
|
40
|
+
|
|
41
|
+
os.environ.update(
|
|
42
|
+
{
|
|
43
|
+
"MODEL_PROVIDER": "fake",
|
|
44
|
+
"MODEL_NAME": "fake",
|
|
45
|
+
"CHECKPOINTER": "memory",
|
|
46
|
+
"AUTH_POLICY": "shared-bearer",
|
|
47
|
+
"API_KEY": "test-key",
|
|
48
|
+
"APP_ENV": "dev",
|
|
49
|
+
"TRACING_ENABLED": "false",
|
|
50
|
+
"RUNTIME": "fastapi",
|
|
51
|
+
"APP_URL": "http://testserver",
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
import httpx
|
|
56
|
+
import pytest
|
|
57
|
+
from fake_openai import CHAT_USAGE, RESPONSES_USAGE, FakeOpenAI
|
|
58
|
+
from langchain_core.tools import tool
|
|
59
|
+
|
|
60
|
+
from {{cookiecutter.agent_directory}}.app_utils.model import get_judge_model, get_model
|
|
61
|
+
from {{cookiecutter.agent_directory}}.fast_api_app import app
|
|
62
|
+
|
|
63
|
+
AUTH = {"Authorization": "Bearer test-key"}
|
|
64
|
+
MODEL_ENV = ("MODEL_REASONING_EFFORT", "MODEL_USE_RESPONSES_API")
|
|
65
|
+
JUDGE_ENV = ("JUDGE_MODEL_PROVIDER", "JUDGE_MODEL_NAME", "JUDGE_BASE_URL", "JUDGE_API_KEY")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@tool
|
|
69
|
+
def probe(query: str) -> str:
|
|
70
|
+
"""Look up a city's probe reading."""
|
|
71
|
+
return f"probe reading for {query}: 42"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@pytest.fixture(scope="module")
|
|
75
|
+
def server() -> Iterator[FakeOpenAI]:
|
|
76
|
+
fake = FakeOpenAI()
|
|
77
|
+
try:
|
|
78
|
+
yield fake
|
|
79
|
+
finally:
|
|
80
|
+
fake.close()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@pytest.fixture
|
|
84
|
+
def openai_env(server: FakeOpenAI, monkeypatch: pytest.MonkeyPatch) -> FakeOpenAI:
|
|
85
|
+
"""The agent's model is an OpenAI-API model at the fake server."""
|
|
86
|
+
monkeypatch.setenv("MODEL_PROVIDER", "openai-compatible")
|
|
87
|
+
monkeypatch.setenv("MODEL_NAME", "gpt-test-terra")
|
|
88
|
+
monkeypatch.setenv("OPENAI_BASE_URL", server.base_url())
|
|
89
|
+
monkeypatch.setenv("MODEL_API_KEY", "test-model-key")
|
|
90
|
+
monkeypatch.setenv("MODEL_MAX_RETRIES", "0")
|
|
91
|
+
for name in (*MODEL_ENV, *JUDGE_ENV, "JUDGE_REASONING_EFFORT", "JUDGE_USE_RESPONSES_API"):
|
|
92
|
+
monkeypatch.delenv(name, raising=False)
|
|
93
|
+
server.requests.clear()
|
|
94
|
+
server.effort_refuses_tools = False
|
|
95
|
+
return server
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@pytest.fixture
|
|
99
|
+
async def client(openai_env: FakeOpenAI) -> AsyncIterator[httpx.AsyncClient]:
|
|
100
|
+
async with app.router.lifespan_context(app):
|
|
101
|
+
transport = httpx.ASGITransport(app=app, raise_app_exceptions=False)
|
|
102
|
+
async with httpx.AsyncClient(
|
|
103
|
+
transport=transport, base_url="http://testserver", timeout=30
|
|
104
|
+
) as c:
|
|
105
|
+
yield c
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _events(text: str) -> list[tuple[str, dict[str, Any]]]:
|
|
109
|
+
events, event = [], None
|
|
110
|
+
for line in text.splitlines():
|
|
111
|
+
if line.startswith("event:"):
|
|
112
|
+
event = line[6:].strip()
|
|
113
|
+
elif line.startswith("data:") and event:
|
|
114
|
+
events.append((event, json.loads(line[5:].strip())))
|
|
115
|
+
event = None
|
|
116
|
+
return events
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
async def _chat(client: httpx.AsyncClient, message: str) -> list[tuple[str, dict[str, Any]]]:
|
|
120
|
+
r = await client.post(
|
|
121
|
+
"/chat", json={"message": message, "thread_id": f"t-{uuid.uuid4().hex[:8]}"}, headers=AUTH
|
|
122
|
+
)
|
|
123
|
+
assert r.status_code == 200, r.text
|
|
124
|
+
return _events(r.text)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _reply(events: list[tuple[str, dict[str, Any]]]) -> str:
|
|
128
|
+
return "".join(data.get("text", "") for name, data in events if name == "message.delta")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _tool_round_trip(events: list[tuple[str, dict[str, Any]]]) -> None:
|
|
132
|
+
"""The model called the tool with the city, read its result and answered with it."""
|
|
133
|
+
[call] = [data for name, data in events if name == "tool.call"]
|
|
134
|
+
assert call["name"] == "probe" and call["args"] == {"query": "Paris"}, call
|
|
135
|
+
[result] = [data for name, data in events if name == "tool.result"]
|
|
136
|
+
assert result["is_error"] is False and "probe reading for Paris: 42" in result["result"]
|
|
137
|
+
assert "Found:" in _reply(events) and "probe reading for Paris: 42" in _reply(events)
|
|
138
|
+
assert events[-1][0] == "message.end" and events[-1][1]["status"] == "ok", events[-1]
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
async def test_the_responses_api_with_a_tool_and_a_reasoning_effort(
|
|
142
|
+
client: httpx.AsyncClient,
|
|
143
|
+
openai_env: FakeOpenAI,
|
|
144
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
145
|
+
use_test_tools: Any,
|
|
146
|
+
) -> None:
|
|
147
|
+
server = openai_env
|
|
148
|
+
server.effort_refuses_tools = True # a model that needs the Responses API for tools (F15)
|
|
149
|
+
monkeypatch.setenv("MODEL_USE_RESPONSES_API", "true")
|
|
150
|
+
monkeypatch.setenv("MODEL_REASONING_EFFORT", "high")
|
|
151
|
+
use_test_tools(probe)
|
|
152
|
+
events = await _chat(client, "Run the probe for Paris")
|
|
153
|
+
_tool_round_trip(events)
|
|
154
|
+
assert server.paths() == ["/v1/responses", "/v1/responses"]
|
|
155
|
+
first, second = (r["body"] for r in server.requests)
|
|
156
|
+
for body in (first, second):
|
|
157
|
+
assert body["reasoning"] == {"effort": "high"} and body["stream"] is True
|
|
158
|
+
assert "reasoning_effort" not in body and "stream_options" not in body
|
|
159
|
+
assert body["model"] == "gpt-test-terra"
|
|
160
|
+
[function] = first["tools"]
|
|
161
|
+
assert (function["type"], function["name"]) == ("function", "probe")
|
|
162
|
+
outputs = [i for i in second["input"] if i.get("type") == "function_call_output"]
|
|
163
|
+
assert len(outputs) == 1 and "probe reading for Paris: 42" in outputs[0]["output"]
|
|
164
|
+
# The run records the usage the Responses API reports, for both model calls.
|
|
165
|
+
assert events[-1][1]["usage"] == {
|
|
166
|
+
"input_tokens": 2 * RESPONSES_USAGE["input_tokens"],
|
|
167
|
+
"output_tokens": 2 * RESPONSES_USAGE["output_tokens"],
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@pytest.mark.parametrize("switch", ["false", None])
|
|
172
|
+
async def test_chat_completions_with_a_tool_and_a_reasoning_effort(
|
|
173
|
+
client: httpx.AsyncClient,
|
|
174
|
+
openai_env: FakeOpenAI,
|
|
175
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
176
|
+
use_test_tools: Any,
|
|
177
|
+
switch: str | None,
|
|
178
|
+
) -> None:
|
|
179
|
+
"""`false`, or unset for a model langchain-openai does not know to need the Responses API."""
|
|
180
|
+
server = openai_env
|
|
181
|
+
if switch is not None:
|
|
182
|
+
monkeypatch.setenv("MODEL_USE_RESPONSES_API", switch)
|
|
183
|
+
monkeypatch.setenv("MODEL_REASONING_EFFORT", "low")
|
|
184
|
+
use_test_tools(probe)
|
|
185
|
+
events = await _chat(client, "Run the probe for Paris")
|
|
186
|
+
_tool_round_trip(events)
|
|
187
|
+
assert server.paths() == ["/v1/chat/completions", "/v1/chat/completions"]
|
|
188
|
+
first, second = (r["body"] for r in server.requests)
|
|
189
|
+
for body in (first, second):
|
|
190
|
+
assert body["reasoning_effort"] == "low" and "reasoning" not in body
|
|
191
|
+
assert [t["function"]["name"] for t in first["tools"]] == ["probe"]
|
|
192
|
+
assert second["messages"][-1]["role"] == "tool"
|
|
193
|
+
# Usage is asked for on the stream (F1), so the run records what the server reports.
|
|
194
|
+
assert all(r["body"]["stream_options"] == {"include_usage": True} for r in server.requests)
|
|
195
|
+
assert events[-1][1]["usage"] == {
|
|
196
|
+
"input_tokens": 2 * CHAT_USAGE["prompt_tokens"],
|
|
197
|
+
"output_tokens": 2 * CHAT_USAGE["completion_tokens"],
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
async def test_a_model_that_refuses_tools_with_an_effort_on_chat_completions(
|
|
202
|
+
client: httpx.AsyncClient,
|
|
203
|
+
openai_env: FakeOpenAI,
|
|
204
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
205
|
+
use_test_tools: Any,
|
|
206
|
+
) -> None:
|
|
207
|
+
"""Track C's F15: with Chat Completions the first call fails, naming the Responses API;
|
|
208
|
+
`MODEL_REASONING_EFFORT=none` (or the switch, above) makes it work."""
|
|
209
|
+
server = openai_env
|
|
210
|
+
server.effort_refuses_tools = True
|
|
211
|
+
use_test_tools(probe)
|
|
212
|
+
failed = await _chat(client, "Run the probe for Paris")
|
|
213
|
+
[error] = [data for name, data in failed if name == "error"]
|
|
214
|
+
assert "/v1/responses" in json.dumps(error), error
|
|
215
|
+
assert server.paths() == ["/v1/chat/completions"]
|
|
216
|
+
server.requests.clear()
|
|
217
|
+
monkeypatch.setenv("MODEL_REASONING_EFFORT", "none")
|
|
218
|
+
use_test_tools(probe) # the graph is built with the model the settings name now
|
|
219
|
+
_tool_round_trip(await _chat(client, "Run the probe for Paris"))
|
|
220
|
+
assert server.paths() == ["/v1/chat/completions", "/v1/chat/completions"]
|
|
221
|
+
assert all(r["body"]["reasoning_effort"] == "none" for r in server.requests)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
async def test_the_judge_takes_its_own_settings_or_the_agents(
|
|
225
|
+
openai_env: FakeOpenAI, monkeypatch: pytest.MonkeyPatch
|
|
226
|
+
) -> None:
|
|
227
|
+
server = openai_env
|
|
228
|
+
monkeypatch.setenv("MODEL_USE_RESPONSES_API", "true")
|
|
229
|
+
monkeypatch.setenv("MODEL_REASONING_EFFORT", "medium")
|
|
230
|
+
judge = get_judge_model() # the agent's model and settings
|
|
231
|
+
reply = await judge.ainvoke('Give a score in JSON: {"score": 5}')
|
|
232
|
+
assert "ok" in str(reply.content)
|
|
233
|
+
assert server.paths() == ["/v1/responses"]
|
|
234
|
+
assert server.requests[-1]["body"]["reasoning"] == {"effort": "medium"}
|
|
235
|
+
monkeypatch.setenv("JUDGE_USE_RESPONSES_API", "false")
|
|
236
|
+
monkeypatch.setenv("JUDGE_REASONING_EFFORT", "minimal")
|
|
237
|
+
await get_judge_model().ainvoke("score this")
|
|
238
|
+
assert server.paths()[-1] == "/v1/chat/completions"
|
|
239
|
+
assert server.requests[-1]["body"]["reasoning_effort"] == "minimal"
|
|
240
|
+
# The agent keeps its own.
|
|
241
|
+
await get_model().ainvoke("hello")
|
|
242
|
+
assert server.paths()[-1] == "/v1/responses"
|