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,103 @@
|
|
|
1
|
+
# NetworkPolicy for staging and prod: a worked example of `networkPolicy` (off
|
|
2
|
+
# by default in values.yaml). Copy the block below into values-staging.yaml or
|
|
3
|
+
# values-prod.yaml and replace every address marked CHANGE. It needs a CNI that
|
|
4
|
+
# enforces NetworkPolicy (Calico, Cilium, Antrea, kube-router, recent kindnet
|
|
5
|
+
# and most managed clusters); without one the policy is accepted and ignored.
|
|
6
|
+
#
|
|
7
|
+
# What the agent pods may then do, and nothing else:
|
|
8
|
+
# in: the http port, from the Gateway's (or ingress controller's) namespace
|
|
9
|
+
# and from Prometheus (for /metrics); the kubelet's probes are not
|
|
10
|
+
# subject to NetworkPolicy
|
|
11
|
+
# out: DNS (the cluster's kube-dns / CoreDNS pods), the database, the model
|
|
12
|
+
# endpoint and the APIs in api-policy.yaml; add anything else the agent
|
|
13
|
+
# must reach, such as the jwt policy's JWKS URL (AUTH_JWT_JWKS_URL) or an
|
|
14
|
+
# OTLP collector
|
|
15
|
+
#
|
|
16
|
+
# NetworkPolicy matches addresses, not host names. A hosted service (a model
|
|
17
|
+
# provider, an identity provider's JWKS, a SaaS API) is therefore "public
|
|
18
|
+
# addresses on port 443", which excludes every private range and the cloud
|
|
19
|
+
# metadata endpoint, so nothing inside your networks is reachable unless it is
|
|
20
|
+
# listed. Check the result: `graph-agents-cli deploy --env <env> --dry-run`
|
|
21
|
+
# renders the policy; once deployed, a pod in another namespace must not reach
|
|
22
|
+
# the agent, and `/ready` must answer 200 (the database is reachable).
|
|
23
|
+
networkPolicy:
|
|
24
|
+
enabled: true
|
|
25
|
+
ingressFrom:
|
|
26
|
+
# CHANGE: the namespace of the Gateway (or ingress controller) routing to the agent.
|
|
27
|
+
- namespaceSelector:
|
|
28
|
+
matchLabels:
|
|
29
|
+
kubernetes.io/metadata.name: gateway-system
|
|
30
|
+
# CHANGE or remove: your Prometheus's namespace, for /metrics.
|
|
31
|
+
- namespaceSelector:
|
|
32
|
+
matchLabels:
|
|
33
|
+
kubernetes.io/metadata.name: monitoring
|
|
34
|
+
# DNS to the kube-dns pods is always allowed once egress is restricted.
|
|
35
|
+
restrictEgress: true
|
|
36
|
+
egressTo:
|
|
37
|
+
{%- if cookiecutter.runtime == 'langgraph-server' %}
|
|
38
|
+
# The database (DATABASE_URI) and Redis (REDIS_URI): CHANGE to their addresses...
|
|
39
|
+
- to:
|
|
40
|
+
- ipBlock:
|
|
41
|
+
cidr: 192.0.2.10/32
|
|
42
|
+
ports:
|
|
43
|
+
- port: 5432
|
|
44
|
+
protocol: TCP
|
|
45
|
+
- to:
|
|
46
|
+
- ipBlock:
|
|
47
|
+
cidr: 192.0.2.11/32
|
|
48
|
+
ports:
|
|
49
|
+
- port: 6379
|
|
50
|
+
protocol: TCP
|
|
51
|
+
{%- else %}
|
|
52
|
+
# The database (POSTGRES_DSN): CHANGE to its address...
|
|
53
|
+
- to:
|
|
54
|
+
- ipBlock:
|
|
55
|
+
cidr: 192.0.2.10/32
|
|
56
|
+
ports:
|
|
57
|
+
- port: 5432
|
|
58
|
+
protocol: TCP
|
|
59
|
+
{%- endif %}
|
|
60
|
+
# ...or, for a database running in this cluster, select its pods instead:
|
|
61
|
+
# - to:
|
|
62
|
+
# - namespaceSelector:
|
|
63
|
+
# matchLabels:
|
|
64
|
+
# kubernetes.io/metadata.name: databases
|
|
65
|
+
# podSelector:
|
|
66
|
+
# matchLabels:
|
|
67
|
+
# app.kubernetes.io/name: postgresql
|
|
68
|
+
# ports:
|
|
69
|
+
# - port: 5432
|
|
70
|
+
# protocol: TCP
|
|
71
|
+
{%- if cookiecutter.model_provider == 'openai-compatible' %}
|
|
72
|
+
# The on-network model server (OPENAI_BASE_URL): CHANGE to its address and port.
|
|
73
|
+
- to:
|
|
74
|
+
- ipBlock:
|
|
75
|
+
cidr: 192.0.2.20/32
|
|
76
|
+
ports:
|
|
77
|
+
- port: 11434
|
|
78
|
+
protocol: TCP
|
|
79
|
+
{%- endif %}
|
|
80
|
+
# HTTPS to public addresses: the hosted model provider, the APIs in
|
|
81
|
+
# api-policy.yaml that live on the internet{% if cookiecutter.runtime == 'langgraph-server' %}, the LangGraph Server licence check{% endif %}.
|
|
82
|
+
# Never the private ranges or the metadata endpoint (169.254.169.254).
|
|
83
|
+
- to:
|
|
84
|
+
- ipBlock:
|
|
85
|
+
cidr: 0.0.0.0/0
|
|
86
|
+
except:
|
|
87
|
+
- 10.0.0.0/8
|
|
88
|
+
- 172.16.0.0/12
|
|
89
|
+
- 192.168.0.0/16
|
|
90
|
+
- 169.254.0.0/16
|
|
91
|
+
- 100.64.0.0/10
|
|
92
|
+
- 127.0.0.0/8
|
|
93
|
+
ports:
|
|
94
|
+
- port: 443
|
|
95
|
+
protocol: TCP
|
|
96
|
+
# An API of api-policy.yaml on your own network (its <NAME>_API_BASE_URL is a
|
|
97
|
+
# private address): one entry per API, CHANGE to its address and port.
|
|
98
|
+
# - to:
|
|
99
|
+
# - ipBlock:
|
|
100
|
+
# cidr: 192.0.2.30/32
|
|
101
|
+
# ports:
|
|
102
|
+
# - port: 8443
|
|
103
|
+
# protocol: TCP
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{{ .Release.Name }} ({{ .Values.runtime }} runtime, image tag {{ include "agent.imageTag" . }}) is installed in namespace {{ .Release.Namespace }}.
|
|
2
|
+
Pods receive traffic once {{ .Values.probes.readiness.path }} answers (the database is reachable).
|
|
3
|
+
|
|
4
|
+
App Secret {{ if .Values.secretOptional }}expected (optional here: pods start without it){{ else }}required (pods do not start without it){{ end }}: {{ include "agent.secretName" . }}
|
|
5
|
+
create or rotate it with: graph-agents-cli secrets apply --env <env> (reads .env.<env>)
|
|
6
|
+
then, after rotation: graph-agents-cli deploy --env <env> --restart (waits for the new pods)
|
|
7
|
+
|
|
8
|
+
{{- $published := list }}
|
|
9
|
+
{{- $everything := false }}
|
|
10
|
+
{{- if or .Values.gateway.enabled .Values.ingress.enabled }}
|
|
11
|
+
{{- range (include "agent.publicPaths" . | fromYamlArray) }}
|
|
12
|
+
{{- $published = append $published (printf "%s%s" .path (ternary "" " (prefix)" (eq .type "Exact"))) }}
|
|
13
|
+
{{- if and (eq .path "/") (eq .type "PathPrefix") }}{{ $everything = true }}{{ end }}
|
|
14
|
+
{{- end }}
|
|
15
|
+
{{- end }}
|
|
16
|
+
{{- if .Values.gateway.enabled }}
|
|
17
|
+
Traffic: HTTPRoute {{ include "agent.fullname" . }} attached to Gateway {{ .Values.gateway.parentRef.name }}{{ if .Values.gateway.hostname }} for {{ .Values.gateway.hostname }}{{ end }}.
|
|
18
|
+
Published paths: {{ join ", " $published }} (route.publicPaths).
|
|
19
|
+
{{- else if .Values.ingress.enabled }}
|
|
20
|
+
Traffic: Ingress {{ include "agent.fullname" . }}{{ if .Values.ingress.hostname }} for {{ .Values.ingress.hostname }}{{ end }}.
|
|
21
|
+
Published paths: {{ join ", " $published }} (route.publicPaths).
|
|
22
|
+
{{- else }}
|
|
23
|
+
Traffic: ClusterIP only. Port-forward for a quick check:
|
|
24
|
+
kubectl -n {{ .Release.Namespace }} port-forward svc/{{ include "agent.fullname" . }} 8000:{{ .Values.service.port }}
|
|
25
|
+
curl http://127.0.0.1:8000/health
|
|
26
|
+
{{- end }}
|
|
27
|
+
{{- if .Values.postgresql.enabled }}
|
|
28
|
+
Postgres: bundled subchart {{ include "agent.postgresql.host" . }} (dev only).
|
|
29
|
+
{{- else }}
|
|
30
|
+
Postgres: external; the connection string comes from the Secret.
|
|
31
|
+
{{- end }}
|
|
32
|
+
{{- $replicas := ternary .Values.hpa.minReplicas .Values.replicaCount (and .Values.hpa.enabled true) }}
|
|
33
|
+
{{- if and .Values.pdb.enabled (not (kindIs "string" .Values.pdb.minAvailable)) (ge (int .Values.pdb.minAvailable) (int $replicas)) }}
|
|
34
|
+
|
|
35
|
+
WARNING: pdb.minAvailable ({{ .Values.pdb.minAvailable }}) is not below the replica count ({{ $replicas }}):
|
|
36
|
+
node drains will wait forever on this Deployment. Lower pdb.minAvailable or raise the replicas.
|
|
37
|
+
{{- end }}
|
|
38
|
+
{{- if and (or .Values.gateway.enabled .Values.ingress.enabled) (not (include "agent.appUrl" .)) }}
|
|
39
|
+
|
|
40
|
+
WARNING: APP_URL resolves to nothing (no appUrl and no gateway/ingress hostname): the A2A
|
|
41
|
+
agent card advertises the pod's bind address, which remote clients cannot dial. Set
|
|
42
|
+
appUrl or a hostname in values-<env>.yaml.
|
|
43
|
+
{{- end }}
|
|
44
|
+
{{- if $everything }}
|
|
45
|
+
|
|
46
|
+
WARNING: route.publicPaths publishes every path (PathPrefix /), /metrics, /health and
|
|
47
|
+
/ready included. List only the agent's API paths.
|
|
48
|
+
{{- end }}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
{{/*
|
|
2
|
+
Helpers for the graph-agents-cli agent chart. Copied verbatim into projects.
|
|
3
|
+
*/}}
|
|
4
|
+
|
|
5
|
+
{{- define "agent.name" -}}
|
|
6
|
+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
|
7
|
+
{{- end -}}
|
|
8
|
+
|
|
9
|
+
{{/* Release name = project name; resources are named after the release. */}}
|
|
10
|
+
{{- define "agent.fullname" -}}
|
|
11
|
+
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
|
12
|
+
{{- end -}}
|
|
13
|
+
|
|
14
|
+
{{- define "agent.chart" -}}
|
|
15
|
+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
|
16
|
+
{{- end -}}
|
|
17
|
+
|
|
18
|
+
{{/*
|
|
19
|
+
image.tag as a string. A number written unquoted in a values file reaches the
|
|
20
|
+
chart as a float that may already have lost digits (0123456 is read as octal
|
|
21
|
+
42798, long digit strings are rounded), so only a string is accepted, plus the
|
|
22
|
+
exact integer `--set image.tag=1234567` produces (`--set-string` is preferred).
|
|
23
|
+
*/}}
|
|
24
|
+
{{- define "agent.imageTag" -}}
|
|
25
|
+
{{- $tag := .Values.image.tag -}}
|
|
26
|
+
{{- if or (kindIs "string" $tag) (kindIs "int64" $tag) -}}
|
|
27
|
+
{{- toString $tag -}}
|
|
28
|
+
{{- else if not (kindIs "invalid" $tag) -}}
|
|
29
|
+
{{- fail (printf "image.tag must be a quoted string, got the %s %v: quote it in the values file (tag: \"<tag>\"); an unquoted number loses digits (0123456 reads as 42798)." (kindOf $tag) $tag) -}}
|
|
30
|
+
{{- end -}}
|
|
31
|
+
{{- end -}}
|
|
32
|
+
|
|
33
|
+
{{/*
|
|
34
|
+
What the HTTPRoute / Ingress publish, as a YAML list of {path, type}:
|
|
35
|
+
route.publicPaths, plus route.devPaths while env.APP_ENV is exactly dev (the app's
|
|
36
|
+
own test: `DEV` or ` dev` is a deployed environment). Read it back
|
|
37
|
+
with `include "agent.publicPaths" . | fromYamlArray`. Every entry is checked
|
|
38
|
+
here, so each template that publishes paths fails with the same message. An
|
|
39
|
+
empty list is refused while a Gateway or Ingress is enabled: it would publish
|
|
40
|
+
nothing, and a Gateway API rule without matches would publish every path.
|
|
41
|
+
*/}}
|
|
42
|
+
{{- define "agent.publicPaths" -}}
|
|
43
|
+
{{- $paths := .Values.route.publicPaths | default list -}}
|
|
44
|
+
{{- if eq (dig "APP_ENV" "" (.Values.env | default dict) | toString) "dev" -}}
|
|
45
|
+
{{- $paths = concat $paths (.Values.route.devPaths | default list) -}}
|
|
46
|
+
{{- end -}}
|
|
47
|
+
{{- if and (or .Values.gateway.enabled .Values.ingress.enabled) (not $paths) -}}
|
|
48
|
+
{{- fail "route.publicPaths is empty: the HTTPRoute / Ingress would publish nothing (and a Gateway API rule without matches publishes every path). List the agent's API paths." -}}
|
|
49
|
+
{{- end -}}
|
|
50
|
+
{{- if gt (len $paths) 64 -}}
|
|
51
|
+
{{- fail (printf "route.publicPaths lists %d paths; a Gateway API rule takes at most 64." (len $paths)) -}}
|
|
52
|
+
{{- end -}}
|
|
53
|
+
{{- range $paths -}}
|
|
54
|
+
{{- if not (kindIs "map" .) -}}
|
|
55
|
+
{{- fail (printf "route.publicPaths: each entry is {path, type}, got %v." .) -}}
|
|
56
|
+
{{- end -}}
|
|
57
|
+
{{- $path := .path | default "" | toString -}}
|
|
58
|
+
{{- if not (regexMatch "^/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$" $path) -}}
|
|
59
|
+
{{- fail (printf "route.publicPaths: path %q must be an absolute URL path (start with /, no spaces, query or fragment)." $path) -}}
|
|
60
|
+
{{- end -}}
|
|
61
|
+
{{- if or (contains "//" $path) (contains "/./" $path) (contains "/../" $path) (hasSuffix "/." $path) (hasSuffix "/.." $path) (contains "%2f" (lower $path)) -}}
|
|
62
|
+
{{- fail (printf "route.publicPaths: path %q holds //, /./, /../ or an encoded slash, which the Gateway API and Ingress refuse." $path) -}}
|
|
63
|
+
{{- end -}}
|
|
64
|
+
{{- if not (has (.type | default "" | toString) (list "PathPrefix" "Exact")) -}}
|
|
65
|
+
{{- fail (printf "route.publicPaths: %s has type %q; use PathPrefix or Exact." $path (.type | default "" | toString)) -}}
|
|
66
|
+
{{- end -}}
|
|
67
|
+
{{- end -}}
|
|
68
|
+
{{- toYaml $paths -}}
|
|
69
|
+
{{- end -}}
|
|
70
|
+
|
|
71
|
+
{{/*
|
|
72
|
+
Render-time checks: a misconfiguration fails `helm template` / `helm upgrade`
|
|
73
|
+
(and shows as a comparison error in Argo CD) instead of producing pods that
|
|
74
|
+
pull a missing image or an autoscaler that cannot compute utilisation.
|
|
75
|
+
*/}}
|
|
76
|
+
{{- define "agent.validate" -}}
|
|
77
|
+
{{- if not (include "agent.imageTag" .) -}}
|
|
78
|
+
{{- fail "image.tag is empty: deploy a built image (`graph-agents-cli deploy --env <env>` passes the tag it deploys; in argocd mode CI or `deploy` writes image.tag into values-<env>.yaml). The chart never defaults to latest." -}}
|
|
79
|
+
{{- end -}}
|
|
80
|
+
{{- if .Values.hpa.enabled -}}
|
|
81
|
+
{{- if not (dig "requests" "cpu" "" (.Values.resources | default dict)) -}}
|
|
82
|
+
{{- fail "hpa.enabled needs resources.requests.cpu: the HPA targets a percentage of the CPU request, so without one it can never scale." -}}
|
|
83
|
+
{{- end -}}
|
|
84
|
+
{{- if gt (int .Values.hpa.minReplicas) (int .Values.hpa.maxReplicas) -}}
|
|
85
|
+
{{- fail (printf "hpa.minReplicas (%v) is greater than hpa.maxReplicas (%v)." .Values.hpa.minReplicas .Values.hpa.maxReplicas) -}}
|
|
86
|
+
{{- end -}}
|
|
87
|
+
{{- end -}}
|
|
88
|
+
{{- if or .Values.gateway.enabled .Values.ingress.enabled -}}
|
|
89
|
+
{{- $_ := include "agent.publicPaths" . -}}
|
|
90
|
+
{{- end -}}
|
|
91
|
+
{{- $shutdown := .Values.shutdown | default dict -}}
|
|
92
|
+
{{- $pause := int ($shutdown.preStopSleepSeconds | default 0) -}}
|
|
93
|
+
{{- $drain := int ($shutdown.drainSeconds | default 0) -}}
|
|
94
|
+
{{- $grace := int .Values.terminationGracePeriodSeconds -}}
|
|
95
|
+
{{- if or (lt $pause 0) (lt $drain 0) -}}
|
|
96
|
+
{{- fail "shutdown.preStopSleepSeconds and shutdown.drainSeconds must be 0 or more." -}}
|
|
97
|
+
{{- end -}}
|
|
98
|
+
{{- if le $grace (add $pause $drain) -}}
|
|
99
|
+
{{- fail (printf "terminationGracePeriodSeconds (%d) must be greater than shutdown.preStopSleepSeconds + shutdown.drainSeconds (%d + %d): Kubernetes kills the pod at the grace period, counted from the start of the preStop pause." $grace $pause $drain) -}}
|
|
100
|
+
{{- end -}}
|
|
101
|
+
{{- if not (or (kindIs "bool" .Values.secretOptional) (kindIs "invalid" .Values.secretOptional)) -}}
|
|
102
|
+
{{- fail (printf "secretOptional must be true or false, got %v." .Values.secretOptional) -}}
|
|
103
|
+
{{- end -}}
|
|
104
|
+
{{- if or .Values.metrics.scrapeAnnotations .Values.metrics.serviceMonitor.enabled -}}
|
|
105
|
+
{{- if has (dig "METRICS_ENABLED" "" (.Values.env | default dict) | toString | trim | lower) (list "0" "false" "no" "off") -}}
|
|
106
|
+
{{- fail "metrics.scrapeAnnotations / metrics.serviceMonitor.enabled scrape /metrics, which env.METRICS_ENABLED turns off: turn scraping off, or set env.METRICS_ENABLED to true." -}}
|
|
107
|
+
{{- end -}}
|
|
108
|
+
{{- end -}}
|
|
109
|
+
{{- end -}}
|
|
110
|
+
|
|
111
|
+
{{- define "agent.labels" -}}
|
|
112
|
+
helm.sh/chart: {{ include "agent.chart" . }}
|
|
113
|
+
{{ include "agent.selectorLabels" . }}
|
|
114
|
+
app.kubernetes.io/version: {{ include "agent.imageTag" . | default .Chart.AppVersion | trunc 63 | trimSuffix "-" | trimSuffix "." | quote }}
|
|
115
|
+
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
116
|
+
graph-agents-cli/runtime: {{ .Values.runtime | quote }}
|
|
117
|
+
{{- end -}}
|
|
118
|
+
|
|
119
|
+
{{- define "agent.selectorLabels" -}}
|
|
120
|
+
app.kubernetes.io/name: {{ include "agent.name" . }}
|
|
121
|
+
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
122
|
+
{{- end -}}
|
|
123
|
+
|
|
124
|
+
{{- define "agent.serviceAccountName" -}}
|
|
125
|
+
{{- if .Values.serviceAccount.create -}}
|
|
126
|
+
{{- default (include "agent.fullname" .) .Values.serviceAccount.name -}}
|
|
127
|
+
{{- else -}}
|
|
128
|
+
{{- default "default" .Values.serviceAccount.name -}}
|
|
129
|
+
{{- end -}}
|
|
130
|
+
{{- end -}}
|
|
131
|
+
|
|
132
|
+
{{/* The app Secret: existingSecret, default "<release>-app". */}}
|
|
133
|
+
{{- define "agent.secretName" -}}
|
|
134
|
+
{{- default (printf "%s-app" (include "agent.fullname" .)) .Values.existingSecret -}}
|
|
135
|
+
{{- end -}}
|
|
136
|
+
|
|
137
|
+
{{/* The TLS Secret: tls.existingSecret, else "<release>-tls" (cert-manager writes it). */}}
|
|
138
|
+
{{- define "agent.tlsSecretName" -}}
|
|
139
|
+
{{- default (printf "%s-tls" (include "agent.fullname" .)) .Values.tls.existingSecret -}}
|
|
140
|
+
{{- end -}}
|
|
141
|
+
|
|
142
|
+
{{/* Bitnami postgresql subchart service and secret names. */}}
|
|
143
|
+
{{- define "agent.postgresql.host" -}}
|
|
144
|
+
{{- printf "%s-postgresql" .Release.Name -}}
|
|
145
|
+
{{- end -}}
|
|
146
|
+
|
|
147
|
+
{{/* The subchart renders auth.existingSecret through tpl; so does this chart. */}}
|
|
148
|
+
{{- define "agent.postgresql.secretName" -}}
|
|
149
|
+
{{- if .Values.postgresql.auth.existingSecret -}}
|
|
150
|
+
{{- tpl .Values.postgresql.auth.existingSecret . -}}
|
|
151
|
+
{{- else -}}
|
|
152
|
+
{{- printf "%s-postgresql" .Release.Name -}}
|
|
153
|
+
{{- end -}}
|
|
154
|
+
{{- end -}}
|
|
155
|
+
|
|
156
|
+
{{/* Connection string for the bundled Postgres; $(POSTGRES_PASSWORD) expands in the container. */}}
|
|
157
|
+
{{- define "agent.postgresql.dsn" -}}
|
|
158
|
+
{{- printf "postgresql://%s:$(POSTGRES_PASSWORD)@%s:5432/%s" .Values.postgresql.auth.username (include "agent.postgresql.host" .) .Values.postgresql.auth.database -}}
|
|
159
|
+
{{- end -}}
|
|
160
|
+
|
|
161
|
+
{{/* Bitnami redis subchart (standalone) master service. */}}
|
|
162
|
+
{{- define "agent.redis.uri" -}}
|
|
163
|
+
{{- printf "redis://%s-redis-master:6379" .Release.Name -}}
|
|
164
|
+
{{- end -}}
|
|
165
|
+
|
|
166
|
+
{{- define "agent.hostname" -}}
|
|
167
|
+
{{- if .Values.gateway.enabled -}}{{ .Values.gateway.hostname }}{{- else -}}{{ .Values.ingress.hostname }}{{- end -}}
|
|
168
|
+
{{- end -}}
|
|
169
|
+
|
|
170
|
+
{{/*
|
|
171
|
+
Public base URL for the A2A agent card (APP_URL): appUrl, else env.APP_URL,
|
|
172
|
+
else derived from the traffic entry's hostname (https on a Gateway listener or
|
|
173
|
+
a TLS Ingress, http on a plain Ingress). Empty when nothing is known.
|
|
174
|
+
*/}}
|
|
175
|
+
{{- define "agent.appUrl" -}}
|
|
176
|
+
{{- if .Values.appUrl -}}
|
|
177
|
+
{{- .Values.appUrl -}}
|
|
178
|
+
{{- else if (index .Values.env "APP_URL") -}}
|
|
179
|
+
{{- index .Values.env "APP_URL" -}}
|
|
180
|
+
{{- else if and .Values.gateway.enabled .Values.gateway.hostname -}}
|
|
181
|
+
{{- printf "https://%s" .Values.gateway.hostname -}}
|
|
182
|
+
{{- else if and .Values.ingress.enabled .Values.ingress.hostname -}}
|
|
183
|
+
{{- if or .Values.tls.existingSecret .Values.tls.certManager.enabled -}}
|
|
184
|
+
{{- printf "https://%s" .Values.ingress.hostname -}}
|
|
185
|
+
{{- else -}}
|
|
186
|
+
{{- printf "http://%s" .Values.ingress.hostname -}}
|
|
187
|
+
{{- end -}}
|
|
188
|
+
{{- end -}}
|
|
189
|
+
{{- end -}}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{{- if .Values.tls.certManager.enabled }}
|
|
2
|
+
apiVersion: cert-manager.io/v1
|
|
3
|
+
kind: Certificate
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "agent.fullname" . }}
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "agent.labels" . | nindent 4 }}
|
|
8
|
+
spec:
|
|
9
|
+
secretName: {{ include "agent.tlsSecretName" . }}
|
|
10
|
+
dnsNames:
|
|
11
|
+
- {{ required "a hostname (gateway.hostname or ingress.hostname) is required for cert-manager" (include "agent.hostname" .) | quote }}
|
|
12
|
+
issuerRef:
|
|
13
|
+
name: {{ required "tls.certManager.issuerRef.name is required" .Values.tls.certManager.issuerRef.name }}
|
|
14
|
+
kind: {{ .Values.tls.certManager.issuerRef.kind | default "ClusterIssuer" }}
|
|
15
|
+
{{- end }}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
{{- include "agent.validate" . }}
|
|
2
|
+
apiVersion: apps/v1
|
|
3
|
+
kind: Deployment
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "agent.fullname" . }}
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "agent.labels" . | nindent 4 }}
|
|
8
|
+
spec:
|
|
9
|
+
{{- if not .Values.hpa.enabled }}
|
|
10
|
+
replicas: {{ .Values.replicaCount }}
|
|
11
|
+
{{- end }}
|
|
12
|
+
selector:
|
|
13
|
+
matchLabels:
|
|
14
|
+
{{- include "agent.selectorLabels" . | nindent 6 }}
|
|
15
|
+
template:
|
|
16
|
+
metadata:
|
|
17
|
+
labels:
|
|
18
|
+
{{- include "agent.selectorLabels" . | nindent 8 }}
|
|
19
|
+
annotations:
|
|
20
|
+
# Roll the pods when the non-secret configuration changes. Secret
|
|
21
|
+
# rotation is a `graph-agents-cli deploy --restart`.
|
|
22
|
+
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
|
23
|
+
{{- if .Values.metrics.scrapeAnnotations }}
|
|
24
|
+
prometheus.io/scrape: "true"
|
|
25
|
+
prometheus.io/path: /metrics
|
|
26
|
+
prometheus.io/port: {{ .Values.service.targetPort | quote }}
|
|
27
|
+
{{- end }}
|
|
28
|
+
{{- with .Values.podAnnotations }}
|
|
29
|
+
{{- toYaml . | nindent 8 }}
|
|
30
|
+
{{- end }}
|
|
31
|
+
spec:
|
|
32
|
+
{{- with .Values.imagePullSecrets }}
|
|
33
|
+
imagePullSecrets:
|
|
34
|
+
{{- toYaml . | nindent 8 }}
|
|
35
|
+
{{- end }}
|
|
36
|
+
serviceAccountName: {{ include "agent.serviceAccountName" . }}
|
|
37
|
+
# The agent never calls the Kubernetes API: no token in the pod.
|
|
38
|
+
automountServiceAccountToken: false
|
|
39
|
+
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
|
|
40
|
+
{{- with .Values.podSecurityContext }}
|
|
41
|
+
securityContext:
|
|
42
|
+
{{- toYaml . | nindent 8 }}
|
|
43
|
+
{{- end }}
|
|
44
|
+
containers:
|
|
45
|
+
- name: agent
|
|
46
|
+
image: "{{ .Values.image.repository }}:{{ include "agent.imageTag" . }}"
|
|
47
|
+
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
48
|
+
{{- with .Values.securityContext }}
|
|
49
|
+
securityContext:
|
|
50
|
+
{{- toYaml . | nindent 12 }}
|
|
51
|
+
{{- end }}
|
|
52
|
+
ports:
|
|
53
|
+
- name: http
|
|
54
|
+
containerPort: {{ .Values.service.targetPort }}
|
|
55
|
+
protocol: TCP
|
|
56
|
+
{{- $shutdown := .Values.shutdown | default dict }}
|
|
57
|
+
{{- if gt (int ($shutdown.preStopSleepSeconds | default 0)) 0 }}
|
|
58
|
+
# Keep serving while the Service endpoints drain, then SIGTERM (see `shutdown`).
|
|
59
|
+
lifecycle:
|
|
60
|
+
preStop:
|
|
61
|
+
exec:
|
|
62
|
+
command: ["/bin/sh", "-c", "sleep {{ int $shutdown.preStopSleepSeconds }}"]
|
|
63
|
+
{{- end }}
|
|
64
|
+
# Secrets by reference (never templated here), then the ConfigMap.
|
|
65
|
+
# Required outside dev (secretOptional): no Secret, no start.
|
|
66
|
+
envFrom:
|
|
67
|
+
- secretRef:
|
|
68
|
+
name: {{ include "agent.secretName" . }}
|
|
69
|
+
optional: {{ .Values.secretOptional | default false }}
|
|
70
|
+
- configMapRef:
|
|
71
|
+
name: {{ include "agent.fullname" . }}
|
|
72
|
+
# Chart-set variables; `env` wins over `envFrom`.
|
|
73
|
+
env:
|
|
74
|
+
- name: PORT
|
|
75
|
+
value: {{ .Values.service.targetPort | quote }}
|
|
76
|
+
- name: HOST
|
|
77
|
+
value: "0.0.0.0"
|
|
78
|
+
{{- if not (hasKey .Values.env "PYTHONDONTWRITEBYTECODE") }}
|
|
79
|
+
- name: PYTHONDONTWRITEBYTECODE
|
|
80
|
+
value: "1"
|
|
81
|
+
{{- end }}
|
|
82
|
+
{{- if and (dig "readOnlyRootFilesystem" false (.Values.securityContext | default dict)) (not (hasKey .Values.env "HOME")) }}
|
|
83
|
+
# The root filesystem is read-only: caches under ~ go to the /tmp emptyDir.
|
|
84
|
+
- name: HOME
|
|
85
|
+
value: /tmp
|
|
86
|
+
{{- end }}
|
|
87
|
+
{{- $appUrl := include "agent.appUrl" . }}
|
|
88
|
+
{{- if $appUrl }}
|
|
89
|
+
- name: APP_URL
|
|
90
|
+
value: {{ $appUrl | quote }}
|
|
91
|
+
{{- end }}
|
|
92
|
+
- name: TRACING_ENABLED
|
|
93
|
+
value: {{ .Values.tracing.enabled | quote }}
|
|
94
|
+
- name: TRACE_CAPTURE
|
|
95
|
+
value: {{ .Values.tracing.capture | quote }}
|
|
96
|
+
{{- if .Values.tracing.otlpEndpoint }}
|
|
97
|
+
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
|
98
|
+
value: {{ .Values.tracing.otlpEndpoint | quote }}
|
|
99
|
+
{{- end }}
|
|
100
|
+
{{- if .Values.tracing.langsmith.project }}
|
|
101
|
+
- name: LANGSMITH_PROJECT
|
|
102
|
+
value: {{ .Values.tracing.langsmith.project | quote }}
|
|
103
|
+
{{- end }}
|
|
104
|
+
{{- if eq .Values.runtime "langgraph-server" }}
|
|
105
|
+
- name: LANGGRAPH_SERVER
|
|
106
|
+
value: "1"
|
|
107
|
+
{{- end }}
|
|
108
|
+
{{- $drain := int ($shutdown.drainSeconds | default 0) }}
|
|
109
|
+
{{- $drainVar := ternary "BG_JOB_SHUTDOWN_GRACE_PERIOD_SECS" "UVICORN_TIMEOUT_GRACEFUL_SHUTDOWN" (eq .Values.runtime "langgraph-server") }}
|
|
110
|
+
{{- if and (gt $drain 0) (not (hasKey .Values.env $drainVar)) }}
|
|
111
|
+
# SIGTERM to exit within the grace period (see `shutdown.drainSeconds`).
|
|
112
|
+
- name: {{ $drainVar }}
|
|
113
|
+
value: {{ $drain | quote }}
|
|
114
|
+
{{- end }}
|
|
115
|
+
{{- if .Values.postgresql.enabled }}
|
|
116
|
+
- name: POSTGRES_PASSWORD
|
|
117
|
+
valueFrom:
|
|
118
|
+
secretKeyRef:
|
|
119
|
+
name: {{ include "agent.postgresql.secretName" . }}
|
|
120
|
+
key: password
|
|
121
|
+
{{- if eq .Values.runtime "langgraph-server" }}
|
|
122
|
+
- name: DATABASE_URI
|
|
123
|
+
value: {{ include "agent.postgresql.dsn" . | quote }}
|
|
124
|
+
{{- else }}
|
|
125
|
+
- name: POSTGRES_DSN
|
|
126
|
+
value: {{ include "agent.postgresql.dsn" . | quote }}
|
|
127
|
+
{{- end }}
|
|
128
|
+
{{- end }}
|
|
129
|
+
{{- if .Values.redis.enabled }}
|
|
130
|
+
- name: REDIS_URI
|
|
131
|
+
value: {{ include "agent.redis.uri" . | quote }}
|
|
132
|
+
{{- end }}
|
|
133
|
+
# Liveness and startup: the process answers. Readiness: its database
|
|
134
|
+
# answers too, so traffic stops (without a restart) while it does not.
|
|
135
|
+
startupProbe:
|
|
136
|
+
httpGet:
|
|
137
|
+
path: {{ .Values.probes.startup.path }}
|
|
138
|
+
port: http
|
|
139
|
+
periodSeconds: {{ .Values.probes.startup.periodSeconds }}
|
|
140
|
+
timeoutSeconds: {{ .Values.probes.startup.timeoutSeconds }}
|
|
141
|
+
failureThreshold: {{ .Values.probes.startup.failureThreshold }}
|
|
142
|
+
livenessProbe:
|
|
143
|
+
httpGet:
|
|
144
|
+
path: {{ .Values.probes.liveness.path }}
|
|
145
|
+
port: http
|
|
146
|
+
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
|
|
147
|
+
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
|
|
148
|
+
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
|
|
149
|
+
readinessProbe:
|
|
150
|
+
httpGet:
|
|
151
|
+
path: {{ .Values.probes.readiness.path }}
|
|
152
|
+
port: http
|
|
153
|
+
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
|
|
154
|
+
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
|
|
155
|
+
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
|
|
156
|
+
{{- with .Values.resources }}
|
|
157
|
+
resources:
|
|
158
|
+
{{- toYaml . | nindent 12 }}
|
|
159
|
+
{{- end }}
|
|
160
|
+
volumeMounts:
|
|
161
|
+
- name: tmp
|
|
162
|
+
mountPath: /tmp
|
|
163
|
+
{{- with .Values.extraVolumeMounts }}
|
|
164
|
+
{{- toYaml . | nindent 12 }}
|
|
165
|
+
{{- end }}
|
|
166
|
+
volumes:
|
|
167
|
+
# Writable scratch space; everything else is read-only.
|
|
168
|
+
- name: tmp
|
|
169
|
+
emptyDir:
|
|
170
|
+
{{- with .Values.tmpVolume.medium }}
|
|
171
|
+
medium: {{ . }}
|
|
172
|
+
{{- end }}
|
|
173
|
+
{{- with .Values.tmpVolume.sizeLimit }}
|
|
174
|
+
sizeLimit: {{ . }}
|
|
175
|
+
{{- end }}
|
|
176
|
+
{{- with .Values.extraVolumes }}
|
|
177
|
+
{{- toYaml . | nindent 8 }}
|
|
178
|
+
{{- end }}
|
|
179
|
+
{{- if .Values.topologySpread.enabled }}
|
|
180
|
+
topologySpreadConstraints:
|
|
181
|
+
- maxSkew: 1
|
|
182
|
+
topologyKey: {{ .Values.topologySpread.topologyKey }}
|
|
183
|
+
whenUnsatisfiable: ScheduleAnyway
|
|
184
|
+
labelSelector:
|
|
185
|
+
matchLabels:
|
|
186
|
+
{{- include "agent.selectorLabels" . | nindent 14 }}
|
|
187
|
+
{{- end }}
|
|
188
|
+
{{- with .Values.nodeSelector }}
|
|
189
|
+
nodeSelector:
|
|
190
|
+
{{- toYaml . | nindent 8 }}
|
|
191
|
+
{{- end }}
|
|
192
|
+
{{- with .Values.affinity }}
|
|
193
|
+
affinity:
|
|
194
|
+
{{- toYaml . | nindent 8 }}
|
|
195
|
+
{{- end }}
|
|
196
|
+
{{- with .Values.tolerations }}
|
|
197
|
+
tolerations:
|
|
198
|
+
{{- toYaml . | nindent 8 }}
|
|
199
|
+
{{- end }}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{{- if .Values.hpa.enabled }}
|
|
2
|
+
apiVersion: autoscaling/v2
|
|
3
|
+
kind: HorizontalPodAutoscaler
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "agent.fullname" . }}
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "agent.labels" . | nindent 4 }}
|
|
8
|
+
spec:
|
|
9
|
+
scaleTargetRef:
|
|
10
|
+
apiVersion: apps/v1
|
|
11
|
+
kind: Deployment
|
|
12
|
+
name: {{ include "agent.fullname" . }}
|
|
13
|
+
minReplicas: {{ .Values.hpa.minReplicas }}
|
|
14
|
+
maxReplicas: {{ .Values.hpa.maxReplicas }}
|
|
15
|
+
metrics:
|
|
16
|
+
- type: Resource
|
|
17
|
+
resource:
|
|
18
|
+
name: cpu
|
|
19
|
+
target:
|
|
20
|
+
type: Utilization
|
|
21
|
+
averageUtilization: {{ .Values.hpa.targetCPU }}
|
|
22
|
+
{{- end }}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{{- if .Values.gateway.enabled }}
|
|
2
|
+
apiVersion: gateway.networking.k8s.io/v1
|
|
3
|
+
kind: HTTPRoute
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "agent.fullname" . }}
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "agent.labels" . | nindent 4 }}
|
|
8
|
+
spec:
|
|
9
|
+
parentRefs:
|
|
10
|
+
- name: {{ required "gateway.parentRef.name is required when gateway.enabled (the Gateway to attach to)" .Values.gateway.parentRef.name }}
|
|
11
|
+
{{- if .Values.gateway.parentRef.namespace }}
|
|
12
|
+
namespace: {{ .Values.gateway.parentRef.namespace }}
|
|
13
|
+
{{- end }}
|
|
14
|
+
{{- if .Values.gateway.hostname }}
|
|
15
|
+
hostnames:
|
|
16
|
+
- {{ .Values.gateway.hostname | quote }}
|
|
17
|
+
{{- end }}
|
|
18
|
+
rules:
|
|
19
|
+
# Only the agent's API (route.publicPaths, plus route.devPaths under
|
|
20
|
+
# APP_ENV=dev): /health, /ready and /metrics are not published.
|
|
21
|
+
- matches:
|
|
22
|
+
{{- range (include "agent.publicPaths" . | fromYamlArray) }}
|
|
23
|
+
- path:
|
|
24
|
+
type: {{ .type }}
|
|
25
|
+
value: {{ .path | quote }}
|
|
26
|
+
{{- end }}
|
|
27
|
+
backendRefs:
|
|
28
|
+
- name: {{ include "agent.fullname" . }}
|
|
29
|
+
port: {{ .Values.service.port }}
|
|
30
|
+
{{- end }}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{{- if .Values.ingress.enabled }}
|
|
2
|
+
apiVersion: networking.k8s.io/v1
|
|
3
|
+
kind: Ingress
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "agent.fullname" . }}
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "agent.labels" . | nindent 4 }}
|
|
8
|
+
{{- with .Values.ingress.annotations }}
|
|
9
|
+
annotations:
|
|
10
|
+
{{- toYaml . | nindent 4 }}
|
|
11
|
+
{{- end }}
|
|
12
|
+
spec:
|
|
13
|
+
{{- if .Values.ingress.className }}
|
|
14
|
+
ingressClassName: {{ .Values.ingress.className }}
|
|
15
|
+
{{- end }}
|
|
16
|
+
{{- if or .Values.tls.existingSecret .Values.tls.certManager.enabled }}
|
|
17
|
+
tls:
|
|
18
|
+
- hosts:
|
|
19
|
+
- {{ required "ingress.hostname is required for TLS" .Values.ingress.hostname | quote }}
|
|
20
|
+
secretName: {{ include "agent.tlsSecretName" . }}
|
|
21
|
+
{{- end }}
|
|
22
|
+
rules:
|
|
23
|
+
- {{- if .Values.ingress.hostname }}
|
|
24
|
+
host: {{ .Values.ingress.hostname | quote }}
|
|
25
|
+
{{- end }}
|
|
26
|
+
# Only the agent's API (route.publicPaths, plus route.devPaths under
|
|
27
|
+
# APP_ENV=dev): /health, /ready and /metrics are not published.
|
|
28
|
+
http:
|
|
29
|
+
paths:
|
|
30
|
+
{{- range (include "agent.publicPaths" . | fromYamlArray) }}
|
|
31
|
+
- path: {{ .path | quote }}
|
|
32
|
+
pathType: {{ ternary "Exact" "Prefix" (eq .type "Exact") }}
|
|
33
|
+
backend:
|
|
34
|
+
service:
|
|
35
|
+
name: {{ include "agent.fullname" $ }}
|
|
36
|
+
port:
|
|
37
|
+
number: {{ $.Values.service.port }}
|
|
38
|
+
{{- end }}
|
|
39
|
+
{{- end }}
|