vtx-coding-agent 0.1.1__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 (225) hide show
  1. vtx_coding_agent-0.1.1/.agents/skills/vtx-release-publish/SKILL.md +98 -0
  2. vtx_coding_agent-0.1.1/.agents/skills/vtx-tmux-test/SKILL.md +250 -0
  3. vtx_coding_agent-0.1.1/.agents/skills/vtx-tmux-test/run-e2e-tests.sh +312 -0
  4. vtx_coding_agent-0.1.1/.agents/skills/vtx-tmux-test/setup-test-project.sh +27 -0
  5. vtx_coding_agent-0.1.1/.gitignore +24 -0
  6. vtx_coding_agent-0.1.1/.pre-commit-config.yaml +7 -0
  7. vtx_coding_agent-0.1.1/.python-version +1 -0
  8. vtx_coding_agent-0.1.1/AGENTS.md +44 -0
  9. vtx_coding_agent-0.1.1/CHANGELOG.md +113 -0
  10. vtx_coding_agent-0.1.1/LICENSE +201 -0
  11. vtx_coding_agent-0.1.1/PKG-INFO +259 -0
  12. vtx_coding_agent-0.1.1/README.md +237 -0
  13. vtx_coding_agent-0.1.1/docs/README.md +36 -0
  14. vtx_coding_agent-0.1.1/docs/architecture.md +319 -0
  15. vtx_coding_agent-0.1.1/docs/configuration.md +353 -0
  16. vtx_coding_agent-0.1.1/docs/development.md +238 -0
  17. vtx_coding_agent-0.1.1/docs/e2e-test-coverage-review.md +214 -0
  18. vtx_coding_agent-0.1.1/docs/headless.md +128 -0
  19. vtx_coding_agent-0.1.1/docs/local-models.md +88 -0
  20. vtx_coding_agent-0.1.1/docs/permissions.md +88 -0
  21. vtx_coding_agent-0.1.1/docs/providers.md +247 -0
  22. vtx_coding_agent-0.1.1/docs/sessions.md +231 -0
  23. vtx_coding_agent-0.1.1/docs/skills.md +172 -0
  24. vtx_coding_agent-0.1.1/docs/storage-layout.md +186 -0
  25. vtx_coding_agent-0.1.1/docs/theming.md +117 -0
  26. vtx_coding_agent-0.1.1/docs/tools.md +197 -0
  27. vtx_coding_agent-0.1.1/pyproject.toml +84 -0
  28. vtx_coding_agent-0.1.1/scripts/show_themes.py +226 -0
  29. vtx_coding_agent-0.1.1/src/vtx/__init__.py +63 -0
  30. vtx_coding_agent-0.1.1/src/vtx/async_utils.py +40 -0
  31. vtx_coding_agent-0.1.1/src/vtx/builtin_skills/github/SKILL.md +139 -0
  32. vtx_coding_agent-0.1.1/src/vtx/builtin_skills/init/SKILL.md +74 -0
  33. vtx_coding_agent-0.1.1/src/vtx/builtin_skills/review/SKILL.md +73 -0
  34. vtx_coding_agent-0.1.1/src/vtx/builtin_skills/skill-builder/SKILL.md +133 -0
  35. vtx_coding_agent-0.1.1/src/vtx/cli.py +90 -0
  36. vtx_coding_agent-0.1.1/src/vtx/config.py +741 -0
  37. vtx_coding_agent-0.1.1/src/vtx/context/__init__.py +15 -0
  38. vtx_coding_agent-0.1.1/src/vtx/context/_xml.py +8 -0
  39. vtx_coding_agent-0.1.1/src/vtx/context/agent_mds.py +128 -0
  40. vtx_coding_agent-0.1.1/src/vtx/context/git.py +64 -0
  41. vtx_coding_agent-0.1.1/src/vtx/context/loader.py +41 -0
  42. vtx_coding_agent-0.1.1/src/vtx/context/skills.py +423 -0
  43. vtx_coding_agent-0.1.1/src/vtx/core/__init__.py +47 -0
  44. vtx_coding_agent-0.1.1/src/vtx/core/compaction.py +89 -0
  45. vtx_coding_agent-0.1.1/src/vtx/core/errors.py +17 -0
  46. vtx_coding_agent-0.1.1/src/vtx/core/handoff.py +51 -0
  47. vtx_coding_agent-0.1.1/src/vtx/core/scratchpad.py +54 -0
  48. vtx_coding_agent-0.1.1/src/vtx/core/types.py +197 -0
  49. vtx_coding_agent-0.1.1/src/vtx/defaults/__init__.py +0 -0
  50. vtx_coding_agent-0.1.1/src/vtx/defaults/config.yml +53 -0
  51. vtx_coding_agent-0.1.1/src/vtx/diff_display.py +12 -0
  52. vtx_coding_agent-0.1.1/src/vtx/events.py +224 -0
  53. vtx_coding_agent-0.1.1/src/vtx/gh_cli.py +82 -0
  54. vtx_coding_agent-0.1.1/src/vtx/git_branch.py +90 -0
  55. vtx_coding_agent-0.1.1/src/vtx/headless.py +127 -0
  56. vtx_coding_agent-0.1.1/src/vtx/llm/__init__.py +93 -0
  57. vtx_coding_agent-0.1.1/src/vtx/llm/base.py +217 -0
  58. vtx_coding_agent-0.1.1/src/vtx/llm/context_length.py +150 -0
  59. vtx_coding_agent-0.1.1/src/vtx/llm/dynamic_models.py +735 -0
  60. vtx_coding_agent-0.1.1/src/vtx/llm/model_fetcher.py +279 -0
  61. vtx_coding_agent-0.1.1/src/vtx/llm/models.py +78 -0
  62. vtx_coding_agent-0.1.1/src/vtx/llm/oauth/__init__.py +59 -0
  63. vtx_coding_agent-0.1.1/src/vtx/llm/oauth/copilot.py +358 -0
  64. vtx_coding_agent-0.1.1/src/vtx/llm/oauth/dynamic.py +236 -0
  65. vtx_coding_agent-0.1.1/src/vtx/llm/oauth/openai.py +400 -0
  66. vtx_coding_agent-0.1.1/src/vtx/llm/phase_parser.py +270 -0
  67. vtx_coding_agent-0.1.1/src/vtx/llm/provider.yaml +280 -0
  68. vtx_coding_agent-0.1.1/src/vtx/llm/provider_catalog.py +230 -0
  69. vtx_coding_agent-0.1.1/src/vtx/llm/providers/__init__.py +45 -0
  70. vtx_coding_agent-0.1.1/src/vtx/llm/providers/anthropic_sdk.py +256 -0
  71. vtx_coding_agent-0.1.1/src/vtx/llm/providers/mock.py +249 -0
  72. vtx_coding_agent-0.1.1/src/vtx/llm/providers/openai_sdk.py +246 -0
  73. vtx_coding_agent-0.1.1/src/vtx/llm/providers/sanitize.py +14 -0
  74. vtx_coding_agent-0.1.1/src/vtx/llm/sdk/__init__.py +13 -0
  75. vtx_coding_agent-0.1.1/src/vtx/llm/sdk/anthropic.py +382 -0
  76. vtx_coding_agent-0.1.1/src/vtx/llm/sdk/base.py +82 -0
  77. vtx_coding_agent-0.1.1/src/vtx/llm/sdk/openai.py +344 -0
  78. vtx_coding_agent-0.1.1/src/vtx/llm/tool_parser.py +161 -0
  79. vtx_coding_agent-0.1.1/src/vtx/loop.py +272 -0
  80. vtx_coding_agent-0.1.1/src/vtx/notify.py +109 -0
  81. vtx_coding_agent-0.1.1/src/vtx/permissions.py +114 -0
  82. vtx_coding_agent-0.1.1/src/vtx/prompts/__init__.py +45 -0
  83. vtx_coding_agent-0.1.1/src/vtx/prompts/builder.py +86 -0
  84. vtx_coding_agent-0.1.1/src/vtx/prompts/env.py +58 -0
  85. vtx_coding_agent-0.1.1/src/vtx/prompts/identity.py +166 -0
  86. vtx_coding_agent-0.1.1/src/vtx/prompts/tooling.py +36 -0
  87. vtx_coding_agent-0.1.1/src/vtx/py.typed +0 -0
  88. vtx_coding_agent-0.1.1/src/vtx/runtime.py +580 -0
  89. vtx_coding_agent-0.1.1/src/vtx/session.py +868 -0
  90. vtx_coding_agent-0.1.1/src/vtx/sounds/completion.wav +0 -0
  91. vtx_coding_agent-0.1.1/src/vtx/sounds/error.wav +0 -0
  92. vtx_coding_agent-0.1.1/src/vtx/sounds/permission.wav +0 -0
  93. vtx_coding_agent-0.1.1/src/vtx/themes.py +1104 -0
  94. vtx_coding_agent-0.1.1/src/vtx/tools/__init__.py +68 -0
  95. vtx_coding_agent-0.1.1/src/vtx/tools/_read_image.py +106 -0
  96. vtx_coding_agent-0.1.1/src/vtx/tools/_tool_utils.py +90 -0
  97. vtx_coding_agent-0.1.1/src/vtx/tools/base.py +36 -0
  98. vtx_coding_agent-0.1.1/src/vtx/tools/bash.py +371 -0
  99. vtx_coding_agent-0.1.1/src/vtx/tools/edit.py +261 -0
  100. vtx_coding_agent-0.1.1/src/vtx/tools/find.py +132 -0
  101. vtx_coding_agent-0.1.1/src/vtx/tools/read.py +238 -0
  102. vtx_coding_agent-0.1.1/src/vtx/tools/skill.py +278 -0
  103. vtx_coding_agent-0.1.1/src/vtx/tools/web.py +238 -0
  104. vtx_coding_agent-0.1.1/src/vtx/tools/write.py +88 -0
  105. vtx_coding_agent-0.1.1/src/vtx/tools_manager.py +216 -0
  106. vtx_coding_agent-0.1.1/src/vtx/turn.py +789 -0
  107. vtx_coding_agent-0.1.1/src/vtx/ui/__init__.py +0 -0
  108. vtx_coding_agent-0.1.1/src/vtx/ui/agent_runner.py +417 -0
  109. vtx_coding_agent-0.1.1/src/vtx/ui/app.py +665 -0
  110. vtx_coding_agent-0.1.1/src/vtx/ui/app_protocol.py +29 -0
  111. vtx_coding_agent-0.1.1/src/vtx/ui/autocomplete.py +440 -0
  112. vtx_coding_agent-0.1.1/src/vtx/ui/blocks.py +735 -0
  113. vtx_coding_agent-0.1.1/src/vtx/ui/chat.py +613 -0
  114. vtx_coding_agent-0.1.1/src/vtx/ui/clipboard.py +59 -0
  115. vtx_coding_agent-0.1.1/src/vtx/ui/commands/__init__.py +100 -0
  116. vtx_coding_agent-0.1.1/src/vtx/ui/commands/auth.py +306 -0
  117. vtx_coding_agent-0.1.1/src/vtx/ui/commands/base.py +122 -0
  118. vtx_coding_agent-0.1.1/src/vtx/ui/commands/models.py +144 -0
  119. vtx_coding_agent-0.1.1/src/vtx/ui/commands/sessions.py +388 -0
  120. vtx_coding_agent-0.1.1/src/vtx/ui/commands/settings.py +286 -0
  121. vtx_coding_agent-0.1.1/src/vtx/ui/completion_ui.py +313 -0
  122. vtx_coding_agent-0.1.1/src/vtx/ui/export.py +703 -0
  123. vtx_coding_agent-0.1.1/src/vtx/ui/floating_list.py +370 -0
  124. vtx_coding_agent-0.1.1/src/vtx/ui/formatting.py +287 -0
  125. vtx_coding_agent-0.1.1/src/vtx/ui/input.py +760 -0
  126. vtx_coding_agent-0.1.1/src/vtx/ui/latex.py +349 -0
  127. vtx_coding_agent-0.1.1/src/vtx/ui/launch.py +108 -0
  128. vtx_coding_agent-0.1.1/src/vtx/ui/path_complete.py +228 -0
  129. vtx_coding_agent-0.1.1/src/vtx/ui/prompt_history.py +102 -0
  130. vtx_coding_agent-0.1.1/src/vtx/ui/queue_ui.py +141 -0
  131. vtx_coding_agent-0.1.1/src/vtx/ui/selection_mode.py +18 -0
  132. vtx_coding_agent-0.1.1/src/vtx/ui/session_ui.py +235 -0
  133. vtx_coding_agent-0.1.1/src/vtx/ui/startup.py +124 -0
  134. vtx_coding_agent-0.1.1/src/vtx/ui/styles.py +327 -0
  135. vtx_coding_agent-0.1.1/src/vtx/ui/tool_output.py +34 -0
  136. vtx_coding_agent-0.1.1/src/vtx/ui/tree.py +437 -0
  137. vtx_coding_agent-0.1.1/src/vtx/ui/welcome.py +51 -0
  138. vtx_coding_agent-0.1.1/src/vtx/ui/widgets.py +558 -0
  139. vtx_coding_agent-0.1.1/src/vtx/update_check.py +49 -0
  140. vtx_coding_agent-0.1.1/src/vtx/version.py +22 -0
  141. vtx_coding_agent-0.1.1/tests/conftest.py +61 -0
  142. vtx_coding_agent-0.1.1/tests/context/test_agents.py +301 -0
  143. vtx_coding_agent-0.1.1/tests/context/test_skills.py +683 -0
  144. vtx_coding_agent-0.1.1/tests/llm/__init__.py +0 -0
  145. vtx_coding_agent-0.1.1/tests/llm/test_anthropic_provider.py +105 -0
  146. vtx_coding_agent-0.1.1/tests/llm/test_mock_provider.py +142 -0
  147. vtx_coding_agent-0.1.1/tests/llm/test_openai_oauth.py +86 -0
  148. vtx_coding_agent-0.1.1/tests/llm/test_tls_verify.py +44 -0
  149. vtx_coding_agent-0.1.1/tests/test_agentic_loop.py +780 -0
  150. vtx_coding_agent-0.1.1/tests/test_cli.py +35 -0
  151. vtx_coding_agent-0.1.1/tests/test_cli_auth_flags.py +27 -0
  152. vtx_coding_agent-0.1.1/tests/test_cli_provider_resolution.py +22 -0
  153. vtx_coding_agent-0.1.1/tests/test_compaction.py +485 -0
  154. vtx_coding_agent-0.1.1/tests/test_config_binaries.py +34 -0
  155. vtx_coding_agent-0.1.1/tests/test_config_error_fallback.py +29 -0
  156. vtx_coding_agent-0.1.1/tests/test_config_injection.py +92 -0
  157. vtx_coding_agent-0.1.1/tests/test_config_migration.py +232 -0
  158. vtx_coding_agent-0.1.1/tests/test_dynamic_auth.py +91 -0
  159. vtx_coding_agent-0.1.1/tests/test_dynamic_models.py +472 -0
  160. vtx_coding_agent-0.1.1/tests/test_errors.py +17 -0
  161. vtx_coding_agent-0.1.1/tests/test_git_branch.py +84 -0
  162. vtx_coding_agent-0.1.1/tests/test_handoff.py +303 -0
  163. vtx_coding_agent-0.1.1/tests/test_handoff_link_interrupt.py +79 -0
  164. vtx_coding_agent-0.1.1/tests/test_headless.py +194 -0
  165. vtx_coding_agent-0.1.1/tests/test_launch_warnings.py +64 -0
  166. vtx_coding_agent-0.1.1/tests/test_llm_lazy_imports.py +50 -0
  167. vtx_coding_agent-0.1.1/tests/test_local_auth_config.py +64 -0
  168. vtx_coding_agent-0.1.1/tests/test_model_provider_resolution.py +33 -0
  169. vtx_coding_agent-0.1.1/tests/test_notifications_config.py +64 -0
  170. vtx_coding_agent-0.1.1/tests/test_notify.py +152 -0
  171. vtx_coding_agent-0.1.1/tests/test_openai_compat.py +84 -0
  172. vtx_coding_agent-0.1.1/tests/test_permissions.py +90 -0
  173. vtx_coding_agent-0.1.1/tests/test_phase_parser.py +482 -0
  174. vtx_coding_agent-0.1.1/tests/test_prompts.py +185 -0
  175. vtx_coding_agent-0.1.1/tests/test_runtime_switch_model.py +165 -0
  176. vtx_coding_agent-0.1.1/tests/test_session_persistence.py +689 -0
  177. vtx_coding_agent-0.1.1/tests/test_session_queries.py +61 -0
  178. vtx_coding_agent-0.1.1/tests/test_session_resume.py +155 -0
  179. vtx_coding_agent-0.1.1/tests/test_session_tree.py +43 -0
  180. vtx_coding_agent-0.1.1/tests/test_system_prompt.py +57 -0
  181. vtx_coding_agent-0.1.1/tests/test_system_prompt_git_context.py +31 -0
  182. vtx_coding_agent-0.1.1/tests/test_themes.py +38 -0
  183. vtx_coding_agent-0.1.1/tests/test_tool_parser.py +68 -0
  184. vtx_coding_agent-0.1.1/tests/test_tools_manager.py +43 -0
  185. vtx_coding_agent-0.1.1/tests/test_ui_notifications.py +43 -0
  186. vtx_coding_agent-0.1.1/tests/test_update_check.py +39 -0
  187. vtx_coding_agent-0.1.1/tests/test_update_notice_behavior.py +45 -0
  188. vtx_coding_agent-0.1.1/tests/tools/test_bash_shell.py +92 -0
  189. vtx_coding_agent-0.1.1/tests/tools/test_bash_truncation.py +87 -0
  190. vtx_coding_agent-0.1.1/tests/tools/test_diff.py +147 -0
  191. vtx_coding_agent-0.1.1/tests/tools/test_edit.py +76 -0
  192. vtx_coding_agent-0.1.1/tests/tools/test_edit_display.py +45 -0
  193. vtx_coding_agent-0.1.1/tests/tools/test_read.py +183 -0
  194. vtx_coding_agent-0.1.1/tests/tools/test_read_image.py +46 -0
  195. vtx_coding_agent-0.1.1/tests/tools/test_read_image_integration.py +44 -0
  196. vtx_coding_agent-0.1.1/tests/tools/test_read_image_resize.py +39 -0
  197. vtx_coding_agent-0.1.1/tests/tools/test_skill.py +98 -0
  198. vtx_coding_agent-0.1.1/tests/tools/test_subprocess_cancellation.py +88 -0
  199. vtx_coding_agent-0.1.1/tests/tools/test_write.py +31 -0
  200. vtx_coding_agent-0.1.1/tests/ui/test_app_approval_keys.py +95 -0
  201. vtx_coding_agent-0.1.1/tests/ui/test_autocomplete.py +347 -0
  202. vtx_coding_agent-0.1.1/tests/ui/test_completion_chrome.py +502 -0
  203. vtx_coding_agent-0.1.1/tests/ui/test_export.py +101 -0
  204. vtx_coding_agent-0.1.1/tests/ui/test_floating_list.py +52 -0
  205. vtx_coding_agent-0.1.1/tests/ui/test_info_bar_clicks.py +35 -0
  206. vtx_coding_agent-0.1.1/tests/ui/test_info_bar_permissions.py +62 -0
  207. vtx_coding_agent-0.1.1/tests/ui/test_input_approval_submit.py +49 -0
  208. vtx_coding_agent-0.1.1/tests/ui/test_input_cursor_theme.py +19 -0
  209. vtx_coding_agent-0.1.1/tests/ui/test_input_handoff.py +53 -0
  210. vtx_coding_agent-0.1.1/tests/ui/test_input_paste.py +118 -0
  211. vtx_coding_agent-0.1.1/tests/ui/test_input_shell_style.py +77 -0
  212. vtx_coding_agent-0.1.1/tests/ui/test_keybindings.py +19 -0
  213. vtx_coding_agent-0.1.1/tests/ui/test_latex.py +60 -0
  214. vtx_coding_agent-0.1.1/tests/ui/test_login_command.py +253 -0
  215. vtx_coding_agent-0.1.1/tests/ui/test_permission_selection_status.py +54 -0
  216. vtx_coding_agent-0.1.1/tests/ui/test_permissions_command.py +147 -0
  217. vtx_coding_agent-0.1.1/tests/ui/test_prompt_history.py +98 -0
  218. vtx_coding_agent-0.1.1/tests/ui/test_queue_editing.py +154 -0
  219. vtx_coding_agent-0.1.1/tests/ui/test_shell_command_detection.py +251 -0
  220. vtx_coding_agent-0.1.1/tests/ui/test_status_line.py +46 -0
  221. vtx_coding_agent-0.1.1/tests/ui/test_streaming_blocks.py +203 -0
  222. vtx_coding_agent-0.1.1/tests/ui/test_styles.py +25 -0
  223. vtx_coding_agent-0.1.1/tests/ui/test_thinking_notifications_commands.py +202 -0
  224. vtx_coding_agent-0.1.1/tests/ui/test_tool_output_expansion.py +125 -0
  225. vtx_coding_agent-0.1.1/uv.lock +1857 -0
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: vtx-release-publish
3
+ description: Tag, publish to PyPI, and create GitHub release for Vtx with validation and rollback-safe steps
4
+ ---
5
+
6
+ # Vtx Release + PyPI Publish
7
+
8
+ Use this skill when the user asks to cut a new Vtx version, tag it, publish to PyPI, and/or create a GitHub release.
9
+
10
+ ## Inputs to confirm
11
+
12
+ - Target version (example: `0.2.1`)
13
+ - Base range for notes (usually previous tag, example: `v0.2.0..HEAD`)
14
+ - Whether to push `main`
15
+ - Whether to publish to PyPI now
16
+ - Whether to create GitHub release now
17
+
18
+ ## Versioning requirement
19
+
20
+ - Vtx's update check only supports strict numeric `MAJOR.MINOR.PATCH` versions such as `0.2.7` and `0.3.0`.
21
+ - Do **not** cut releases with PyPI/PEP 440 prerelease or suffix forms like `0.3.0rc1`, `0.3.0b1`, `0.3.0.post1`, or `0.3.0.dev1` unless the update-check logic is updated first.
22
+ - Even though PyPI commonly allows those formats, Vtx releases should continue following plain `X.Y.Z` so update detection stays correct.
23
+
24
+ ## Files to bump
25
+
26
+ - `pyproject.toml` → `[project].version`
27
+ - `src/vtx/version.py` → fallback `VERSION = "..."`
28
+ - `uv.lock` → local package version block
29
+
30
+ ## Release workflow
31
+
32
+ 1. **Preflight**
33
+ - `git status --short --branch` must be clean (or confirm with user)
34
+ - `git tag --list` and `git log --oneline <prev_tag>..HEAD` to summarize changes
35
+
36
+ 2. **Update CHANGELOG.md**
37
+ - Replace the `## [Unreleased]` section's `- No changes yet.` with a new versioned heading: `## <version> - YYYY-MM-DD`
38
+ - Use `git log --oneline <prev_tag>..HEAD` to categorize changes into `### Added`, `### Changed`, `### Fixed` sections
39
+ - Credit external contributors with `- @username`
40
+ - Commit message: `docs: update changelog for <version>`
41
+
42
+ 3. **Version bump**
43
+ - Update version in all 3 files above
44
+
45
+ 4. **Quality gates**
46
+ - `uv run ruff format .`
47
+ - `uv run ruff check .`
48
+ - `uvx ty check .`
49
+ - `uv run python -m pytest`
50
+
51
+ 5. **Commit**
52
+ - Commit message: `build: bump version to <version>`
53
+
54
+ 6. **Tag**
55
+ - Annotated tag: `git tag -a v<version> -m "v<version> ..."`
56
+ - Include concise "changes since previous tag" bullets
57
+
58
+ 7. **Push**
59
+ - `git push vtx main`
60
+ - `git push vtx v<version>`
61
+
62
+ 8. **Build + verify artifacts**
63
+ - `rm -rf dist && uv build`
64
+ - `uv run python -m twine check dist/*`
65
+
66
+ 9. **Publish to PyPI**
67
+ - Prefer token file if present (example `~/.pypi-token`):
68
+ - `TWINE_USERNAME=__token__ TWINE_PASSWORD="$(< ~/.pypi-token)" uv run python -m twine upload dist/*`
69
+ - Verify:
70
+ - `https://pypi.org/project/vtx-coding-agent/<version>/`
71
+ - `https://pypi.org/pypi/vtx-coding-agent/json` reports latest version
72
+
73
+ 10. **Create GitHub release**
74
+ - If token exists at `~/.github-token`, call Releases API:
75
+ - `POST /repos/<owner>/<repo>/releases` with:
76
+ - `tag_name: v<version>`
77
+ - `target_commitish: main`
78
+ - `name: v<version>`
79
+ - `generate_release_notes: true`
80
+ - If 403 occurs, report missing token scopes/permissions (`contents:write` required)
81
+
82
+ ## Important notes
83
+
84
+ - **Tagging and GitHub release are separate**:
85
+ - Tag = git ref in repository
86
+ - Release = GitHub object attached to a tag (notes/assets)
87
+ - You can do either independently, but most projects do both together for user-facing releases.
88
+ - If PyPI publish succeeds but GitHub release fails, do **not** retag/re-publish. Just fix auth and create the release for the existing tag.
89
+
90
+ ## Output checklist to report
91
+
92
+ - Changelog updated for `<version>`
93
+ - Version bumped in all files
94
+ - Checks passed
95
+ - Commit hash
96
+ - Tag created and pushed
97
+ - PyPI upload URL
98
+ - GitHub release URL (or exact error + remediation)
@@ -0,0 +1,250 @@
1
+ ---
2
+ name: vtx-tmux-test
3
+ description: "E2E testing of vtx using tmux sessions; IMPORTANT: only trigger this skill when user asks for e2e testing of vtx"
4
+ ---
5
+
6
+ # Vtx Tmux E2E Testing
7
+
8
+ End-to-end testing of vtx using tmux sessions to programmatically control the TUI application.
9
+
10
+ ## Why Tmux?
11
+
12
+ Vtx is a TUI (Textual-based) app. Running tests programmatically is hard. Tmux provides:
13
+
14
+ - `tmux new-session` - isolate test environment
15
+ - `tmux send-keys` - send keyboard input
16
+ - `tmux capture-pane` - capture output
17
+ - `tmux has-session` - check if vtx is running
18
+
19
+ ## Test Design Philosophy
20
+
21
+ - **Deterministic**: Shell scripts create reproducible test environments
22
+ - **Isolated config**: Tests run with `HOME=/tmp/vtx-e2e-home` so runtime settings do not mutate the real user config; auth JSON files are copied into the temp HOME when present so provider startup still works
23
+ - **Separation of concerns**: Shell script runs steps and captures output; vtx/the reviewer evaluates results
24
+ - **Output-based evaluation**: Test success/failure determined by reading output files, not shell script heuristics
25
+ - **UI-focused**: Test triggers (`@`, `/`, runtime pickers, keybindings) by checking UI elements appear
26
+ - **Filesystem verification**: Tool execution is verified through files under `/tmp/vtx-test-project`
27
+
28
+ ## Quick Start
29
+
30
+ ```bash
31
+ # Run all e2e tests from the repo root
32
+ bash .agents/skills/vtx-tmux-test/run-e2e-tests.sh
33
+
34
+ # Optional: keep the temporary HOME for debugging
35
+ KEEP_E2E_HOME=1 bash .agents/skills/vtx-tmux-test/run-e2e-tests.sh
36
+
37
+ # Optional: override launch command/provider/model
38
+ VTX_CMD='uv run vtx --model gpt-5.5' \
39
+ bash .agents/skills/vtx-tmux-test/run-e2e-tests.sh
40
+ ```
41
+
42
+ After running, read `/tmp/vtx-test-*.txt` and evaluate the captured pane/config/filesystem outputs.
43
+
44
+ ## Test Scripts
45
+
46
+ ### Setup Script: `setup-test-project.sh`
47
+
48
+ Creates a deterministic test project structure at `/tmp/vtx-test-project/`.
49
+
50
+ ```bash
51
+ bash .agents/skills/vtx-tmux-test/setup-test-project.sh
52
+ ```
53
+
54
+ ### Main Test Script: `run-e2e-tests.sh`
55
+
56
+ Runs comprehensive e2e tests including UI triggers, runtime controls, tab completion, and tool execution.
57
+
58
+ ```bash
59
+ bash .agents/skills/vtx-tmux-test/run-e2e-tests.sh
60
+ ```
61
+
62
+ ## Test Categories
63
+
64
+ ### UI Trigger Tests (LLM-independent)
65
+
66
+ - **/ commands**: Type `/`, verify slash command list appears with core and newer commands
67
+ - **@ file search**: Type `@pyproject`, verify file picker appears with `pyproject.toml`
68
+ - **/model command**: Type `/model`, verify model selector appears, then dismiss
69
+ - **/new command**: Type `/new`, verify new conversation is started
70
+ - **/resume command**: Type `/resume`, verify session list appears, then dismiss
71
+ - **/session command**: Type `/session`, verify session info/statistics displayed
72
+
73
+ ### Runtime Mode Tests (LLM-independent)
74
+
75
+ - **/permissions picker**: Shows `prompt` and `auto`, with current mode checked
76
+ - **/permissions auto/prompt**: Info bar updates (`✓✓ auto` / `⏸ prompt`) and temp config persists `permissions.mode`
77
+ - **Shift+Tab**: Cycles permission mode and persists it in temp config
78
+ - **/thinking picker**: Shows `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, with current level checked
79
+ - **/thinking minimal**: Info bar model/thinking area updates to `minimal`
80
+ - **Ctrl+Shift+T**: Cycles thinking level in the info bar
81
+ - **/notifications picker**: Shows `on` and `off`, with current mode checked
82
+ - **/notifications on/off**: Status says saved and temp config persists `notifications.enabled`
83
+ - **Info bar row2 regression**: Permission mode remains row2-left while model/provider/thinking remains row2-right after runtime changes
84
+
85
+ ### Tab Path Completion Tests (LLM-independent)
86
+
87
+ - **Unique match**: Type `pypr` + Tab, verify completes to `pyproject.toml`
88
+ - **Multiple alternatives**: Type `src/vtx/ui/s` + Tab, verify floating list shows `selection_mode.py`, `session_ui.py`, `styles.py`
89
+ - **Nested unique file**: Type `src/vtx/ui/widg` + Tab, verify completes to `src/vtx/ui/widgets.py`
90
+ - **Select from list**: Type `src/vtx/ui/s` + Tab + Enter, verify first completion is applied to input
91
+
92
+ ### Tool Execution Tests (Filesystem verification)
93
+
94
+ - **Write tool**: Creates `/tmp/vtx-test-project/test1.txt`, verified by file existence
95
+ - **Edit tool**: Modifies `test1.txt`, verified by content changing from `hello` to `world`
96
+ - **List files**: Shows directory contents in captured pane
97
+ - **Calculation**: Computes `3+3`, verified in LLM output where practical
98
+
99
+ ## Configuration
100
+
101
+ Edit or override environment variables for `run-e2e-tests.sh`:
102
+
103
+ ```bash
104
+ WAIT_TIME=30 # Time for LLM to complete all tool tasks
105
+ COMMAND_WAIT_TIME=3 # Time for UI commands to settle
106
+ SESSION_NAME="vtx-test" # Tmux session name
107
+ TEST_DIR="/tmp/vtx-test-project" # Test project directory for tool execution
108
+ TEST_HOME="/tmp/vtx-e2e-home" # Isolated HOME/config/session directory
109
+ VTX_DIR="$PWD" # Vtx repo directory for tab completion tests
110
+ VTX_CMD="uv run vtx --model gpt-5.5"
111
+ KEEP_E2E_HOME=0 # Set to 1 to preserve temp HOME after run
112
+ ```
113
+
114
+ ## Output Files
115
+
116
+ The main script writes captured outputs to `/tmp/vtx-test-*.txt`:
117
+
118
+ - `/tmp/vtx-test-1-commands.txt` - `/` slash command list
119
+ - `/tmp/vtx-test-2-at-trigger.txt` - `@pyproject` file picker
120
+ - `/tmp/vtx-test-3-model.txt` - `/model` selector
121
+ - `/tmp/vtx-test-4-new.txt` - `/new` result
122
+ - `/tmp/vtx-test-5-permissions-picker.txt` - `/permissions` picker
123
+ - `/tmp/vtx-test-6-permissions-auto.txt` and `...-config.txt` - `/permissions auto`
124
+ - `/tmp/vtx-test-7-permissions-prompt.txt` and `...-config.txt` - `/permissions prompt`
125
+ - `/tmp/vtx-test-8-permissions-shift-tab.txt` and `...-config.txt` - Shift+Tab mode cycling
126
+ - `/tmp/vtx-test-9-thinking-picker.txt` - `/thinking` picker
127
+ - `/tmp/vtx-test-10-thinking-minimal.txt` - `/thinking minimal`
128
+ - `/tmp/vtx-test-11-thinking-cycle.txt` - Ctrl+Shift+T thinking cycle
129
+ - `/tmp/vtx-test-12-notifications-picker.txt` - `/notifications` picker
130
+ - `/tmp/vtx-test-13-notifications-on.txt` and `...-config.txt` - `/notifications on`
131
+ - `/tmp/vtx-test-14-notifications-off.txt` and `...-config.txt` - `/notifications off`
132
+ - `/tmp/vtx-test-15-tab-unique.txt` - Tab completion unique match
133
+ - `/tmp/vtx-test-16-tab-multiple.txt` - Tab completion alternatives
134
+ - `/tmp/vtx-test-17-tab-nested-unique.txt` - Nested unique file completion
135
+ - `/tmp/vtx-test-18-tab-select.txt` - Tab completion selection
136
+ - `/tmp/vtx-test-19-tools.txt` - Tool execution turn
137
+ - `/tmp/vtx-test-20-session.txt` - `/session` stats
138
+ - `/tmp/vtx-test-21-resume.txt` - `/resume` session list
139
+ - `/tmp/vtx-test-files.txt` - Test project file listing
140
+ - `/tmp/vtx-test-test1-content.txt` - Final `test1.txt` content or `FILE_NOT_FOUND`
141
+ - `/tmp/vtx-test-session-files.txt` - Session JSONL paths under temp HOME
142
+ - `/tmp/vtx-test-final-config.txt` - Final temp config
143
+
144
+ ## Key Tmux Gotchas
145
+
146
+ - **Use `Escape` not `Esc`**: tmux recognizes `Escape`. `Esc` sends literal characters.
147
+ - **Always clear input between tests**: Use `Escape` to dismiss completions, then `C-u` to clear text.
148
+ - **Completion selectors block input**: Selectors intercept Enter/Escape; dismiss them before the next test.
149
+ - **Shift+Tab**: The script sends CSI Z via `Escape '[' 'Z'` rather than relying on a tmux key name.
150
+ - **Ctrl+Shift+T**: The script sends CSI-u `Escape '[84;6u'` because `C-S-t` often collapses to Ctrl+T.
151
+
152
+ ## Test Evaluation (by Vtx/reviewer)
153
+
154
+ After running the test script, evaluate results by reading the output files.
155
+
156
+ ### What to Check
157
+
158
+ **UI Trigger Tests:**
159
+
160
+ - `/` test: Slash command list includes `github`, `themes`, `permissions`, `thinking`, `notifications`, `init`, `compact`, `handoff`, `export`, `copy`, `login`, `logout`
161
+ - `@` test: File picker appears and shows `pyproject.toml`
162
+ - `/model` test: Model selector appears with model list/current markers
163
+ - `/new` test: `Started new conversation` appears
164
+ - `/resume` test: Session list appears with prior sessions
165
+ - `/session` test: Session info/statistics displayed
166
+
167
+ **Runtime Mode Tests:**
168
+
169
+ - `/permissions` picker shows `prompt` and `auto`, current item checked
170
+ - `/permissions auto` shows `✓✓ auto`, saved status, and config has `mode = "auto"`
171
+ - `/permissions prompt` shows `⏸ prompt`, saved status, and config has `mode = "prompt"`
172
+ - Shift+Tab toggles back to `auto` and config has `mode = "auto"`
173
+ - `/thinking` picker shows `none`, `minimal`, `low`, `medium`, `high`, `xhigh`
174
+ - `/thinking minimal` shows `Thinking level changed to minimal` and info bar row2-right includes `minimal`
175
+ - Ctrl+Shift+T changes info bar thinking level from `minimal` to the next level
176
+ - `/notifications` picker shows `on` and `off`, current item checked
177
+ - `/notifications on/off` status says saved and config flips `enabled = true/false`
178
+ - Permission mode remains in row2-left and model/provider/thinking remains row2-right
179
+
180
+ **Tab Path Completion Tests:**
181
+
182
+ - `pypr` + Tab shows `pyproject.toml`
183
+ - `src/vtx/ui/s` + Tab shows `selection_mode.py`, `session_ui.py`, `styles.py`
184
+ - `src/vtx/ui/widg` + Tab shows `src/vtx/ui/widgets.py`
185
+ - `src/vtx/ui/s` + Tab + Enter applies a selected completion
186
+
187
+ **Tool Execution Tests:**
188
+
189
+ - `/tmp/vtx-test-project/test1.txt` exists
190
+ - `/tmp/vtx-test-test1-content.txt` contains `world`
191
+ - `/tmp/vtx-test-files.txt` lists `test1.txt`
192
+ - `/tmp/vtx-test-19-tools.txt` shows relevant tool blocks/results
193
+
194
+ ### Tabular Report
195
+
196
+ Provide a summary showing:
197
+
198
+ - Test name
199
+ - Status (PASS/FAIL)
200
+ - Description/failure reason
201
+ - Overall success rate
202
+
203
+ ### IMPORTANT: Always offer the view command
204
+
205
+ After presenting the report, ALWAYS give the user this shell command so they can inspect raw captured outputs:
206
+
207
+ ```bash
208
+ for f in /tmp/vtx-test-*.txt; do printf "\n\033[1;36m▶▶▶ %s\033[0m\n" "$f"; awk 'NF{found=1} found{lines[++n]=$0} END{while(n>0 && lines[n]=="") n--; for(i=1;i<=n;i++) print lines[i]}' "$f"; done
209
+ ```
210
+
211
+ ## Cleanup
212
+
213
+ ```bash
214
+ # Test script auto-cleans tmux session and temp HOME unless KEEP_E2E_HOME=1.
215
+ # Output files remain for evaluation (/tmp/vtx-test-*.txt).
216
+ # Manual cleanup if needed:
217
+ tmux kill-session -t vtx-test 2>/dev/null
218
+ rm -rf /tmp/vtx-test-project /tmp/vtx-e2e-home
219
+ rm -f /tmp/vtx-test-*.txt
220
+ ```
221
+
222
+ ## Tmux Commands Reference
223
+
224
+ ```bash
225
+ # Session management
226
+ tmux new-session -d -s <name> -c <dir> '<command>'
227
+ tmux kill-session -t <name>
228
+ tmux has-session -t <name>
229
+
230
+ # Input — IMPORTANT: use full key names (Escape, Enter, not Esc)
231
+ tmux send-keys -t <name> "text"
232
+ tmux send-keys -t <name> Enter
233
+ tmux send-keys -t <name> Escape
234
+ tmux send-keys -t <name> Tab
235
+ tmux send-keys -t <name> C-c
236
+ tmux send-keys -t <name> C-u
237
+
238
+ # Output
239
+ tmux capture-pane -t <name> -p
240
+ tmux capture-pane -t <name> -p > file.txt
241
+ ```
242
+
243
+ ## Tips
244
+
245
+ - Tests are deterministic: project/config structure is recreated each run.
246
+ - Runtime mode tests are LLM-independent and should be checked first.
247
+ - Tab completion tests run from the vtx repo to use known paths.
248
+ - Tool tests verify filesystem state; avoid relying solely on LLM prose.
249
+ - Use `KEEP_E2E_HOME=1` to inspect temp config/session files after failures.
250
+ - Run tool execution before `/resume` so there is a session with messages in the list.
@@ -0,0 +1,312 @@
1
+ #!/bin/bash
2
+
3
+ # Comprehensive e2e test script for vtx
4
+ # Tests UI triggers (@, / commands, runtime mode controls, Tab completion) and tool execution.
5
+ # This script runs steps and captures output — evaluation is done by vtx reading the output files.
6
+
7
+ set -u
8
+
9
+ # Configuration
10
+ WAIT_TIME=${WAIT_TIME:-30} # Time for LLM to complete tool tasks
11
+ COMMAND_WAIT_TIME=${COMMAND_WAIT_TIME:-3} # Time for UI commands to settle
12
+ SESSION_NAME=${SESSION_NAME:-"vtx-test"}
13
+ TEST_DIR=${TEST_DIR:-"/tmp/vtx-test-project"}
14
+ TEST_HOME=${TEST_HOME:-"/tmp/vtx-e2e-home"}
15
+ VTX_DIR=${VTX_DIR:-"$PWD"} # use caller's current working directory
16
+ VTX_CMD=${VTX_CMD:-"uv run vtx --model gpt-5.5"}
17
+ KEEP_E2E_HOME=${KEEP_E2E_HOME:-0}
18
+
19
+ # Helper functions
20
+ cleanup() {
21
+ tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
22
+ if [ "$KEEP_E2E_HOME" != "1" ]; then
23
+ rm -rf "$TEST_HOME"
24
+ fi
25
+ }
26
+
27
+ capture() {
28
+ tmux capture-pane -t "$SESSION_NAME" -p > "$1"
29
+ }
30
+
31
+ capture_config() {
32
+ if [ -f "$TEST_HOME/.vtx/config.yml" ]; then
33
+ cp "$TEST_HOME/.vtx/config.yml" "$1"
34
+ else
35
+ echo "CONFIG_NOT_FOUND" > "$1"
36
+ fi
37
+ }
38
+
39
+ # Dismiss any open completion/selector and clear the input line.
40
+ # Uses Escape (NOT "Esc" which tmux would send as literal text).
41
+ clear_input() {
42
+ tmux send-keys -t "$SESSION_NAME" Escape
43
+ sleep 0.5
44
+ tmux send-keys -t "$SESSION_NAME" Escape
45
+ sleep 0.5
46
+ tmux send-keys -t "$SESSION_NAME" C-u
47
+ sleep 0.5
48
+ }
49
+
50
+ run_command() {
51
+ local command="$1"
52
+ tmux send-keys -t "$SESSION_NAME" "$command"
53
+ sleep 1
54
+ tmux send-keys -t "$SESSION_NAME" Enter
55
+ sleep "$COMMAND_WAIT_TIME"
56
+ }
57
+
58
+ send_shift_tab() {
59
+ # tmux doesn't reliably expose a portable S-Tab key name, so send the terminal
60
+ # escape sequence directly: CSI Z.
61
+ tmux send-keys -t "$SESSION_NAME" Escape '[' 'Z'
62
+ }
63
+
64
+ send_ctrl_shift_t() {
65
+ # CSI-u encoding for Ctrl+Shift+T. This is more reliable in tmux than C-S-t,
66
+ # which collapses to Ctrl+T in many terminals.
67
+ tmux send-keys -t "$SESSION_NAME" Escape '[84;6u'
68
+ }
69
+
70
+ # Cleanup on exit
71
+ trap cleanup EXIT
72
+
73
+ # === Setup ===
74
+ echo "Setting up isolated e2e environment..."
75
+ cleanup
76
+ rm -rf "$TEST_DIR" "$TEST_HOME"
77
+ mkdir -p "$TEST_DIR" "$TEST_HOME/.vtx"
78
+ if [ -f "$HOME/.vtx/openai_auth.json" ]; then
79
+ cp "$HOME/.vtx/openai_auth.json" "$TEST_HOME/.vtx/openai_auth.json"
80
+ fi
81
+ if [ -f "$HOME/.vtx/copilot_auth.json" ]; then
82
+ cp "$HOME/.vtx/copilot_auth.json" "$TEST_HOME/.vtx/copilot_auth.json"
83
+ fi
84
+ cd "$TEST_DIR" || exit 1
85
+ printf '# Test Project\n' > README.md
86
+ printf '{"name": "test"}\n' > config.json
87
+
88
+ # Let vtx create its default config in the temp HOME. Runtime tests mutate only
89
+ # this isolated file, never the real user config.
90
+
91
+ # Clean up old test output files
92
+ rm -f /tmp/vtx-test-*.txt
93
+
94
+ # === Start vtx (from vtx repo for tab completion tests) ===
95
+ echo "Starting vtx in tmux from vtx repo with HOME=$TEST_HOME..."
96
+ tmux new-session -d -s "$SESSION_NAME" -c "$VTX_DIR" "HOME=$TEST_HOME OPENAI_API_KEY=\"${OPENAI_API_KEY:-}\" ZAI_API_KEY=\"${ZAI_API_KEY:-}\" ANTHROPIC_API_KEY=\"${ANTHROPIC_API_KEY:-}\" AZURE_AI_FOUNDRY_API_KEY=\"${AZURE_AI_FOUNDRY_API_KEY:-}\" AZURE_AI_FOUNDRY_BASE_URL=\"${AZURE_AI_FOUNDRY_BASE_URL:-}\" $VTX_CMD"
97
+ sleep 5 # Give vtx time to start and render UI
98
+
99
+ # =============================================================================
100
+ # Test 1: / slash commands trigger
101
+ # Verify: typing / shows the slash command list, including newer runtime commands
102
+ # =============================================================================
103
+ echo "Test 1: / slash commands trigger..."
104
+ tmux send-keys -t "$SESSION_NAME" '/'
105
+ sleep 2
106
+ capture /tmp/vtx-test-1-commands.txt
107
+ clear_input
108
+
109
+ # =============================================================================
110
+ # Test 2: @ file search trigger
111
+ # Verify: typing @pyproject shows file picker with pyproject.toml (from vtx repo)
112
+ # =============================================================================
113
+ echo "Test 2: @ file search trigger..."
114
+ tmux send-keys -t "$SESSION_NAME" '@pyproject'
115
+ sleep 2
116
+ capture /tmp/vtx-test-2-at-trigger.txt
117
+ clear_input
118
+
119
+ # =============================================================================
120
+ # Test 3: /model command
121
+ # Verify: /model shows model selector list, then dismiss without selecting
122
+ # =============================================================================
123
+ echo "Test 3: /model command..."
124
+ tmux send-keys -t "$SESSION_NAME" '/model'
125
+ sleep 2
126
+ tmux send-keys -t "$SESSION_NAME" Enter
127
+ sleep "$COMMAND_WAIT_TIME"
128
+ capture /tmp/vtx-test-3-model.txt
129
+ clear_input
130
+
131
+ # =============================================================================
132
+ # Test 4: /new command
133
+ # Verify: /new starts a new conversation ("Started new conversation" message)
134
+ # =============================================================================
135
+ echo "Test 4: /new command..."
136
+ run_command '/new'
137
+ capture /tmp/vtx-test-4-new.txt
138
+
139
+ # =============================================================================
140
+ # P0 runtime mode controls and info bar
141
+ # =============================================================================
142
+ echo "Test 5: /permissions picker..."
143
+ tmux send-keys -t "$SESSION_NAME" '/permissions'
144
+ sleep 2
145
+ tmux send-keys -t "$SESSION_NAME" Enter
146
+ sleep "$COMMAND_WAIT_TIME"
147
+ capture /tmp/vtx-test-5-permissions-picker.txt
148
+ clear_input
149
+
150
+ echo "Test 6: /permissions auto..."
151
+ run_command '/permissions auto'
152
+ capture /tmp/vtx-test-6-permissions-auto.txt
153
+ capture_config /tmp/vtx-test-6-permissions-auto-config.txt
154
+
155
+ echo "Test 7: /permissions prompt..."
156
+ run_command '/permissions prompt'
157
+ capture /tmp/vtx-test-7-permissions-prompt.txt
158
+ capture_config /tmp/vtx-test-7-permissions-prompt-config.txt
159
+
160
+ echo "Test 8: Shift+Tab permission cycling..."
161
+ send_shift_tab
162
+ sleep "$COMMAND_WAIT_TIME"
163
+ capture /tmp/vtx-test-8-permissions-shift-tab.txt
164
+ capture_config /tmp/vtx-test-8-permissions-shift-tab-config.txt
165
+
166
+ echo "Test 9: /thinking picker..."
167
+ tmux send-keys -t "$SESSION_NAME" '/thinking'
168
+ sleep 2
169
+ tmux send-keys -t "$SESSION_NAME" Enter
170
+ sleep "$COMMAND_WAIT_TIME"
171
+ capture /tmp/vtx-test-9-thinking-picker.txt
172
+ clear_input
173
+
174
+ echo "Test 10: /thinking minimal..."
175
+ run_command '/thinking minimal'
176
+ capture /tmp/vtx-test-10-thinking-minimal.txt
177
+
178
+ echo "Test 11: Ctrl+Shift+T thinking cycling..."
179
+ send_ctrl_shift_t
180
+ sleep "$COMMAND_WAIT_TIME"
181
+ capture /tmp/vtx-test-11-thinking-cycle.txt
182
+
183
+ echo "Test 12: /notifications picker..."
184
+ tmux send-keys -t "$SESSION_NAME" '/notifications'
185
+ sleep 2
186
+ tmux send-keys -t "$SESSION_NAME" Enter
187
+ sleep "$COMMAND_WAIT_TIME"
188
+ capture /tmp/vtx-test-12-notifications-picker.txt
189
+ clear_input
190
+
191
+ echo "Test 13: /notifications on..."
192
+ run_command '/notifications on'
193
+ capture /tmp/vtx-test-13-notifications-on.txt
194
+ capture_config /tmp/vtx-test-13-notifications-on-config.txt
195
+
196
+ echo "Test 14: /notifications off..."
197
+ run_command '/notifications off'
198
+ capture /tmp/vtx-test-14-notifications-off.txt
199
+ capture_config /tmp/vtx-test-14-notifications-off-config.txt
200
+
201
+ # =============================================================================
202
+ # Test 15: Tab completion - unique match
203
+ # Verify: typing "pypr" then Tab completes to "pyproject.toml"
204
+ # =============================================================================
205
+ echo "Test 15: Tab completion - unique match..."
206
+ tmux send-keys -t "$SESSION_NAME" 'pypr'
207
+ sleep 1
208
+ tmux send-keys -t "$SESSION_NAME" Tab
209
+ sleep 2
210
+ capture /tmp/vtx-test-15-tab-unique.txt
211
+ clear_input
212
+
213
+ # =============================================================================
214
+ # Test 16: Tab completion - multiple alternatives (floating list)
215
+ # Verify: typing "src/vtx/ui/s" then Tab shows a list including:
216
+ # selection_mode.py, session_ui.py, styles.py
217
+ # =============================================================================
218
+ echo "Test 16: Tab completion - multiple alternatives..."
219
+ tmux send-keys -t "$SESSION_NAME" 'src/vtx/ui/s'
220
+ sleep 1
221
+ tmux send-keys -t "$SESSION_NAME" Tab
222
+ sleep 2
223
+ capture /tmp/vtx-test-16-tab-multiple.txt
224
+ clear_input
225
+
226
+ # =============================================================================
227
+ # Test 17: Tab completion - nested unique file
228
+ # Verify: typing "src/vtx/ui/widg" then Tab completes to "src/vtx/ui/widgets.py"
229
+ # =============================================================================
230
+ echo "Test 17: Tab completion - nested unique file..."
231
+ tmux send-keys -t "$SESSION_NAME" 'src/vtx/ui/widg'
232
+ sleep 1
233
+ tmux send-keys -t "$SESSION_NAME" Tab
234
+ sleep 2
235
+ capture /tmp/vtx-test-17-tab-nested-unique.txt
236
+ clear_input
237
+
238
+ # =============================================================================
239
+ # Test 18: Tab completion - select from list
240
+ # Verify: typing "src/vtx/ui/s" Tab shows list, then Enter applies first completion
241
+ # =============================================================================
242
+ echo "Test 18: Tab completion - select from list..."
243
+ tmux send-keys -t "$SESSION_NAME" 'src/vtx/ui/s'
244
+ sleep 1
245
+ tmux send-keys -t "$SESSION_NAME" Tab
246
+ sleep 2
247
+ tmux send-keys -t "$SESSION_NAME" Enter
248
+ sleep 1
249
+ capture /tmp/vtx-test-18-tab-select.txt
250
+ clear_input
251
+
252
+ # =============================================================================
253
+ # Test 19: Tool execution (multiple tool calls)
254
+ # Verify: creates test1.txt, edits it, lists files, calculates 3+3
255
+ # Running this BEFORE /resume so there's a session with messages to resume.
256
+ # Permission mode is auto from Shift+Tab above, so approval prompts should not block.
257
+ # =============================================================================
258
+ echo "Test 19: Tool execution..."
259
+ run_command '/new'
260
+ tmux send-keys -t "$SESSION_NAME" "Create $TEST_DIR/test1.txt containing \"hello\", then edit $TEST_DIR/test1.txt to change \"hello\" to \"world\", list files in $TEST_DIR, and calculate 3+3. Use parallel tool calls, be quick."
261
+ sleep 1
262
+ tmux send-keys -t "$SESSION_NAME" Enter
263
+ sleep "$WAIT_TIME"
264
+ capture /tmp/vtx-test-19-tools.txt
265
+
266
+ # =============================================================================
267
+ # Test 20: /session command
268
+ # Verify: shows session info (messages, tokens, file path)
269
+ # =============================================================================
270
+ echo "Test 20: /session command..."
271
+ run_command '/session'
272
+ capture /tmp/vtx-test-20-session.txt
273
+
274
+ # =============================================================================
275
+ # Test 21: /resume command
276
+ # Verify: shows list of sessions (at least one from tool execution above)
277
+ # =============================================================================
278
+ echo "Test 21: /resume command..."
279
+ tmux send-keys -t "$SESSION_NAME" '/resume'
280
+ sleep 2
281
+ tmux send-keys -t "$SESSION_NAME" Enter
282
+ sleep "$COMMAND_WAIT_TIME"
283
+ capture /tmp/vtx-test-21-resume.txt
284
+ clear_input
285
+
286
+ # =============================================================================
287
+ # Capture file system/session/config state for verification
288
+ # =============================================================================
289
+ echo "Capturing file system and persisted state..."
290
+ ls -la "$TEST_DIR" > /tmp/vtx-test-files.txt 2>/dev/null
291
+ find "$TEST_HOME/.vtx/sessions" -type f -name '*.jsonl' -print > /tmp/vtx-test-session-files.txt 2>/dev/null || true
292
+ capture_config /tmp/vtx-test-final-config.txt
293
+
294
+ # Retry a few times in case the LLM is still finishing file writes
295
+ for _ in 1 2 3; do
296
+ if [ -f "$TEST_DIR/test1.txt" ]; then
297
+ cat "$TEST_DIR/test1.txt" > /tmp/vtx-test-test1-content.txt
298
+ break
299
+ fi
300
+ sleep 3
301
+ done
302
+ # Final check
303
+ if [ ! -f "$TEST_DIR/test1.txt" ]; then
304
+ echo "FILE_NOT_FOUND" > /tmp/vtx-test-test1-content.txt
305
+ ls -la "$TEST_DIR" > /tmp/vtx-test-files.txt 2>/dev/null
306
+ fi
307
+
308
+ printf '\n%s\n' "${SEP:-==============================}"
309
+ echo "All tests complete"
310
+ echo "Output files saved to /tmp/vtx-test-*.txt"
311
+ echo "Temp HOME: $TEST_HOME (KEEP_E2E_HOME=1 to keep after run)"
312
+ printf '%s\n' "${SEP:-==============================}"
@@ -0,0 +1,27 @@
1
+ #!/bin/bash
2
+
3
+ # Setup script for vtx e2e testing
4
+ # Creates a deterministic test project structure at /tmp/vtx-test-project
5
+
6
+ TEST_DIR="/tmp/vtx-test-project"
7
+
8
+ # Cleanup and recreate test project
9
+ rm -rf $TEST_DIR
10
+ mkdir -p $TEST_DIR
11
+ cd $TEST_DIR
12
+
13
+ # Create deterministic test files
14
+ echo "# Test Project" > README.md
15
+ echo '{"name": "test", "version": "1.0.0"}' > config.json
16
+ echo "Todo:
17
+ - Read config.json
18
+ - Calculate sum" > notes.txt
19
+ echo 'def add(a, b): return a + b
20
+ def multiply(a, b): return a * b
21
+ result = multiply(5, 3)
22
+ print(f"5 * 3 = {result}")' > utils.py
23
+ echo 'DATA = ["item1", "item2", "item3"]
24
+ for item in DATA:
25
+ print(item)' > data.py
26
+
27
+ echo "✓ Test project created at $TEST_DIR"