keboola-cli 0.76.0__tar.gz → 0.76.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 (439) hide show
  1. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/CLAUDE.md +3 -0
  2. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/PKG-INFO +1 -1
  3. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/pyproject.toml +1 -1
  4. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/auto_update.py +145 -64
  5. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/changelog.py +25 -0
  6. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/serve.py +50 -3
  7. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/version.py +6 -5
  8. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_semantic_layer_internals.py +10 -5
  9. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/version_service.py +265 -131
  10. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_auto_update.py +121 -22
  11. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_semantic_layer_service.py +38 -5
  12. keboola_cli-0.76.2/tests/test_serve_banner_encoding.py +252 -0
  13. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_version_service.py +97 -12
  14. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/.gitignore +0 -0
  15. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/CONTRIBUTING.md +0 -0
  16. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/Makefile +0 -0
  17. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/README.md +0 -0
  18. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/examples/README.md +0 -0
  19. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/examples/storage_tui/README.md +0 -0
  20. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/plugins/kbagent/.claude-plugin/CLAUDE.md +0 -0
  21. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/benchmark.py +0 -0
  22. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/check_command_sync.py +0 -0
  23. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/check_error_codes.py +0 -0
  24. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/check_mcp_parity.py +0 -0
  25. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/check_wheel_ui.py +0 -0
  26. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/debug_linkedby_type.sh +0 -0
  27. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/gen_command_reference.py +0 -0
  28. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/gen_release_notes.py +0 -0
  29. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/generate_changelog.py +0 -0
  30. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/generate_skill.py +0 -0
  31. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/hatch_build.py +0 -0
  32. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/lineage_deep.py +0 -0
  33. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/post-edit-quality.sh +0 -0
  34. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/pre-commit +0 -0
  35. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/sync_version.py +0 -0
  36. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/scripts/web-dev.sh +0 -0
  37. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/__init__.py +0 -0
  38. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/__main__.py +0 -0
  39. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/ai_client.py +0 -0
  40. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/cli.py +0 -0
  41. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/__init__.py +0 -0
  42. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/_client.py +0 -0
  43. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/_core.py +0 -0
  44. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/_transfer.py +0 -0
  45. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/branches.py +0 -0
  46. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/configs.py +0 -0
  47. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/misc.py +0 -0
  48. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/query.py +0 -0
  49. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/queue.py +0 -0
  50. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/storage_files.py +0 -0
  51. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/storage_tables.py +0 -0
  52. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/stream.py +0 -0
  53. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/tokens.py +0 -0
  54. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/client/workspaces.py +0 -0
  55. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/__init__.py +0 -0
  56. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/_data_app_git.py +0 -0
  57. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/_data_app_runtime.py +0 -0
  58. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/_helpers.py +0 -0
  59. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/_metadata_input.py +0 -0
  60. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/_semantic_layer_crud.py +0 -0
  61. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/_semantic_layer_helpers.py +0 -0
  62. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/_semantic_layer_reference_data.py +0 -0
  63. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/_storage_snapshots.py +0 -0
  64. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/agent.py +0 -0
  65. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/branch.py +0 -0
  66. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/changelog.py +0 -0
  67. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/component.py +0 -0
  68. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/config.py +0 -0
  69. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/context.py +0 -0
  70. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/data_app.py +0 -0
  71. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/dev_portal.py +0 -0
  72. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/docs.py +0 -0
  73. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/doctor.py +0 -0
  74. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/encrypt.py +0 -0
  75. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/feature.py +0 -0
  76. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/flow.py +0 -0
  77. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/http_client.py +0 -0
  78. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/init.py +0 -0
  79. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/job.py +0 -0
  80. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/kai.py +0 -0
  81. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/lineage.py +0 -0
  82. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/org.py +0 -0
  83. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/permissions.py +0 -0
  84. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/project.py +0 -0
  85. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/repl.py +0 -0
  86. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/schedule.py +0 -0
  87. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/search.py +0 -0
  88. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/semantic_layer.py +0 -0
  89. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/sharing.py +0 -0
  90. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/storage.py +0 -0
  91. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/stream.py +0 -0
  92. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/sync.py +0 -0
  93. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/token.py +0 -0
  94. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/tool.py +0 -0
  95. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/transformation.py +0 -0
  96. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/commands/workspace.py +0 -0
  97. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/config_store.py +0 -0
  98. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/constants.py +0 -0
  99. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/data_science_client.py +0 -0
  100. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/dev_portal_client.py +0 -0
  101. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/errors.py +0 -0
  102. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/http_base.py +0 -0
  103. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/json_utils.py +0 -0
  104. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/lib.py +0 -0
  105. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/manage_client.py +0 -0
  106. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/mcp_parity.py +0 -0
  107. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/metastore_client.py +0 -0
  108. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/models.py +0 -0
  109. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/output.py +0 -0
  110. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/permissions.py +0 -0
  111. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/py.typed +0 -0
  112. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/resources/__init__.py +0 -0
  113. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/resources/flow/__init__.py +0 -0
  114. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/resources/flow/conditional-flow-schema.json +0 -0
  115. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/resources/flow/conditional_flow_examples.jsonl +0 -0
  116. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/resources/flow/flow-schema.json +0 -0
  117. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/resources/flow/legacy_flow_examples.jsonl +0 -0
  118. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/result_models.py +0 -0
  119. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/scheduler_client.py +0 -0
  120. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/__init__.py +0 -0
  121. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/agent_runner.py +0 -0
  122. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/agents_store.py +0 -0
  123. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/app.py +0 -0
  124. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/auth.py +0 -0
  125. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/dependencies.py +0 -0
  126. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/pricing.py +0 -0
  127. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/__init__.py +0 -0
  128. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/agents.py +0 -0
  129. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/ai_chat.py +0 -0
  130. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/branches.py +0 -0
  131. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/components.py +0 -0
  132. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/configs.py +0 -0
  133. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/data_apps.py +0 -0
  134. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/dev_portal.py +0 -0
  135. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/docs.py +0 -0
  136. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/encrypt.py +0 -0
  137. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/feature.py +0 -0
  138. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/flows.py +0 -0
  139. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/health.py +0 -0
  140. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/jobs.py +0 -0
  141. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/kai.py +0 -0
  142. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/lineage.py +0 -0
  143. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/mcp.py +0 -0
  144. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/members.py +0 -0
  145. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/org.py +0 -0
  146. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/projects.py +0 -0
  147. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/schedules.py +0 -0
  148. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/search.py +0 -0
  149. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/semantic_layer.py +0 -0
  150. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/sharing.py +0 -0
  151. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/storage.py +0 -0
  152. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/stream.py +0 -0
  153. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/token.py +0 -0
  154. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/transformation.py +0 -0
  155. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/routers/workspaces.py +0 -0
  156. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/run_broadcaster.py +0 -0
  157. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/server/sse.py +0 -0
  158. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/__init__.py +0 -0
  159. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_encryption.py +0 -0
  160. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_semantic_layer_cascade.py +0 -0
  161. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_semantic_layer_crud.py +0 -0
  162. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_semantic_layer_lookup.py +0 -0
  163. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_semantic_layer_reference_data.py +0 -0
  164. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_sync_bindings.py +0 -0
  165. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_sync_branch.py +0 -0
  166. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_sync_bulk.py +0 -0
  167. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_sync_clone.py +0 -0
  168. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_sync_models.py +0 -0
  169. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_sync_push_ops.py +0 -0
  170. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_sync_storage.py +0 -0
  171. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_sync_writeback.py +0 -0
  172. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/_transformation_ops.py +0 -0
  173. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/agent_service.py +0 -0
  174. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/base.py +0 -0
  175. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/branch_service.py +0 -0
  176. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/component_service.py +0 -0
  177. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/config_service.py +0 -0
  178. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/data_app_git_service.py +0 -0
  179. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/data_app_service.py +0 -0
  180. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/deep_lineage_service.py +0 -0
  181. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/dev_portal_service.py +0 -0
  182. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/docs_service.py +0 -0
  183. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/doctor_service.py +0 -0
  184. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/encrypt_service.py +0 -0
  185. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/feature_service.py +0 -0
  186. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/flow_service.py +0 -0
  187. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/flow_validation.py +0 -0
  188. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/http_forwarder_service.py +0 -0
  189. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/job_idempotency_store.py +0 -0
  190. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/job_service.py +0 -0
  191. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/kai_service.py +0 -0
  192. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/lineage_service.py +0 -0
  193. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/mcp_service.py +0 -0
  194. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/mcp_transport.py +0 -0
  195. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/member_service.py +0 -0
  196. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/org_service.py +0 -0
  197. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/project_service.py +0 -0
  198. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/repo_validate_service.py +0 -0
  199. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/schedule_service.py +0 -0
  200. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/search_service.py +0 -0
  201. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/semantic_layer_service.py +0 -0
  202. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/sharing_service.py +0 -0
  203. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/snapshot_service.py +0 -0
  204. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/storage_service.py +0 -0
  205. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/stream_service.py +0 -0
  206. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/sync_service.py +0 -0
  207. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/token_service.py +0 -0
  208. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/transformation_service.py +0 -0
  209. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/variables_service.py +0 -0
  210. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/services/workspace_service.py +0 -0
  211. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/stream_client.py +0 -0
  212. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/__init__.py +0 -0
  213. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/branch_mapping.py +0 -0
  214. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/clone.py +0 -0
  215. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/code_extraction.py +0 -0
  216. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/config_format.py +0 -0
  217. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/diff_engine.py +0 -0
  218. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/git_utils.py +0 -0
  219. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/manifest.py +0 -0
  220. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/naming.py +0 -0
  221. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/secrets.py +0 -0
  222. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/src/keboola_agent_cli/sync/sql_split.py +0 -0
  223. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/__init__.py +0 -0
  224. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/conftest.py +0 -0
  225. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/helpers.py +0 -0
  226. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_agent_cli.py +0 -0
  227. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_agent_prompt.py +0 -0
  228. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_agent_prompt_helper.py +0 -0
  229. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_agent_runner.py +0 -0
  230. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_agent_service.py +0 -0
  231. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_agents_store_events.py +0 -0
  232. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_ai_client.py +0 -0
  233. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_base_service.py +0 -0
  234. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_branch_metadata_cli.py +0 -0
  235. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_branch_metadata_service.py +0 -0
  236. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_branch_service.py +0 -0
  237. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_build_hook.py +0 -0
  238. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_changelog_check.py +0 -0
  239. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_changelog_render.py +0 -0
  240. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_check_command_sync.py +0 -0
  241. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_choice_enums.py +0 -0
  242. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_cli.py +0 -0
  243. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_client.py +0 -0
  244. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_client_device_enrollment.py +0 -0
  245. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_component_cli.py +0 -0
  246. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_component_service.py +0 -0
  247. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_component_sync_action.py +0 -0
  248. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_create_cli.py +0 -0
  249. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_create_service.py +0 -0
  250. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_encryption.py +0 -0
  251. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_examples.py +0 -0
  252. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_metadata.py +0 -0
  253. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_rename.py +0 -0
  254. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_rename_cli.py +0 -0
  255. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_resolution.py +0 -0
  256. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_row_cli.py +0 -0
  257. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_row_service.py +0 -0
  258. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_search.py +0 -0
  259. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_search_cli.py +0 -0
  260. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_set_default_bucket.py +0 -0
  261. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_store.py +0 -0
  262. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_config_update.py +0 -0
  263. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_data_app_cli.py +0 -0
  264. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_data_app_git_repo.py +0 -0
  265. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_data_app_plain_env_keys.py +0 -0
  266. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_data_app_secrets_cli.py +0 -0
  267. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_data_app_secrets_service.py +0 -0
  268. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_data_app_service.py +0 -0
  269. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_data_app_validate_repo_service.py +0 -0
  270. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_deep_lineage_service.py +0 -0
  271. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_dev_portal_cli.py +0 -0
  272. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_dev_portal_client.py +0 -0
  273. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_dev_portal_service.py +0 -0
  274. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_docs_cli.py +0 -0
  275. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_doctor_service.py +0 -0
  276. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_e2e.py +0 -0
  277. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_e2e_config_dir_mode.py +0 -0
  278. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_e2e_lineage_deep.py +0 -0
  279. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_encrypt_cli.py +0 -0
  280. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_encrypt_service.py +0 -0
  281. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_encryption.py +0 -0
  282. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_errors.py +0 -0
  283. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_feature_cli.py +0 -0
  284. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_feature_service.py +0 -0
  285. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_file_locking.py +0 -0
  286. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_flow_cli.py +0 -0
  287. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_flow_examples.py +0 -0
  288. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_flow_service.py +0 -0
  289. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_flow_validation.py +0 -0
  290. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_gen_command_reference.py +0 -0
  291. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_gen_release_notes.py +0 -0
  292. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_helpers.py +0 -0
  293. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_http_base.py +0 -0
  294. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_http_client_cmd.py +0 -0
  295. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_http_forwarder_service.py +0 -0
  296. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_integration.py +0 -0
  297. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_job_idempotency_store.py +0 -0
  298. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_json_utils.py +0 -0
  299. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_kai_cli.py +0 -0
  300. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_kai_service.py +0 -0
  301. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_lib.py +0 -0
  302. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_lib_device_enrollment.py +0 -0
  303. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_lineage_service.py +0 -0
  304. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_local_ai_chat.py +0 -0
  305. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_manage_client.py +0 -0
  306. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_manage_token_bulk.py +0 -0
  307. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_manage_token_cli.py +0 -0
  308. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_mcp_deprecation_warnings.py +0 -0
  309. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_mcp_parity_map.py +0 -0
  310. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_mcp_service.py +0 -0
  311. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_mcp_transport.py +0 -0
  312. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_member_cli.py +0 -0
  313. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_member_service.py +0 -0
  314. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_metastore_client.py +0 -0
  315. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_models.py +0 -0
  316. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_normalize_script.py +0 -0
  317. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_org_service.py +0 -0
  318. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_output.py +0 -0
  319. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_permissions.py +0 -0
  320. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_permissions_cli.py +0 -0
  321. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_pricing.py +0 -0
  322. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_project_edit.py +0 -0
  323. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_project_edit_cli.py +0 -0
  324. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_project_info_cli.py +0 -0
  325. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_project_info_service.py +0 -0
  326. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_repl.py +0 -0
  327. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_result_models.py +0 -0
  328. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_run_broadcaster.py +0 -0
  329. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_schedule_cli.py +0 -0
  330. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_schedule_service.py +0 -0
  331. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_scheduler_client.py +0 -0
  332. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_search_cli.py +0 -0
  333. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_search_service.py +0 -0
  334. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_semantic_layer_cli.py +0 -0
  335. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_semantic_layer_schema.py +0 -0
  336. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_serve_conversation_id.py +0 -0
  337. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_serve_ui.py +0 -0
  338. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_server_router_calls.py +0 -0
  339. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_server_semantic_layer_routes_e2e.py +0 -0
  340. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_server_smoke.py +0 -0
  341. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_services.py +0 -0
  342. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sharing_service.py +0 -0
  343. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_skill_frontmatter.py +0 -0
  344. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sql_split.py +0 -0
  345. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_clone.py +0 -0
  346. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_create_table.py +0 -0
  347. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_delete.py +0 -0
  348. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_describe_cli.py +0 -0
  349. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_describe_service.py +0 -0
  350. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_empty_definition.py +0 -0
  351. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_export_filters.py +0 -0
  352. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_files.py +0 -0
  353. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_snapshots.py +0 -0
  354. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_swap.py +0 -0
  355. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_tables.py +0 -0
  356. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_truncate.py +0 -0
  357. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_storage_write.py +0 -0
  358. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_stream_cli.py +0 -0
  359. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_stream_client.py +0 -0
  360. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_stream_service.py +0 -0
  361. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_branch_mapping.py +0 -0
  362. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_cli.py +0 -0
  363. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_clone.py +0 -0
  364. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_code_extraction.py +0 -0
  365. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_config_format.py +0 -0
  366. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_diff_engine.py +0 -0
  367. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_e2e.py +0 -0
  368. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_encrypt.py +0 -0
  369. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_force_pull_baseline.py +0 -0
  370. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_manifest.py +0 -0
  371. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_naming.py +0 -0
  372. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_plaintext_audit.py +0 -0
  373. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_reconcile.py +0 -0
  374. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_secrets.py +0 -0
  375. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_service.py +0 -0
  376. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_storage_jobs.py +0 -0
  377. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_sync_version_script.py +0 -0
  378. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_token_cli.py +0 -0
  379. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_token_service.py +0 -0
  380. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_tool_call_permissions.py +0 -0
  381. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_transformation_cli.py +0 -0
  382. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_transformation_ops.py +0 -0
  383. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_variables_cli.py +0 -0
  384. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_variables_service.py +0 -0
  385. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_workspace_cli.py +0 -0
  386. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_workspace_gc.py +0 -0
  387. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_workspace_service.py +0 -0
  388. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/tests/test_workspace_sql_helper.py +0 -0
  389. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/README.md +0 -0
  390. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/index.html +0 -0
  391. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/package-lock.json +0 -0
  392. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/package.json +0 -0
  393. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/postcss.config.js +0 -0
  394. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/App.tsx +0 -0
  395. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/api/client.ts +0 -0
  396. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/components/AgentRunView.tsx +0 -0
  397. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/components/ConfirmModal.tsx +0 -0
  398. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/components/Drawer.tsx +0 -0
  399. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/components/Empty.tsx +0 -0
  400. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/components/JsonView.tsx +0 -0
  401. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/components/ManageTokenModal.tsx +0 -0
  402. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/components/Table.tsx +0 -0
  403. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/index.css +0 -0
  404. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/layout/Shell.tsx +0 -0
  405. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/layout/Sidebar.tsx +0 -0
  406. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/layout/StatusBar.tsx +0 -0
  407. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/layout/TopBar.tsx +0 -0
  408. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/main.tsx +0 -0
  409. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Agents.tsx +0 -0
  410. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Branches.tsx +0 -0
  411. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Changelog.tsx +0 -0
  412. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Components.tsx +0 -0
  413. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Configs.tsx +0 -0
  414. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Dashboard.tsx +0 -0
  415. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/DataApps.tsx +0 -0
  416. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Doctor.tsx +0 -0
  417. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Encrypt.tsx +0 -0
  418. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Flows.tsx +0 -0
  419. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Jobs.tsx +0 -0
  420. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Lineage.tsx +0 -0
  421. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/LocalAi.tsx +0 -0
  422. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Mcp.tsx +0 -0
  423. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Members.tsx +0 -0
  424. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Org.tsx +0 -0
  425. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Projects.tsx +0 -0
  426. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Schedules.tsx +0 -0
  427. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Search.tsx +0 -0
  428. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/SemanticLayer.tsx +0 -0
  429. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/SemanticLayerDialogs.tsx +0 -0
  430. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Sharing.tsx +0 -0
  431. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Storage.tsx +0 -0
  432. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Streams.tsx +0 -0
  433. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/pages/Workspaces.tsx +0 -0
  434. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/state.tsx +0 -0
  435. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/theme.tsx +0 -0
  436. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/src/types.ts +0 -0
  437. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/tailwind.config.ts +0 -0
  438. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/tsconfig.json +0 -0
  439. {keboola_cli-0.76.0 → keboola_cli-0.76.2}/web/frontend/vite.config.ts +0 -0
@@ -664,6 +664,9 @@ kbagent update [--beta]
664
664
  # source build; falls back to git+ when absent). Env `KBAGENT_UPDATE_TIMEOUT` (integer
665
665
  # seconds, default 300) raises the self-update subprocess timeout for the slow git+
666
666
  # fallback on WSL. Bootstrap install: `curl -LsSf .../main/install.sh | sh`.
667
+ # Since 0.76.2 self-update completes discovery first, updates MCP before the terminal
668
+ # exact-version full kbagent reinstall, then immediately re-executes; failures print a
669
+ # copy-paste recovery command.
667
670
  kbagent changelog [--limit N] [--full]
668
671
  # Default shows a one-line summary (first sentence) per version; --full / -v expands every note.
669
672
  kbagent serve [--host HOST] [--port PORT] [--ui] [--ui-dist PATH] [--reload] [--log-level LVL] [--cors-origin ORIGIN] [--config-dir DIR]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: keboola-cli
3
- Version: 0.76.0
3
+ Version: 0.76.2
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.76.0"
3
+ version = "0.76.2"
4
4
  description = "AI-friendly CLI for managing Keboola projects"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -34,6 +34,8 @@ from .constants import (
34
34
  from .services.version_service import (
35
35
  MCP_PACKAGE_NAME,
36
36
  MCP_UV_PRERELEASE_FLAG,
37
+ KbagentUpdatePlan,
38
+ McpUpdatePlan,
37
39
  _detect_mcp_install_method,
38
40
  _fetch_kbagent_latest_version,
39
41
  _fetch_mcp_latest_version,
@@ -42,6 +44,8 @@ from .services.version_service import (
42
44
  _perform_mcp_update,
43
45
  build_kbagent_upgrade_command,
44
46
  get_update_timeout,
47
+ prepare_kbagent_update_plan,
48
+ prepare_mcp_update_plan,
45
49
  resolve_kbagent_wheel_url,
46
50
  )
47
51
 
@@ -264,7 +268,9 @@ def _should_skip() -> bool:
264
268
  return _should_skip_kbagent_stage() or _should_skip_all()
265
269
 
266
270
 
267
- def _perform_update(latest_version: str) -> UpdateOutcome:
271
+ def _perform_update(
272
+ latest_version: str, *, command: tuple[str, ...] | None = None
273
+ ) -> UpdateOutcome:
268
274
  """Download and install the latest version.
269
275
 
270
276
  Delegates to :func:`build_kbagent_upgrade_command` so this path stays
@@ -283,10 +289,14 @@ def _perform_update(latest_version: str) -> UpdateOutcome:
283
289
  the install subprocess outran :func:`get_update_timeout` (a slow git+
284
290
  build -- retried next run, not a real failure), ``FAILED`` otherwise.
285
291
  """
286
- # Prefer the prebuilt-wheel Release asset (issue #353) when present; falls
287
- # back to the git+ source build for releases without an asset.
288
- wheel_url = resolve_kbagent_wheel_url(latest_version)
289
- cmd = build_kbagent_upgrade_command(wheel_url=wheel_url)
292
+ # ``command`` is supplied by the startup planner. Keep the fallback only
293
+ # for direct legacy callers; it must never be used after another stage has
294
+ # mutated the kbagent environment.
295
+ if command is None:
296
+ wheel_url = resolve_kbagent_wheel_url(latest_version)
297
+ cmd = build_kbagent_upgrade_command(target_version=latest_version, wheel_url=wheel_url)
298
+ else:
299
+ cmd = list(command)
290
300
  if cmd is None:
291
301
  return UpdateOutcome.FAILED
292
302
 
@@ -435,6 +445,58 @@ def _maybe_update_mcp(cache: dict | None, fetched_now: bool) -> str | None:
435
445
  return mcp_latest
436
446
 
437
447
 
448
+ def _apply_prepared_mcp_update(plan: McpUpdatePlan) -> None:
449
+ """Apply a previously prepared MCP update while kbagent is still intact."""
450
+ if plan.latest_version is None or plan.up_to_date is True or plan.install_method == "none":
451
+ return
452
+ if plan.current_version is None or plan.command is None:
453
+ return
454
+
455
+ sys.stderr.write(
456
+ f"Updating keboola-mcp-server v{plan.current_version} -> v{plan.latest_version}"
457
+ f" (via {plan.install_method})...\n"
458
+ )
459
+ success, info = _perform_mcp_update(
460
+ method=plan.install_method,
461
+ timeout=MCP_UPGRADE_TIMEOUT,
462
+ command=plan.command,
463
+ )
464
+ if not success:
465
+ sys.stderr.write(
466
+ f"keboola-mcp-server upgrade skipped: {info}; continuing with current version.\n"
467
+ )
468
+ return
469
+
470
+ # A post-MCP probe is permitted: the kbagent environment has not yet
471
+ # changed. It is deliberately the last discovery operation in this flow.
472
+ post_version = _get_local_mcp_version()
473
+ if post_version and post_version != plan.current_version:
474
+ sys.stderr.write(f"Updated keboola-mcp-server to v{post_version}.\n")
475
+ elif post_version is None:
476
+ sys.stderr.write(
477
+ f"Updated keboola-mcp-server (probe failed; latest on PyPI: v{plan.latest_version}).\n"
478
+ )
479
+ else:
480
+ sys.stderr.write(
481
+ f"keboola-mcp-server upgrade exit 0 but local version still v{plan.current_version} "
482
+ f"(latest: v{plan.latest_version}). Run `uv tool install --reinstall "
483
+ f"{MCP_UV_PRERELEASE_FLAG} {MCP_PACKAGE_NAME}` to force the latest.\n"
484
+ )
485
+
486
+
487
+ def _prepare_auto_kbagent_plan(latest_version: str | None) -> KbagentUpdatePlan:
488
+ """Adapt the shared plan to the startup comparison seam used by tests."""
489
+ prepared = prepare_kbagent_update_plan(latest_version)
490
+ up_to_date = _is_up_to_date(__version__, latest_version)
491
+ return KbagentUpdatePlan(
492
+ current_version=prepared.current_version,
493
+ latest_version=prepared.latest_version,
494
+ up_to_date=up_to_date,
495
+ command=prepared.command if up_to_date is False else None,
496
+ recovery_command=prepared.recovery_command,
497
+ )
498
+
499
+
438
500
  def maybe_auto_update() -> None:
439
501
  """Main entry point for the auto-update flow.
440
502
 
@@ -484,66 +546,85 @@ def maybe_auto_update() -> None:
484
546
 
485
547
  cache = _read_cache()
486
548
  cache_is_fresh = bool(cache and _is_cache_fresh(cache, AUTO_UPDATE_CHECK_INTERVAL))
487
- latest_version: str | None = None
488
-
489
- # ----- Stage 1: kbagent self-update --------------------------------
490
- # The re-exec guard skips ONLY this stage (so a freshly upgraded
491
- # kbagent in the re-exec'd process does NOT double-upgrade itself
492
- # but still proceeds to Stage 2 below).
493
- if not _should_skip_kbagent_stage():
494
- if cache_is_fresh:
495
- latest_version = cache.get("latest_version") # type: ignore[union-attr]
496
- else:
497
- latest_version = _fetch_kbagent_latest_version(timeout=VERSION_CHECK_TIMEOUT)
498
-
499
- if latest_version is not None:
500
- up_to_date = _is_up_to_date(__version__, latest_version)
501
- if up_to_date is False:
502
- sys.stderr.write(f"Updating kbagent v{__version__} -> v{latest_version}...\n")
503
- outcome = _perform_update(latest_version)
504
- if outcome is UpdateOutcome.SUCCESS:
505
- sys.stderr.write(f"Updated to v{latest_version}. Re-launching...\n")
506
- # Persist cache before re-exec so the new process does
507
- # not refetch immediately. The re-exec'd process will
508
- # skip Stage 1 (KBAGENT_SKIP_UPDATE=1) and run Stage 2
509
- # against the just-refreshed cache.
510
- _write_cache(
511
- latest_version,
512
- mcp_latest_version=cache.get("mcp_latest_version") if cache else None,
513
- mcp_install_method=cache.get("mcp_install_method") if cache else None,
514
- )
515
- os.environ[ENV_UPDATED_FROM] = __version__
516
- _re_exec()
517
- return # Defensive: _re_exec replaces the process.
518
- if outcome is UpdateOutcome.TIMEOUT:
519
- # Not a failure: the git+ source build outran the timeout.
520
- # The wheel fast path makes this rare; when it happens, say
521
- # so plainly instead of "failed" and let a later run finish
522
- # what uv already started (issue #353).
523
- sys.stderr.write(
524
- f"Update still building after {int(get_update_timeout())}s; "
525
- "it will finish on a later run. Continuing with current version.\n"
526
- )
527
- else:
528
- sys.stderr.write("Auto-update failed; continuing with current version.\n")
529
-
530
- # ----- Stage 2: keboola-mcp-server update --------------------------
531
- # Always runs (subject only to _should_skip_all above). After a
532
- # kbagent self-upgrade, this is the re-exec'd process executing
533
- # Stage 2 for the first time -- exactly the path B-1 broke before.
534
- mcp_latest = _maybe_update_mcp(cache, fetched_now=not cache_is_fresh)
535
- mcp_install_method = _detect_mcp_install_method()
536
-
537
- # Persist combined cache (kbagent + MCP) when we did any fresh fetch.
538
- # Note: in the re-exec'd path, latest_version stays None (Stage 1
539
- # was skipped); _write_cache handles that by falling back to the
540
- # running __version__, so we still persist the MCP-side fields and
541
- # don't break the next run's cache TTL check.
542
- if not cache_is_fresh:
549
+ cached_kbagent = cache.get("latest_version") if cache else None
550
+ cached_mcp = cache.get("mcp_latest_version") if cache else None
551
+ skip_kbagent_stage = _should_skip_kbagent_stage()
552
+ use_cached_kbagent = cache_is_fresh and isinstance(cached_kbagent, str)
553
+ use_cached_mcp = cache_is_fresh and isinstance(cached_mcp, str)
554
+ latest_version = (
555
+ cached_kbagent
556
+ if use_cached_kbagent
557
+ else (
558
+ None
559
+ if skip_kbagent_stage
560
+ else _fetch_kbagent_latest_version(timeout=VERSION_CHECK_TIMEOUT)
561
+ )
562
+ )
563
+ mcp_latest = (
564
+ cached_mcp
565
+ if use_cached_mcp
566
+ else _fetch_mcp_latest_version(timeout=VERSION_CHECK_TIMEOUT)
567
+ )
568
+
569
+ # Planning is complete before any subprocess can mutate either tool.
570
+ # In particular, all HTTP requests, import probes, PATH inspection,
571
+ # and command construction are above this line.
572
+ mcp_plan = prepare_mcp_update_plan(mcp_latest)
573
+ kbagent_plan = (
574
+ _prepare_auto_kbagent_plan(latest_version)
575
+ if not skip_kbagent_stage
576
+ else KbagentUpdatePlan(__version__, latest_version, True, None, None)
577
+ )
578
+
579
+ # MCP is an independent environment. Finish it before the terminal
580
+ # self-reinstall and persist the prepared cache before self-mutation.
581
+ _apply_prepared_mcp_update(mcp_plan)
582
+ if not (use_cached_kbagent and use_cached_mcp):
543
583
  _write_cache(
544
- latest_version=latest_version or (cache.get("latest_version") if cache else None),
545
- mcp_latest_version=mcp_latest,
546
- mcp_install_method=mcp_install_method,
584
+ latest_version=(
585
+ latest_version
586
+ if latest_version is not None
587
+ else cached_kbagent
588
+ if isinstance(cached_kbagent, str)
589
+ else None
590
+ ),
591
+ mcp_latest_version=(
592
+ mcp_latest
593
+ if mcp_latest is not None
594
+ else cached_mcp
595
+ if isinstance(cached_mcp, str)
596
+ else None
597
+ ),
598
+ mcp_install_method=mcp_plan.install_method,
599
+ )
600
+
601
+ if kbagent_plan.up_to_date is not False:
602
+ return
603
+ if kbagent_plan.command is None:
604
+ sys.stderr.write(
605
+ "Auto-update could not prepare a reinstall command. "
606
+ f"Recover with: {kbagent_plan.recovery_command}\n"
607
+ )
608
+ return
609
+
610
+ sys.stderr.write(f"Updating kbagent v{__version__} -> v{kbagent_plan.latest_version}...\n")
611
+ outcome = _perform_update(
612
+ kbagent_plan.latest_version or __version__, command=kbagent_plan.command
613
+ )
614
+ if outcome is UpdateOutcome.SUCCESS:
615
+ sys.stderr.write(f"Updated to v{kbagent_plan.latest_version}. Re-launching...\n")
616
+ os.environ[ENV_UPDATED_FROM] = __version__
617
+ _re_exec()
618
+ return
619
+ if outcome is UpdateOutcome.TIMEOUT:
620
+ sys.stderr.write(
621
+ f"Update timed out after {int(get_update_timeout())}s. Recover with: "
622
+ f"{kbagent_plan.recovery_command}\n"
623
+ )
624
+ else:
625
+ sys.stderr.write(
626
+ "Auto-update failed; continuing with current version. Recover with: "
627
+ f"{kbagent_plan.recovery_command}\n"
547
628
  )
548
629
  except Exception:
549
630
  # Blanket catch: auto-update must NEVER crash the CLI.
@@ -24,6 +24,31 @@ 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.76.2": [
28
+ "Fix (#528, #530): self-update no longer risks leaving the running Windows uv tool "
29
+ "environment partially upgraded. kbagent now completes all network checks and command "
30
+ "planning before mutation, upgrades the independent keboola-mcp-server environment "
31
+ "first, caches the result, then performs an exact-version full reinstall as the terminal "
32
+ "step and immediately re-executes. Failed or timed-out updates print a copy-paste recovery "
33
+ "command instead of continuing without repair guidance. Thanks to @papousek-radan for "
34
+ "the detailed corruption reports.",
35
+ "Fix (#529, #531): `kbagent semantic-layer export` now writes snapshots on Windows. "
36
+ "The writer conditionally enables platform-specific `O_NOFOLLOW` and `O_BINARY` flags, "
37
+ "so Windows no longer raises `AttributeError` while POSIX keeps its existing final-path "
38
+ "symlink protection; the real Windows export path is covered by CI. Thanks to "
39
+ "@papousek-radan for the report.",
40
+ ],
41
+ "0.76.1": [
42
+ "Fix (#522, #526): `kbagent serve --ui` no longer crashes on startup on Windows "
43
+ "consoles with a non-UTF-8 codepage (cp1250 on Czech/Polish/Hungarian Windows). The "
44
+ "startup banner's box-drawing glyphs (`├─` / `└─`) raised `UnicodeEncodeError` from "
45
+ "`sys.stdout.write` before uvicorn bound the port, so the server never started. They "
46
+ "now degrade to ASCII (`|-` / `` `- ``) when the console can't encode them -- the same "
47
+ "UTF-8/ASCII fallback `install.sh` already uses -- with a belt-and-braces `try/except` "
48
+ "so a cosmetic banner can never abort startup. Modern UTF-8 terminals are unchanged. "
49
+ "The `set PYTHONUTF8=1` workaround is no longer needed. Thanks to @papousek-radan for "
50
+ "the detailed report.",
51
+ ],
27
52
  "0.76.0": [
28
53
  "Change (#520): the ~3,960-LOC `client.py` is split into a `client/` package by "
29
54
  "endpoint family (storage tables/files, configs, queue, tokens, branches, stream, "
@@ -86,6 +86,53 @@ def _autodetect_ui_dist() -> Path | None:
86
86
  return None
87
87
 
88
88
 
89
+ # Box-drawing glyphs used by the startup banner, mapped to ASCII so the banner
90
+ # degrades to `|-` / `` `- `` on a console that can't render Unicode -- the same
91
+ # fallback install.sh uses (Unicode only under a UTF-8 locale, ASCII otherwise).
92
+ _BANNER_ASCII_FALLBACK = str.maketrans({"├": "|", "└": "`", "─": "-"})
93
+
94
+
95
+ def _encode_safe(text: str, encoding: str | None) -> str:
96
+ """Return ``text`` with box-drawing glyphs stripped to ASCII if unencodable.
97
+
98
+ On Windows with a non-UTF-8 console codepage (cp1250 on Czech/Polish/
99
+ Hungarian locales, and any other legacy single-byte encoding) the ``├─`` /
100
+ ``└─`` glyphs in the startup banner cannot be encoded, so ``sys.stdout.write``
101
+ raises ``UnicodeEncodeError`` -- which crashed ``kbagent serve`` before
102
+ uvicorn ever bound the port (issue #522). When ``encoding`` can represent the
103
+ banner we keep the Unicode glyphs; otherwise we transliterate to ASCII.
104
+
105
+ ``encoding`` is ``sys.stdout.encoding`` at the call site (``None`` on an
106
+ exotic stream); an unknown codec name (``LookupError``) also degrades to
107
+ ASCII rather than propagating.
108
+ """
109
+ enc = encoding or "utf-8"
110
+ try:
111
+ text.encode(enc)
112
+ except (UnicodeEncodeError, LookupError):
113
+ return text.translate(_BANNER_ASCII_FALLBACK)
114
+ return text
115
+
116
+
117
+ def _write_banner(text: str) -> None:
118
+ """Write the startup banner without ever letting a glyph crash startup.
119
+
120
+ Two layers of defense (issue #522): first transliterate to ASCII when
121
+ stdout's encoding can't represent the banner, then wrap the write in a
122
+ belt-and-braces ``try/except`` so even an unforeseen un-encodable character
123
+ re-emits with lossy replacement instead of aborting the server. A degraded
124
+ banner is always better than a server that won't start.
125
+ """
126
+ encoding = getattr(sys.stdout, "encoding", None)
127
+ safe = _encode_safe(text, encoding)
128
+ try:
129
+ sys.stdout.write(safe)
130
+ except UnicodeEncodeError:
131
+ enc = encoding or "ascii"
132
+ sys.stdout.write(safe.encode(enc, "replace").decode(enc, "replace"))
133
+ sys.stdout.flush()
134
+
135
+
89
136
  def serve_command(
90
137
  host: str = typer.Option(
91
138
  "127.0.0.1",
@@ -232,7 +279,7 @@ def serve_command(
232
279
  # UI mode: the user opens the browser directly; there is no BFF to
233
280
  # paste the token into. The token is still printed so scripted
234
281
  # callers / curl one-liners keep working.
235
- sys.stdout.write(
282
+ banner = (
236
283
  "\n"
237
284
  " kbagent serve (single-process UI mode)\n"
238
285
  f" ├─ open: http://{host}:{port}/\n"
@@ -252,7 +299,7 @@ def serve_command(
252
299
  "\n"
253
300
  )
254
301
  else:
255
- sys.stdout.write(
302
+ banner = (
256
303
  "\n"
257
304
  " kbagent serve\n"
258
305
  f" ├─ host: http://{host}:{port}\n"
@@ -270,7 +317,7 @@ def serve_command(
270
317
  f" export KBAGENT_CONVERSATION_ID={conversation_id}\n"
271
318
  "\n"
272
319
  )
273
- sys.stdout.flush()
320
+ _write_banner(banner)
274
321
 
275
322
  uvicorn.run(
276
323
  app,
@@ -142,12 +142,13 @@ def update_command(
142
142
 
143
143
  Two-stage upgrade (since v0.30.1):
144
144
 
145
- 1. **kbagent** -- ``uv tool install --upgrade`` (preferred) or
146
- ``pip install --upgrade`` from the GitHub repository.
147
- 2. **keboola-mcp-server** -- detects install method and runs the
145
+ 1. **keboola-mcp-server** -- detects install method and runs the
148
146
  matching upgrade command (``uv tool upgrade`` / ``pip install -U``
149
- / ``uvx --refresh``). Always runs, regardless of whether kbagent
150
- itself needed an upgrade.
147
+ / ``uvx --refresh``).
148
+ 2. **kbagent** -- final terminal stage: ``uv tool install --force
149
+ --reinstall`` from an exact release wheel or Git tag. This recreates
150
+ the whole tool environment and preserves ``[server]`` extras. On a
151
+ failure the result includes a copy/paste recovery command.
151
152
 
152
153
  JSON output reports both stages independently. Human mode prints a
153
154
  one-line summary such as
@@ -1059,16 +1059,21 @@ def build_export_snapshot(
1059
1059
 
1060
1060
 
1061
1061
  def write_snapshot_to_file(snapshot: dict[str, Any], output_path: Path) -> None:
1062
- """Atomic-write a JSON snapshot with 0o644 perms and O_NOFOLLOW.
1062
+ """Write a JSON snapshot with 0o644 permissions where supported.
1063
1063
 
1064
- O_NOFOLLOW refuses to follow a pre-existing symlink at the chosen
1065
- path so a malicious --output (or a planted symlink in CWD) cannot
1066
- redirect the write to a sensitive file.
1064
+ On platforms that expose ``O_NOFOLLOW``, reject a pre-existing symlink at
1065
+ the output path so a malicious ``--output`` (or a planted symlink in the
1066
+ current directory) cannot redirect the write to a sensitive file. Windows
1067
+ does not provide that flag through :mod:`os`; its portable flags still
1068
+ write the encoded JSON bytes without text-mode newline translation.
1067
1069
  """
1068
1070
  payload = json.dumps(snapshot, indent=2).encode("utf-8")
1071
+ flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
1072
+ flags |= getattr(os, "O_NOFOLLOW", 0)
1073
+ flags |= getattr(os, "O_BINARY", 0)
1069
1074
  fd = os.open(
1070
1075
  str(output_path),
1071
- os.O_WRONLY | os.O_CREAT | os.O_TRUNC | os.O_NOFOLLOW,
1076
+ flags,
1072
1077
  0o644,
1073
1078
  )
1074
1079
  try: