10xscale-agentflow-cli 0.3.2.1__tar.gz → 0.3.2.2__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 (179) hide show
  1. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/10xscale_agentflow_cli.egg-info/PKG-INFO +2 -1
  2. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/10xscale_agentflow_cli.egg-info/SOURCES.txt +29 -2
  3. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/10xscale_agentflow_cli.egg-info/requires.txt +1 -0
  4. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/PKG-INFO +2 -1
  5. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow.json +1 -1
  6. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/commands/init.py +392 -0
  7. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/main.py +3 -11
  8. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/dev/agentflow.json +6 -0
  9. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/dev/graph/agent.py +132 -0
  10. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/.pre-commot-config.yaml +50 -0
  11. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/agentflow.json +19 -0
  12. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/auth/agent_auth.py +19 -0
  13. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/evals/weather_agents.py +119 -0
  14. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/agent.py +45 -0
  15. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/nodes/__init__.py +5 -0
  16. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/nodes/main_node.py +27 -0
  17. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/nodes/tool_node.py +10 -0
  18. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/state.py +5 -0
  19. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod}/graph/thread_name_generator.py +1 -0
  20. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/tools/weather_tool.py +43 -0
  21. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/utils/__init__.py +0 -0
  22. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/utils/tool_decision.py +30 -0
  23. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/validators/__init__.py +0 -0
  24. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/validators/lifecyle.py +107 -0
  25. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/validators/manager.py +9 -0
  26. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/validators/validators.py +21 -0
  27. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/tests/__init__.py +0 -0
  28. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/tests/conftest.py +6 -0
  29. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/tests/test_agent_eval.py +88 -0
  30. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/tests/test_catalog_tools.py +47 -0
  31. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/tests/test_graph_nodes.py +57 -0
  32. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/src/__init__.py +0 -0
  33. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/src/app/core/auth/__init__.py +0 -0
  34. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/src/app/core/config/__init__.py +0 -0
  35. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/config/settings.py +1 -1
  36. 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/src/app/tasks/__init__.py +0 -0
  37. 10xscale_agentflow_cli-0.3.2.2/graph/__init__.py +0 -0
  38. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/pyproject.toml +9 -2
  39. 10xscale_agentflow_cli-0.3.2.1/agentflow_cli/cli/commands/init.py +0 -129
  40. 10xscale_agentflow_cli-0.3.2.1/scripts/generate_docs.py +0 -21
  41. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/10xscale_agentflow_cli.egg-info/dependency_links.txt +0 -0
  42. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/10xscale_agentflow_cli.egg-info/entry_points.txt +0 -0
  43. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/10xscale_agentflow_cli.egg-info/not-zip-safe +0 -0
  44. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/10xscale_agentflow_cli.egg-info/top_level.txt +0 -0
  45. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/MANIFEST.in +0 -0
  46. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/README.md +0 -0
  47. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/__init__.py +0 -0
  48. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/__init__.py +0 -0
  49. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/commands/__init__.py +0 -0
  50. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/commands/api.py +0 -0
  51. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/commands/build.py +0 -0
  52. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/commands/skills.py +0 -0
  53. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/commands/version.py +0 -0
  54. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/constants.py +0 -0
  55. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/core/__init__.py +0 -0
  56. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/core/config.py +0 -0
  57. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/core/output.py +0 -0
  58. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/core/validation.py +0 -0
  59. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/exceptions.py +0 -0
  60. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/logger.py +0 -0
  61. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/__init__.py +0 -0
  62. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/defaults.py +0 -0
  63. {10xscale_agentflow_cli-0.3.2.1/agentflow_cli/src → 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/dev/graph}/__init__.py +0 -0
  64. {10xscale_agentflow_cli-0.3.2.1/agentflow_cli/src/app/core → 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod}/auth/__init__.py +0 -0
  65. {10xscale_agentflow_cli-0.3.2.1/agentflow_cli/src/app/core/config → 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/evals}/__init__.py +0 -0
  66. {10xscale_agentflow_cli-0.3.2.1/agentflow_cli/src/app/tasks → 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph}/__init__.py +0 -0
  67. {10xscale_agentflow_cli-0.3.2.1/graph → 10xscale_agentflow_cli-0.3.2.2/agentflow_cli/cli/templates/prod/graph/tools}/__init__.py +0 -0
  68. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/SKILL.md +0 -0
  69. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/agents-and-tools.md +0 -0
  70. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/api-client.md +0 -0
  71. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/api-configuration.md +0 -0
  72. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/api-settings-and-middleware.md +0 -0
  73. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/architecture.md +0 -0
  74. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/auth-and-authorization.md +0 -0
  75. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/callbacks-and-command.md +0 -0
  76. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/checkpointing-and-threads.md +0 -0
  77. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/cli-commands.md +0 -0
  78. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/client-auth-and-errors.md +0 -0
  79. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/client-messages-invoke-stream.md +0 -0
  80. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/client-threads-memory-files.md +0 -0
  81. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/context-id-background.md +0 -0
  82. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/dependency-injection.md +0 -0
  83. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/id-and-thread-name-generators.md +0 -0
  84. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/media-and-files.md +0 -0
  85. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/memory-and-store.md +0 -0
  86. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/prebuilt-agents-and-tools.md +0 -0
  87. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/production-runtime.md +0 -0
  88. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/providers-and-adapters.md +0 -0
  89. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/publishers-and-runtime-protocols.md +0 -0
  90. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/rate-limiting.md +0 -0
  91. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/remote-tools.md +0 -0
  92. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/rest-api-and-errors.md +0 -0
  93. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/security-and-validators.md +0 -0
  94. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/state-and-messages.md +0 -0
  95. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/state-graph.md +0 -0
  96. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/stream-emitter.md +0 -0
  97. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/streaming.md +0 -0
  98. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/agent-skills/references/testing-and-evaluation.md +0 -0
  99. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/cli/templates/skills/copilot/agentflow.instructions.md +0 -0
  100. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/__init__.py +0 -0
  101. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/__init__.py +0 -0
  102. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/auth/auth_backend.py +0 -0
  103. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/auth/authorization.py +0 -0
  104. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/auth/base_auth.py +0 -0
  105. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/auth/jwt_auth.py +0 -0
  106. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/auth/permissions.py +0 -0
  107. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/config/graph_config.py +0 -0
  108. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/config/media_settings.py +0 -0
  109. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/config/sentry_config.py +0 -0
  110. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/config/setup_logs.py +0 -0
  111. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/config/setup_middleware.py +0 -0
  112. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/config/worker_middleware.py +0 -0
  113. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/exceptions/__init__.py +0 -0
  114. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/exceptions/general_exception.py +0 -0
  115. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/exceptions/handle_errors.py +0 -0
  116. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/exceptions/resources_exceptions.py +0 -0
  117. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/exceptions/user_exception.py +0 -0
  118. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/__init__.py +0 -0
  119. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/rate_limit/__init__.py +0 -0
  120. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/rate_limit/base.py +0 -0
  121. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/rate_limit/factory.py +0 -0
  122. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/rate_limit/memory.py +0 -0
  123. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/rate_limit/middleware.py +0 -0
  124. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/rate_limit/redis.py +0 -0
  125. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/request_limits.py +0 -0
  126. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/middleware/security_headers.py +0 -0
  127. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/utils/__init__.py +0 -0
  128. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/core/utils/log_sanitizer.py +0 -0
  129. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/loader.py +0 -0
  130. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/main.py +0 -0
  131. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/__init__.py +0 -0
  132. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/a2a.py +0 -0
  133. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/a2ui.py +0 -0
  134. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/checkpointer/__init__.py +0 -0
  135. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/checkpointer/router.py +0 -0
  136. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/checkpointer/schemas/__init__.py +0 -0
  137. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/checkpointer/schemas/checkpointer_schemas.py +0 -0
  138. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/checkpointer/services/__init__.py +0 -0
  139. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/checkpointer/services/checkpointer_service.py +0 -0
  140. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/graph/__init__.py +0 -0
  141. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/graph/router.py +0 -0
  142. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/graph/schemas/__init__.py +0 -0
  143. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/graph/schemas/graph_schemas.py +0 -0
  144. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/graph/services/__init__.py +0 -0
  145. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/graph/services/graph_service.py +0 -0
  146. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/graph/services/multimodal_preprocessor.py +0 -0
  147. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/media/__init__.py +0 -0
  148. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/media/router.py +0 -0
  149. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/media/schemas.py +0 -0
  150. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/ping/__init__.py +0 -0
  151. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/ping/router.py +0 -0
  152. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/setup_router.py +0 -0
  153. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/store/__init__.py +0 -0
  154. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/store/router.py +0 -0
  155. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/store/schemas/__init__.py +0 -0
  156. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/store/schemas/store_schemas.py +0 -0
  157. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/store/services/__init__.py +0 -0
  158. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/routers/store/services/store_service.py +0 -0
  159. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/tasks/user_tasks.py +0 -0
  160. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/__init__.py +0 -0
  161. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/callable_helper.py +0 -0
  162. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/media/__init__.py +0 -0
  163. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/media/extractor.py +0 -0
  164. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/media/pipeline.py +0 -0
  165. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/parse_output.py +0 -0
  166. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/response_helper.py +0 -0
  167. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/schemas/__init__.py +0 -0
  168. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/schemas/output_schemas.py +0 -0
  169. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/schemas/user_schemas.py +0 -0
  170. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/snowflake_id_generator.py +0 -0
  171. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/swagger_helper.py +0 -0
  172. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/utils/thread_name_generator.py +0 -0
  173. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/agentflow_cli/src/app/worker.py +0 -0
  174. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/graph/react.py +0 -0
  175. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/requirements.txt +0 -0
  176. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/setup.cfg +0 -0
  177. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/tests/test_multimodal_sprint2_extraction.py +0 -0
  178. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/tests/test_sprint4_media_api.py +0 -0
  179. {10xscale_agentflow_cli-0.3.2.1 → 10xscale_agentflow_cli-0.3.2.2}/tests/test_utils_parse_and_callable.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: 10xscale-agentflow-cli
3
- Version: 0.3.2.1
3
+ Version: 0.3.2.2
4
4
  Summary: CLI and API for 10xscale AgentFlow
5
5
  Author-email: 10xscale <contact@10xscale.ai>
6
6
  Maintainer-email: Shudipto Trafder <shudiptotrafder@gmail.com>
@@ -31,6 +31,7 @@ Requires-Dist: pydantic-settings
31
31
  Requires-Dist: uvicorn
32
32
  Requires-Dist: typer
33
33
  Requires-Dist: python-dotenv
34
+ Requires-Dist: questionary
34
35
  Provides-Extra: sentry
35
36
  Requires-Dist: sentry-sdk>=2.10.0; extra == "sentry"
36
37
  Provides-Extra: firebase
@@ -28,6 +28,35 @@ agentflow_cli/cli/core/output.py
28
28
  agentflow_cli/cli/core/validation.py
29
29
  agentflow_cli/cli/templates/__init__.py
30
30
  agentflow_cli/cli/templates/defaults.py
31
+ agentflow_cli/cli/templates/dev/agentflow.json
32
+ agentflow_cli/cli/templates/dev/graph/__init__.py
33
+ agentflow_cli/cli/templates/dev/graph/agent.py
34
+ agentflow_cli/cli/templates/prod/.pre-commot-config.yaml
35
+ agentflow_cli/cli/templates/prod/agentflow.json
36
+ agentflow_cli/cli/templates/prod/auth/__init__.py
37
+ agentflow_cli/cli/templates/prod/auth/agent_auth.py
38
+ agentflow_cli/cli/templates/prod/evals/__init__.py
39
+ agentflow_cli/cli/templates/prod/evals/weather_agents.py
40
+ agentflow_cli/cli/templates/prod/graph/__init__.py
41
+ agentflow_cli/cli/templates/prod/graph/agent.py
42
+ agentflow_cli/cli/templates/prod/graph/state.py
43
+ agentflow_cli/cli/templates/prod/graph/thread_name_generator.py
44
+ agentflow_cli/cli/templates/prod/graph/nodes/__init__.py
45
+ agentflow_cli/cli/templates/prod/graph/nodes/main_node.py
46
+ agentflow_cli/cli/templates/prod/graph/nodes/tool_node.py
47
+ agentflow_cli/cli/templates/prod/graph/tools/__init__.py
48
+ agentflow_cli/cli/templates/prod/graph/tools/weather_tool.py
49
+ agentflow_cli/cli/templates/prod/graph/utils/__init__.py
50
+ agentflow_cli/cli/templates/prod/graph/utils/tool_decision.py
51
+ agentflow_cli/cli/templates/prod/graph/validators/__init__.py
52
+ agentflow_cli/cli/templates/prod/graph/validators/lifecyle.py
53
+ agentflow_cli/cli/templates/prod/graph/validators/manager.py
54
+ agentflow_cli/cli/templates/prod/graph/validators/validators.py
55
+ agentflow_cli/cli/templates/prod/tests/__init__.py
56
+ agentflow_cli/cli/templates/prod/tests/conftest.py
57
+ agentflow_cli/cli/templates/prod/tests/test_agent_eval.py
58
+ agentflow_cli/cli/templates/prod/tests/test_catalog_tools.py
59
+ agentflow_cli/cli/templates/prod/tests/test_graph_nodes.py
31
60
  agentflow_cli/cli/templates/skills/agent-skills/SKILL.md
32
61
  agentflow_cli/cli/templates/skills/agent-skills/references/agents-and-tools.md
33
62
  agentflow_cli/cli/templates/skills/agent-skills/references/api-client.md
@@ -141,8 +170,6 @@ agentflow_cli/src/app/utils/schemas/output_schemas.py
141
170
  agentflow_cli/src/app/utils/schemas/user_schemas.py
142
171
  graph/__init__.py
143
172
  graph/react.py
144
- graph/thread_name_generator.py
145
- scripts/generate_docs.py
146
173
  tests/test_multimodal_sprint2_extraction.py
147
174
  tests/test_sprint4_media_api.py
148
175
  tests/test_utils_parse_and_callable.py
@@ -8,6 +8,7 @@ pydantic-settings
8
8
  uvicorn
9
9
  typer
10
10
  python-dotenv
11
+ questionary
11
12
 
12
13
  [firebase]
13
14
  firebase-admin>=6.5.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: 10xscale-agentflow-cli
3
- Version: 0.3.2.1
3
+ Version: 0.3.2.2
4
4
  Summary: CLI and API for 10xscale AgentFlow
5
5
  Author-email: 10xscale <contact@10xscale.ai>
6
6
  Maintainer-email: Shudipto Trafder <shudiptotrafder@gmail.com>
@@ -31,6 +31,7 @@ Requires-Dist: pydantic-settings
31
31
  Requires-Dist: uvicorn
32
32
  Requires-Dist: typer
33
33
  Requires-Dist: python-dotenv
34
+ Requires-Dist: questionary
34
35
  Provides-Extra: sentry
35
36
  Requires-Dist: sentry-sdk>=2.10.0; extra == "sentry"
36
37
  Provides-Extra: firebase
@@ -12,4 +12,4 @@
12
12
  "trusted_proxy_headers": false,
13
13
  "exclude_paths": ["/health", "/docs", "/redoc", "/openapi.json"]
14
14
  }
15
- }
15
+ }
@@ -0,0 +1,392 @@
1
+ """Init command implementation."""
2
+
3
+ import contextlib
4
+ import json
5
+ import re
6
+ from pathlib import Path
7
+ from string import Template
8
+ from typing import Any
9
+
10
+ import questionary
11
+ import typer
12
+
13
+ from agentflow_cli.cli.commands import BaseCommand
14
+ from agentflow_cli.cli.constants import Colors
15
+ from agentflow_cli.cli.exceptions import FileOperationError
16
+
17
+
18
+ _TEMPLATES_DIR = Path(__file__).parent.parent / "templates"
19
+ _SKIP_DIRS = {"__pycache__"}
20
+ _DIVIDER = Colors.colorize(" " + "─" * 46, "cyan")
21
+
22
+ # Directories inside prod/ that are only included based on user choices
23
+ _AUTH_DIR = "auth"
24
+
25
+
26
+ def _dim(text: str) -> str:
27
+ return f"\033[2m{text}\033[0m"
28
+
29
+
30
+ def _bold(text: str) -> str:
31
+ return f"\033[1m{text}\033[0m"
32
+
33
+
34
+ def _slugify(name: str) -> str:
35
+ """Convert 'WeatherBot' → 'weather-bot'."""
36
+ s = re.sub(r"([A-Z])", r"-\1", name).lstrip("-").lower()
37
+ s = re.sub(r"[^a-z0-9]+", "-", s)
38
+ return s.strip("-")
39
+
40
+
41
+ def _strip_env_blocks(content: str, *, keep_redis: bool, keep_jwt: bool) -> str:
42
+ """Remove conditional marker blocks that are not needed."""
43
+ if not keep_redis:
44
+ content = re.sub(r"##\[IF_REDIS\]##.*?##\[/IF_REDIS\]##\n?", "", content, flags=re.DOTALL)
45
+ else:
46
+ content = re.sub(r"##\[IF_REDIS\]##\n?", "", content)
47
+ content = re.sub(r"##\[/IF_REDIS\]##\n?", "", content)
48
+
49
+ if not keep_jwt:
50
+ content = re.sub(r"##\[IF_JWT\]##.*?##\[/IF_JWT\]##\n?", "", content, flags=re.DOTALL)
51
+ else:
52
+ content = re.sub(r"##\[IF_JWT\]##\n?", "", content)
53
+ content = re.sub(r"##\[/IF_JWT\]##\n?", "", content)
54
+
55
+ return content
56
+
57
+
58
+ class InitCommand(BaseCommand):
59
+ """Command to initialize a new agent project interactively."""
60
+
61
+ def execute(self, path: str = ".", force: bool = False, **kwargs: Any) -> int:
62
+ try:
63
+ self.output.print_banner(
64
+ "Init", "Create a new AgentFlow agent project", color="magenta"
65
+ )
66
+
67
+ context = self._prompt_user()
68
+ if context is None:
69
+ typer.echo("\n Cancelled.")
70
+ return 0
71
+
72
+ self._print_summary(context)
73
+
74
+ base_path = Path(path)
75
+ base_path.mkdir(parents=True, exist_ok=True)
76
+
77
+ is_prod = context["setup_type"] == "production"
78
+ template_dir = _TEMPLATES_DIR / ("prod" if is_prod else "dev")
79
+
80
+ typer.echo(f"\n {_bold('Creating project files...')}\n")
81
+ created = self._copy_template_dir(
82
+ template_dir, base_path, context, force=force, is_prod=is_prod
83
+ )
84
+
85
+ # Regenerate agentflow.json from the built config (overrides template copy)
86
+ config_path = base_path / "agentflow.json"
87
+ config = self._build_config(context, is_prod)
88
+ self._write_file(config_path, json.dumps(config, indent=2) + "\n", force=True)
89
+ if config_path not in created:
90
+ self._print_file_line(config_path, base_path)
91
+
92
+ agent_name = context["agent_name"]
93
+ typer.echo("")
94
+ typer.echo(_DIVIDER)
95
+ typer.echo(
96
+ " ✨ "
97
+ + Colors.colorize(f'Project "{agent_name}" ready at ', "green")
98
+ + Colors.colorize(str(base_path.resolve()), "cyan")
99
+ )
100
+ typer.echo(_DIVIDER)
101
+
102
+ self._print_next_steps(context, is_prod)
103
+
104
+ return 0
105
+
106
+ except FileOperationError as e:
107
+ return self.handle_error(e)
108
+ except Exception as e:
109
+ return self.handle_error(FileOperationError(f"Failed to initialize project: {e}"))
110
+
111
+ # ------------------------------------------------------------------
112
+ # Prompts
113
+ # ------------------------------------------------------------------
114
+
115
+ def _prompt_user(self) -> dict | None: # noqa: PLR0911
116
+ agent_name = questionary.text(
117
+ "What is your agent name?",
118
+ default="MyAgent",
119
+ ).ask()
120
+ if agent_name is None:
121
+ return None
122
+
123
+ setup_choice = questionary.select(
124
+ "Quick Start or Production setup?",
125
+ choices=["Quick Start", "Production"],
126
+ default="Quick Start",
127
+ ).ask()
128
+ if setup_choice is None:
129
+ return None
130
+
131
+ is_prod = setup_choice == "Production"
132
+
133
+ context: dict[str, Any] = {
134
+ "agent_name": agent_name,
135
+ "agent_name_slug": _slugify(agent_name),
136
+ "setup_type": "production" if is_prod else "quick_start",
137
+ "auth": "none",
138
+ "rate_limit": "none",
139
+ }
140
+
141
+ if not is_prod:
142
+ return context
143
+
144
+ # --- Production questions ---
145
+
146
+ auth_choice = questionary.select(
147
+ "Authentication type?",
148
+ choices=["None", "JWT", "Custom"],
149
+ default="None",
150
+ ).ask()
151
+ if auth_choice is None:
152
+ return None
153
+ context["auth"] = auth_choice.lower()
154
+
155
+ rl_choice = questionary.select(
156
+ "Rate limiting?",
157
+ choices=["None", "Memory Based", "Redis Based"],
158
+ default="None",
159
+ ).ask()
160
+ if rl_choice is None:
161
+ return None
162
+ context["rate_limit"] = {
163
+ "None": "none",
164
+ "Memory Based": "memory",
165
+ "Redis Based": "redis",
166
+ }[rl_choice]
167
+
168
+ if context["rate_limit"] != "none":
169
+ rl_requests = questionary.text(
170
+ "Max requests per window?",
171
+ default="100",
172
+ validate=lambda v: v.isdigit() and int(v) > 0 or "Enter a positive integer",
173
+ ).ask()
174
+ if rl_requests is None:
175
+ return None
176
+ context["rl_requests"] = int(rl_requests)
177
+
178
+ rl_window = questionary.text(
179
+ "Window size (seconds)?",
180
+ default="60",
181
+ validate=lambda v: v.isdigit() and int(v) > 0 or "Enter a positive integer",
182
+ ).ask()
183
+ if rl_window is None:
184
+ return None
185
+ context["rl_window"] = int(rl_window)
186
+
187
+ rl_by = questionary.select(
188
+ "Limit by?",
189
+ choices=["Per IP (recommended)", "Global"],
190
+ default="Per IP (recommended)",
191
+ ).ask()
192
+ if rl_by is None:
193
+ return None
194
+ context["rl_by"] = "ip" if "IP" in rl_by else "global"
195
+
196
+ rl_proxy = questionary.confirm(
197
+ "Behind a reverse proxy? (reads real IP from forwarded headers)",
198
+ default=False,
199
+ ).ask()
200
+ if rl_proxy is None:
201
+ return None
202
+ context["rl_trusted_proxy"] = rl_proxy
203
+
204
+ return context
205
+
206
+ # ------------------------------------------------------------------
207
+ # Output helpers
208
+ # ------------------------------------------------------------------
209
+
210
+ def _print_summary(self, context: dict) -> None:
211
+ is_prod = context["setup_type"] == "production"
212
+ setup_label = "Production" if is_prod else "Quick Start"
213
+
214
+ typer.echo("")
215
+ typer.echo(_DIVIDER)
216
+ typer.echo(" " + _bold("Project Summary"))
217
+ typer.echo(_DIVIDER)
218
+
219
+ rows: list[tuple[str, str]] = [
220
+ ("Agent name", context["agent_name"]),
221
+ ("Package name", context["agent_name_slug"]),
222
+ ("Setup", setup_label),
223
+ ]
224
+ if is_prod:
225
+ auth = context["auth"]
226
+ rows.append(("Auth", "None" if auth == "none" else auth.upper()))
227
+
228
+ rl = context["rate_limit"]
229
+ if rl == "none":
230
+ rows.append(("Rate limit", "None"))
231
+ else:
232
+ rl_by = "Global" if context.get("rl_by") == "global" else "Per IP"
233
+ proxy = " · proxy headers on" if context.get("rl_trusted_proxy") else ""
234
+ rows.append(
235
+ (
236
+ "Rate limit",
237
+ f"{rl.capitalize()} · {context.get('rl_requests', 100)} req / "
238
+ f"{context.get('rl_window', 60)}s · {rl_by}{proxy}",
239
+ )
240
+ )
241
+
242
+ label_width = max(len(k) for k, _ in rows) + 2
243
+ for label, value in rows:
244
+ padded = (label + " ").ljust(label_width, "·")
245
+ typer.echo(
246
+ " " + Colors.colorize(padded, "cyan") + " " + Colors.colorize(value, "white")
247
+ )
248
+ typer.echo(_DIVIDER)
249
+
250
+ def _print_file_line(self, dest: Path, base_path: Path) -> None:
251
+ rel = dest.relative_to(base_path)
252
+ typer.echo(
253
+ " " + Colors.colorize("✓", "green") + " " + Colors.colorize(str(rel), "white")
254
+ )
255
+
256
+ def _print_next_steps(self, context: dict, is_prod: bool) -> None:
257
+ steps: list[tuple[str, str]] = []
258
+
259
+ steps.append(("agentflow skills", "Install coding agent skills"))
260
+
261
+ if is_prod:
262
+ steps.append(("pre-commit install", "Set up Git hooks (ruff, bandit, etc.)"))
263
+
264
+ steps.append(("pip install google-genai", "Add the AI provider library"))
265
+ steps.append(("cp .env.example .env", "Copy env template, then fill in your API keys"))
266
+
267
+ if context["auth"] == "jwt":
268
+ steps.append(("# Set JWT_SECRET_KEY in .env", "Required for JWT auth to work"))
269
+
270
+ if context["rate_limit"] == "redis":
271
+ steps.append(("# Set REDIS_URL in .env", "Required for Redis rate limiting"))
272
+
273
+ steps.append(("agentflow play", "Launch your agent"))
274
+
275
+ typer.echo("")
276
+ typer.echo(" " + Colors.colorize("🚀 Next steps", "magenta"))
277
+ typer.echo("")
278
+
279
+ cmd_width = max(len(cmd) for cmd, _ in steps) + 2
280
+ for i, (cmd, description) in enumerate(steps, 1):
281
+ num = Colors.colorize(f" {i}", "cyan")
282
+ command = Colors.colorize(cmd.ljust(cmd_width), "yellow")
283
+ desc = _dim(description)
284
+ typer.echo(f"{num} {command} {desc}")
285
+
286
+ typer.echo("")
287
+
288
+ # ------------------------------------------------------------------
289
+ # Config generation
290
+ # ------------------------------------------------------------------
291
+
292
+ def _build_config(self, context: dict, is_prod: bool) -> dict:
293
+ config: dict = {
294
+ "agent": "graph.agent:app",
295
+ "env": ".env",
296
+ "auth": None,
297
+ "thread_name_generator": None,
298
+ }
299
+
300
+ if not is_prod:
301
+ return config
302
+
303
+ auth = context["auth"]
304
+ if auth == "jwt":
305
+ config["auth"] = {"method": "jwt"}
306
+ elif auth == "custom":
307
+ config["auth"] = {"method": "custom", "path": "auth.agent_auth:AgentAuth"}
308
+
309
+ config["thread_name_generator"] = "graph.thread_name_generator:MyNameGenerator"
310
+ config["injectq"] = "graph.agent:container"
311
+
312
+ rate_limit = context["rate_limit"]
313
+ if rate_limit != "none":
314
+ config["rate_limit"] = {
315
+ "enabled": True,
316
+ "backend": rate_limit,
317
+ "requests": context.get("rl_requests", 100),
318
+ "window": context.get("rl_window", 60),
319
+ "by": context.get("rl_by", "ip"),
320
+ "trusted_proxy_headers": context.get("rl_trusted_proxy", False),
321
+ "exclude_paths": ["/health", "/docs", "/redoc", "/openapi.json"],
322
+ }
323
+
324
+ return config
325
+
326
+ # ------------------------------------------------------------------
327
+ # File helpers
328
+ # ------------------------------------------------------------------
329
+
330
+ def _should_skip(self, src: Path, template_dir: Path, context: dict, is_prod: bool) -> bool:
331
+ """Return True if this template file should not be copied."""
332
+ if any(part in _SKIP_DIRS for part in src.parts):
333
+ return True
334
+ if not is_prod:
335
+ return False
336
+ # auth/ is only included for custom auth; skip for none and jwt
337
+ rel_parts = src.relative_to(template_dir).parts
338
+ return rel_parts[0] == _AUTH_DIR and context["auth"] != "custom"
339
+
340
+ def _render(self, src: Path, context: dict, is_prod: bool) -> str:
341
+ content = src.read_text(encoding="utf-8")
342
+
343
+ # Strip conditional blocks in .env.example before substitution
344
+ if src.name == ".env.example" and is_prod:
345
+ content = _strip_env_blocks(
346
+ content,
347
+ keep_redis=context["rate_limit"] == "redis",
348
+ keep_jwt=context["auth"] == "jwt",
349
+ )
350
+
351
+ with contextlib.suppress(Exception):
352
+ content = Template(content).safe_substitute(context)
353
+
354
+ return content
355
+
356
+ def _copy_template_dir(
357
+ self,
358
+ template_dir: Path,
359
+ dest_dir: Path,
360
+ context: dict,
361
+ *,
362
+ force: bool,
363
+ is_prod: bool,
364
+ ) -> set[Path]:
365
+ created: set[Path] = set()
366
+ for src in sorted(template_dir.rglob("*")):
367
+ if src.is_dir():
368
+ continue
369
+ if self._should_skip(src, template_dir, context, is_prod):
370
+ continue
371
+ rel = src.relative_to(template_dir)
372
+ dest = dest_dir / rel
373
+ content = self._render(src, context, is_prod)
374
+ self._write_file(dest, content, force=force)
375
+ self._print_file_line(dest, dest_dir)
376
+ created.add(dest)
377
+ return created
378
+
379
+ def _write_file(self, path: Path, content: str, *, force: bool) -> None:
380
+ try:
381
+ path.parent.mkdir(parents=True, exist_ok=True)
382
+ if path.exists() and not force:
383
+ raise FileOperationError(
384
+ f"File already exists: {path}. Use --force to overwrite.",
385
+ file_path=str(path),
386
+ )
387
+ path.write_text(content, encoding="utf-8")
388
+ self.logger.debug("Wrote file: %s", path)
389
+ except OSError as e:
390
+ raise FileOperationError(
391
+ f"Failed to write file {path}: {e}", file_path=str(path)
392
+ ) from e
@@ -202,7 +202,7 @@ def init(
202
202
  ".",
203
203
  "--path",
204
204
  "-p",
205
- help="Directory to initialize config and graph files in",
205
+ help="Directory to initialize the agent project in",
206
206
  ),
207
207
  force: bool = typer.Option(
208
208
  False,
@@ -210,13 +210,6 @@ def init(
210
210
  "-f",
211
211
  help="Overwrite existing files if they exist",
212
212
  ),
213
- prod: bool = typer.Option(
214
- False,
215
- "--prod",
216
- help=(
217
- "Initialize production-ready project (adds pyproject.toml and .pre-commit-config.yaml)"
218
- ),
219
- ),
220
213
  verbose: bool = typer.Option(
221
214
  False,
222
215
  "--verbose",
@@ -230,13 +223,12 @@ def init(
230
223
  help="Suppress all output except errors",
231
224
  ),
232
225
  ) -> None:
233
- """Initialize default config and graph files (agentflow.json and graph/react.py)."""
234
- # Setup logging
226
+ """Interactively initialize a new agent project."""
235
227
  setup_cli_logging(verbose=verbose, quiet=quiet)
236
228
 
237
229
  try:
238
230
  command = InitCommand(output)
239
- exit_code = command.execute(path=path, force=force, prod=prod)
231
+ exit_code = command.execute(path=path, force=force)
240
232
  sys.exit(exit_code)
241
233
  except Exception as e:
242
234
  sys.exit(handle_exception(e))
@@ -0,0 +1,6 @@
1
+ {
2
+ "agent": "graph.agent:app",
3
+ "env": ".env",
4
+ "auth": null,
5
+ "thread_name_generator": null
6
+ }
@@ -0,0 +1,132 @@
1
+ import logging
2
+ import random
3
+ from datetime import datetime
4
+
5
+ from agentflow.core import Agent, StateGraph, ToolNode
6
+ from agentflow.core.state import AgentState
7
+ from agentflow.core.state.stream_emitter import StreamEmitter
8
+ from agentflow.storage.checkpointer import InMemoryCheckpointer
9
+ from agentflow.utils.constants import END
10
+ from dotenv import load_dotenv
11
+
12
+
13
+ load_dotenv()
14
+
15
+ checkpointer = InMemoryCheckpointer()
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ def call_weather_api(location: str) -> str:
21
+ is_failed = random.choice([True, False]) # Randomly simulate success or failure # noqa: S311
22
+ if is_failed:
23
+ raise Exception("Failed to fetch weather data due to a simulated API error.")
24
+ return f"The weather in {location} is sunny"
25
+
26
+
27
+ def get_weather(
28
+ location: str,
29
+ tool_call_id: str | None = None,
30
+ state: AgentState | None = None,
31
+ emit: StreamEmitter | None = None,
32
+ ) -> str:
33
+ """
34
+ Get the current weather for a specific location.
35
+ This demo shows injectable parameters: tool_call_id and state are automatically injected.
36
+ """
37
+ # You can access injected parameters here
38
+ if tool_call_id:
39
+ logger.info(f"Tool call ID: {tool_call_id}")
40
+ if state and hasattr(state, "context"):
41
+ logger.info(f"Number of messages in context: {len(state.context)}") # type: ignore
42
+ if emit:
43
+ emit.progress("Fetching weather data...")
44
+
45
+ # return f"The weather in {location} is sunny"
46
+
47
+ result = ""
48
+ for i in range(3): # Try up to 3 times
49
+ try:
50
+ result = call_weather_api(location)
51
+ break # If successful, exit the loop
52
+ except Exception as e:
53
+ logger.error(f"Attempt {i + 1} failed: {e}")
54
+ result = f"Sorry, I couldn't fetch the weather for {location} after multiple attempts."
55
+ if emit:
56
+ emit.progress(f"Attempt {i + 1} failed, retrying...")
57
+
58
+ return result
59
+
60
+
61
+ tool_node = ToolNode(
62
+ [
63
+ get_weather,
64
+ ]
65
+ )
66
+
67
+ # Create agent with tools
68
+ agent = Agent(
69
+ model="gemini-3-flash-preview",
70
+ provider="google",
71
+ system_prompt=[
72
+ {
73
+ "role": "system",
74
+ "content": """
75
+ You are a helpful assistant.
76
+ Your task is to assist the user in finding information and answering questions.
77
+ """,
78
+ },
79
+ {
80
+ "role": "user",
81
+ "content": f"Today Date is {datetime.now().strftime('%Y-%m-%d')}",
82
+ }, # Inject current date into system prompt
83
+ ],
84
+ trim_context=True,
85
+ reasoning_config=True,
86
+ tool_node=tool_node,
87
+ )
88
+
89
+
90
+ def should_use_tools(state: AgentState) -> str:
91
+ """Determine if we should use tools or end the conversation."""
92
+ if not state.context or len(state.context) == 0:
93
+ return "TOOL" # No context, might need tools
94
+
95
+ last_message = state.context[-1]
96
+
97
+ # If the last message is from assistant and has tool calls, go to TOOL
98
+ if (
99
+ hasattr(last_message, "tools_calls")
100
+ and last_message.tools_calls
101
+ and len(last_message.tools_calls) > 0
102
+ and last_message.role == "assistant"
103
+ ):
104
+ return "TOOL"
105
+
106
+ # If last message is a tool result, we should be done (AI will make final response)
107
+ if last_message.role == "tool":
108
+ return "MAIN"
109
+
110
+ # Default to END for other cases
111
+ return END
112
+
113
+
114
+ graph = StateGraph()
115
+ graph.add_node("MAIN", agent)
116
+ graph.add_node("TOOL", tool_node)
117
+
118
+ # Add conditional edges from MAIN
119
+ graph.add_conditional_edges(
120
+ "MAIN",
121
+ should_use_tools,
122
+ {"TOOL": "TOOL", END: END},
123
+ )
124
+
125
+ # Always go back to MAIN after TOOL execution
126
+ graph.add_edge("TOOL", "MAIN")
127
+ graph.set_entry_point("MAIN")
128
+
129
+
130
+ app = graph.compile(
131
+ checkpointer=checkpointer,
132
+ )