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,400 @@
1
+ # Copyright 2026 graph-agents-cli contributors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """graph-agents-cli eval submit command: upload a dataset and results to LangSmith.
16
+
17
+ Optional and never required (nothing hosted is needed to evaluate): needs
18
+ ``LANGSMITH_API_KEY`` and the ``langsmith`` extra (the error names the install
19
+ command when it is missing). The SDK is imported lazily so the CLI works
20
+ without it.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import uuid
26
+ from datetime import UTC, datetime, timedelta
27
+ from pathlib import Path
28
+ from typing import Any
29
+
30
+ import click
31
+
32
+ from graph_agents_cli._output import Console
33
+ from graph_agents_cli._project import find_project_root
34
+ from graph_agents_cli.eval import _paths
35
+ from graph_agents_cli.eval._common import (
36
+ EvalConfigError,
37
+ load_json_file,
38
+ project_env,
39
+ project_meta,
40
+ )
41
+ from graph_agents_cli.eval.cmd_grade import load_traces
42
+ from graph_agents_cli.eval.dataset import Dataset, cases_from_raw, load_dataset
43
+ from graph_agents_cli.eval.gate import STATUS_PASSED
44
+
45
+ LANGSMITH_API_KEY = "LANGSMITH_API_KEY"
46
+ LANGSMITH_ENDPOINT = "LANGSMITH_ENDPOINT"
47
+ # The upload failed (network, auth, the service): a tool failure, not the gate.
48
+ EXIT_SUBMIT_FAILED = 2
49
+
50
+
51
+ class SubmitFailedError(click.ClickException):
52
+ """LangSmith rejected or never received the upload (exit 2)."""
53
+
54
+ exit_code = EXIT_SUBMIT_FAILED
55
+
56
+
57
+ def _describe_upload_failure(exc: Exception, endpoint: str | None) -> str:
58
+ endpoint = endpoint or "the default LangSmith endpoint"
59
+ first_line = (str(exc).strip().splitlines() or [""])[0][:300]
60
+ name = type(exc).__name__
61
+ lowered = name.lower()
62
+ if "connection" in lowered or "timeout" in lowered or isinstance(exc, OSError):
63
+ hint = (
64
+ f"could not reach {endpoint}; check --endpoint / {LANGSMITH_ENDPOINT} and the network"
65
+ )
66
+ elif "auth" in lowered or "forbidden" in lowered:
67
+ hint = f"LangSmith refused the credentials; check {LANGSMITH_API_KEY}"
68
+ else:
69
+ hint = "LangSmith refused the upload"
70
+ detail = f" ({name}: {first_line})" if first_line else f" ({name})"
71
+ return (
72
+ f"eval submit failed: {hint}{detail}.\n"
73
+ " The local results are unchanged; the eval gate never depends on this upload."
74
+ )
75
+
76
+
77
+ def _langsmith_client(api_key: str, endpoint: str | None) -> Any:
78
+ try:
79
+ import langsmith
80
+ except ImportError as exc:
81
+ from graph_agents_cli.scaffold.utils.version import get_current_version, install_command
82
+
83
+ raise EvalConfigError(
84
+ "the langsmith package is not installed; install the extra: "
85
+ + install_command("langsmith", version=get_current_version())
86
+ ) from exc
87
+ kwargs: dict[str, Any] = {"api_key": api_key}
88
+ if endpoint:
89
+ kwargs["api_url"] = endpoint
90
+ return langsmith.Client(**kwargs)
91
+
92
+
93
+ def _resolve_results(project_root: Path | None, results: str | None) -> Path:
94
+ if results:
95
+ path = Path(results)
96
+ if not path.is_absolute() and project_root is not None and not path.exists():
97
+ path = project_root / path
98
+ if not path.is_file():
99
+ raise EvalConfigError(f"results file not found: {path}")
100
+ return path
101
+ if project_root is None:
102
+ raise EvalConfigError("not inside a graph-agents-cli project; pass --results PATH")
103
+ latest = _paths.latest_file(
104
+ _paths.default_grade_results_dir(project_root), _paths.RESULTS_FILE_PREFIX
105
+ )
106
+ if latest is None:
107
+ raise EvalConfigError(
108
+ "no results found; run `graph-agents-cli eval grade` first or pass --results PATH"
109
+ )
110
+ return latest
111
+
112
+
113
+ def _resolve_traces(
114
+ project_root: Path | None, traces: str | None, results: dict[str, Any]
115
+ ) -> tuple[dict[str, Any], dict[str, dict[str, Any]]]:
116
+ candidates: list[Path] = []
117
+ if traces:
118
+ path = Path(traces)
119
+ if not path.is_absolute() and project_root is not None and not path.exists():
120
+ path = project_root / path
121
+ candidates = sorted(path.glob("*.json")) if path.is_dir() else [path]
122
+ else:
123
+ for recorded in results.get("traces_files") or []:
124
+ path = Path(recorded)
125
+ if not path.is_absolute() and project_root is not None:
126
+ path = project_root / path
127
+ if path.is_file():
128
+ candidates.append(path)
129
+ if not candidates:
130
+ return {}, {}
131
+ return load_traces(candidates)
132
+
133
+
134
+ def _resolve_dataset(
135
+ project_root: Path | None,
136
+ dataset: str | None,
137
+ results: dict[str, Any],
138
+ trace_meta: dict[str, Any],
139
+ ) -> Dataset:
140
+ root = project_root or Path.cwd()
141
+ if dataset:
142
+ files = _paths.resolve_input_datasets(root, dataset)
143
+ if not files:
144
+ raise EvalConfigError(f"dataset not found: {dataset}")
145
+ return load_dataset(files)
146
+ recorded = results.get("dataset_paths") or trace_meta.get("dataset_paths") or []
147
+ files = [root / p if not Path(p).is_absolute() else Path(p) for p in recorded]
148
+ if files and all(f.is_file() for f in files):
149
+ return load_dataset(files)
150
+ embedded = trace_meta.get("embedded_cases") or []
151
+ if embedded:
152
+ return cases_from_raw(embedded)
153
+ raise EvalConfigError("cannot locate the dataset for these results; pass --dataset PATH")
154
+
155
+
156
+ def upload(
157
+ client: Any,
158
+ *,
159
+ dataset: Dataset,
160
+ results: dict[str, Any],
161
+ traces: dict[str, dict[str, Any]],
162
+ dataset_name: str,
163
+ experiment: str,
164
+ console: Console,
165
+ ) -> dict[str, Any]:
166
+ """Create/update the dataset and examples, then an experiment with runs and feedback."""
167
+ try:
168
+ ls_dataset = client.read_dataset(dataset_name=dataset_name)
169
+ console.print(f"Updating LangSmith dataset [cyan]{dataset_name}[/cyan]")
170
+ except Exception:
171
+ ls_dataset = client.create_dataset(
172
+ dataset_name=dataset_name,
173
+ description="graph-agents-cli eval dataset (tests/eval/datasets)",
174
+ )
175
+ console.print(f"Created LangSmith dataset [cyan]{dataset_name}[/cyan]")
176
+
177
+ existing: dict[str, Any] = {}
178
+ for example in client.list_examples(dataset_id=ls_dataset.id):
179
+ metadata = getattr(example, "metadata", None) or {}
180
+ case_id = metadata.get("case_id")
181
+ if case_id:
182
+ existing[str(case_id)] = example
183
+
184
+ example_ids: dict[str, Any] = {}
185
+ for case in dataset.cases:
186
+ inputs = {"messages": case.messages}
187
+ outputs: dict[str, Any] = {}
188
+ if case.reference is not None:
189
+ outputs["reference"] = case.reference
190
+ if case.context is not None:
191
+ outputs["context"] = case.context
192
+ metadata = {
193
+ "case_id": case.id,
194
+ "dataset_hash": dataset.hash,
195
+ "expect": case.expect,
196
+ "judge": case.judge,
197
+ **case.metadata,
198
+ }
199
+ if case.id in existing:
200
+ example = existing[case.id]
201
+ client.update_example(
202
+ example_id=example.id, inputs=inputs, outputs=outputs or None, metadata=metadata
203
+ )
204
+ example_ids[case.id] = example.id
205
+ else:
206
+ example = client.create_example(
207
+ inputs=inputs, outputs=outputs or None, dataset_id=ls_dataset.id, metadata=metadata
208
+ )
209
+ example_ids[case.id] = getattr(example, "id", None)
210
+
211
+ project = client.create_project(
212
+ project_name=experiment,
213
+ reference_dataset_id=ls_dataset.id,
214
+ metadata={
215
+ "dataset_hash": results.get("dataset_hash"),
216
+ "traces_dataset_hash": results.get("traces_dataset_hash"),
217
+ "graded_at": results.get("graded_at"),
218
+ "agent_version": results.get("agent_version"),
219
+ "model": results.get("model"),
220
+ "judge": results.get("judge"),
221
+ "summary": results.get("summary"),
222
+ "quality": results.get("quality"),
223
+ },
224
+ )
225
+ console.print(f"Created LangSmith experiment [cyan]{experiment}[/cyan]")
226
+
227
+ run_count = 0
228
+ feedback_count = 0
229
+ for case_result in results.get("cases", []):
230
+ case_id = case_result["id"]
231
+ trace = traces.get(case_id) or {}
232
+ case = dataset.by_id().get(case_id)
233
+ run_id = uuid.uuid4()
234
+ end = datetime.now(UTC)
235
+ latency = trace.get("latency_ms")
236
+ start = (
237
+ end - timedelta(milliseconds=float(latency))
238
+ if isinstance(latency, int | float)
239
+ else end
240
+ )
241
+ client.create_run(
242
+ id=run_id,
243
+ name=case_id,
244
+ run_type="chain",
245
+ inputs={"messages": case.messages} if case else {},
246
+ outputs={
247
+ "response": trace.get("response"),
248
+ "tool_calls": trace.get("tool_calls"),
249
+ "status": case_result.get("status"),
250
+ },
251
+ error=trace.get("error"),
252
+ start_time=start,
253
+ end_time=end,
254
+ project_name=experiment,
255
+ reference_example_id=example_ids.get(case_id),
256
+ extra={
257
+ "metadata": {
258
+ "case_id": case_id,
259
+ "thread_id": trace.get("thread_id"),
260
+ "run_id": trace.get("run_id"),
261
+ "usage": trace.get("usage"),
262
+ "latency_ms": latency,
263
+ "reasons": case_result.get("reasons"),
264
+ }
265
+ },
266
+ )
267
+ run_count += 1
268
+ client.create_feedback(
269
+ run_id,
270
+ key="gate",
271
+ score=1 if case_result.get("status") == STATUS_PASSED else 0,
272
+ value=case_result.get("status"),
273
+ comment="; ".join(case_result.get("reasons") or []) or None,
274
+ )
275
+ feedback_count += 1
276
+ for name, check in (case_result.get("checks") or {}).items():
277
+ client.create_feedback(
278
+ run_id,
279
+ key=f"check:{name}",
280
+ score=1 if check.get("passed") else 0,
281
+ comment=check.get("reason") or None,
282
+ )
283
+ feedback_count += 1
284
+ for name, entry in (case_result.get("judge_scores") or {}).items():
285
+ score = entry.get("score")
286
+ if isinstance(score, int | float):
287
+ client.create_feedback(
288
+ run_id, key=name, score=score, comment=entry.get("reasoning") or None
289
+ )
290
+ feedback_count += 1
291
+
292
+ return {
293
+ "dataset_id": str(getattr(ls_dataset, "id", "")),
294
+ "dataset_url": getattr(ls_dataset, "url", None),
295
+ "project_id": str(getattr(project, "id", "")),
296
+ "project_url": getattr(project, "url", None),
297
+ "examples": len(example_ids),
298
+ "runs": run_count,
299
+ "feedback": feedback_count,
300
+ }
301
+
302
+
303
+ @click.command("submit")
304
+ @click.option(
305
+ "--results",
306
+ default=None,
307
+ help="Results file. Defaults to the newest artifacts/grade_results/results_<ts>.json.",
308
+ )
309
+ @click.option(
310
+ "--traces",
311
+ default=None,
312
+ help="Traces file or directory. Defaults to the traces recorded in the results.",
313
+ )
314
+ @click.option(
315
+ "--dataset",
316
+ default=None,
317
+ help="Dataset file or directory. Defaults to the dataset recorded in the results.",
318
+ )
319
+ @click.option(
320
+ "--dataset-name", default=None, help="LangSmith dataset name. Defaults to '<project>-eval'."
321
+ )
322
+ @click.option(
323
+ "--experiment",
324
+ default=None,
325
+ help="LangSmith experiment (project) name. Defaults to '<dataset-name>-<graded_at>'.",
326
+ )
327
+ @click.option("--endpoint", default=None, help="LangSmith API URL. Defaults to LANGSMITH_ENDPOINT.")
328
+ def cmd_submit(
329
+ *,
330
+ results: str | None,
331
+ traces: str | None,
332
+ dataset: str | None,
333
+ dataset_name: str | None,
334
+ experiment: str | None,
335
+ endpoint: str | None,
336
+ ) -> None:
337
+ """Upload the dataset and a results file to LangSmith as an experiment.
338
+
339
+ Creates or updates the dataset and its examples (one per case, keyed by
340
+ case id), then creates an experiment whose runs carry each case's
341
+ response, tool calls and status, with feedback scores for the gate, every
342
+ deterministic check and every judge metric. Requires LANGSMITH_API_KEY in
343
+ the environment or the project's .env, and the `langsmith` extra.
344
+ """
345
+ console = Console()
346
+ project_root = find_project_root()
347
+ env = project_env(project_root)
348
+ api_key = env.get(LANGSMITH_API_KEY)
349
+ if not api_key:
350
+ raise EvalConfigError(
351
+ "LangSmith is not configured: set LANGSMITH_API_KEY in the environment or the "
352
+ "project's .env (optional; the local eval gate does not need it)"
353
+ )
354
+ results_path = _resolve_results(project_root, results)
355
+ results_doc = load_json_file(results_path, "results file")
356
+ if not isinstance(results_doc, dict) or not isinstance(results_doc.get("cases"), list):
357
+ raise EvalConfigError(f"results file {results_path} has no 'cases' list")
358
+ trace_meta, trace_map = _resolve_traces(project_root, traces, results_doc)
359
+ if not trace_map:
360
+ console.print("[yellow]Warning:[/yellow] no traces found; runs will carry statuses only.")
361
+ ds = _resolve_dataset(project_root, dataset, results_doc, trace_meta)
362
+
363
+ meta = project_meta(project_root)
364
+ name = dataset_name or f"{meta['name'] or 'graph-agents-cli'}-eval"
365
+ stamp = (
366
+ str(results_doc.get("graded_at") or _paths.timestamp())
367
+ .replace(":", "")
368
+ .replace("+0000", "Z")
369
+ )
370
+ experiment_name = experiment or f"{name}-{stamp}"
371
+
372
+ client = _langsmith_client(api_key, endpoint or env.get(LANGSMITH_ENDPOINT))
373
+ console.print(
374
+ f"Submitting [cyan]{results_path}[/cyan] ({len(results_doc['cases'])} case(s)) to LangSmith..."
375
+ )
376
+ try:
377
+ report = upload(
378
+ client,
379
+ dataset=ds,
380
+ results=results_doc,
381
+ traces=trace_map,
382
+ dataset_name=name,
383
+ experiment=experiment_name,
384
+ console=console,
385
+ )
386
+ except click.ClickException:
387
+ raise
388
+ except Exception as exc:
389
+ # The LangSmith SDK raises its own classes (connection, auth, rate
390
+ # limit, ...): one line naming what failed, not the SDK's traceback.
391
+ raise SubmitFailedError(
392
+ _describe_upload_failure(exc, endpoint or env.get(LANGSMITH_ENDPOINT))
393
+ ) from exc
394
+ console.print(
395
+ f"[green]Uploaded[/green] {report['examples']} example(s), {report['runs']} run(s), "
396
+ f"{report['feedback']} feedback score(s)."
397
+ )
398
+ for label, key in (("Dataset", "dataset_url"), ("Experiment", "project_url")):
399
+ if report.get(key):
400
+ console.print(f"{label}: [cyan]{report[key]}[/cyan]")