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.
- vtx_coding_agent-0.1.1/.agents/skills/vtx-release-publish/SKILL.md +98 -0
- vtx_coding_agent-0.1.1/.agents/skills/vtx-tmux-test/SKILL.md +250 -0
- vtx_coding_agent-0.1.1/.agents/skills/vtx-tmux-test/run-e2e-tests.sh +312 -0
- vtx_coding_agent-0.1.1/.agents/skills/vtx-tmux-test/setup-test-project.sh +27 -0
- vtx_coding_agent-0.1.1/.gitignore +24 -0
- vtx_coding_agent-0.1.1/.pre-commit-config.yaml +7 -0
- vtx_coding_agent-0.1.1/.python-version +1 -0
- vtx_coding_agent-0.1.1/AGENTS.md +44 -0
- vtx_coding_agent-0.1.1/CHANGELOG.md +113 -0
- vtx_coding_agent-0.1.1/LICENSE +201 -0
- vtx_coding_agent-0.1.1/PKG-INFO +259 -0
- vtx_coding_agent-0.1.1/README.md +237 -0
- vtx_coding_agent-0.1.1/docs/README.md +36 -0
- vtx_coding_agent-0.1.1/docs/architecture.md +319 -0
- vtx_coding_agent-0.1.1/docs/configuration.md +353 -0
- vtx_coding_agent-0.1.1/docs/development.md +238 -0
- vtx_coding_agent-0.1.1/docs/e2e-test-coverage-review.md +214 -0
- vtx_coding_agent-0.1.1/docs/headless.md +128 -0
- vtx_coding_agent-0.1.1/docs/local-models.md +88 -0
- vtx_coding_agent-0.1.1/docs/permissions.md +88 -0
- vtx_coding_agent-0.1.1/docs/providers.md +247 -0
- vtx_coding_agent-0.1.1/docs/sessions.md +231 -0
- vtx_coding_agent-0.1.1/docs/skills.md +172 -0
- vtx_coding_agent-0.1.1/docs/storage-layout.md +186 -0
- vtx_coding_agent-0.1.1/docs/theming.md +117 -0
- vtx_coding_agent-0.1.1/docs/tools.md +197 -0
- vtx_coding_agent-0.1.1/pyproject.toml +84 -0
- vtx_coding_agent-0.1.1/scripts/show_themes.py +226 -0
- vtx_coding_agent-0.1.1/src/vtx/__init__.py +63 -0
- vtx_coding_agent-0.1.1/src/vtx/async_utils.py +40 -0
- vtx_coding_agent-0.1.1/src/vtx/builtin_skills/github/SKILL.md +139 -0
- vtx_coding_agent-0.1.1/src/vtx/builtin_skills/init/SKILL.md +74 -0
- vtx_coding_agent-0.1.1/src/vtx/builtin_skills/review/SKILL.md +73 -0
- vtx_coding_agent-0.1.1/src/vtx/builtin_skills/skill-builder/SKILL.md +133 -0
- vtx_coding_agent-0.1.1/src/vtx/cli.py +90 -0
- vtx_coding_agent-0.1.1/src/vtx/config.py +741 -0
- vtx_coding_agent-0.1.1/src/vtx/context/__init__.py +15 -0
- vtx_coding_agent-0.1.1/src/vtx/context/_xml.py +8 -0
- vtx_coding_agent-0.1.1/src/vtx/context/agent_mds.py +128 -0
- vtx_coding_agent-0.1.1/src/vtx/context/git.py +64 -0
- vtx_coding_agent-0.1.1/src/vtx/context/loader.py +41 -0
- vtx_coding_agent-0.1.1/src/vtx/context/skills.py +423 -0
- vtx_coding_agent-0.1.1/src/vtx/core/__init__.py +47 -0
- vtx_coding_agent-0.1.1/src/vtx/core/compaction.py +89 -0
- vtx_coding_agent-0.1.1/src/vtx/core/errors.py +17 -0
- vtx_coding_agent-0.1.1/src/vtx/core/handoff.py +51 -0
- vtx_coding_agent-0.1.1/src/vtx/core/scratchpad.py +54 -0
- vtx_coding_agent-0.1.1/src/vtx/core/types.py +197 -0
- vtx_coding_agent-0.1.1/src/vtx/defaults/__init__.py +0 -0
- vtx_coding_agent-0.1.1/src/vtx/defaults/config.yml +53 -0
- vtx_coding_agent-0.1.1/src/vtx/diff_display.py +12 -0
- vtx_coding_agent-0.1.1/src/vtx/events.py +224 -0
- vtx_coding_agent-0.1.1/src/vtx/gh_cli.py +82 -0
- vtx_coding_agent-0.1.1/src/vtx/git_branch.py +90 -0
- vtx_coding_agent-0.1.1/src/vtx/headless.py +127 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/__init__.py +93 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/base.py +217 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/context_length.py +150 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/dynamic_models.py +735 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/model_fetcher.py +279 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/models.py +78 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/oauth/__init__.py +59 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/oauth/copilot.py +358 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/oauth/dynamic.py +236 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/oauth/openai.py +400 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/phase_parser.py +270 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/provider.yaml +280 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/provider_catalog.py +230 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/providers/__init__.py +45 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/providers/anthropic_sdk.py +256 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/providers/mock.py +249 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/providers/openai_sdk.py +246 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/providers/sanitize.py +14 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/sdk/__init__.py +13 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/sdk/anthropic.py +382 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/sdk/base.py +82 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/sdk/openai.py +344 -0
- vtx_coding_agent-0.1.1/src/vtx/llm/tool_parser.py +161 -0
- vtx_coding_agent-0.1.1/src/vtx/loop.py +272 -0
- vtx_coding_agent-0.1.1/src/vtx/notify.py +109 -0
- vtx_coding_agent-0.1.1/src/vtx/permissions.py +114 -0
- vtx_coding_agent-0.1.1/src/vtx/prompts/__init__.py +45 -0
- vtx_coding_agent-0.1.1/src/vtx/prompts/builder.py +86 -0
- vtx_coding_agent-0.1.1/src/vtx/prompts/env.py +58 -0
- vtx_coding_agent-0.1.1/src/vtx/prompts/identity.py +166 -0
- vtx_coding_agent-0.1.1/src/vtx/prompts/tooling.py +36 -0
- vtx_coding_agent-0.1.1/src/vtx/py.typed +0 -0
- vtx_coding_agent-0.1.1/src/vtx/runtime.py +580 -0
- vtx_coding_agent-0.1.1/src/vtx/session.py +868 -0
- vtx_coding_agent-0.1.1/src/vtx/sounds/completion.wav +0 -0
- vtx_coding_agent-0.1.1/src/vtx/sounds/error.wav +0 -0
- vtx_coding_agent-0.1.1/src/vtx/sounds/permission.wav +0 -0
- vtx_coding_agent-0.1.1/src/vtx/themes.py +1104 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/__init__.py +68 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/_read_image.py +106 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/_tool_utils.py +90 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/base.py +36 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/bash.py +371 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/edit.py +261 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/find.py +132 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/read.py +238 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/skill.py +278 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/web.py +238 -0
- vtx_coding_agent-0.1.1/src/vtx/tools/write.py +88 -0
- vtx_coding_agent-0.1.1/src/vtx/tools_manager.py +216 -0
- vtx_coding_agent-0.1.1/src/vtx/turn.py +789 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/__init__.py +0 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/agent_runner.py +417 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/app.py +665 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/app_protocol.py +29 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/autocomplete.py +440 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/blocks.py +735 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/chat.py +613 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/clipboard.py +59 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/commands/__init__.py +100 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/commands/auth.py +306 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/commands/base.py +122 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/commands/models.py +144 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/commands/sessions.py +388 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/commands/settings.py +286 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/completion_ui.py +313 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/export.py +703 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/floating_list.py +370 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/formatting.py +287 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/input.py +760 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/latex.py +349 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/launch.py +108 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/path_complete.py +228 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/prompt_history.py +102 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/queue_ui.py +141 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/selection_mode.py +18 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/session_ui.py +235 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/startup.py +124 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/styles.py +327 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/tool_output.py +34 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/tree.py +437 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/welcome.py +51 -0
- vtx_coding_agent-0.1.1/src/vtx/ui/widgets.py +558 -0
- vtx_coding_agent-0.1.1/src/vtx/update_check.py +49 -0
- vtx_coding_agent-0.1.1/src/vtx/version.py +22 -0
- vtx_coding_agent-0.1.1/tests/conftest.py +61 -0
- vtx_coding_agent-0.1.1/tests/context/test_agents.py +301 -0
- vtx_coding_agent-0.1.1/tests/context/test_skills.py +683 -0
- vtx_coding_agent-0.1.1/tests/llm/__init__.py +0 -0
- vtx_coding_agent-0.1.1/tests/llm/test_anthropic_provider.py +105 -0
- vtx_coding_agent-0.1.1/tests/llm/test_mock_provider.py +142 -0
- vtx_coding_agent-0.1.1/tests/llm/test_openai_oauth.py +86 -0
- vtx_coding_agent-0.1.1/tests/llm/test_tls_verify.py +44 -0
- vtx_coding_agent-0.1.1/tests/test_agentic_loop.py +780 -0
- vtx_coding_agent-0.1.1/tests/test_cli.py +35 -0
- vtx_coding_agent-0.1.1/tests/test_cli_auth_flags.py +27 -0
- vtx_coding_agent-0.1.1/tests/test_cli_provider_resolution.py +22 -0
- vtx_coding_agent-0.1.1/tests/test_compaction.py +485 -0
- vtx_coding_agent-0.1.1/tests/test_config_binaries.py +34 -0
- vtx_coding_agent-0.1.1/tests/test_config_error_fallback.py +29 -0
- vtx_coding_agent-0.1.1/tests/test_config_injection.py +92 -0
- vtx_coding_agent-0.1.1/tests/test_config_migration.py +232 -0
- vtx_coding_agent-0.1.1/tests/test_dynamic_auth.py +91 -0
- vtx_coding_agent-0.1.1/tests/test_dynamic_models.py +472 -0
- vtx_coding_agent-0.1.1/tests/test_errors.py +17 -0
- vtx_coding_agent-0.1.1/tests/test_git_branch.py +84 -0
- vtx_coding_agent-0.1.1/tests/test_handoff.py +303 -0
- vtx_coding_agent-0.1.1/tests/test_handoff_link_interrupt.py +79 -0
- vtx_coding_agent-0.1.1/tests/test_headless.py +194 -0
- vtx_coding_agent-0.1.1/tests/test_launch_warnings.py +64 -0
- vtx_coding_agent-0.1.1/tests/test_llm_lazy_imports.py +50 -0
- vtx_coding_agent-0.1.1/tests/test_local_auth_config.py +64 -0
- vtx_coding_agent-0.1.1/tests/test_model_provider_resolution.py +33 -0
- vtx_coding_agent-0.1.1/tests/test_notifications_config.py +64 -0
- vtx_coding_agent-0.1.1/tests/test_notify.py +152 -0
- vtx_coding_agent-0.1.1/tests/test_openai_compat.py +84 -0
- vtx_coding_agent-0.1.1/tests/test_permissions.py +90 -0
- vtx_coding_agent-0.1.1/tests/test_phase_parser.py +482 -0
- vtx_coding_agent-0.1.1/tests/test_prompts.py +185 -0
- vtx_coding_agent-0.1.1/tests/test_runtime_switch_model.py +165 -0
- vtx_coding_agent-0.1.1/tests/test_session_persistence.py +689 -0
- vtx_coding_agent-0.1.1/tests/test_session_queries.py +61 -0
- vtx_coding_agent-0.1.1/tests/test_session_resume.py +155 -0
- vtx_coding_agent-0.1.1/tests/test_session_tree.py +43 -0
- vtx_coding_agent-0.1.1/tests/test_system_prompt.py +57 -0
- vtx_coding_agent-0.1.1/tests/test_system_prompt_git_context.py +31 -0
- vtx_coding_agent-0.1.1/tests/test_themes.py +38 -0
- vtx_coding_agent-0.1.1/tests/test_tool_parser.py +68 -0
- vtx_coding_agent-0.1.1/tests/test_tools_manager.py +43 -0
- vtx_coding_agent-0.1.1/tests/test_ui_notifications.py +43 -0
- vtx_coding_agent-0.1.1/tests/test_update_check.py +39 -0
- vtx_coding_agent-0.1.1/tests/test_update_notice_behavior.py +45 -0
- vtx_coding_agent-0.1.1/tests/tools/test_bash_shell.py +92 -0
- vtx_coding_agent-0.1.1/tests/tools/test_bash_truncation.py +87 -0
- vtx_coding_agent-0.1.1/tests/tools/test_diff.py +147 -0
- vtx_coding_agent-0.1.1/tests/tools/test_edit.py +76 -0
- vtx_coding_agent-0.1.1/tests/tools/test_edit_display.py +45 -0
- vtx_coding_agent-0.1.1/tests/tools/test_read.py +183 -0
- vtx_coding_agent-0.1.1/tests/tools/test_read_image.py +46 -0
- vtx_coding_agent-0.1.1/tests/tools/test_read_image_integration.py +44 -0
- vtx_coding_agent-0.1.1/tests/tools/test_read_image_resize.py +39 -0
- vtx_coding_agent-0.1.1/tests/tools/test_skill.py +98 -0
- vtx_coding_agent-0.1.1/tests/tools/test_subprocess_cancellation.py +88 -0
- vtx_coding_agent-0.1.1/tests/tools/test_write.py +31 -0
- vtx_coding_agent-0.1.1/tests/ui/test_app_approval_keys.py +95 -0
- vtx_coding_agent-0.1.1/tests/ui/test_autocomplete.py +347 -0
- vtx_coding_agent-0.1.1/tests/ui/test_completion_chrome.py +502 -0
- vtx_coding_agent-0.1.1/tests/ui/test_export.py +101 -0
- vtx_coding_agent-0.1.1/tests/ui/test_floating_list.py +52 -0
- vtx_coding_agent-0.1.1/tests/ui/test_info_bar_clicks.py +35 -0
- vtx_coding_agent-0.1.1/tests/ui/test_info_bar_permissions.py +62 -0
- vtx_coding_agent-0.1.1/tests/ui/test_input_approval_submit.py +49 -0
- vtx_coding_agent-0.1.1/tests/ui/test_input_cursor_theme.py +19 -0
- vtx_coding_agent-0.1.1/tests/ui/test_input_handoff.py +53 -0
- vtx_coding_agent-0.1.1/tests/ui/test_input_paste.py +118 -0
- vtx_coding_agent-0.1.1/tests/ui/test_input_shell_style.py +77 -0
- vtx_coding_agent-0.1.1/tests/ui/test_keybindings.py +19 -0
- vtx_coding_agent-0.1.1/tests/ui/test_latex.py +60 -0
- vtx_coding_agent-0.1.1/tests/ui/test_login_command.py +253 -0
- vtx_coding_agent-0.1.1/tests/ui/test_permission_selection_status.py +54 -0
- vtx_coding_agent-0.1.1/tests/ui/test_permissions_command.py +147 -0
- vtx_coding_agent-0.1.1/tests/ui/test_prompt_history.py +98 -0
- vtx_coding_agent-0.1.1/tests/ui/test_queue_editing.py +154 -0
- vtx_coding_agent-0.1.1/tests/ui/test_shell_command_detection.py +251 -0
- vtx_coding_agent-0.1.1/tests/ui/test_status_line.py +46 -0
- vtx_coding_agent-0.1.1/tests/ui/test_streaming_blocks.py +203 -0
- vtx_coding_agent-0.1.1/tests/ui/test_styles.py +25 -0
- vtx_coding_agent-0.1.1/tests/ui/test_thinking_notifications_commands.py +202 -0
- vtx_coding_agent-0.1.1/tests/ui/test_tool_output_expansion.py +125 -0
- 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"
|