keboola-cli 0.63.4__tar.gz → 0.65.0__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 (380) hide show
  1. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/CLAUDE.md +15 -1
  2. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/PKG-INFO +1 -1
  3. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/pyproject.toml +1 -1
  4. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/changelog.py +71 -0
  5. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/_data_app_git.py +67 -0
  6. keboola_cli-0.65.0/src/keboola_agent_cli/commands/_data_app_runtime.py +436 -0
  7. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/context.py +25 -1
  8. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/data_app.py +80 -386
  9. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/data_science_client.py +39 -0
  10. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/permissions.py +2 -0
  11. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/data_apps.py +57 -1
  12. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/data_app_service.py +468 -59
  13. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_data_app_cli.py +185 -0
  14. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_data_app_git_repo.py +52 -0
  15. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_data_app_service.py +300 -0
  16. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_e2e.py +131 -0
  17. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_server_router_calls.py +59 -0
  18. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/.gitignore +0 -0
  19. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/CONTRIBUTING.md +0 -0
  20. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/Makefile +0 -0
  21. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/README.md +0 -0
  22. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/examples/README.md +0 -0
  23. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/examples/storage_tui/README.md +0 -0
  24. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/plugins/kbagent/.claude-plugin/CLAUDE.md +0 -0
  25. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/benchmark.py +0 -0
  26. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/check_command_sync.py +0 -0
  27. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/check_error_codes.py +0 -0
  28. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/check_wheel_ui.py +0 -0
  29. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/debug_linkedby_type.sh +0 -0
  30. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/generate_changelog.py +0 -0
  31. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/generate_skill.py +0 -0
  32. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/hatch_build.py +0 -0
  33. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/lineage_deep.py +0 -0
  34. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/post-edit-quality.sh +0 -0
  35. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/pre-commit +0 -0
  36. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/sync_version.py +0 -0
  37. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/scripts/web-dev.sh +0 -0
  38. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/__init__.py +0 -0
  39. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/__main__.py +0 -0
  40. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/ai_client.py +0 -0
  41. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/auto_update.py +0 -0
  42. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/cli.py +0 -0
  43. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/client.py +0 -0
  44. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/__init__.py +0 -0
  45. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/_helpers.py +0 -0
  46. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/_metadata_input.py +0 -0
  47. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/_semantic_layer_crud.py +0 -0
  48. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/_semantic_layer_helpers.py +0 -0
  49. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/_semantic_layer_reference_data.py +0 -0
  50. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/agent.py +0 -0
  51. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/branch.py +0 -0
  52. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/changelog.py +0 -0
  53. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/component.py +0 -0
  54. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/config.py +0 -0
  55. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/dev_portal.py +0 -0
  56. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/doctor.py +0 -0
  57. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/encrypt.py +0 -0
  58. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/feature.py +0 -0
  59. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/flow.py +0 -0
  60. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/http_client.py +0 -0
  61. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/init.py +0 -0
  62. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/job.py +0 -0
  63. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/kai.py +0 -0
  64. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/lineage.py +0 -0
  65. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/org.py +0 -0
  66. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/permissions.py +0 -0
  67. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/project.py +0 -0
  68. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/repl.py +0 -0
  69. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/schedule.py +0 -0
  70. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/search.py +0 -0
  71. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/semantic_layer.py +0 -0
  72. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/serve.py +0 -0
  73. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/sharing.py +0 -0
  74. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/storage.py +0 -0
  75. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/stream.py +0 -0
  76. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/sync.py +0 -0
  77. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/tool.py +0 -0
  78. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/version.py +0 -0
  79. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/commands/workspace.py +0 -0
  80. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/config_store.py +0 -0
  81. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/constants.py +0 -0
  82. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/dev_portal_client.py +0 -0
  83. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/errors.py +0 -0
  84. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/http_base.py +0 -0
  85. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/json_utils.py +0 -0
  86. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/lib.py +0 -0
  87. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/manage_client.py +0 -0
  88. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/metastore_client.py +0 -0
  89. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/models.py +0 -0
  90. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/output.py +0 -0
  91. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/py.typed +0 -0
  92. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/result_models.py +0 -0
  93. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/__init__.py +0 -0
  94. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/agent_runner.py +0 -0
  95. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/agents_store.py +0 -0
  96. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/app.py +0 -0
  97. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/auth.py +0 -0
  98. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/dependencies.py +0 -0
  99. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/pricing.py +0 -0
  100. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/__init__.py +0 -0
  101. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/agents.py +0 -0
  102. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/ai_chat.py +0 -0
  103. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/branches.py +0 -0
  104. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/components.py +0 -0
  105. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/configs.py +0 -0
  106. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/dev_portal.py +0 -0
  107. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/encrypt.py +0 -0
  108. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/feature.py +0 -0
  109. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/flows.py +0 -0
  110. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/health.py +0 -0
  111. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/jobs.py +0 -0
  112. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/kai.py +0 -0
  113. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/lineage.py +0 -0
  114. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/mcp.py +0 -0
  115. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/members.py +0 -0
  116. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/org.py +0 -0
  117. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/projects.py +0 -0
  118. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/schedules.py +0 -0
  119. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/search.py +0 -0
  120. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/semantic_layer.py +0 -0
  121. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/sharing.py +0 -0
  122. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/storage.py +0 -0
  123. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/stream.py +0 -0
  124. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/routers/workspaces.py +0 -0
  125. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/run_broadcaster.py +0 -0
  126. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/server/sse.py +0 -0
  127. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/__init__.py +0 -0
  128. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_encryption.py +0 -0
  129. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_semantic_layer_cascade.py +0 -0
  130. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_semantic_layer_crud.py +0 -0
  131. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_semantic_layer_internals.py +0 -0
  132. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_semantic_layer_lookup.py +0 -0
  133. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_semantic_layer_reference_data.py +0 -0
  134. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_sync_bindings.py +0 -0
  135. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_sync_branch.py +0 -0
  136. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_sync_bulk.py +0 -0
  137. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_sync_clone.py +0 -0
  138. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_sync_models.py +0 -0
  139. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_sync_push_ops.py +0 -0
  140. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_sync_storage.py +0 -0
  141. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/_sync_writeback.py +0 -0
  142. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/agent_service.py +0 -0
  143. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/base.py +0 -0
  144. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/branch_service.py +0 -0
  145. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/component_service.py +0 -0
  146. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/config_service.py +0 -0
  147. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/data_app_git_service.py +0 -0
  148. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/deep_lineage_service.py +0 -0
  149. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/dev_portal_service.py +0 -0
  150. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/doctor_service.py +0 -0
  151. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/encrypt_service.py +0 -0
  152. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/feature_service.py +0 -0
  153. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/flow_service.py +0 -0
  154. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/flow_validation.py +0 -0
  155. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/http_forwarder_service.py +0 -0
  156. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/job_idempotency_store.py +0 -0
  157. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/job_service.py +0 -0
  158. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/kai_service.py +0 -0
  159. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/lineage_service.py +0 -0
  160. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/mcp_service.py +0 -0
  161. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/mcp_transport.py +0 -0
  162. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/member_service.py +0 -0
  163. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/org_service.py +0 -0
  164. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/project_service.py +0 -0
  165. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/repo_validate_service.py +0 -0
  166. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/schedule_service.py +0 -0
  167. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/search_service.py +0 -0
  168. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/semantic_layer_service.py +0 -0
  169. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/sharing_service.py +0 -0
  170. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/storage_service.py +0 -0
  171. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/stream_service.py +0 -0
  172. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/sync_service.py +0 -0
  173. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/variables_service.py +0 -0
  174. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/version_service.py +0 -0
  175. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/services/workspace_service.py +0 -0
  176. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/stream_client.py +0 -0
  177. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/__init__.py +0 -0
  178. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/branch_mapping.py +0 -0
  179. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/clone.py +0 -0
  180. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/code_extraction.py +0 -0
  181. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/config_format.py +0 -0
  182. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/diff_engine.py +0 -0
  183. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/git_utils.py +0 -0
  184. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/manifest.py +0 -0
  185. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/naming.py +0 -0
  186. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/secrets.py +0 -0
  187. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/src/keboola_agent_cli/sync/sql_split.py +0 -0
  188. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/__init__.py +0 -0
  189. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/conftest.py +0 -0
  190. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/helpers.py +0 -0
  191. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_agent_cli.py +0 -0
  192. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_agent_prompt.py +0 -0
  193. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_agent_prompt_helper.py +0 -0
  194. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_agent_runner.py +0 -0
  195. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_agent_service.py +0 -0
  196. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_agents_store_events.py +0 -0
  197. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_ai_client.py +0 -0
  198. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_auto_update.py +0 -0
  199. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_base_service.py +0 -0
  200. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_branch_metadata_cli.py +0 -0
  201. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_branch_metadata_service.py +0 -0
  202. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_branch_service.py +0 -0
  203. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_build_hook.py +0 -0
  204. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_changelog_check.py +0 -0
  205. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_changelog_render.py +0 -0
  206. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_check_command_sync.py +0 -0
  207. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_choice_enums.py +0 -0
  208. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_cli.py +0 -0
  209. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_client.py +0 -0
  210. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_component_cli.py +0 -0
  211. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_component_service.py +0 -0
  212. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_create_cli.py +0 -0
  213. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_create_service.py +0 -0
  214. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_encryption.py +0 -0
  215. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_metadata.py +0 -0
  216. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_rename.py +0 -0
  217. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_rename_cli.py +0 -0
  218. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_resolution.py +0 -0
  219. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_row_cli.py +0 -0
  220. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_row_service.py +0 -0
  221. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_search.py +0 -0
  222. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_search_cli.py +0 -0
  223. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_set_default_bucket.py +0 -0
  224. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_store.py +0 -0
  225. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_config_update.py +0 -0
  226. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_data_app_plain_env_keys.py +0 -0
  227. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_data_app_secrets_cli.py +0 -0
  228. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_data_app_secrets_service.py +0 -0
  229. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_data_app_validate_repo_service.py +0 -0
  230. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_deep_lineage_service.py +0 -0
  231. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_dev_portal_cli.py +0 -0
  232. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_dev_portal_client.py +0 -0
  233. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_dev_portal_service.py +0 -0
  234. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_doctor_service.py +0 -0
  235. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_e2e_config_dir_mode.py +0 -0
  236. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_e2e_lineage_deep.py +0 -0
  237. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_encrypt_cli.py +0 -0
  238. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_encrypt_service.py +0 -0
  239. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_encryption.py +0 -0
  240. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_errors.py +0 -0
  241. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_feature_cli.py +0 -0
  242. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_feature_service.py +0 -0
  243. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_file_locking.py +0 -0
  244. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_flow_cli.py +0 -0
  245. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_flow_service.py +0 -0
  246. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_flow_validation.py +0 -0
  247. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_helpers.py +0 -0
  248. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_http_base.py +0 -0
  249. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_http_client_cmd.py +0 -0
  250. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_http_forwarder_service.py +0 -0
  251. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_integration.py +0 -0
  252. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_job_idempotency_store.py +0 -0
  253. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_json_utils.py +0 -0
  254. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_kai_cli.py +0 -0
  255. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_kai_service.py +0 -0
  256. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_lib.py +0 -0
  257. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_lineage_service.py +0 -0
  258. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_local_ai_chat.py +0 -0
  259. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_manage_client.py +0 -0
  260. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_manage_token_bulk.py +0 -0
  261. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_manage_token_cli.py +0 -0
  262. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_mcp_service.py +0 -0
  263. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_mcp_transport.py +0 -0
  264. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_member_cli.py +0 -0
  265. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_member_service.py +0 -0
  266. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_metastore_client.py +0 -0
  267. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_models.py +0 -0
  268. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_normalize_script.py +0 -0
  269. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_org_service.py +0 -0
  270. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_output.py +0 -0
  271. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_permissions.py +0 -0
  272. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_permissions_cli.py +0 -0
  273. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_pricing.py +0 -0
  274. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_project_edit.py +0 -0
  275. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_project_edit_cli.py +0 -0
  276. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_project_info_cli.py +0 -0
  277. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_project_info_service.py +0 -0
  278. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_repl.py +0 -0
  279. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_result_models.py +0 -0
  280. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_run_broadcaster.py +0 -0
  281. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_schedule_cli.py +0 -0
  282. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_schedule_service.py +0 -0
  283. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_search_cli.py +0 -0
  284. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_search_service.py +0 -0
  285. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_semantic_layer_cli.py +0 -0
  286. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_semantic_layer_service.py +0 -0
  287. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_serve_conversation_id.py +0 -0
  288. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_serve_ui.py +0 -0
  289. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_server_semantic_layer_routes_e2e.py +0 -0
  290. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_server_smoke.py +0 -0
  291. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_services.py +0 -0
  292. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sharing_service.py +0 -0
  293. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sql_split.py +0 -0
  294. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_clone.py +0 -0
  295. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_delete.py +0 -0
  296. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_describe_cli.py +0 -0
  297. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_describe_service.py +0 -0
  298. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_empty_definition.py +0 -0
  299. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_export_filters.py +0 -0
  300. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_files.py +0 -0
  301. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_swap.py +0 -0
  302. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_tables.py +0 -0
  303. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_truncate.py +0 -0
  304. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_storage_write.py +0 -0
  305. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_stream_cli.py +0 -0
  306. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_stream_client.py +0 -0
  307. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_stream_service.py +0 -0
  308. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_branch_mapping.py +0 -0
  309. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_cli.py +0 -0
  310. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_clone.py +0 -0
  311. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_code_extraction.py +0 -0
  312. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_config_format.py +0 -0
  313. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_diff_engine.py +0 -0
  314. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_e2e.py +0 -0
  315. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_encrypt.py +0 -0
  316. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_force_pull_baseline.py +0 -0
  317. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_manifest.py +0 -0
  318. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_naming.py +0 -0
  319. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_plaintext_audit.py +0 -0
  320. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_secrets.py +0 -0
  321. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_service.py +0 -0
  322. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_storage_jobs.py +0 -0
  323. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_sync_version_script.py +0 -0
  324. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_variables_cli.py +0 -0
  325. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_variables_service.py +0 -0
  326. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_version_service.py +0 -0
  327. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_workspace_cli.py +0 -0
  328. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_workspace_gc.py +0 -0
  329. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_workspace_service.py +0 -0
  330. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/tests/test_workspace_sql_helper.py +0 -0
  331. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/README.md +0 -0
  332. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/index.html +0 -0
  333. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/package-lock.json +0 -0
  334. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/package.json +0 -0
  335. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/postcss.config.js +0 -0
  336. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/App.tsx +0 -0
  337. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/api/client.ts +0 -0
  338. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/components/AgentRunView.tsx +0 -0
  339. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/components/Drawer.tsx +0 -0
  340. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/components/Empty.tsx +0 -0
  341. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/components/JsonView.tsx +0 -0
  342. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/components/ManageTokenModal.tsx +0 -0
  343. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/components/Table.tsx +0 -0
  344. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/index.css +0 -0
  345. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/layout/Shell.tsx +0 -0
  346. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/layout/Sidebar.tsx +0 -0
  347. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/layout/StatusBar.tsx +0 -0
  348. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/layout/TopBar.tsx +0 -0
  349. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/main.tsx +0 -0
  350. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Agents.tsx +0 -0
  351. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Branches.tsx +0 -0
  352. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Changelog.tsx +0 -0
  353. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Components.tsx +0 -0
  354. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Configs.tsx +0 -0
  355. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Dashboard.tsx +0 -0
  356. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/DataApps.tsx +0 -0
  357. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Doctor.tsx +0 -0
  358. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Encrypt.tsx +0 -0
  359. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Flows.tsx +0 -0
  360. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Jobs.tsx +0 -0
  361. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Lineage.tsx +0 -0
  362. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/LocalAi.tsx +0 -0
  363. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Mcp.tsx +0 -0
  364. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Members.tsx +0 -0
  365. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Org.tsx +0 -0
  366. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Projects.tsx +0 -0
  367. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Schedules.tsx +0 -0
  368. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Search.tsx +0 -0
  369. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/SemanticLayer.tsx +0 -0
  370. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/SemanticLayerDialogs.tsx +0 -0
  371. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Sharing.tsx +0 -0
  372. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Storage.tsx +0 -0
  373. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Streams.tsx +0 -0
  374. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/pages/Workspaces.tsx +0 -0
  375. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/state.tsx +0 -0
  376. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/theme.tsx +0 -0
  377. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/src/types.ts +0 -0
  378. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/tailwind.config.ts +0 -0
  379. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/tsconfig.json +0 -0
  380. {keboola_cli-0.63.4 → keboola_cli-0.65.0}/web/frontend/vite.config.ts +0 -0
@@ -424,13 +424,26 @@ kbagent workspace from-transformation --project ALIAS --component-id ID --config
424
424
 
425
425
  kbagent data-app list [--project NAME ...] [--branch ID]
426
426
  kbagent data-app detail --project NAME --app-id ID [--branch ID]
427
- kbagent data-app create --project ALIAS --name NAME --slug SLUG --git-repo URL [--description STR | --description-file PATH] [--git-branch main] [--git-public/--no-git-public] [--git-username USER] [--git-pat-env VAR | --git-pat-file PATH | --git-pat-encrypted KBC::Project...] [--auth password|public] [--size tiny|small|medium|large] [--auto-suspend SECONDS] [--type python-js|python|streamlit|r|...] [--branch ID] [--no-deploy] [--wait] [--timeout SECONDS] [--keep-on-failure] [--dry-run]
427
+ kbagent data-app create --project ALIAS --name NAME --slug SLUG (--git-repo URL | --use-managed-git-repo) [--description STR | --description-file PATH] [--git-branch main] [--git-public/--no-git-public] [--git-username USER] [--git-pat-env VAR | --git-pat-file PATH | --git-pat-encrypted KBC::Project...] [--auth password|public] [--size tiny|small|medium|large] [--auto-suspend SECONDS] [--type python-js|python|streamlit|r|...] [--branch ID] [--no-deploy] [--wait] [--timeout SECONDS] [--keep-on-failure] [--dry-run]
428
+ # Exactly one git source is required: --git-repo URL (external) OR --use-managed-git-repo (0.65.0+).
429
+ # --use-managed-git-repo provisions an EMPTY Keboola-hosted repo (POST useManagedGitRepo:true), writes
430
+ # NO parameters.dataApp.git block, and forces --no-deploy (nothing to run yet). Mutually exclusive with
431
+ # --git-repo and all --git-*/PAT auth flags. Full flow to a RUNNING managed-repo app (0.65.0+):
432
+ # (1) create --use-managed-git-repo -> (2) `git-credentials-create --type http_token --permissions
433
+ # readWrite` + `git push` code to the managed repo URL (from `git-repo`) -> (3) `data-app
434
+ # git-bind-credential` (mints an http_token ON the app, encrypts it under the project KMS, and writes
435
+ # parameters.dataApp.git so the runtime's `git clone` can authenticate -- required on stacks that do NOT
436
+ # inject managed-repo creds at deploy time) -> (4) `data-app deploy`. deploy pins the LATEST
437
+ # configVersion when a git block is present and omits it for a PURE managed repo (deploys from
438
+ # managedGitRepoId). Use `data-app runs` to debug a deploy that reverts to stopped (setup-phase
439
+ # failures, e.g. git-clone "could not read Username", produce no container logs).
428
440
  kbagent data-app deploy --project NAME --app-id ID [--config-version N] [--wait] [--timeout SECONDS] [--branch ID]
429
441
  kbagent data-app start --project NAME --app-id ID [--wait] [--timeout SECONDS]
430
442
  kbagent data-app stop --project NAME --app-id ID [--wait] [--timeout SECONDS]
431
443
  kbagent data-app delete --project NAME --app-id ID [--yes]
432
444
  kbagent data-app password --project NAME --app-id ID
433
445
  kbagent data-app logs --project NAME --app-id ID [--lines N] [--since ISO8601]
446
+ kbagent data-app runs --project NAME --app-id ID [--limit N]
434
447
  kbagent data-app secrets-set --project ALIAS --app-id ID --secret '#KEY=VALUE' [--secret ...] [--secrets-file PATH] [--branch ID] [--allow-plaintext-on-encrypt-failure] [--dry-run] [--no-hint-next]
435
448
  kbagent data-app secrets-list --project ALIAS --app-id ID [--branch ID] [--show-fingerprint]
436
449
  kbagent data-app secrets-get --project ALIAS --app-id ID --key 'KEY' [--branch ID] # '#' optional; plain values return their value, encrypted return metadata only
@@ -441,6 +454,7 @@ kbagent data-app git-branches --project NAME --app-id ID
441
454
  kbagent data-app git-entrypoints --project NAME --app-id ID
442
455
  kbagent data-app git-credentials --project NAME --app-id ID
443
456
  kbagent data-app git-credentials-create --project NAME --app-id ID --type ssh_key|http_token --permissions readOnly|readWrite [--public-key KEY | --public-key-file PATH] [--name LABEL] [--yes]
457
+ kbagent data-app git-bind-credential --project NAME --app-id ID [--branch-name main] [--permissions readOnly|readWrite] [--dry-run]
444
458
  # git-repo/git-branches/git-entrypoints introspect the deployed-from git repo (sandboxes-service /apps/{id}/git-repo/*); they return 409 "no Git repository configured" until the app has been DEPLOYED at least once (git config syncs Storage->DS record at deploy). git-credentials* manage credentials for a MANAGED repo only; apps from `data-app create --git-repo` are external => git-credentials-create returns 409. http_token mints a ONE-TIME secret (shown once); credentials endpoints need an admin storage token.
445
459
 
446
460
  kbagent component list [--project NAME] [--type TYPE] [--query QUERY]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: keboola-cli
3
- Version: 0.63.4
3
+ Version: 0.65.0
4
4
  Summary: AI-friendly CLI for managing Keboola projects
5
5
  Author-email: Keboola <dev@keboola.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "keboola-cli"
3
- version = "0.63.4"
3
+ version = "0.65.0"
4
4
  description = "AI-friendly CLI for managing Keboola projects"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -24,6 +24,77 @@ from .constants import CHANGELOG_HEADLINE_MAX_CHARS
24
24
 
25
25
  # Ordered newest-first. Each value is a list of brief one-line descriptions.
26
26
  CHANGELOG: dict[str, list[str]] = {
27
+ "0.65.0": [
28
+ "New: deploy a data app from a Keboola-MANAGED git repository end-to-end. "
29
+ "`data-app create --use-managed-git-repo` provisions an EMPTY Keboola-hosted repo (POST "
30
+ "`useManagedGitRepo:true`, no `parameters.dataApp.git` block, forces `--no-deploy`; "
31
+ "mutually exclusive with `--git-repo` and every `--git-*`/PAT flag). The full flow to a "
32
+ "running app: create -> `git-credentials-create --type http_token --permissions readWrite` "
33
+ "+ `git push` to the managed URL -> `data-app git-bind-credential` -> `data-app deploy`. "
34
+ "Verified live (tic-tac-toe serving from a managed repo).",
35
+ "New: `data-app git-bind-credential --project P --app-id ID [--branch-name main] "
36
+ "[--permissions readOnly|readWrite]` mints an `http_token` ON the app, encrypts it under "
37
+ "the project KMS, and writes `parameters.dataApp.git` (repository + placeholder username + "
38
+ "encrypted `#password` + branch). Required on stacks that do not inject managed-repo "
39
+ "credentials at deploy time -- without it the runtime's `git clone` of the managed repo "
40
+ "fails `could not read Username` and the deploy reverts to stopped. The token is encrypted "
41
+ "in place and never printed; `--dry-run` previews what would be wired without minting the "
42
+ "one-time credential or touching the config.",
43
+ "New: `data-app runs --project P --app-id ID [--limit N]` lists a data app's recent "
44
+ "deployment attempts with `failure_reason` + `startup_logs`, including setup-phase failures "
45
+ "(e.g. a git-clone error during `app_setup`) that produce no container logs. It works on "
46
+ "never-started / failed apps where `data-app logs` returns HTTP 400 -- the canonical way to "
47
+ "find out why a deploy reverted to `stopped` without the app ever serving.",
48
+ "Fix: `data-app deploy` now resolves the deployed `configVersion` by source location -- it "
49
+ "pins the latest Storage version when a git block is present (external repos AND a "
50
+ "credential-wired managed repo) so the operator reads the current source, and omits "
51
+ "`configVersion` only for a pure managed repo (deploys from `app.managedGitRepoId`). "
52
+ "Previously it always pinned, which pointed managed-repo deploys at a config snapshot with "
53
+ "no git source and made them silently revert to stopped.",
54
+ "UX: when `data-app deploy --wait` times out or the app reaches state=error, the error now "
55
+ "auto-fetches the latest run's `failure_reason` (via /apps/{id}/runs) and includes it inline "
56
+ '-- including setup-phase failures with no container logs -- instead of a bare "timed out" '
57
+ "message. A managed-repo clone-auth failure (`could not read Username`) adds an actionable "
58
+ "hint to run `data-app git-bind-credential`. The diagnostic is best-effort and never masks "
59
+ "the original error.",
60
+ "All of the above are mirrored 1:1 on the `kbagent serve` REST API "
61
+ "(`/data-app/.../runs`, `/data-app/.../git-repo/bind-credential`, and the "
62
+ "`use_managed_git_repo` field on create).",
63
+ "New (#446): the `install.sh` bootstrap got a first-run onboarding pass -- it "
64
+ "auto-installs `uv` when it is missing (opt out with `KBAGENT_NO_UV_BOOTSTRAP=1`), quiets "
65
+ "the install output behind tidy step lines, and finishes with a Keboola banner plus a "
66
+ "'next steps' footer (`kbagent project add`, `kbagent --help`) so first-time users know "
67
+ "what to run next.",
68
+ ],
69
+ "0.64.0": [
70
+ "New: data-app git-repo introspection + managed-repo credentials -- five `data-app "
71
+ "git-*` commands over the sandboxes-service `/apps/{id}/git-repo/*` endpoints. "
72
+ "`git-repo` shows the clone URLs + a managed flag, `git-branches` lists remote branches "
73
+ "with commit metadata, `git-entrypoints` lists root-level `.py` files, `git-credentials` "
74
+ "lists managed-repo credentials, and `git-credentials-create` mints an SSH key or HTTP "
75
+ "token (a one-time secret for `http_token`). Mirrored 1:1 on the `kbagent serve` REST "
76
+ "API. The read trio needs only the project storage token; the credential pair is "
77
+ "managed-repo only (admin token). Gotcha: the introspection endpoints return 409 until "
78
+ "the app has been deployed at least once -- the git block syncs from the Storage config "
79
+ "into the Data Science app record at deploy time (first tagged 0.63.3, #414).",
80
+ "Security: `kbagent serve --ui` now decides which paths require auth via the router "
81
+ "match protocol and fails closed, fixing a fastapi-0.137 nested-router bypass that "
82
+ "served `/doctor`, `/version`, `/changelog`, and `/agents` unauthenticated "
83
+ "(GHSA-ffpq-prmh-3gx2); the temporary `fastapi<0.137` cap is lifted (0.63.4).",
84
+ "Fix: invalid `--mode` / `--poll-strategy` (`job run`), `--role` / `--default-role` "
85
+ "(`project invite`, `member-set-role`) and `--role-hint` (`dev-portal identity`) values "
86
+ "fail with a clean exit-2 usage error again instead of an uncaught traceback -- they "
87
+ "regressed under Typer >=0.25's vendored Click, so the choice options now use `StrEnum`. "
88
+ "The interactive REPL `help` and tab-completion again list every command (0.63.4).",
89
+ "Change: kbagent now ships as a self-contained native binary via Homebrew / apt / dnf / "
90
+ "apk / Chocolatey / WinGet (PyInstaller + nfpm release pipeline), alongside the existing "
91
+ "pip / uv install (#405).",
92
+ "Internal: the data-app command and service layers were split into sibling modules "
93
+ "(`commands/_data_app_git.py`, `commands/_data_app_runtime.py`, "
94
+ "`services/data_app_git_service.py`) to keep `data_app.py` under the file-size budget -- "
95
+ "no behavior change (#423). Dependency bumps: cryptography 48, starlette 1.3, "
96
+ "python-multipart 0.0.31, pyjwt 2.13.",
97
+ ],
27
98
  "0.63.4": [
28
99
  "Fix: the interactive REPL `help` command and tab-completion again list every "
29
100
  "command instead of only `help`/`exit`. `_build_command_tree` guarded its walk "
@@ -341,3 +341,70 @@ def register_git_commands(app: typer.Typer) -> None:
341
341
  )
342
342
 
343
343
  formatter.output(result, _human)
344
+
345
+ @app.command("git-bind-credential")
346
+ def data_app_git_bind_credential(
347
+ ctx: typer.Context,
348
+ project: str = typer.Option(..., "--project", help="Project alias"),
349
+ app_id: str = typer.Option(..., "--app-id", help="Data Science numeric app id"),
350
+ branch: str = typer.Option(
351
+ "main", "--branch-name", help="Managed-repo branch to deploy from (default main)."
352
+ ),
353
+ permissions: str = typer.Option(
354
+ "readOnly",
355
+ "--permissions",
356
+ help="Credential access level: readOnly (default) | readWrite.",
357
+ ),
358
+ dry_run: bool = typer.Option(
359
+ False,
360
+ "--dry-run",
361
+ help="Preview what would be wired (repo/branch/permissions) WITHOUT minting a credential or editing the config.",
362
+ ),
363
+ ) -> None:
364
+ """Make a MANAGED-repo app deployable by wiring a credential into its config.
365
+
366
+ A `--use-managed-git-repo` app owns an empty Keboola-hosted repo but its
367
+ Storage config has no git block. On stacks that do NOT inject managed-repo
368
+ credentials at deploy time, the runtime's `git clone` of the managed repo
369
+ fails ("could not read Username") and the deploy reverts to stopped. This
370
+ command mints a fresh `http_token` ON the app, encrypts it under the
371
+ project KMS, and writes `parameters.dataApp.git` (repository + placeholder
372
+ username + encrypted `#password` + branch) so the next `data-app deploy`
373
+ can clone. The token is encrypted in-place and never printed.
374
+
375
+ `--dry-run` validates the app + resolves the managed repo URL but mints
376
+ nothing and leaves the config untouched -- the http_token is one-time, so
377
+ a real run that you abort would orphan it.
378
+ """
379
+ formatter = get_formatter(ctx)
380
+ service = get_service(ctx, "data_app_service")
381
+ try:
382
+ result = service.bind_managed_credential(
383
+ project, app_id, branch=branch, permissions=permissions, dry_run=dry_run
384
+ )
385
+ except KeboolaApiError as exc:
386
+ formatter.error(
387
+ message=exc.message,
388
+ error_code=exc.error_code,
389
+ retryable=exc.retryable,
390
+ details=exc.details,
391
+ )
392
+ raise typer.Exit(code=map_error_to_exit_code(exc)) from None
393
+ except ConfigError as exc:
394
+ formatter.error(message=exc.message, error_code=ErrorCode.CONFIG_ERROR)
395
+ raise typer.Exit(code=5) from None
396
+
397
+ def _human(c: Console, d: dict) -> None:
398
+ if d.get("dry_run"):
399
+ c.print("[bold]DRY RUN -- no credential minted, config unchanged.[/bold]")
400
+ c.print(f" [bold]Repository:[/bold] {d.get('repository', '')}")
401
+ c.print(f" [bold]Branch:[/bold] {d.get('branch', '')}")
402
+ c.print(f" [bold]Permissions:[/bold] {d.get('permissions', '')}")
403
+ return
404
+ c.print(f"[bold green]Success:[/bold green] {d['message']}")
405
+ c.print(f" [bold]Repository:[/bold] {d.get('repository', '')}")
406
+ c.print(f" [bold]Branch:[/bold] {d.get('branch', '')}")
407
+ c.print(f" [bold]Permissions:[/bold] {d.get('permissions', '')}")
408
+ c.print(f" [bold]Config version:[/bold] {d.get('config_version', '')}")
409
+
410
+ formatter.output(result, _human)
@@ -0,0 +1,436 @@
1
+ """Data-app runtime-secrets commands -- secrets-set / -list / -get / -remove.
2
+
3
+ Split out of ``data_app.py`` to keep that module under the CONTRIBUTING.md
4
+ file-size budget (see "File-size budgets"). These commands manage the
5
+ ``parameters.dataApp.secrets`` block of a data app's Storage config (the
6
+ app-runtime env-var secrets); the business logic stays on ``DataAppService``.
7
+ They attach to the existing ``data-app`` Typer sub-app via
8
+ :func:`register_secrets_commands`, called at the bottom of ``data_app.py``, so
9
+ they still surface as ``kbagent data-app secrets-*`` with identical names,
10
+ permission keys, and serve REST routes.
11
+
12
+ The module is deliberately NOT named ``_data_app_secrets.py``: the repo's
13
+ permission config denies Read/Write/Edit on any path matching ``*secrets*``.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ from pathlib import Path
20
+
21
+ import typer
22
+
23
+ from ..errors import ConfigError, ErrorCode, KeboolaApiError
24
+ from ._helpers import get_formatter, get_service, map_error_to_exit_code
25
+
26
+ # Canonical Keboola help-doc reference (mirrors data_app.py).
27
+ _REF_STORAGE_ACCESS = "https://help.keboola.com/data-apps/storage-access/"
28
+
29
+
30
+ def _parse_secret_arg(arg: str) -> tuple[str, str]:
31
+ """Split ``#KEY=VALUE`` into ``(key, value)``.
32
+
33
+ The value may contain ``=``; only the FIRST ``=`` is the separator.
34
+ """
35
+ if "=" not in arg:
36
+ raise typer.BadParameter(
37
+ f"Expected '#KEY=VALUE'; got {arg!r} (no '=' separator).",
38
+ param_hint="--secret",
39
+ )
40
+ key, _, value = arg.partition("=")
41
+ if not key:
42
+ raise typer.BadParameter(
43
+ f"Empty secret key in {arg!r}; expected '#KEY=VALUE'.",
44
+ param_hint="--secret",
45
+ )
46
+ return key, value
47
+
48
+
49
+ def _read_secrets_file(path: Path) -> dict[str, str]:
50
+ try:
51
+ text = path.read_text(encoding="utf-8")
52
+ except OSError as exc:
53
+ raise typer.BadParameter(
54
+ f"Cannot read secrets file {path}: {exc}",
55
+ param_hint="--secrets-file",
56
+ ) from exc
57
+ try:
58
+ parsed = json.loads(text)
59
+ except json.JSONDecodeError as exc:
60
+ raise typer.BadParameter(
61
+ f"Secrets file {path} is not valid JSON: {exc}",
62
+ param_hint="--secrets-file",
63
+ ) from exc
64
+ if not isinstance(parsed, dict):
65
+ raise typer.BadParameter(
66
+ f"Secrets file {path} must be a JSON object mapping #KEY -> value.",
67
+ param_hint="--secrets-file",
68
+ )
69
+ out: dict[str, str] = {}
70
+ for key, value in parsed.items():
71
+ if not isinstance(key, str) or not isinstance(value, str):
72
+ raise typer.BadParameter(
73
+ f"Secrets file {path} contains non-string entry for {key!r}.",
74
+ param_hint="--secrets-file",
75
+ )
76
+ out[key] = value
77
+ if not out:
78
+ raise typer.BadParameter(
79
+ f"Secrets file {path} is empty.",
80
+ param_hint="--secrets-file",
81
+ )
82
+ return out
83
+
84
+
85
+ def data_app_secrets_set(
86
+ ctx: typer.Context,
87
+ project: str = typer.Option(..., "--project", help="Project alias"),
88
+ app_id: str = typer.Option(..., "--app-id", help="Data Science numeric app id"),
89
+ secret: list[str] | None = typer.Option(
90
+ None,
91
+ "--secret",
92
+ help=(
93
+ "One or more '#KEY=VALUE' plaintext entries. Repeatable. "
94
+ "Mutually exclusive with --secrets-file."
95
+ ),
96
+ ),
97
+ secrets_file: Path | None = typer.Option(
98
+ None,
99
+ "--secrets-file",
100
+ help="Path to a JSON file mapping '#KEY' -> 'plaintext value'.",
101
+ exists=True,
102
+ readable=True,
103
+ dir_okay=False,
104
+ ),
105
+ branch: int | None = typer.Option(
106
+ None,
107
+ "--branch",
108
+ help="Storage branch ID for the linked config (defaults to production).",
109
+ ),
110
+ allow_plaintext_on_encrypt_failure: bool = typer.Option(
111
+ False,
112
+ "--allow-plaintext-on-encrypt-failure",
113
+ help=(
114
+ "Bootstrap/debug only: write the value as-is if the Encryption API "
115
+ "did not return a project-scoped ciphertext. NEVER use in production."
116
+ ),
117
+ ),
118
+ dry_run: bool = typer.Option(
119
+ False,
120
+ "--dry-run",
121
+ help="Show the encryption request and Storage PUT body without making either call.",
122
+ ),
123
+ no_hint_next: bool = typer.Option(
124
+ False,
125
+ "--no-hint-next",
126
+ help="Suppress the 'now run kbagent data-app deploy' hint in the output.",
127
+ ),
128
+ ) -> None:
129
+ """Encrypt and write app-runtime secrets to the linked Storage config.
130
+
131
+ The '#'-prefix is required on every key (Keboola encryption convention).
132
+ The runtime exposes each secret as an env var with '#' stripped, '-'
133
+ replaced with '_', and uppercased ('#my-api-key' -> 'MY_API_KEY').
134
+
135
+ The command never auto-deploys; the running container keeps the old
136
+ config until the next 'kbagent data-app deploy' call.
137
+
138
+ Reference: https://help.keboola.com/data-apps/python-js/
139
+ """
140
+
141
+ formatter = get_formatter(ctx)
142
+ service = get_service(ctx, "data_app_service")
143
+
144
+ if secret and secrets_file:
145
+ formatter.error(
146
+ message=("--secret and --secrets-file are mutually exclusive; pick one input mode."),
147
+ error_code=ErrorCode.USAGE_ERROR,
148
+ )
149
+ raise typer.Exit(code=2) from None
150
+
151
+ if not secret and not secrets_file:
152
+ formatter.error(
153
+ message=("Provide at least one --secret '#KEY=VALUE' or --secrets-file PATH."),
154
+ error_code=ErrorCode.MISSING_PARAMETER,
155
+ )
156
+ raise typer.Exit(code=2) from None
157
+
158
+ secrets_map: dict[str, str] = {}
159
+ if secret:
160
+ for entry in secret:
161
+ try:
162
+ key, value = _parse_secret_arg(entry)
163
+ except typer.BadParameter as exc:
164
+ formatter.error(
165
+ message=str(exc),
166
+ error_code=ErrorCode.DATA_APP_INVALID_SECRET,
167
+ )
168
+ raise typer.Exit(code=2) from None
169
+ secrets_map[key] = value
170
+ if secrets_file:
171
+ try:
172
+ secrets_map.update(_read_secrets_file(secrets_file))
173
+ except typer.BadParameter as exc:
174
+ formatter.error(
175
+ message=str(exc),
176
+ error_code=ErrorCode.DATA_APP_INVALID_SECRET,
177
+ )
178
+ raise typer.Exit(code=2) from None
179
+
180
+ try:
181
+ result = service.set_data_app_secrets(
182
+ alias=project,
183
+ app_id=app_id,
184
+ secrets=secrets_map,
185
+ branch_id=branch,
186
+ allow_plaintext_on_encrypt_failure=allow_plaintext_on_encrypt_failure,
187
+ dry_run=dry_run,
188
+ )
189
+ except KeboolaApiError as exc:
190
+ formatter.error(
191
+ message=exc.message,
192
+ error_code=exc.error_code,
193
+ retryable=exc.retryable,
194
+ details=exc.details,
195
+ )
196
+ raise typer.Exit(code=map_error_to_exit_code(exc)) from None
197
+ except ConfigError as exc:
198
+ formatter.error(message=exc.message, error_code=ErrorCode.CONFIG_ERROR)
199
+ raise typer.Exit(code=5) from None
200
+
201
+ # Reserved-name shadowing -- emit stderr WARN per collision so a
202
+ # script piping stdout to a JSON parser is unaffected.
203
+ shadowed = result.get("shadowed_by_runtime", [])
204
+ if shadowed and not formatter.json_mode:
205
+ for env_var in shadowed:
206
+ formatter.err_console.print(
207
+ f"[yellow]Warning:[/yellow] {env_var} is auto-injected by the data-app "
208
+ f"runtime; the platform value silently shadows yours. See {_REF_STORAGE_ACCESS}.",
209
+ style="yellow",
210
+ )
211
+
212
+ if no_hint_next and isinstance(result, dict):
213
+ result.pop("next_step", None)
214
+
215
+ formatter.output(
216
+ result,
217
+ lambda c, d: c.print(f"[bold green]Success:[/bold green] {d['message']}"),
218
+ )
219
+ if not no_hint_next and not formatter.json_mode and result.get("next_step"):
220
+ formatter.console.print(f"[dim]Next: {result['next_step']}[/dim]")
221
+
222
+
223
+ def data_app_secrets_list(
224
+ ctx: typer.Context,
225
+ project: str = typer.Option(..., "--project", help="Project alias"),
226
+ app_id: str = typer.Option(..., "--app-id", help="Data Science numeric app id"),
227
+ branch: int | None = typer.Option(
228
+ None,
229
+ "--branch",
230
+ help="Storage branch ID for the linked config (defaults to production).",
231
+ ),
232
+ show_fingerprint: bool = typer.Option(
233
+ False,
234
+ "--show-fingerprint",
235
+ help="Include a short ciphertext fingerprint per key. Default omits to keep --json safe to paste into tickets.",
236
+ ),
237
+ ) -> None:
238
+ """List the keys in parameters.dataApp.secrets, with derived runtime env-var names.
239
+
240
+ Never echoes the encrypted ciphertext in full and never decrypts.
241
+
242
+ Reference: https://help.keboola.com/data-apps/python-js/
243
+ """
244
+
245
+ formatter = get_formatter(ctx)
246
+ service = get_service(ctx, "data_app_service")
247
+ try:
248
+ result = service.list_data_app_secrets(
249
+ alias=project,
250
+ app_id=app_id,
251
+ branch_id=branch,
252
+ show_fingerprint=show_fingerprint,
253
+ )
254
+ except KeboolaApiError as exc:
255
+ formatter.error(
256
+ message=exc.message,
257
+ error_code=exc.error_code,
258
+ retryable=exc.retryable,
259
+ details=exc.details,
260
+ )
261
+ raise typer.Exit(code=map_error_to_exit_code(exc)) from None
262
+ except ConfigError as exc:
263
+ formatter.error(message=exc.message, error_code=ErrorCode.CONFIG_ERROR)
264
+ raise typer.Exit(code=5) from None
265
+
266
+ if formatter.json_mode:
267
+ formatter.output(result)
268
+ return
269
+
270
+ if not result["secrets"]:
271
+ formatter.console.print("[dim]No secrets set on this data app.[/dim]")
272
+ return
273
+ formatter.console.print(
274
+ f"\n[bold]{result['count']} secret(s)[/bold] on data app "
275
+ f"[cyan]{result['app_id']}[/cyan] in [magenta]{result['project_alias']}[/magenta]:"
276
+ )
277
+ for entry in result["secrets"]:
278
+ marker = (
279
+ " [yellow](shadowed by runtime)[/yellow]" if entry.get("shadowed_by_runtime") else ""
280
+ )
281
+ line = f" [bold]{entry['key']}[/bold] -> env [cyan]{entry['env_var']}[/cyan]{marker}"
282
+ if "fingerprint" in entry:
283
+ line += f" [dim]fingerprint={entry['fingerprint']} prefix={entry.get('encryption_prefix', '')}[/dim]"
284
+ formatter.console.print(line)
285
+
286
+
287
+ def data_app_secrets_get(
288
+ ctx: typer.Context,
289
+ project: str = typer.Option(..., "--project", help="Project alias"),
290
+ app_id: str = typer.Option(..., "--app-id", help="Data Science numeric app id"),
291
+ key: str = typer.Option(
292
+ ..., "--key", help="Env-var key (with optional '#' prefix for encrypted secrets)."
293
+ ),
294
+ branch: int | None = typer.Option(
295
+ None,
296
+ "--branch",
297
+ help="Storage branch ID for the linked config (defaults to production).",
298
+ ),
299
+ ) -> None:
300
+ """Show ONE key from parameters.dataApp.secrets.
301
+
302
+ For an ENCRYPTED ('#') secret this is metadata only -- the Encryption
303
+ API has no decrypt endpoint, so the CLI never echoes the decrypted
304
+ value. For a PLAIN (unencrypted) config value the literal value is
305
+ shown; it is already stored in clear and visible via `config detail`.
306
+
307
+ Reference: https://help.keboola.com/data-apps/python-js/
308
+ """
309
+
310
+ formatter = get_formatter(ctx)
311
+ service = get_service(ctx, "data_app_service")
312
+ try:
313
+ result = service.get_data_app_secret(
314
+ alias=project,
315
+ app_id=app_id,
316
+ key=key,
317
+ branch_id=branch,
318
+ )
319
+ except KeboolaApiError as exc:
320
+ formatter.error(
321
+ message=exc.message,
322
+ error_code=exc.error_code,
323
+ retryable=exc.retryable,
324
+ details=exc.details,
325
+ )
326
+ raise typer.Exit(code=map_error_to_exit_code(exc)) from None
327
+ except ConfigError as exc:
328
+ formatter.error(message=exc.message, error_code=ErrorCode.CONFIG_ERROR)
329
+ raise typer.Exit(code=5) from None
330
+
331
+ if formatter.json_mode:
332
+ formatter.output(result)
333
+ return
334
+ formatter.console.print(
335
+ f"\n[bold]{result['key']}[/bold] -> env [cyan]{result['env_var']}[/cyan]"
336
+ )
337
+ if result.get("encrypted"):
338
+ formatter.console.print(
339
+ f" [dim]fingerprint={result['fingerprint']} prefix={result['encryption_prefix']}[/dim]"
340
+ )
341
+ else:
342
+ formatter.console.print(f" value (plaintext, unencrypted): {result['value']}")
343
+ formatter.err_console.print(
344
+ " [yellow]Note:[/yellow] this value is stored unencrypted in the config. "
345
+ "Use `data-app secrets-set '#KEY=...'` to store sensitive values encrypted."
346
+ )
347
+ if result.get("shadowed_by_runtime"):
348
+ # Same stdout/stderr-separation rationale as secrets-set: keep
349
+ # warnings off stdout so a script piping the metadata to a parser
350
+ # is unaffected.
351
+ formatter.err_console.print(
352
+ f" [yellow]Warning:[/yellow] {result['env_var']} is auto-injected by "
353
+ f"the data-app runtime; the platform value silently shadows yours. "
354
+ f"See {_REF_STORAGE_ACCESS}."
355
+ )
356
+
357
+
358
+ def data_app_secrets_remove(
359
+ ctx: typer.Context,
360
+ project: str = typer.Option(..., "--project", help="Project alias"),
361
+ app_id: str = typer.Option(..., "--app-id", help="Data Science numeric app id"),
362
+ key: list[str] = typer.Option(
363
+ ...,
364
+ "--key",
365
+ help="Env-var key to remove (with optional '#' prefix). Repeatable.",
366
+ ),
367
+ branch: int | None = typer.Option(
368
+ None,
369
+ "--branch",
370
+ help="Storage branch ID for the linked config (defaults to production).",
371
+ ),
372
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip the confirmation prompt."),
373
+ dry_run: bool = typer.Option(
374
+ False, "--dry-run", help="Preview the Storage PUT body without making the call."
375
+ ),
376
+ ) -> None:
377
+ """Remove one or more app-runtime secrets. Idempotent (missing keys are exit 0).
378
+
379
+ A removal can break the running app at the next deploy if it relied on
380
+ the secret; the command flags this in the response and never auto-deploys.
381
+
382
+ Reference: https://help.keboola.com/data-apps/python-js/
383
+ """
384
+
385
+ formatter = get_formatter(ctx)
386
+ service = get_service(ctx, "data_app_service")
387
+
388
+ if (
389
+ not yes
390
+ and not formatter.json_mode
391
+ and not dry_run
392
+ and not typer.confirm(
393
+ f"Remove {len(key)} secret(s) from data app {app_id} in '{project}'? "
394
+ "This may break the app at next deploy if it depends on these values."
395
+ )
396
+ ):
397
+ formatter.console.print("Aborted.")
398
+ raise typer.Exit(code=0)
399
+
400
+ try:
401
+ result = service.remove_data_app_secrets(
402
+ alias=project,
403
+ app_id=app_id,
404
+ keys=key,
405
+ branch_id=branch,
406
+ dry_run=dry_run,
407
+ )
408
+ except KeboolaApiError as exc:
409
+ formatter.error(
410
+ message=exc.message,
411
+ error_code=exc.error_code,
412
+ retryable=exc.retryable,
413
+ details=exc.details,
414
+ )
415
+ raise typer.Exit(code=map_error_to_exit_code(exc)) from None
416
+ except ConfigError as exc:
417
+ formatter.error(message=exc.message, error_code=ErrorCode.CONFIG_ERROR)
418
+ raise typer.Exit(code=5) from None
419
+
420
+ formatter.output(
421
+ result,
422
+ lambda c, d: c.print(f"[bold green]Success:[/bold green] {d['message']}"),
423
+ )
424
+
425
+
426
+ def register_secrets_commands(app: typer.Typer) -> None:
427
+ """Attach the data-app secrets-* commands to the data-app sub-app.
428
+
429
+ Module-level command functions registered explicitly (rather than via
430
+ inline ``@app.command`` closures) keep the large bodies un-indented and
431
+ diff-friendly relative to their previous home in ``data_app.py``.
432
+ """
433
+ app.command("secrets-set")(data_app_secrets_set)
434
+ app.command("secrets-list")(data_app_secrets_list)
435
+ app.command("secrets-get")(data_app_secrets_get)
436
+ app.command("secrets-remove")(data_app_secrets_remove)