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.
Files changed (291) hide show
  1. graph_agents_cli/__init__.py +26 -0
  2. graph_agents_cli/_api_policy.py +2145 -0
  3. graph_agents_cli/_approvals.py +400 -0
  4. graph_agents_cli/_build.py +186 -0
  5. graph_agents_cli/_build_info.json +7 -0
  6. graph_agents_cli/_chat_client.py +462 -0
  7. graph_agents_cli/_click.py +157 -0
  8. graph_agents_cli/_defaults.py +139 -0
  9. graph_agents_cli/_experiments.py +64 -0
  10. graph_agents_cli/_http.py +192 -0
  11. graph_agents_cli/_output.py +83 -0
  12. graph_agents_cli/_project.py +462 -0
  13. graph_agents_cli/_remote.py +220 -0
  14. graph_agents_cli/_response_schema.py +264 -0
  15. graph_agents_cli/_runner.py +319 -0
  16. graph_agents_cli/_skills_check.py +274 -0
  17. graph_agents_cli/_tools.py +189 -0
  18. graph_agents_cli/_trust.py +66 -0
  19. graph_agents_cli/api/__init__.py +15 -0
  20. graph_agents_cli/api/_changes.py +506 -0
  21. graph_agents_cli/api/_files.py +658 -0
  22. graph_agents_cli/api/cmd_api.py +2480 -0
  23. graph_agents_cli/deploy/__init__.py +15 -0
  24. graph_agents_cli/deploy/_config.py +171 -0
  25. graph_agents_cli/deploy/_image.py +128 -0
  26. graph_agents_cli/deploy/_kube.py +286 -0
  27. graph_agents_cli/deploy/_modes.py +234 -0
  28. graph_agents_cli/deploy/_preflight.py +370 -0
  29. graph_agents_cli/deploy/_values.py +168 -0
  30. graph_agents_cli/deploy/cmd_deploy.py +1866 -0
  31. graph_agents_cli/deploy/gitops.py +562 -0
  32. graph_agents_cli/deploy/local_load.py +273 -0
  33. graph_agents_cli/dev/__init__.py +13 -0
  34. graph_agents_cli/dev/cmd_build.py +131 -0
  35. graph_agents_cli/dev/cmd_install.py +78 -0
  36. graph_agents_cli/dev/cmd_lint.py +119 -0
  37. graph_agents_cli/dev/cmd_playground.py +297 -0
  38. graph_agents_cli/dev/policy_check.py +1287 -0
  39. graph_agents_cli/eval/__init__.py +22 -0
  40. graph_agents_cli/eval/_client.py +670 -0
  41. graph_agents_cli/eval/_common.py +177 -0
  42. graph_agents_cli/eval/_judge.py +168 -0
  43. graph_agents_cli/eval/_judge_runner.py +238 -0
  44. graph_agents_cli/eval/_paths.py +212 -0
  45. graph_agents_cli/eval/checks.py +581 -0
  46. graph_agents_cli/eval/cmd_analyze.py +278 -0
  47. graph_agents_cli/eval/cmd_compare.py +284 -0
  48. graph_agents_cli/eval/cmd_eval_group.py +80 -0
  49. graph_agents_cli/eval/cmd_generate.py +558 -0
  50. graph_agents_cli/eval/cmd_grade.py +466 -0
  51. graph_agents_cli/eval/cmd_metric.py +156 -0
  52. graph_agents_cli/eval/cmd_run.py +370 -0
  53. graph_agents_cli/eval/cmd_submit.py +400 -0
  54. graph_agents_cli/eval/config.py +435 -0
  55. graph_agents_cli/eval/dataset.py +350 -0
  56. graph_agents_cli/eval/gate.py +420 -0
  57. graph_agents_cli/eval/transcript.py +192 -0
  58. graph_agents_cli/extension/__init__.py +13 -0
  59. graph_agents_cli/extension/_compat.py +86 -0
  60. graph_agents_cli/extension/_loader.py +293 -0
  61. graph_agents_cli/extension/_manifest.py +135 -0
  62. graph_agents_cli/extension/_overrides.py +195 -0
  63. graph_agents_cli/extension/_paths.py +91 -0
  64. graph_agents_cli/extension/_refs.py +193 -0
  65. graph_agents_cli/extension/_resolver.py +453 -0
  66. graph_agents_cli/extension/_schema.py +106 -0
  67. graph_agents_cli/extension/_spec.py +253 -0
  68. graph_agents_cli/extension/_sync.py +102 -0
  69. graph_agents_cli/extension/_trust.py +58 -0
  70. graph_agents_cli/extension/cmd_extension_add.py +259 -0
  71. graph_agents_cli/extension/cmd_extension_group.py +57 -0
  72. graph_agents_cli/extension/cmd_extension_list.py +56 -0
  73. graph_agents_cli/extension/cmd_extension_remove.py +61 -0
  74. graph_agents_cli/extension/cmd_extension_update.py +195 -0
  75. graph_agents_cli/info/__init__.py +13 -0
  76. graph_agents_cli/info/cmd_info.py +222 -0
  77. graph_agents_cli/infra/__init__.py +15 -0
  78. graph_agents_cli/infra/checks.py +1169 -0
  79. graph_agents_cli/infra/cmd_infra.py +103 -0
  80. graph_agents_cli/main.py +591 -0
  81. graph_agents_cli/peer/__init__.py +15 -0
  82. graph_agents_cli/peer/_generate.py +254 -0
  83. graph_agents_cli/peer/cmd_peer.py +1151 -0
  84. graph_agents_cli/run/__init__.py +13 -0
  85. graph_agents_cli/run/_local_server.py +1157 -0
  86. graph_agents_cli/run/_signals.py +141 -0
  87. graph_agents_cli/run/cmd_approvals.py +530 -0
  88. graph_agents_cli/run/cmd_run.py +1421 -0
  89. graph_agents_cli/scaffold/__init__.py +19 -0
  90. graph_agents_cli/scaffold/agents/README.md +24 -0
  91. graph_agents_cli/scaffold/agents/empty_py/.template/templateconfig.yaml +22 -0
  92. graph_agents_cli/scaffold/agents/langgraph/.env.example +292 -0
  93. graph_agents_cli/scaffold/agents/langgraph/.template/templateconfig.yaml +28 -0
  94. graph_agents_cli/scaffold/agents/langgraph/Dockerfile +59 -0
  95. graph_agents_cli/scaffold/agents/langgraph/Dockerfile.langgraph-server +59 -0
  96. graph_agents_cli/scaffold/agents/langgraph/README.md +571 -0
  97. graph_agents_cli/scaffold/agents/langgraph/api-policy.yaml +60 -0
  98. graph_agents_cli/scaffold/agents/langgraph/app/__init__.py +20 -0
  99. graph_agents_cli/scaffold/agents/langgraph/app/agent.py +174 -0
  100. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/__init__.py +15 -0
  101. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/a2a.py +2162 -0
  102. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/a2a_client.py +1167 -0
  103. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/api_client.py +4220 -0
  104. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/approvals.py +1349 -0
  105. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/auth.py +1986 -0
  106. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/chat.py +2962 -0
  107. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/checkpointer.py +432 -0
  108. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/content.py +569 -0
  109. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/db.py +580 -0
  110. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/limits.py +203 -0
  111. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/metrics.py +231 -0
  112. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/middleware.py +361 -0
  113. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/model.py +611 -0
  114. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/playground.py +230 -0
  115. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/run_locks.py +459 -0
  116. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/structured.py +755 -0
  117. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/telemetry.py +681 -0
  118. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/threads.py +493 -0
  119. graph_agents_cli/scaffold/agents/langgraph/app/app_utils/token_exchange.py +959 -0
  120. graph_agents_cli/scaffold/agents/langgraph/app/fast_api_app.py +770 -0
  121. graph_agents_cli/scaffold/agents/langgraph/app/policies/__init__.py +55 -0
  122. graph_agents_cli/scaffold/agents/langgraph/app/policies/custom.py +97 -0
  123. graph_agents_cli/scaffold/agents/langgraph/app/tools/__init__.py +46 -0
  124. graph_agents_cli/scaffold/agents/langgraph/app/tools/example_api.py +92 -0
  125. graph_agents_cli/scaffold/agents/langgraph/app/tools/weather.py +33 -0
  126. graph_agents_cli/scaffold/agents/langgraph/langgraph.json +14 -0
  127. graph_agents_cli/scaffold/agents/langgraph/pyproject.toml +78 -0
  128. graph_agents_cli/scaffold/agents/langgraph/tests/conftest.py +376 -0
  129. graph_agents_cli/scaffold/agents/langgraph/tests/eval/datasets/basic-dataset.json +53 -0
  130. graph_agents_cli/scaffold/agents/langgraph/tests/eval/eval_config.yaml +32 -0
  131. graph_agents_cli/scaffold/agents/langgraph/tests/integration/approval_graph.py +137 -0
  132. graph_agents_cli/scaffold/agents/langgraph/tests/integration/fake_issuer.py +216 -0
  133. graph_agents_cli/scaffold/agents/langgraph/tests/integration/fake_openai.py +357 -0
  134. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_a2a_outcomes.py +569 -0
  135. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_a2a_relay.py +479 -0
  136. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_api_surface.py +812 -0
  137. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_approvals.py +1367 -0
  138. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_approvals_server.py +794 -0
  139. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_cross_actor.py +497 -0
  140. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_cross_actor_server.py +247 -0
  141. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_history_repair.py +278 -0
  142. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_model_apis.py +242 -0
  143. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_postgres.py +637 -0
  144. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_resilience_postgres.py +770 -0
  145. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_runtime_guardrails.py +854 -0
  146. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_server_e2e.py +340 -0
  147. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_server_runtime.py +989 -0
  148. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_structured_answers.py +584 -0
  149. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_structured_server.py +222 -0
  150. graph_agents_cli/scaffold/agents/langgraph/tests/integration/test_token_exchange_issuer.py +650 -0
  151. graph_agents_cli/scaffold/agents/langgraph/tests/load_test/.results/.placeholder +0 -0
  152. graph_agents_cli/scaffold/agents/langgraph/tests/load_test/README.md +22 -0
  153. graph_agents_cli/scaffold/agents/langgraph/tests/load_test/conftest.py +21 -0
  154. graph_agents_cli/scaffold/agents/langgraph/tests/load_test/load_test.py +81 -0
  155. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_a2a_client.py +824 -0
  156. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_a2a_scoping.py +724 -0
  157. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_client.py +1214 -0
  158. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_client_hardening.py +716 -0
  159. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_api_policy_rpc.py +767 -0
  160. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_approval_ledger.py +1536 -0
  161. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_fake_model.py +115 -0
  162. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_jwt_policy.py +991 -0
  163. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_limits.py +310 -0
  164. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_logging.py +148 -0
  165. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_logging_hardening.py +271 -0
  166. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_policy.py +378 -0
  167. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_resilience.py +610 -0
  168. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_server_auth.py +702 -0
  169. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_structured.py +673 -0
  170. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_telemetry.py +404 -0
  171. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_thread_listing.py +255 -0
  172. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_threads.py +268 -0
  173. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_token_exchange.py +1320 -0
  174. graph_agents_cli/scaffold/agents/langgraph/tests/unit/test_untrusted_content.py +393 -0
  175. graph_agents_cli/scaffold/agents/langgraph/uv-fastapi.lock +2084 -0
  176. graph_agents_cli/scaffold/agents/langgraph/uv-langgraph-server.lock +2106 -0
  177. graph_agents_cli/scaffold/agents/langgraph/{{cookiecutter.agent_guidance_filename}} +129 -0
  178. graph_agents_cli/scaffold/base_templates/_shared/graph-agents-cli-manifest.yaml +36 -0
  179. graph_agents_cli/scaffold/base_templates/python/.dockerignore +32 -0
  180. graph_agents_cli/scaffold/base_templates/python/.github/CODEOWNERS +30 -0
  181. graph_agents_cli/scaffold/base_templates/python/.github/agent.env +7 -0
  182. graph_agents_cli/scaffold/base_templates/python/.github/workflows/pr_checks.yaml +214 -0
  183. graph_agents_cli/scaffold/base_templates/python/.gitignore +209 -0
  184. graph_agents_cli/scaffold/base_templates/python/tests/unit/test_dummy.py +23 -0
  185. graph_agents_cli/scaffold/base_templates/python/{{cookiecutter.agent_guidance_filename}} +35 -0
  186. graph_agents_cli/scaffold/cmd_scaffold_group.py +49 -0
  187. graph_agents_cli/scaffold/commands/__init__.py +13 -0
  188. graph_agents_cli/scaffold/commands/create.py +1424 -0
  189. graph_agents_cli/scaffold/commands/enhance.py +1652 -0
  190. graph_agents_cli/scaffold/commands/upgrade.py +570 -0
  191. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/agent.env +12 -0
  192. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/workflows/promote-to-prod.yaml +371 -0
  193. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/.github/workflows/staging.yaml +450 -0
  194. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-dev.yaml +43 -0
  195. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-prod.yaml +41 -0
  196. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/argocd/application-staging.yaml +43 -0
  197. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/.helmignore +14 -0
  198. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/Chart.yaml +21 -0
  199. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/examples/networkpolicy.yaml +103 -0
  200. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/NOTES.txt +48 -0
  201. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/_helpers.tpl +189 -0
  202. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/certificate.yaml +15 -0
  203. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/configmap.yaml +10 -0
  204. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/deployment.yaml +199 -0
  205. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/hpa.yaml +22 -0
  206. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/httproute.yaml +30 -0
  207. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/ingress.yaml +39 -0
  208. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/networkpolicy.yaml +48 -0
  209. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/pdb.yaml +13 -0
  210. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/postgresql-secret.yaml +37 -0
  211. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/service.yaml +15 -0
  212. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/serviceaccount.yaml +13 -0
  213. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/templates/servicemonitor.yaml +42 -0
  214. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-dev.yaml +22 -0
  215. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-prod.yaml +45 -0
  216. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values-staging.yaml +29 -0
  217. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/deployment/helm/{{cookiecutter.project_name}}/values.yaml +396 -0
  218. graph_agents_cli/scaffold/deployment_targets/kubernetes/python/tests/integration/test_chart.py +269 -0
  219. graph_agents_cli/scaffold/deployment_targets/none/README.md +5 -0
  220. graph_agents_cli/scaffold/deployment_targets/none/python/README.md +6 -0
  221. graph_agents_cli/scaffold/utils/__init__.py +13 -0
  222. graph_agents_cli/scaffold/utils/backup.py +212 -0
  223. graph_agents_cli/scaffold/utils/build_record.py +257 -0
  224. graph_agents_cli/scaffold/utils/cli_options.py +184 -0
  225. graph_agents_cli/scaffold/utils/fs.py +83 -0
  226. graph_agents_cli/scaffold/utils/generate_locks.py +214 -0
  227. graph_agents_cli/scaffold/utils/generation_metadata.py +88 -0
  228. graph_agents_cli/scaffold/utils/keyedit.py +768 -0
  229. graph_agents_cli/scaffold/utils/keymerge.py +537 -0
  230. graph_agents_cli/scaffold/utils/language.py +138 -0
  231. graph_agents_cli/scaffold/utils/lock_utils.py +94 -0
  232. graph_agents_cli/scaffold/utils/logging.py +77 -0
  233. graph_agents_cli/scaffold/utils/manifest.py +292 -0
  234. graph_agents_cli/scaffold/utils/merge.py +970 -0
  235. graph_agents_cli/scaffold/utils/merge3.py +216 -0
  236. graph_agents_cli/scaffold/utils/openapi_seed.py +199 -0
  237. graph_agents_cli/scaffold/utils/remote_template.py +376 -0
  238. graph_agents_cli/scaffold/utils/template.py +1352 -0
  239. graph_agents_cli/scaffold/utils/upgrade.py +894 -0
  240. graph_agents_cli/scaffold/utils/version.py +438 -0
  241. graph_agents_cli/secrets/__init__.py +15 -0
  242. graph_agents_cli/secrets/_apply.py +954 -0
  243. graph_agents_cli/secrets/_required.py +188 -0
  244. graph_agents_cli/secrets/cmd_secrets.py +211 -0
  245. graph_agents_cli/setup/__init__.py +13 -0
  246. graph_agents_cli/setup/_antigravity.py +221 -0
  247. graph_agents_cli/setup/cmd_auth.py +1030 -0
  248. graph_agents_cli/setup/cmd_dev_token.py +513 -0
  249. graph_agents_cli/setup/cmd_setup.py +428 -0
  250. graph_agents_cli/setup/cmd_update.py +140 -0
  251. graph_agents_cli/skills/__init__.py +13 -0
  252. graph_agents_cli/skills/_bundle.py +65 -0
  253. graph_agents_cli/skills/data/README.md +19 -0
  254. graph_agents_cli/skills/data/graph-agents-cli-deploy/SKILL.md +357 -0
  255. graph_agents_cli/skills/data/graph-agents-cli-deploy/references/github-settings.md +113 -0
  256. graph_agents_cli/skills/data/graph-agents-cli-deploy/references/gitops.md +137 -0
  257. graph_agents_cli/skills/data/graph-agents-cli-deploy/references/kubernetes.md +315 -0
  258. graph_agents_cli/skills/data/graph-agents-cli-deploy/references/secrets.md +160 -0
  259. graph_agents_cli/skills/data/graph-agents-cli-eval/SKILL.md +303 -0
  260. graph_agents_cli/skills/data/graph-agents-cli-eval/references/dataset_schema.md +282 -0
  261. graph_agents_cli/skills/data/graph-agents-cli-eval/references/metrics-guide.md +143 -0
  262. graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/SKILL.md +659 -0
  263. graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/langchain-models.md +124 -0
  264. graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/langgraph.md +235 -0
  265. graph_agents_cli/skills/data/graph-agents-cli-langgraph-code/references/template-contract.md +477 -0
  266. graph_agents_cli/skills/data/graph-agents-cli-observability/SKILL.md +231 -0
  267. graph_agents_cli/skills/data/graph-agents-cli-observability/references/langsmith.md +46 -0
  268. graph_agents_cli/skills/data/graph-agents-cli-observability/references/otel.md +59 -0
  269. graph_agents_cli/skills/data/graph-agents-cli-scaffold/SKILL.md +414 -0
  270. graph_agents_cli/skills/data/graph-agents-cli-scaffold/references/flags.md +134 -0
  271. graph_agents_cli/skills/data/graph-agents-cli-workflow/SKILL.md +478 -0
  272. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/brainstorming.md +118 -0
  273. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/commands.md +419 -0
  274. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/extension.md +156 -0
  275. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/internals.md +67 -0
  276. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/spec-template.md +56 -0
  277. graph_agents_cli/skills/data/graph-agents-cli-workflow/references/terminology.md +119 -0
  278. graph_agents_cli/system/__init__.py +15 -0
  279. graph_agents_cli/system/_apply.py +519 -0
  280. graph_agents_cli/system/_checks.py +1023 -0
  281. graph_agents_cli/system/_deploy.py +215 -0
  282. graph_agents_cli/system/_model.py +363 -0
  283. graph_agents_cli/system/_system.py +664 -0
  284. graph_agents_cli/system/_views.py +208 -0
  285. graph_agents_cli/system/cmd_system.py +423 -0
  286. graph_agents_cli-0.3.1.dist-info/METADATA +162 -0
  287. graph_agents_cli-0.3.1.dist-info/RECORD +291 -0
  288. graph_agents_cli-0.3.1.dist-info/WHEEL +4 -0
  289. graph_agents_cli-0.3.1.dist-info/entry_points.txt +2 -0
  290. graph_agents_cli-0.3.1.dist-info/licenses/LICENSE +201 -0
  291. graph_agents_cli-0.3.1.dist-info/licenses/NOTICE +19 -0
@@ -0,0 +1,361 @@
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
+ """HTTP plumbing shared by every route: request ids, metrics, the body cap, SSE responses.
16
+
17
+ * `RequestContextMiddleware`: takes the caller's `X-Request-ID` (letters,
18
+ digits and `._:-`, at most 128) or makes one, returns it on the response,
19
+ binds it to every log record of the request, continues the caller's W3C
20
+ trace (`traceparent`, under OTLP tracing), and records the request metrics.
21
+ * `BodySizeLimitMiddleware`: refuses a body over `MAX_REQUEST_BYTES` with 413,
22
+ from `Content-Length` before reading anything, or while reading a chunked body.
23
+ * `max_message_chars()`: `MAX_MESSAGE_CHARS` (default 32000), the longest user
24
+ message a run accepts, on every surface that reaches the model (`/chat`
25
+ answers 422 above it, A2A an invalid-params error).
26
+ * `RunStreamingResponse`: the `/chat` SSE response. It watches for the client
27
+ going away and cancels the stream right then (the run is recorded as
28
+ `cancelled` and stops spending model tokens), and it always calls
29
+ `on_close` (which releases the thread's run lock), even when the stream
30
+ never started.
31
+
32
+ Under langgraph-server the server installs this app's middleware for every
33
+ route, its own native API included, and two more apply there only:
34
+
35
+ * `AuthErrorMiddleware`: the server answers an auth failure on its native API
36
+ with a bare 401 (the policy's `WWW-Authenticate` challenge dropped) and lets
37
+ any other status escape as an exception (a 500). This puts the challenge
38
+ back and answers an escaped auth error (for example the 503 of a
39
+ misconfigured policy or an unreachable token issuer) with its own status.
40
+ * `ThreadDeleteHookMiddleware`: after the server's own
41
+ `DELETE /threads/{thread_id}` succeeds, drops that thread's run records and
42
+ its A2A tasks.
43
+
44
+ Both rely on the server's default middleware order (this app's middleware
45
+ around the server's auth; no `"middleware_order": "auth_first"`).
46
+ """
47
+
48
+ from __future__ import annotations
49
+
50
+ import asyncio
51
+ import logging
52
+ import os
53
+ import re
54
+ import time
55
+ import uuid
56
+ from collections.abc import Awaitable, Callable
57
+ from typing import Any
58
+
59
+ from fastapi import HTTPException
60
+ from fastapi.responses import JSONResponse, StreamingResponse
61
+ from starlette.datastructures import MutableHeaders
62
+ from starlette.types import ASGIApp, Message, Receive, Scope, Send
63
+
64
+ from {{cookiecutter.agent_directory}}.app_utils.auth import AUTH_CHALLENGE_STATE_KEY
65
+ from {{cookiecutter.agent_directory}}.app_utils.limits import SettingsError, max_request_bytes
66
+ from {{cookiecutter.agent_directory}}.app_utils.metrics import observe_request, route_label
67
+ from {{cookiecutter.agent_directory}}.app_utils.telemetry import (
68
+ attach_trace_context,
69
+ bind_log_context,
70
+ detach_trace_context,
71
+ )
72
+
73
+ logger = logging.getLogger(__name__)
74
+
75
+ MAX_MESSAGE_CHARS = ("MAX_MESSAGE_CHARS", 32_000)
76
+
77
+
78
+ def max_message_chars() -> int:
79
+ """`MAX_MESSAGE_CHARS`: the longest user message (in characters) a run accepts.
80
+
81
+ One cap for every surface that reaches the model (`/chat` and A2A), so a
82
+ message refused on one is refused on the other. Anything but a whole
83
+ number >= 1 is a `SettingsError`, reported at startup with every other
84
+ bad setting.
85
+ """
86
+ name, default = MAX_MESSAGE_CHARS
87
+ raw = (os.environ.get(name) or "").strip()
88
+ if not raw:
89
+ return default
90
+ try:
91
+ value = int(raw)
92
+ except ValueError:
93
+ raise SettingsError(f"{name}={raw!r} is not an integer.") from None
94
+ if value < 1:
95
+ raise SettingsError(f"{name}={value} must be >= 1.")
96
+ return value
97
+
98
+
99
+ REQUEST_ID_HEADER = "x-request-id"
100
+ _REQUEST_ID = re.compile(r"^[A-Za-z0-9._:-]{1,128}$")
101
+ # The server's native thread delete: `DELETE /threads/{thread_id}` (any mount prefix).
102
+ _THREAD_DELETE_PATH = re.compile(r"(?:^|/)threads/([^/]+)/?$")
103
+
104
+
105
+ def _header(scope: Scope, name: bytes) -> str | None:
106
+ for key, value in scope.get("headers") or ():
107
+ if key.lower() == name:
108
+ return value.decode("latin-1")
109
+ return None
110
+
111
+
112
+ class RequestContextMiddleware:
113
+ def __init__(self, app: ASGIApp) -> None:
114
+ self.app = app
115
+
116
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
117
+ if scope["type"] != "http":
118
+ await self.app(scope, receive, send)
119
+ return
120
+ incoming = _header(scope, REQUEST_ID_HEADER.encode())
121
+ if incoming and _REQUEST_ID.fullmatch(incoming):
122
+ request_id = incoming
123
+ else:
124
+ request_id = uuid.uuid4().hex
125
+ # Downstream code (LangGraph Server's own request-id middleware
126
+ # included) sees the same id.
127
+ scope["headers"] = [
128
+ (k, v) for k, v in scope.get("headers") or () if k.lower() != b"x-request-id"
129
+ ] + [(b"x-request-id", request_id.encode())]
130
+ scope.setdefault("state", {})["request_id"] = request_id
131
+ bind_log_context(
132
+ request_id=request_id, run_id=None, thread_id=None, principal_hash=None, actor=None
133
+ )
134
+ status = 500
135
+ started = time.perf_counter()
136
+
137
+ async def send_with_id(message: Message) -> None:
138
+ nonlocal status
139
+ if message["type"] == "http.response.start":
140
+ status = int(message["status"])
141
+ MutableHeaders(scope=message)[REQUEST_ID_HEADER] = request_id
142
+ await send(message)
143
+
144
+ # A caller's W3C trace context (another agent's `traceparent`): this request's
145
+ # spans join its trace (OTLP tracing only; under PROPAGATE_TRACE_HEADERS=peers, the
146
+ # default, on the A2A routes only; see telemetry.attach_trace_context).
147
+ trace_token = attach_trace_context(scope.get("headers") or (), _app_path(scope))
148
+ try:
149
+ await self.app(scope, receive, send_with_id)
150
+ finally:
151
+ detach_trace_context(trace_token)
152
+ observe_request(
153
+ scope.get("method", "GET"),
154
+ route_label(scope),
155
+ status,
156
+ time.perf_counter() - started,
157
+ )
158
+
159
+
160
+ def _app_path(scope: Scope) -> str:
161
+ """The request's path within the app (`root_path` taken off when the path carries it)."""
162
+ path = str(scope.get("path") or "")
163
+ root = str(scope.get("root_path") or "").rstrip("/")
164
+ return path[len(root) :] if root and path.startswith(root + "/") else path
165
+
166
+
167
+ async def read_body(receive: Receive) -> bytes:
168
+ """The whole request body, read from `receive` (pair it with `replay_body`)."""
169
+ chunks: list[bytes] = []
170
+ while True:
171
+ message = await receive()
172
+ if message["type"] != "http.request":
173
+ break # the client left
174
+ chunks.append(message.get("body") or b"")
175
+ if not message.get("more_body"):
176
+ break
177
+ return b"".join(chunks)
178
+
179
+
180
+ def replay_body(body: bytes, receive: Receive) -> Receive:
181
+ """A `receive` that hands the app `body` (already read), then the connection's own messages."""
182
+ replayed = False
183
+
184
+ async def replay() -> Message:
185
+ nonlocal replayed
186
+ if not replayed:
187
+ replayed = True
188
+ return {"type": "http.request", "body": body, "more_body": False}
189
+ return await receive()
190
+
191
+ return replay
192
+
193
+
194
+ class BodySizeLimitMiddleware:
195
+ def __init__(self, app: ASGIApp) -> None:
196
+ self.app = app
197
+
198
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
199
+ if scope["type"] != "http":
200
+ await self.app(scope, receive, send)
201
+ return
202
+ limit = max_request_bytes()
203
+ detail = f"Request body exceeds MAX_REQUEST_BYTES ({limit} bytes)."
204
+ declared = _header(scope, b"content-length")
205
+ if declared is not None:
206
+ try:
207
+ too_large = int(declared) > limit
208
+ except ValueError:
209
+ too_large = False # the server rejects a malformed length itself
210
+ if too_large:
211
+ await JSONResponse({"detail": detail}, status_code=413)(scope, receive, send)
212
+ return
213
+ received = 0
214
+
215
+ async def limited_receive() -> Message:
216
+ nonlocal received
217
+ message = await receive()
218
+ if message["type"] == "http.request":
219
+ received += len(message.get("body") or b"")
220
+ if received > limit:
221
+ # Raised inside the route's body read: FastAPI and Starlette
222
+ # both turn it into the 413 response.
223
+ raise HTTPException(status_code=413, detail=detail)
224
+ return message
225
+
226
+ await self.app(scope, limited_receive, send)
227
+
228
+
229
+ class RunStreamingResponse(StreamingResponse):
230
+ """A streaming response that stops as soon as the client disconnects."""
231
+
232
+ def __init__(
233
+ self,
234
+ content: Any,
235
+ *,
236
+ on_close: Callable[[], Awaitable[None]] | None = None,
237
+ **kwargs: Any,
238
+ ) -> None:
239
+ super().__init__(content, **kwargs)
240
+ self._on_close = on_close
241
+
242
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
243
+ task = asyncio.current_task()
244
+ disconnected = False
245
+
246
+ async def watch_disconnect() -> None:
247
+ nonlocal disconnected
248
+ while True:
249
+ message = await receive()
250
+ if message["type"] == "http.disconnect":
251
+ disconnected = True
252
+ if task is not None:
253
+ task.cancel()
254
+ return
255
+
256
+ watcher = asyncio.ensure_future(watch_disconnect())
257
+ try:
258
+ await self.stream_response(send)
259
+ except asyncio.CancelledError:
260
+ if not disconnected or task is None:
261
+ raise
262
+ task.uncancel() # the client left: a normal end for this request
263
+ except OSError:
264
+ pass # the client left while a chunk was being sent
265
+ finally:
266
+ watcher.cancel()
267
+ aclose = getattr(self.body_iterator, "aclose", None)
268
+ try:
269
+ if aclose is not None:
270
+ await aclose()
271
+ finally:
272
+ if self._on_close is not None:
273
+ await self._on_close()
274
+
275
+
276
+ def _sdk_auth_error(exc: BaseException) -> Any:
277
+ """`exc` when it is a `langgraph_sdk` auth `HTTPException`, else None."""
278
+ try:
279
+ from langgraph_sdk.auth.exceptions import HTTPException as SdkHTTPException
280
+ except ImportError: # not under langgraph-server
281
+ return None
282
+ return exc if isinstance(exc, SdkHTTPException) else None
283
+
284
+
285
+ class AuthErrorMiddleware:
286
+ """langgraph-server: the policy's own 401 challenge and error status on the native API."""
287
+
288
+ def __init__(self, app: ASGIApp) -> None:
289
+ self.app = app
290
+
291
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
292
+ if scope["type"] != "http":
293
+ await self.app(scope, receive, send)
294
+ return
295
+ # The auth handler leaves the challenge here (`auth._stash_challenge`).
296
+ state = scope.setdefault("state", {})
297
+ started = False
298
+
299
+ async def send_with_challenge(message: Message) -> None:
300
+ nonlocal started
301
+ if message["type"] == "http.response.start":
302
+ started = True
303
+ challenge = state.get(AUTH_CHALLENGE_STATE_KEY) if isinstance(state, dict) else None
304
+ if message["status"] == 401 and challenge:
305
+ headers = MutableHeaders(scope=message)
306
+ if "www-authenticate" not in headers:
307
+ headers["www-authenticate"] = challenge
308
+ await send(message)
309
+
310
+ try:
311
+ await self.app(scope, receive, send_with_challenge)
312
+ except Exception as exc:
313
+ error = _sdk_auth_error(exc)
314
+ if error is None or started:
315
+ raise
316
+ logger.warning("request refused by the auth policy with %s", error.status_code)
317
+ response = JSONResponse(
318
+ {"detail": str(error.detail)},
319
+ status_code=int(error.status_code),
320
+ headers=dict(error.headers or {}),
321
+ )
322
+ await response(scope, receive, send_with_challenge)
323
+
324
+
325
+ class ThreadDeleteHookMiddleware:
326
+ """langgraph-server: `on_deleted(thread_id)` after the server's own thread delete succeeds.
327
+
328
+ The server deletes a thread's checkpoints but knows nothing of the run
329
+ records this app keeps (`agent_runs`) or of its A2A tasks; `on_deleted`
330
+ drops them. It runs only after a 2xx, so a refused delete (someone else's
331
+ thread, an unknown one, a busy one) never touches them.
332
+ """
333
+
334
+ def __init__(self, app: ASGIApp, on_deleted: Callable[[str], Awaitable[None]]) -> None:
335
+ self.app = app
336
+ self.on_deleted = on_deleted
337
+
338
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
339
+ match = None
340
+ if scope["type"] == "http" and scope.get("method") == "DELETE":
341
+ match = _THREAD_DELETE_PATH.search(scope.get("path") or "")
342
+ if match is None:
343
+ await self.app(scope, receive, send)
344
+ return
345
+ status = 0
346
+
347
+ async def watch(message: Message) -> None:
348
+ nonlocal status
349
+ if message["type"] == "http.response.start":
350
+ status = int(message["status"])
351
+ await send(message)
352
+
353
+ await self.app(scope, receive, watch)
354
+ if 200 <= status < 300:
355
+ try:
356
+ await self.on_deleted(match.group(1))
357
+ except Exception:
358
+ logger.warning(
359
+ "could not remove the run records or A2A tasks of a deleted thread",
360
+ exc_info=True,
361
+ )