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,216 @@
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
+ """Line-based three-way text merge (the diff3 algorithm) for config files.
16
+
17
+ ``scaffold enhance`` uses it on the config files a runtime, provider, target or
18
+ CD change re-renders (``values-*.yaml``, ``.env.example``, Argo CD
19
+ Applications): the template's own change (old snapshot -> new snapshot) is
20
+ applied to the developer's copy when the two sets of edits touch different
21
+ lines. Overlapping edits are never resolved automatically: ``merge3`` returns
22
+ ``None`` and the caller leaves the file alone and tells the developer.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import difflib
28
+ import re
29
+ from collections.abc import Callable, Sequence
30
+ from typing import Any
31
+
32
+ import yaml
33
+
34
+
35
+ def _sync_regions(
36
+ base: Sequence[str], ours: Sequence[str], theirs: Sequence[str]
37
+ ) -> list[tuple[int, int, int, int, int, int]]:
38
+ """Base ranges left unchanged by both sides, with their positions in each side.
39
+
40
+ Each tuple is ``(base_start, base_end, ours_start, ours_end, theirs_start,
41
+ theirs_end)``; the list ends with an empty sentinel region at the end of
42
+ every sequence.
43
+ """
44
+ ours_blocks = difflib.SequenceMatcher(None, base, ours, autojunk=False).get_matching_blocks()
45
+ theirs_blocks = difflib.SequenceMatcher(
46
+ None, base, theirs, autojunk=False
47
+ ).get_matching_blocks()
48
+ regions: list[tuple[int, int, int, int, int, int]] = []
49
+ i = j = 0
50
+ while i < len(ours_blocks) and j < len(theirs_blocks):
51
+ o_base, o_start, o_len = ours_blocks[i]
52
+ t_base, t_start, t_len = theirs_blocks[j]
53
+ start = max(o_base, t_base)
54
+ end = min(o_base + o_len, t_base + t_len)
55
+ if start < end:
56
+ o_sub = o_start + (start - o_base)
57
+ t_sub = t_start + (start - t_base)
58
+ regions.append((start, end, o_sub, o_sub + end - start, t_sub, t_sub + end - start))
59
+ if o_base + o_len < t_base + t_len:
60
+ i += 1
61
+ else:
62
+ j += 1
63
+ regions.append((len(base), len(base), len(ours), len(ours), len(theirs), len(theirs)))
64
+ return regions
65
+
66
+
67
+ def merge3(base: Sequence[str], ours: Sequence[str], theirs: Sequence[str]) -> list[str] | None:
68
+ """Apply the base->theirs changes to ``ours``; ``None`` when the edits overlap.
69
+
70
+ Between two regions both sides left alone, a stretch changed on one side
71
+ only takes that side, a stretch changed identically on both takes either,
72
+ and a stretch changed differently on both is a conflict.
73
+ """
74
+ merged: list[str] = []
75
+ b = o = t = 0
76
+ for b_start, b_end, o_start, o_end, t_start, t_end in _sync_regions(base, ours, theirs):
77
+ base_chunk = list(base[b:b_start])
78
+ ours_chunk = list(ours[o:o_start])
79
+ theirs_chunk = list(theirs[t:t_start])
80
+ if ours_chunk == theirs_chunk:
81
+ merged.extend(ours_chunk)
82
+ elif ours_chunk == base_chunk:
83
+ merged.extend(theirs_chunk)
84
+ elif theirs_chunk == base_chunk:
85
+ merged.extend(ours_chunk)
86
+ else:
87
+ return None
88
+ merged.extend(base[b_start:b_end])
89
+ b, o, t = b_end, o_end, t_end
90
+ return merged
91
+
92
+
93
+ def merge3_text(base: str, ours: str, theirs: str) -> str | None:
94
+ """:func:`merge3` over the lines of three texts (line endings kept as they are)."""
95
+ result = merge3(
96
+ base.splitlines(keepends=True),
97
+ ours.splitlines(keepends=True),
98
+ theirs.splitlines(keepends=True),
99
+ )
100
+ return None if result is None else "".join(result)
101
+
102
+
103
+ class _Conflict(Exception):
104
+ """Both sides changed the same value differently."""
105
+
106
+
107
+ _MISSING = object()
108
+
109
+
110
+ def _merge_values(base: Any, ours: Any, theirs: Any) -> Any:
111
+ """Three-way merge of parsed documents (mappings merged key by key)."""
112
+ if ours == theirs:
113
+ return ours
114
+ if ours == base:
115
+ return theirs
116
+ if theirs == base:
117
+ return ours
118
+ if all(isinstance(v, dict) for v in (ours, theirs)) and isinstance(base, dict | type(None)):
119
+ base = base or {}
120
+ merged: dict[Any, Any] = {}
121
+ for key in [*ours, *(k for k in theirs if k not in ours)]:
122
+ value = _merge_values(
123
+ base.get(key, _MISSING), ours.get(key, _MISSING), theirs.get(key, _MISSING)
124
+ )
125
+ if value is not _MISSING:
126
+ merged[key] = value
127
+ return merged
128
+ raise _Conflict
129
+
130
+
131
+ class _StrictLoader(yaml.SafeLoader):
132
+ """SafeLoader that refuses a repeated mapping key (a text merge can produce one)."""
133
+
134
+
135
+ def _construct_mapping(loader: _StrictLoader, node: yaml.MappingNode, deep: bool = False) -> dict:
136
+ loader.flatten_mapping(node)
137
+ seen: set[Any] = set()
138
+ for key_node, _value in node.value:
139
+ key = loader.construct_object(key_node, deep=deep)
140
+ if key in seen:
141
+ raise yaml.constructor.ConstructorError(
142
+ None, None, f"repeated key {key!r}", key_node.start_mark
143
+ )
144
+ seen.add(key)
145
+ return yaml.SafeLoader.construct_mapping(loader, node, deep=deep)
146
+
147
+
148
+ _StrictLoader.add_constructor(
149
+ yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
150
+ _construct_mapping, # type: ignore[arg-type]
151
+ )
152
+
153
+ _ENV_ASSIGNMENT = re.compile(r"^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=(.*)$")
154
+
155
+
156
+ def _parse_env(text: str) -> dict[str, str]:
157
+ """The ``NAME=value`` assignments of an env file; a repeated name is an error."""
158
+ values: dict[str, str] = {}
159
+ for line in text.splitlines():
160
+ match = _ENV_ASSIGNMENT.match(line)
161
+ if not match:
162
+ continue
163
+ name, value = match.group(1), match.group(2).strip()
164
+ if name in values:
165
+ raise ValueError(f"repeated variable {name}")
166
+ values[name] = value
167
+ return values
168
+
169
+
170
+ def _parse_for(path: str) -> Callable[[str], Any] | None:
171
+ name = path.rsplit("/", 1)[-1]
172
+ if name.endswith((".yaml", ".yml")):
173
+ return lambda text: yaml.load(text, Loader=_StrictLoader)
174
+ if name.startswith(".env"):
175
+ return _parse_env
176
+ return None
177
+
178
+
179
+ def merge3_checked(base: str, ours: str, theirs: str, path: str) -> str | None:
180
+ """:func:`merge3_text` plus a check that the result means what both sides meant.
181
+
182
+ A line merge can succeed while producing something neither side wrote: two
183
+ insertions at almost the same place may land on either side of a shared
184
+ line (a ``redis:`` block added by the template next to one the developer
185
+ added gives two ``redis:`` keys). For YAML and env files the merged text is
186
+ parsed (repeated keys refused) and must equal a key-by-key three-way merge
187
+ of the three parsed documents; anything else is reported as a conflict.
188
+ """
189
+ merged = merge3_text(base, ours, theirs)
190
+ if merged is None:
191
+ return None
192
+ parse = _parse_for(path)
193
+ if parse is None:
194
+ return merged
195
+ try:
196
+ expected = _merge_values(parse(base), parse(ours), parse(theirs))
197
+ if parse(merged) != expected:
198
+ return None
199
+ except (_Conflict, ValueError, yaml.YAMLError):
200
+ return None
201
+ return merged
202
+
203
+
204
+ def template_diff(old: str, new: str, path: str, *, limit: int = 40) -> str:
205
+ """The template's own change to ``path`` as a unified diff, for a manual merge."""
206
+ lines = list(
207
+ difflib.unified_diff(
208
+ old.splitlines(keepends=True),
209
+ new.splitlines(keepends=True),
210
+ fromfile=f"{path} (template before)",
211
+ tofile=f"{path} (template after)",
212
+ )
213
+ )
214
+ if len(lines) > limit:
215
+ lines = [*lines[:limit], f"... ({len(lines) - limit} more diff lines)\n"]
216
+ return "".join(line if line.endswith("\n") else line + "\n" for line in lines)
@@ -0,0 +1,199 @@
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
+ """Carry the OpenAPI specs a seed ``--api-policy`` references into the new project.
16
+
17
+ ``lint`` resolves a relative ``openapi:`` path against the project root, while
18
+ ``create`` reads the seed policy next to the file the developer passed. Copying
19
+ only ``api-policy.yaml`` would leave every ``openapi:`` reference dangling, and
20
+ the first ``lint`` (the pr_checks gate) would fail on a project that was just
21
+ created. So each referenced spec is copied too:
22
+
23
+ * a relative path that stays inside the seed policy's directory keeps its path
24
+ (``specs/orders.yaml`` lands at ``<project>/specs/orders.yaml``);
25
+ * anything else (an absolute path, ``..``, a hidden directory, or a path the
26
+ template already uses) is copied to ``openapi/<api name>/<file name>`` and the
27
+ ``openapi:`` value in the project's ``api-policy.yaml`` is rewritten in place,
28
+ keeping every comment and the rest of the file byte for byte.
29
+
30
+ A reference that does not name a readable file is a configuration error
31
+ (exit 3) raised before anything is rendered.
32
+ """
33
+
34
+ from __future__ import annotations
35
+
36
+ import json
37
+ import logging
38
+ import pathlib
39
+ import shutil
40
+ from dataclasses import dataclass
41
+
42
+ import yaml
43
+
44
+ from graph_agents_cli._api_policy import POLICY_FILENAME, ApiPolicyFileError
45
+
46
+ FALLBACK_DIR = "openapi"
47
+
48
+
49
+ @dataclass(frozen=True)
50
+ class SpecCopy:
51
+ """One ``openapi:`` reference of the seed policy and where it goes in the project."""
52
+
53
+ api: str
54
+ reference: str
55
+ source: pathlib.Path
56
+ # Project-relative POSIX path the reference keeps, or None when it cannot
57
+ # be kept (the spec then goes under openapi/<api>/ and the value is rewritten).
58
+ kept_path: str | None
59
+
60
+ @property
61
+ def fallback_path(self) -> str:
62
+ return f"{FALLBACK_DIR}/{self.api}/{self.source.name}"
63
+
64
+
65
+ def plan_spec_copies(document: dict, policy_path: str | pathlib.Path) -> list[SpecCopy]:
66
+ """The specs to copy for ``document`` (read from ``policy_path``); exit 3 when one is missing."""
67
+ policy_file = pathlib.Path(policy_path)
68
+ policy_dir = policy_file.resolve().parent
69
+ copies: list[SpecCopy] = []
70
+ errors: list[str] = []
71
+ for name, api in (document.get("apis") or {}).items():
72
+ reference = api.get("openapi") if isinstance(api, dict) else None
73
+ if not reference:
74
+ continue
75
+ raw = pathlib.Path(str(reference).strip())
76
+ source = raw if raw.is_absolute() else policy_dir / raw
77
+ if not source.is_file():
78
+ errors.append(
79
+ f"apis.{name}.openapi: {reference} is not a readable file (a relative path "
80
+ f"is read next to {policy_file.name}); the new project needs a local copy "
81
+ "for `lint` to check calls against it"
82
+ )
83
+ continue
84
+ copies.append(
85
+ SpecCopy(
86
+ api=str(name),
87
+ reference=str(reference),
88
+ source=source.resolve(),
89
+ kept_path=_keepable(raw),
90
+ )
91
+ )
92
+ if errors:
93
+ raise ApiPolicyFileError(policy_file, errors)
94
+ return copies
95
+
96
+
97
+ def _keepable(raw: pathlib.Path) -> str | None:
98
+ """The reference as a project path when it can stay as written, else None."""
99
+ if raw.is_absolute() or "\\" in str(raw):
100
+ return None
101
+ parts = raw.parts
102
+ if not parts or any(part in ("", ".", "..") or part.startswith(".") for part in parts):
103
+ return None
104
+ return pathlib.PurePosixPath(*parts).as_posix()
105
+
106
+
107
+ def install_spec_copies(project_dir: pathlib.Path, copies: list[SpecCopy]) -> list[str]:
108
+ """Copy the planned specs into ``project_dir``; return one line per spec for the user.
109
+
110
+ Must run after the template is rendered and the seed policy copied to
111
+ ``api-policy.yaml``: a kept path the template already uses is not
112
+ overwritten, the fallback location is used instead.
113
+ """
114
+ lines: list[str] = []
115
+ policy_path = project_dir / POLICY_FILENAME
116
+ rewrites: dict[str, str] = {}
117
+ for copy in copies:
118
+ target = copy.kept_path
119
+ if target is None or _occupied(project_dir / target, copy.source):
120
+ target = copy.fallback_path
121
+ rewrites[copy.api] = target
122
+ destination = project_dir / target
123
+ destination.parent.mkdir(parents=True, exist_ok=True)
124
+ shutil.copyfile(copy.source, destination)
125
+ lines.append(f"{copy.api}: {copy.reference} -> {target}")
126
+ if rewrites and not _rewrite_openapi_values(policy_path, rewrites):
127
+ for api, target in rewrites.items():
128
+ lines.append(
129
+ f"{api}: could not rewrite openapi: in {POLICY_FILENAME}; set it to {target}"
130
+ )
131
+ return lines
132
+
133
+
134
+ def _occupied(path: pathlib.Path, source: pathlib.Path) -> bool:
135
+ """True when ``path`` holds something other than a copy of ``source``."""
136
+ if not path.exists() and not path.is_symlink():
137
+ return False
138
+ try:
139
+ return not path.is_file() or path.read_bytes() != source.read_bytes()
140
+ except OSError:
141
+ return True
142
+
143
+
144
+ def _rewrite_openapi_values(policy_path: pathlib.Path, rewrites: dict[str, str]) -> bool:
145
+ """Replace ``apis.<api>.openapi`` scalars in place; True when the result parses as intended.
146
+
147
+ The file is edited at the positions YAML reports for each value, so
148
+ comments and formatting survive. The result is re-read and compared: on
149
+ any mismatch (an alias shared by several APIs, say) the file is restored.
150
+ """
151
+ original = policy_path.read_text(encoding="utf-8")
152
+ try:
153
+ root = yaml.compose(original, Loader=yaml.SafeLoader)
154
+ except yaml.YAMLError as exc:
155
+ logging.warning("Could not parse %s to rewrite openapi paths: %s", policy_path, exc)
156
+ return False
157
+ spans: list[tuple[int, int, str]] = []
158
+ for api, target in rewrites.items():
159
+ node = _openapi_node(root, api)
160
+ if node is None or node.start_mark is None or node.end_mark is None:
161
+ return False
162
+ spans.append((node.start_mark.index, node.end_mark.index, json.dumps(target)))
163
+ text = original
164
+ for start, end, value in sorted(spans, reverse=True):
165
+ text = text[:start] + value + text[end:]
166
+ try:
167
+ parsed = yaml.safe_load(text)
168
+ ok = all(parsed["apis"][api]["openapi"] == target for api, target in rewrites.items())
169
+ ok = ok and _without_openapi(parsed) == _without_openapi(yaml.safe_load(original))
170
+ except (yaml.YAMLError, KeyError, TypeError):
171
+ ok = False
172
+ if not ok:
173
+ return False
174
+ policy_path.write_text(text, encoding="utf-8")
175
+ return True
176
+
177
+
178
+ def _openapi_node(root: yaml.Node | None, api: str) -> yaml.ScalarNode | None:
179
+ apis = _mapping_value(root, "apis")
180
+ entry = _mapping_value(apis, api)
181
+ value = _mapping_value(entry, "openapi")
182
+ return value if isinstance(value, yaml.ScalarNode) else None
183
+
184
+
185
+ def _mapping_value(node: yaml.Node | None, key: str) -> yaml.Node | None:
186
+ if not isinstance(node, yaml.MappingNode):
187
+ return None
188
+ for key_node, value_node in node.value:
189
+ if isinstance(key_node, yaml.ScalarNode) and key_node.value == key:
190
+ return value_node
191
+ return None
192
+
193
+
194
+ def _without_openapi(document: dict) -> dict:
195
+ apis = {
196
+ name: {k: v for k, v in (api or {}).items() if k != "openapi"}
197
+ for name, api in (document.get("apis") or {}).items()
198
+ }
199
+ return {**document, "apis": apis}