langgraph-cli 0.4.20__tar.gz → 0.4.22__tar.gz

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 (147) hide show
  1. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/PKG-INFO +1 -1
  2. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/yarn.lock +8 -29
  3. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/yarn.lock +7 -72
  4. langgraph_cli-0.4.22/langgraph_cli/__init__.py +1 -0
  5. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/analytics.py +10 -3
  6. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/cli.py +42 -0
  7. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/config.py +77 -17
  8. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/test_config.py +2 -2
  9. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/uv.lock +6 -6
  10. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/simple/uv.lock +6 -6
  11. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv.lock +79 -79
  12. langgraph_cli-0.4.20/langgraph_cli/__init__.py +0 -1
  13. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/.gitignore +0 -0
  14. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/LICENSE +0 -0
  15. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/Makefile +0 -0
  16. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/README.md +0 -0
  17. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/.env.example +0 -0
  18. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/.gitignore +0 -0
  19. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/Makefile +0 -0
  20. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graph_prerelease_reqs/agent.py +0 -0
  21. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graph_prerelease_reqs/deps/additional_deps/pyproject.toml +0 -0
  22. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graph_prerelease_reqs/deps/zuper_deps/pyproject.toml +0 -0
  23. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graph_prerelease_reqs/langgraph.json +0 -0
  24. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graph_prerelease_reqs/pyproject.toml +0 -0
  25. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graph_prerelease_reqs_fail/agent.py +0 -0
  26. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graph_prerelease_reqs_fail/langgraph.json +0 -0
  27. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graph_prerelease_reqs_fail/pyproject.toml +0 -0
  28. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs/agent.py +0 -0
  29. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs/langgraph.json +0 -0
  30. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs/storm.py +0 -0
  31. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_a/__init__.py +0 -0
  32. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_a/graphs_submod/__init__.py +0 -0
  33. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_a/graphs_submod/agent.py +0 -0
  34. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_a/graphs_submod/subprompt.txt +0 -0
  35. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_a/hello.py +0 -0
  36. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_a/langgraph.json +0 -0
  37. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_a/prompt.txt +0 -0
  38. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_a/requirements.txt +0 -0
  39. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_b/graphs_submod/agent.py +0 -0
  40. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_b/graphs_submod/subprompt.txt +0 -0
  41. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_b/hello.py +0 -0
  42. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_b/langgraph.json +0 -0
  43. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_b/prompt.txt +0 -0
  44. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_b/requirements.txt +0 -0
  45. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_b/utils/__init__.py +0 -0
  46. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/graphs_reqs_b/utils/greeter.py +0 -0
  47. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/langgraph.json +0 -0
  48. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/my_app.py +0 -0
  49. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/pipconf.txt +0 -0
  50. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/poetry.lock +0 -0
  51. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/examples/pyproject.toml +0 -0
  52. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/generate_schema.py +0 -0
  53. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/.dockerignore +0 -0
  54. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/.editorconfig +0 -0
  55. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/.env.example +0 -0
  56. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/.eslintrc.cjs +0 -0
  57. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/.gitignore +0 -0
  58. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/LICENSE +0 -0
  59. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/README.md +0 -0
  60. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/jest.config.js +0 -0
  61. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/langgraph.json +0 -0
  62. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/package.json +0 -0
  63. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/src/agent/graph.ts +0 -0
  64. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/src/agent/state.ts +0 -0
  65. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/static/studio.png +0 -0
  66. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/tests/agent.test.ts +0 -0
  67. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/tests/graph.int.test.ts +0 -0
  68. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-examples/tsconfig.json +0 -0
  69. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/.eslintrc.cjs +0 -0
  70. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/apps/agent/langgraph.json +0 -0
  71. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/apps/agent/package.json +0 -0
  72. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/apps/agent/src/graph.ts +0 -0
  73. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/apps/agent/src/state.ts +0 -0
  74. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/apps/agent/tsconfig.json +0 -0
  75. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/libs/shared/package.json +0 -0
  76. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/libs/shared/src/index.ts +0 -0
  77. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/libs/shared/tsconfig.json +0 -0
  78. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/package.json +0 -0
  79. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/tsconfig.json +0 -0
  80. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/js-monorepo-example/turbo.json +0 -0
  81. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/__main__.py +0 -0
  82. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/archive.py +0 -0
  83. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/constants.py +0 -0
  84. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/deploy.py +0 -0
  85. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/docker.py +0 -0
  86. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/exec.py +0 -0
  87. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/host_backend.py +0 -0
  88. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/progress.py +0 -0
  89. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/py.typed +0 -0
  90. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/schemas.py +0 -0
  91. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/templates.py +0 -0
  92. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/util.py +0 -0
  93. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/uv_lock.py +0 -0
  94. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/langgraph_cli/version.py +0 -0
  95. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/pyproject.toml +0 -0
  96. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/apps/agent/.env.example +0 -0
  97. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/apps/agent/langgraph.json +0 -0
  98. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/apps/agent/pyproject.toml +0 -0
  99. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/apps/agent/src/agent/__init__.py +0 -0
  100. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/apps/agent/src/agent/graph.py +0 -0
  101. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/apps/agent/src/agent/state.py +0 -0
  102. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/libs/common/__init__.py +0 -0
  103. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/libs/common/helpers.py +0 -0
  104. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/libs/shared/pyproject.toml +0 -0
  105. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/libs/shared/src/shared/__init__.py +0 -0
  106. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/libs/shared/src/shared/utils.py +0 -0
  107. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/python-monorepo-example/pyproject.toml +0 -0
  108. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/schemas/schema.json +0 -0
  109. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/schemas/schema.v0.json +0 -0
  110. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/schemas/version.schema.json +0 -0
  111. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/__init__.py +0 -0
  112. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/integration_tests/__init__.py +0 -0
  113. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/integration_tests/test_cli.py +0 -0
  114. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/__init__.py +0 -0
  115. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/agent.py +0 -0
  116. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/cli/__init__.py +0 -0
  117. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/cli/langgraph.json +0 -0
  118. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/cli/pyproject.toml +0 -0
  119. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/cli/test_cli.py +0 -0
  120. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/cli/test_templates.py +0 -0
  121. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/conftest.py +0 -0
  122. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/graphs/agent.py +0 -0
  123. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/helpers.py +0 -0
  124. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/multiplatform/js.mts +0 -0
  125. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/multiplatform/python.py +0 -0
  126. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/pipconfig.txt +0 -0
  127. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/test_archive.py +0 -0
  128. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/test_config.json +0 -0
  129. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/test_deploy_helpers.py +0 -0
  130. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/test_docker.py +0 -0
  131. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/test_host_backend.py +0 -0
  132. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/test_logs_helpers.py +0 -0
  133. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/tests/unit_tests/test_util.py +0 -0
  134. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/apps/agent/.env.example +0 -0
  135. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/apps/agent/langgraph.json +0 -0
  136. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/apps/agent/pyproject.toml +0 -0
  137. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/apps/agent/src/agent/__init__.py +0 -0
  138. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/apps/agent/src/agent/graph.py +0 -0
  139. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/libs/shared/pyproject.toml +0 -0
  140. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/libs/shared/src/shared/__init__.py +0 -0
  141. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/libs/shared/src/shared/utils.py +0 -0
  142. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/monorepo/pyproject.toml +0 -0
  143. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/simple/.env.example +0 -0
  144. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/simple/langgraph.json +0 -0
  145. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/simple/pyproject.toml +0 -0
  146. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/simple/src/agent/__init__.py +0 -0
  147. {langgraph_cli-0.4.20 → langgraph_cli-0.4.22}/uv-examples/simple/src/agent/graph.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-cli
3
- Version: 0.4.20
3
+ Version: 0.4.22
4
4
  Summary: CLI for interacting with LangGraph API
5
5
  Project-URL: Source, https://github.com/langchain-ai/langgraph/tree/main/libs/cli
6
6
  Project-URL: Twitter, https://x.com/LangChain
@@ -1086,11 +1086,6 @@
1086
1086
  resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
1087
1087
  integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==
1088
1088
 
1089
- "@types/uuid@^10.0.0":
1090
- version "10.0.0"
1091
- resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d"
1092
- integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==
1093
-
1094
1089
  "@types/yargs-parser@*":
1095
1090
  version "21.0.3"
1096
1091
  resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
@@ -1782,13 +1777,6 @@ concat-map@0.0.1:
1782
1777
  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
1783
1778
  integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
1784
1779
 
1785
- console-table-printer@^2.12.1:
1786
- version "2.15.0"
1787
- resolved "https://registry.yarnpkg.com/console-table-printer/-/console-table-printer-2.15.0.tgz#5c808204640b8f024d545bde8aabe5d344dfadc1"
1788
- integrity sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw==
1789
- dependencies:
1790
- simple-wcswidth "^1.1.2"
1791
-
1792
1780
  convert-source-map@^2.0.0:
1793
1781
  version "2.0.0"
1794
1782
  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
@@ -3688,16 +3676,12 @@ keyv@^4.5.4:
3688
3676
  json-buffer "3.0.1"
3689
3677
 
3690
3678
  "langsmith@>=0.5.0 <1.0.0":
3691
- version "0.5.4"
3692
- resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.5.4.tgz#f75b82b08e30db72a7d1d595b341e9666bd525e5"
3693
- integrity sha512-qYkNIoKpf0ZYt+cYzrDV+XI3FCexApmZmp8EMs3eDTMv0OvrHMLoxJ9IpkeoXJSX24+GPk0/jXjKx2hWerpy9w==
3679
+ version "0.5.20"
3680
+ resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.5.20.tgz#4021847d2ccd5a86c5eb96060f9bb5f19f80eca5"
3681
+ integrity sha512-ULhLM8RswvQDXufLtNtvclHrWCBx8Cb5UPI6lAZC+8Dq59iHsVPz/3Ac9khWNm1VIvChRsuykixD/WrmzuuA3Q==
3694
3682
  dependencies:
3695
- "@types/uuid" "^10.0.0"
3696
- chalk "^4.1.2"
3697
- console-table-printer "^2.12.1"
3698
- p-queue "^6.6.2"
3699
- semver "^7.6.3"
3700
- uuid "^10.0.0"
3683
+ p-queue "6.6.2"
3684
+ uuid "10.0.0"
3701
3685
 
3702
3686
  leven@^3.1.0:
3703
3687
  version "3.1.0"
@@ -4007,7 +3991,7 @@ p-locate@^5.0.0:
4007
3991
  dependencies:
4008
3992
  p-limit "^3.0.2"
4009
3993
 
4010
- p-queue@^6.6.2:
3994
+ p-queue@6.6.2, p-queue@^6.6.2:
4011
3995
  version "6.6.2"
4012
3996
  resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426"
4013
3997
  integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==
@@ -4303,7 +4287,7 @@ semver@^6.3.1:
4303
4287
  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
4304
4288
  integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
4305
4289
 
4306
- semver@^7.5.3, semver@^7.5.4, semver@^7.6.3, semver@^7.7.2, semver@^7.7.3:
4290
+ semver@^7.5.3, semver@^7.5.4, semver@^7.7.2, semver@^7.7.3:
4307
4291
  version "7.7.4"
4308
4292
  resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a"
4309
4293
  integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==
@@ -4411,11 +4395,6 @@ signal-exit@^4.0.1:
4411
4395
  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
4412
4396
  integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
4413
4397
 
4414
- simple-wcswidth@^1.1.2:
4415
- version "1.1.2"
4416
- resolved "https://registry.yarnpkg.com/simple-wcswidth/-/simple-wcswidth-1.1.2.tgz#66722f37629d5203f9b47c5477b1225b85d6525b"
4417
- integrity sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==
4418
-
4419
4398
  slash@^3.0.0:
4420
4399
  version "3.0.0"
4421
4400
  resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
@@ -4870,7 +4849,7 @@ uri-js@^4.2.2:
4870
4849
  dependencies:
4871
4850
  punycode "^2.1.0"
4872
4851
 
4873
- uuid@^10.0.0:
4852
+ uuid@10.0.0, uuid@^10.0.0:
4874
4853
  version "10.0.0"
4875
4854
  resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294"
4876
4855
  integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==
@@ -217,11 +217,6 @@
217
217
  resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
218
218
  integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
219
219
 
220
- "@types/uuid@^10.0.0":
221
- version "10.0.0"
222
- resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d"
223
- integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==
224
-
225
220
  "@typescript-eslint/eslint-plugin@^8.58.0":
226
221
  version "8.58.0"
227
222
  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.0.tgz#ad40e492f1931f46da1bd888e52b9e56df9063aa"
@@ -343,13 +338,6 @@ ajv@^6.14.0:
343
338
  json-schema-traverse "^0.4.1"
344
339
  uri-js "^4.2.2"
345
340
 
346
- ansi-styles@^4.1.0:
347
- version "4.3.0"
348
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
349
- integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
350
- dependencies:
351
- color-convert "^2.0.1"
352
-
353
341
  ansi-styles@^5.0.0:
354
342
  version "5.2.0"
355
343
  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
@@ -508,38 +496,11 @@ camelcase@6:
508
496
  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
509
497
  integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
510
498
 
511
- chalk@^4.1.2:
512
- version "4.1.2"
513
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
514
- integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
515
- dependencies:
516
- ansi-styles "^4.1.0"
517
- supports-color "^7.1.0"
518
-
519
- color-convert@^2.0.1:
520
- version "2.0.1"
521
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
522
- integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
523
- dependencies:
524
- color-name "~1.1.4"
525
-
526
- color-name@~1.1.4:
527
- version "1.1.4"
528
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
529
- integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
530
-
531
499
  concat-map@0.0.1:
532
500
  version "0.0.1"
533
501
  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
534
502
  integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
535
503
 
536
- console-table-printer@^2.12.1:
537
- version "2.14.6"
538
- resolved "https://registry.yarnpkg.com/console-table-printer/-/console-table-printer-2.14.6.tgz#edfe0bf311fa2701922ed509443145ab51e06436"
539
- integrity sha512-MCBl5HNVaFuuHW6FGbL/4fB7N/ormCy+tQ+sxTrF6QtSbSNETvPuOVbkJBhzDgYhvjWGrTma4eYJa37ZuoQsPw==
540
- dependencies:
541
- simple-wcswidth "^1.0.1"
542
-
543
504
  cross-spawn@^7.0.6:
544
505
  version "7.0.6"
545
506
  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
@@ -1059,11 +1020,6 @@ has-bigints@^1.0.2:
1059
1020
  resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe"
1060
1021
  integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==
1061
1022
 
1062
- has-flag@^4.0.0:
1063
- version "4.0.0"
1064
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
1065
- integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
1066
-
1067
1023
  has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2:
1068
1024
  version "1.0.2"
1069
1025
  resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
@@ -1372,16 +1328,12 @@ keyv@^4.5.4:
1372
1328
  json-buffer "3.0.1"
1373
1329
 
1374
1330
  "langsmith@>=0.5.0 <1.0.0":
1375
- version "0.5.4"
1376
- resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.5.4.tgz#f75b82b08e30db72a7d1d595b341e9666bd525e5"
1377
- integrity sha512-qYkNIoKpf0ZYt+cYzrDV+XI3FCexApmZmp8EMs3eDTMv0OvrHMLoxJ9IpkeoXJSX24+GPk0/jXjKx2hWerpy9w==
1331
+ version "0.5.20"
1332
+ resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.5.20.tgz#4021847d2ccd5a86c5eb96060f9bb5f19f80eca5"
1333
+ integrity sha512-ULhLM8RswvQDXufLtNtvclHrWCBx8Cb5UPI6lAZC+8Dq59iHsVPz/3Ac9khWNm1VIvChRsuykixD/WrmzuuA3Q==
1378
1334
  dependencies:
1379
- "@types/uuid" "^10.0.0"
1380
- chalk "^4.1.2"
1381
- console-table-printer "^2.12.1"
1382
- p-queue "^6.6.2"
1383
- semver "^7.6.3"
1384
- uuid "^10.0.0"
1335
+ p-queue "6.6.2"
1336
+ uuid "10.0.0"
1385
1337
 
1386
1338
  levn@^0.4.1:
1387
1339
  version "0.4.1"
@@ -1528,7 +1480,7 @@ p-locate@^5.0.0:
1528
1480
  dependencies:
1529
1481
  p-limit "^3.0.2"
1530
1482
 
1531
- p-queue@^6.6.2:
1483
+ p-queue@6.6.2, p-queue@^6.6.2:
1532
1484
  version "6.6.2"
1533
1485
  resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426"
1534
1486
  integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==
@@ -1690,11 +1642,6 @@ semver@^6.3.1:
1690
1642
  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
1691
1643
  integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
1692
1644
 
1693
- semver@^7.6.3:
1694
- version "7.7.2"
1695
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58"
1696
- integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==
1697
-
1698
1645
  semver@^7.7.3:
1699
1646
  version "7.7.4"
1700
1647
  resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a"
@@ -1783,11 +1730,6 @@ side-channel@^1.1.0:
1783
1730
  side-channel-map "^1.0.1"
1784
1731
  side-channel-weakmap "^1.0.2"
1785
1732
 
1786
- simple-wcswidth@^1.0.1:
1787
- version "1.1.2"
1788
- resolved "https://registry.yarnpkg.com/simple-wcswidth/-/simple-wcswidth-1.1.2.tgz#66722f37629d5203f9b47c5477b1225b85d6525b"
1789
- integrity sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==
1790
-
1791
1733
  stop-iteration-iterator@^1.1.0:
1792
1734
  version "1.1.0"
1793
1735
  resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz#f481ff70a548f6124d0312c3aa14cbfa7aa542ad"
@@ -1838,13 +1780,6 @@ strip-json-comments@^3.1.1:
1838
1780
  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
1839
1781
  integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
1840
1782
 
1841
- supports-color@^7.1.0:
1842
- version "7.2.0"
1843
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
1844
- integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
1845
- dependencies:
1846
- has-flag "^4.0.0"
1847
-
1848
1783
  supports-preserve-symlinks-flag@^1.0.0:
1849
1784
  version "1.0.0"
1850
1785
  resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
@@ -1966,7 +1901,7 @@ uri-js@^4.2.2:
1966
1901
  dependencies:
1967
1902
  punycode "^2.1.0"
1968
1903
 
1969
- uuid@^10.0.0:
1904
+ uuid@10.0.0, uuid@^10.0.0:
1970
1905
  version "10.0.0"
1971
1906
  resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294"
1972
1907
  integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==
@@ -0,0 +1 @@
1
+ __version__ = "0.4.22"
@@ -26,8 +26,15 @@ class LogData(TypedDict):
26
26
  params: dict[str, Any]
27
27
 
28
28
 
29
- def get_anonymized_params(kwargs: dict[str, Any]) -> dict[str, bool]:
30
- params = {}
29
+ def get_anonymized_params(
30
+ kwargs: dict[str, Any], *, cli_command: str
31
+ ) -> dict[str, bool | str]:
32
+ params: dict[str, bool | str] = {}
33
+
34
+ if cli_command == "deploy" and (
35
+ analytics_source := os.getenv("LANGGRAPH_CLI_ANALYTICS_SOURCE")
36
+ ):
37
+ params["source"] = analytics_source
31
38
 
32
39
  # anonymize params with values
33
40
  if config := kwargs.get("config"):
@@ -88,7 +95,7 @@ def log_command(func):
88
95
  "python_version": platform.python_version(),
89
96
  "cli_version": __version__,
90
97
  "cli_command": func.__name__,
91
- "params": get_anonymized_params(kwargs),
98
+ "params": get_anonymized_params(kwargs, cli_command=func.__name__),
92
99
  }
93
100
 
94
101
  background_thread = threading.Thread(target=log_data, args=(data,))
@@ -817,6 +817,48 @@ def dev(
817
817
  )
818
818
 
819
819
 
820
+ # ---------------------------------------------------------------------------
821
+ # validate command
822
+ # ---------------------------------------------------------------------------
823
+
824
+
825
+ @OPT_CONFIG
826
+ @cli.command(help="✅ Validate the LangGraph configuration file.")
827
+ @log_command
828
+ def validate(config: pathlib.Path):
829
+ import json
830
+
831
+ try:
832
+ with open(config) as f:
833
+ raw_config = json.load(f)
834
+ except json.JSONDecodeError as e:
835
+ raise click.UsageError(f"Invalid JSON in {config}: {e.args[0]}") from None
836
+
837
+ # Check for unknown keys before validation so they show alongside any error.
838
+ unknown_warnings = langgraph_cli.config.get_unknown_keys(raw_config)
839
+
840
+ try:
841
+ config_json = langgraph_cli.config.validate_config_file(config)
842
+ except (click.UsageError, ValueError) as e:
843
+ click.secho(f"Error: {e}", fg="red", err=True)
844
+ if unknown_warnings:
845
+ click.echo(err=True)
846
+ for warning in unknown_warnings:
847
+ click.secho(f" warning: {warning}", fg="yellow", err=True)
848
+ raise SystemExit(1) from None
849
+
850
+ num_graphs = len(config_json.get("graphs", {}))
851
+ click.secho(
852
+ f"Configuration file {config} is valid. "
853
+ f"({num_graphs} graph{'s' if num_graphs != 1 else ''} found)",
854
+ fg="green",
855
+ )
856
+ if unknown_warnings:
857
+ click.echo()
858
+ for warning in unknown_warnings:
859
+ click.secho(f" warning: {warning}", fg="yellow")
860
+
861
+
820
862
  # ---------------------------------------------------------------------------
821
863
  # new command
822
864
  # ---------------------------------------------------------------------------
@@ -182,7 +182,11 @@ def validate_config(config: Config) -> Config:
182
182
  "Version must be major or major.minor or major.minor.patch."
183
183
  )
184
184
  except TypeError:
185
- raise click.UsageError(f"Invalid version format: {api_version}") from None
185
+ raise click.UsageError(
186
+ f"Invalid version format: {api_version}.\n\n"
187
+ "Pin to a minor version, e.g.:\n"
188
+ ' "api_version": "0.8"'
189
+ ) from None
186
190
 
187
191
  config = {
188
192
  "node_version": node_version,
@@ -220,45 +224,51 @@ def validate_config(config: Config) -> Config:
220
224
  if major < min_major:
221
225
  raise click.UsageError(
222
226
  f"Node.js version {node_version} is not supported. "
223
- f"Minimum required version is {MIN_NODE_VERSION}."
227
+ f"Minimum required version is {MIN_NODE_VERSION}.\n\n"
228
+ f"Set node_version to {MIN_NODE_VERSION} or higher:\n"
229
+ f' "node_version": "{MIN_NODE_VERSION}"'
224
230
  )
225
231
  except ValueError as e:
226
232
  raise click.UsageError(str(e)) from None
227
233
 
228
234
  if pip_installer := config.get("pip_installer"):
229
- if pip_installer == "uv_lock":
230
- raise click.UsageError(
231
- "pip_installer 'uv_lock' has been replaced. Use "
232
- '`source: {"kind": "uv", "root": "..", '
233
- '"package": "my-agent"}`.'
234
- )
235
235
  if pip_installer not in ["auto", "pip", "uv"]:
236
236
  raise click.UsageError(
237
237
  f"Invalid pip_installer: '{pip_installer}'. "
238
- "Must be 'auto', 'pip', or 'uv'."
238
+ "Consider using uv-based source management instead:\n\n"
239
+ ' "source": {"kind": "uv", "root": ".."}'
239
240
  )
240
241
 
241
242
  source = config.get("source")
242
243
  source_kind = _get_source_kind(config)
243
244
  if source is not None and not isinstance(source, dict):
244
- raise click.UsageError("`source` must be an object.")
245
+ raise click.UsageError(
246
+ "`source` must be an object, e.g.:\n"
247
+ ' "source": {"kind": "uv", "root": ".."}'
248
+ )
245
249
  if source is not None and source_kind != "uv":
246
- raise click.UsageError("Invalid source.kind. Supported values: 'uv'.")
250
+ raise click.UsageError(
251
+ "Invalid source.kind. The only supported value is 'uv':\n"
252
+ ' "source": {"kind": "uv", "root": ".."}'
253
+ )
247
254
 
248
255
  if config.get("python_version"):
249
256
  pyversion = config["python_version"]
250
257
  if not pyversion.count(".") == 1 or not all(
251
258
  part.isdigit() for part in pyversion.split("-")[0].split(".")
252
259
  ):
260
+ parts = pyversion.split("-")[0].split(".")
261
+ fix = f"{parts[0]}.{parts[1]}" if len(parts) >= 2 else MIN_PYTHON_VERSION
253
262
  raise click.UsageError(
254
263
  f"Invalid Python version format: {pyversion}. "
255
- "Use 'major.minor' format (e.g., '3.11'). "
256
- "Patch version cannot be specified."
264
+ "Use 'major.minor' format patch version cannot be specified.\n\n"
265
+ f' "python_version": "{fix}"'
257
266
  )
258
267
  if _parse_version(pyversion) < _parse_version(MIN_PYTHON_VERSION):
259
268
  raise click.UsageError(
260
269
  f"Python version {pyversion} is not supported. "
261
- f"Minimum required version is {MIN_PYTHON_VERSION}."
270
+ f"Minimum required version is {MIN_PYTHON_VERSION}.\n\n"
271
+ f' "python_version": "{MIN_PYTHON_VERSION}"'
262
272
  )
263
273
  if "bullseye" in pyversion:
264
274
  raise click.UsageError(
@@ -269,12 +279,16 @@ def validate_config(config: Config) -> Config:
269
279
  if source_kind != "uv" and not config["dependencies"]:
270
280
  raise click.UsageError(
271
281
  "No dependencies found in config. "
272
- "Add at least one dependency to 'dependencies' list."
282
+ "Consider using uv-based source management:\n\n"
283
+ ' "source": {"kind": "uv", "root": ".."}'
273
284
  )
274
285
 
275
286
  if not config.get("graphs"):
276
287
  raise click.UsageError(
277
- "No graphs found in config. Add at least one graph to 'graphs' dictionary."
288
+ "No graphs found in config. Add at least one graph, e.g.:\n"
289
+ ' "graphs": {\n'
290
+ ' "agent": "./my_agent/graph.py:graph"\n'
291
+ " }"
278
292
  )
279
293
 
280
294
  # Validate image_distro config
@@ -287,7 +301,8 @@ def validate_config(config: Config) -> Config:
287
301
  if image_distro not in Distros.__args__:
288
302
  raise click.UsageError(
289
303
  f"Invalid image_distro: '{image_distro}'. "
290
- "Must be one of 'debian', 'wolfi', or 'bookworm'."
304
+ f"Must be one of: {', '.join(repr(d) for d in Distros.__args__)}.\n\n"
305
+ ' "image_distro": "wolfi" (recommended)'
291
306
  )
292
307
 
293
308
  if source_kind == "uv":
@@ -369,6 +384,51 @@ def validate_config(config: Config) -> Config:
369
384
  return config
370
385
 
371
386
 
387
+ # Keys recognized by validate_config (used to detect unknown fields).
388
+ _KNOWN_CONFIG_KEYS = {
389
+ "python_version",
390
+ "node_version",
391
+ "api_version",
392
+ "base_image",
393
+ "image_distro",
394
+ "pip_config_file",
395
+ "pip_installer",
396
+ "source",
397
+ "dependencies",
398
+ "dockerfile_lines",
399
+ "graphs",
400
+ "env",
401
+ "store",
402
+ "auth",
403
+ "encryption",
404
+ "http",
405
+ "webhooks",
406
+ "checkpointer",
407
+ "ui",
408
+ "ui_config",
409
+ "keep_pkg_tools",
410
+ # Internal / legacy (still recognized, may error separately)
411
+ "_INTERNAL_docker_tag",
412
+ "project_root",
413
+ "package",
414
+ }
415
+
416
+
417
+ def get_unknown_keys(raw_config: dict) -> list[str]:
418
+ """Return warnings for unrecognized top-level keys (typos, etc.)."""
419
+ import difflib
420
+
421
+ unknown = set(raw_config) - _KNOWN_CONFIG_KEYS
422
+ warnings: list[str] = []
423
+ for key in sorted(unknown):
424
+ close = difflib.get_close_matches(key, _KNOWN_CONFIG_KEYS, n=1)
425
+ if close:
426
+ warnings.append(f"Unknown key '{key}' — did you mean '{close[0]}'?")
427
+ else:
428
+ warnings.append(f"Unknown key '{key}' is not a recognized config field.")
429
+ return warnings
430
+
431
+
372
432
  def validate_config_file(config_path: pathlib.Path) -> Config:
373
433
  """Load and validate a configuration file."""
374
434
  with open(config_path) as f:
@@ -404,7 +404,7 @@ def test_validate_config_pip_installer():
404
404
  }
405
405
  )
406
406
  assert "Invalid pip_installer: 'conda'" in str(exc_info.value)
407
- assert "Must be 'auto', 'pip', or 'uv'" in str(exc_info.value)
407
+ assert "uv-based source management" in str(exc_info.value)
408
408
 
409
409
  with pytest.raises(click.UsageError) as exc_info:
410
410
  validate_config(
@@ -417,7 +417,7 @@ def test_validate_config_pip_installer():
417
417
  )
418
418
  assert "Invalid pip_installer: 'invalid'" in str(exc_info.value)
419
419
 
420
- with pytest.raises(click.UsageError, match="has been replaced"):
420
+ with pytest.raises(click.UsageError, match="Invalid pip_installer: 'uv_lock'"):
421
421
  validate_config(
422
422
  {
423
423
  "python_version": "3.11",
@@ -215,7 +215,7 @@ wheels = [
215
215
 
216
216
  [[package]]
217
217
  name = "langchain-core"
218
- version = "1.2.27"
218
+ version = "1.2.28"
219
219
  source = { registry = "https://pypi.org/simple" }
220
220
  dependencies = [
221
221
  { name = "jsonpatch" },
@@ -227,9 +227,9 @@ dependencies = [
227
227
  { name = "typing-extensions" },
228
228
  { name = "uuid-utils" },
229
229
  ]
230
- sdist = { url = "https://files.pythonhosted.org/packages/13/5c/56d19a252bbb26247b7a7cd20821d48804d7ca03212fec709cd8db7c2516/langchain_core-1.2.27.tar.gz", hash = "sha256:c18372e4c4c1454d49bf23a2e484431e71bd39b64173a0f621f0fc283d7183a4", size = 844935, upload-time = "2026-04-07T14:56:32.364Z" }
230
+ sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/317a1a3ac1df33a64adb3670bf88bbe3b3d5baa274db6863a979db472897/langchain_core-1.2.28.tar.gz", hash = "sha256:271a3d8bd618f795fdeba112b0753980457fc90537c46a0c11998516a74dc2cb", size = 846119, upload-time = "2026-04-08T18:19:34.867Z" }
231
231
  wheels = [
232
- { url = "https://files.pythonhosted.org/packages/c1/c3/6e0865bc130c448270eb9511b47863a3f9145cdb519b19f6e4758fa63d6f/langchain_core-1.2.27-py3-none-any.whl", hash = "sha256:9ecd6b0393b969fe88f6b9b309367134080ab095946d79e6937dd3911aa42bd5", size = 508315, upload-time = "2026-04-07T14:56:30.93Z" },
232
+ { url = "https://files.pythonhosted.org/packages/a8/92/32f785f077c7e898da97064f113c73fbd9ad55d1e2169cf3a391b183dedb/langchain_core-1.2.28-py3-none-any.whl", hash = "sha256:80764232581eaf8057bcefa71dbf8adc1f6a28d257ebd8b95ba9b8b452e8c6ac", size = 508727, upload-time = "2026-04-08T18:19:32.823Z" },
233
233
  ]
234
234
 
235
235
  [[package]]
@@ -290,7 +290,7 @@ wheels = [
290
290
 
291
291
  [[package]]
292
292
  name = "langsmith"
293
- version = "0.7.26"
293
+ version = "0.7.31"
294
294
  source = { registry = "https://pypi.org/simple" }
295
295
  dependencies = [
296
296
  { name = "httpx" },
@@ -303,9 +303,9 @@ dependencies = [
303
303
  { name = "xxhash" },
304
304
  { name = "zstandard" },
305
305
  ]
306
- sdist = { url = "https://files.pythonhosted.org/packages/76/86/6de4f6f0451a9658f26f633e0bb090552a4dafd7df3f1ae7f0d40558e67e/langsmith-0.7.26.tar.gz", hash = "sha256:a3e06f3d689ce7195717aa6b8f91082319819ec7ea9b9a62cdcd3d9dc25bfc7b", size = 1146118, upload-time = "2026-04-06T15:01:03.336Z" }
306
+ sdist = { url = "https://files.pythonhosted.org/packages/e6/11/696019490992db5c87774dc20515529ef42a01e1d770fb754ed6d9b12fb0/langsmith-0.7.31.tar.gz", hash = "sha256:331ee4f7c26bb5be4022b9859b7d7b122cbf8c9d01d9f530114c1914b0349ffb", size = 1178480, upload-time = "2026-04-14T17:55:41.242Z" }
307
307
  wheels = [
308
- { url = "https://files.pythonhosted.org/packages/81/8e/7eb7d65ce62e98e74b9f18f193ea7ac3996d4fbd71fffcc67d0f7ba3103e/langsmith-0.7.26-py3-none-any.whl", hash = "sha256:fe5c877972cea450c1c48251c8fae0f18543c8d19dfdb9ff9a9c4263763dde4e", size = 360160, upload-time = "2026-04-06T15:01:01.516Z" },
308
+ { url = "https://files.pythonhosted.org/packages/1d/a1/a013cf458c301cda86a213dd153ce0a01c93f1ab5833f951e6a44c9763ce/langsmith-0.7.31-py3-none-any.whl", hash = "sha256:0291d49203f6e80dda011af1afda61eb0595a4d697adb684590a8805e1d61fb6", size = 373276, upload-time = "2026-04-14T17:55:39.677Z" },
309
309
  ]
310
310
 
311
311
  [[package]]
@@ -191,7 +191,7 @@ wheels = [
191
191
 
192
192
  [[package]]
193
193
  name = "langchain-core"
194
- version = "1.2.27"
194
+ version = "1.2.28"
195
195
  source = { registry = "https://pypi.org/simple" }
196
196
  dependencies = [
197
197
  { name = "jsonpatch" },
@@ -203,9 +203,9 @@ dependencies = [
203
203
  { name = "typing-extensions" },
204
204
  { name = "uuid-utils" },
205
205
  ]
206
- sdist = { url = "https://files.pythonhosted.org/packages/13/5c/56d19a252bbb26247b7a7cd20821d48804d7ca03212fec709cd8db7c2516/langchain_core-1.2.27.tar.gz", hash = "sha256:c18372e4c4c1454d49bf23a2e484431e71bd39b64173a0f621f0fc283d7183a4", size = 844935, upload-time = "2026-04-07T14:56:32.364Z" }
206
+ sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/317a1a3ac1df33a64adb3670bf88bbe3b3d5baa274db6863a979db472897/langchain_core-1.2.28.tar.gz", hash = "sha256:271a3d8bd618f795fdeba112b0753980457fc90537c46a0c11998516a74dc2cb", size = 846119, upload-time = "2026-04-08T18:19:34.867Z" }
207
207
  wheels = [
208
- { url = "https://files.pythonhosted.org/packages/c1/c3/6e0865bc130c448270eb9511b47863a3f9145cdb519b19f6e4758fa63d6f/langchain_core-1.2.27-py3-none-any.whl", hash = "sha256:9ecd6b0393b969fe88f6b9b309367134080ab095946d79e6937dd3911aa42bd5", size = 508315, upload-time = "2026-04-07T14:56:30.93Z" },
208
+ { url = "https://files.pythonhosted.org/packages/a8/92/32f785f077c7e898da97064f113c73fbd9ad55d1e2169cf3a391b183dedb/langchain_core-1.2.28-py3-none-any.whl", hash = "sha256:80764232581eaf8057bcefa71dbf8adc1f6a28d257ebd8b95ba9b8b452e8c6ac", size = 508727, upload-time = "2026-04-08T18:19:32.823Z" },
209
209
  ]
210
210
 
211
211
  [[package]]
@@ -266,7 +266,7 @@ wheels = [
266
266
 
267
267
  [[package]]
268
268
  name = "langsmith"
269
- version = "0.7.26"
269
+ version = "0.7.31"
270
270
  source = { registry = "https://pypi.org/simple" }
271
271
  dependencies = [
272
272
  { name = "httpx" },
@@ -279,9 +279,9 @@ dependencies = [
279
279
  { name = "xxhash" },
280
280
  { name = "zstandard" },
281
281
  ]
282
- sdist = { url = "https://files.pythonhosted.org/packages/76/86/6de4f6f0451a9658f26f633e0bb090552a4dafd7df3f1ae7f0d40558e67e/langsmith-0.7.26.tar.gz", hash = "sha256:a3e06f3d689ce7195717aa6b8f91082319819ec7ea9b9a62cdcd3d9dc25bfc7b", size = 1146118, upload-time = "2026-04-06T15:01:03.336Z" }
282
+ sdist = { url = "https://files.pythonhosted.org/packages/e6/11/696019490992db5c87774dc20515529ef42a01e1d770fb754ed6d9b12fb0/langsmith-0.7.31.tar.gz", hash = "sha256:331ee4f7c26bb5be4022b9859b7d7b122cbf8c9d01d9f530114c1914b0349ffb", size = 1178480, upload-time = "2026-04-14T17:55:41.242Z" }
283
283
  wheels = [
284
- { url = "https://files.pythonhosted.org/packages/81/8e/7eb7d65ce62e98e74b9f18f193ea7ac3996d4fbd71fffcc67d0f7ba3103e/langsmith-0.7.26-py3-none-any.whl", hash = "sha256:fe5c877972cea450c1c48251c8fae0f18543c8d19dfdb9ff9a9c4263763dde4e", size = 360160, upload-time = "2026-04-06T15:01:01.516Z" },
284
+ { url = "https://files.pythonhosted.org/packages/1d/a1/a013cf458c301cda86a213dd153ce0a01c93f1ab5833f951e6a44c9763ce/langsmith-0.7.31-py3-none-any.whl", hash = "sha256:0291d49203f6e80dda011af1afda61eb0595a4d697adb684590a8805e1d61fb6", size = 373276, upload-time = "2026-04-14T17:55:39.677Z" },
285
285
  ]
286
286
 
287
287
  [[package]]