vtx-coding-agent 0.1.1__py3-none-any.whl

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 (117) hide show
  1. vtx/__init__.py +63 -0
  2. vtx/async_utils.py +40 -0
  3. vtx/builtin_skills/github/SKILL.md +139 -0
  4. vtx/builtin_skills/init/SKILL.md +74 -0
  5. vtx/builtin_skills/review/SKILL.md +73 -0
  6. vtx/builtin_skills/skill-builder/SKILL.md +133 -0
  7. vtx/cli.py +90 -0
  8. vtx/config.py +741 -0
  9. vtx/context/__init__.py +15 -0
  10. vtx/context/_xml.py +8 -0
  11. vtx/context/agent_mds.py +128 -0
  12. vtx/context/git.py +64 -0
  13. vtx/context/loader.py +41 -0
  14. vtx/context/skills.py +423 -0
  15. vtx/core/__init__.py +47 -0
  16. vtx/core/compaction.py +89 -0
  17. vtx/core/errors.py +17 -0
  18. vtx/core/handoff.py +51 -0
  19. vtx/core/scratchpad.py +54 -0
  20. vtx/core/types.py +197 -0
  21. vtx/defaults/__init__.py +0 -0
  22. vtx/defaults/config.yml +53 -0
  23. vtx/diff_display.py +12 -0
  24. vtx/events.py +224 -0
  25. vtx/gh_cli.py +82 -0
  26. vtx/git_branch.py +90 -0
  27. vtx/headless.py +127 -0
  28. vtx/llm/__init__.py +93 -0
  29. vtx/llm/base.py +217 -0
  30. vtx/llm/context_length.py +150 -0
  31. vtx/llm/dynamic_models.py +735 -0
  32. vtx/llm/model_fetcher.py +279 -0
  33. vtx/llm/models.py +78 -0
  34. vtx/llm/oauth/__init__.py +59 -0
  35. vtx/llm/oauth/copilot.py +358 -0
  36. vtx/llm/oauth/dynamic.py +236 -0
  37. vtx/llm/oauth/openai.py +400 -0
  38. vtx/llm/phase_parser.py +270 -0
  39. vtx/llm/provider.yaml +280 -0
  40. vtx/llm/provider_catalog.py +230 -0
  41. vtx/llm/providers/__init__.py +45 -0
  42. vtx/llm/providers/anthropic_sdk.py +256 -0
  43. vtx/llm/providers/mock.py +249 -0
  44. vtx/llm/providers/openai_sdk.py +246 -0
  45. vtx/llm/providers/sanitize.py +14 -0
  46. vtx/llm/sdk/__init__.py +13 -0
  47. vtx/llm/sdk/anthropic.py +382 -0
  48. vtx/llm/sdk/base.py +82 -0
  49. vtx/llm/sdk/openai.py +344 -0
  50. vtx/llm/tool_parser.py +161 -0
  51. vtx/loop.py +272 -0
  52. vtx/notify.py +109 -0
  53. vtx/permissions.py +114 -0
  54. vtx/prompts/__init__.py +45 -0
  55. vtx/prompts/builder.py +86 -0
  56. vtx/prompts/env.py +58 -0
  57. vtx/prompts/identity.py +166 -0
  58. vtx/prompts/tooling.py +36 -0
  59. vtx/py.typed +0 -0
  60. vtx/runtime.py +580 -0
  61. vtx/session.py +868 -0
  62. vtx/sounds/completion.wav +0 -0
  63. vtx/sounds/error.wav +0 -0
  64. vtx/sounds/permission.wav +0 -0
  65. vtx/themes.py +1104 -0
  66. vtx/tools/__init__.py +68 -0
  67. vtx/tools/_read_image.py +106 -0
  68. vtx/tools/_tool_utils.py +90 -0
  69. vtx/tools/base.py +36 -0
  70. vtx/tools/bash.py +371 -0
  71. vtx/tools/edit.py +261 -0
  72. vtx/tools/find.py +132 -0
  73. vtx/tools/read.py +238 -0
  74. vtx/tools/skill.py +278 -0
  75. vtx/tools/web.py +238 -0
  76. vtx/tools/write.py +88 -0
  77. vtx/tools_manager.py +216 -0
  78. vtx/turn.py +789 -0
  79. vtx/ui/__init__.py +0 -0
  80. vtx/ui/agent_runner.py +417 -0
  81. vtx/ui/app.py +665 -0
  82. vtx/ui/app_protocol.py +29 -0
  83. vtx/ui/autocomplete.py +440 -0
  84. vtx/ui/blocks.py +735 -0
  85. vtx/ui/chat.py +613 -0
  86. vtx/ui/clipboard.py +59 -0
  87. vtx/ui/commands/__init__.py +100 -0
  88. vtx/ui/commands/auth.py +306 -0
  89. vtx/ui/commands/base.py +122 -0
  90. vtx/ui/commands/models.py +144 -0
  91. vtx/ui/commands/sessions.py +388 -0
  92. vtx/ui/commands/settings.py +286 -0
  93. vtx/ui/completion_ui.py +313 -0
  94. vtx/ui/export.py +703 -0
  95. vtx/ui/floating_list.py +370 -0
  96. vtx/ui/formatting.py +287 -0
  97. vtx/ui/input.py +760 -0
  98. vtx/ui/latex.py +349 -0
  99. vtx/ui/launch.py +108 -0
  100. vtx/ui/path_complete.py +228 -0
  101. vtx/ui/prompt_history.py +102 -0
  102. vtx/ui/queue_ui.py +141 -0
  103. vtx/ui/selection_mode.py +18 -0
  104. vtx/ui/session_ui.py +235 -0
  105. vtx/ui/startup.py +124 -0
  106. vtx/ui/styles.py +327 -0
  107. vtx/ui/tool_output.py +34 -0
  108. vtx/ui/tree.py +437 -0
  109. vtx/ui/welcome.py +51 -0
  110. vtx/ui/widgets.py +558 -0
  111. vtx/update_check.py +49 -0
  112. vtx/version.py +22 -0
  113. vtx_coding_agent-0.1.1.dist-info/METADATA +259 -0
  114. vtx_coding_agent-0.1.1.dist-info/RECORD +117 -0
  115. vtx_coding_agent-0.1.1.dist-info/WHEEL +4 -0
  116. vtx_coding_agent-0.1.1.dist-info/entry_points.txt +2 -0
  117. vtx_coding_agent-0.1.1.dist-info/licenses/LICENSE +201 -0
vtx/ui/styles.py ADDED
@@ -0,0 +1,327 @@
1
+ """TUI styles for vtx."""
2
+
3
+ from vtx import config
4
+
5
+
6
+ def _blend_hex(base: str, overlay: str, overlay_weight: float) -> str:
7
+ """Blend two hex colors, biasing toward the base color."""
8
+ base_rgb = tuple(int(base[i : i + 2], 16) for i in (1, 3, 5))
9
+ overlay_rgb = tuple(int(overlay[i : i + 2], 16) for i in (1, 3, 5))
10
+ channels = tuple(
11
+ round((base_channel * (1 - overlay_weight)) + (overlay_channel * overlay_weight))
12
+ for base_channel, overlay_channel in zip(base_rgb, overlay_rgb, strict=True)
13
+ )
14
+ return f"#{channels[0]:02x}{channels[1]:02x}{channels[2]:02x}"
15
+
16
+
17
+ def get_styles() -> str:
18
+ colors = config.ui.colors
19
+ approval_bg = _blend_hex(colors.bg, colors.accent, overlay_weight=0.05)
20
+ shell_bg = _blend_hex(colors.editor, colors.success, overlay_weight=0.15)
21
+ thinking_medium_bg = _blend_hex(colors.editor, colors.accent, overlay_weight=0.08)
22
+ thinking_high_bg = _blend_hex(colors.editor, colors.accent, overlay_weight=0.18)
23
+ thinking_xhigh_bg = _blend_hex(colors.editor, colors.badge.label, overlay_weight=0.18)
24
+
25
+ return f"""
26
+ Screen {{
27
+ layout: grid;
28
+ grid-size: 1;
29
+ grid-rows: 1fr auto auto auto auto auto;
30
+ background: transparent;
31
+ color: {colors.fg};
32
+ }}
33
+
34
+ #chat-log {{
35
+ height: 100%;
36
+ padding: 0 0 1 0;
37
+ scrollbar-size: 0 0;
38
+ align-vertical: bottom;
39
+ background: transparent;
40
+ color: {colors.fg};
41
+ }}
42
+
43
+ /* Thinking block - dim italic */
44
+ .thinking-block {{
45
+ color: {colors.dim};
46
+ text-style: italic;
47
+ padding: 0 1 0 1;
48
+ margin: 1 0 0 0;
49
+ }}
50
+
51
+ .thinking-block.-hidden {{
52
+ display: none;
53
+ height: 0;
54
+ margin: 0;
55
+ border: none;
56
+ }}
57
+
58
+ #thinking-content {{
59
+ color: {colors.dim};
60
+ text-style: italic;
61
+ }}
62
+
63
+ /* Content block */
64
+ .content-block {{
65
+ padding: 0 1;
66
+ margin-top: 1;
67
+ }}
68
+
69
+ /* Ensure text wraps in all blocks */
70
+ .thinking-block Label,
71
+ .content-block Label,
72
+ .user-block Label,
73
+ .update-available-block Label,
74
+ .launch-warnings-block Label,
75
+ .tool-block Label,
76
+ .handoff-link-block Label {{
77
+ width: 100%;
78
+ }}
79
+
80
+ /* User message */
81
+ .user-block {{
82
+ padding: 1 1;
83
+ margin: 1 0 0 0;
84
+ background: {colors.editor};
85
+ }}
86
+
87
+ .user-block.skill-trigger-message {{
88
+ background: {colors.editor};
89
+ }}
90
+
91
+ /* Update available message */
92
+ .update-available-block {{
93
+ padding: 0 1;
94
+ margin: 1 0 0 0;
95
+ border-top: solid {colors.notice};
96
+ border-bottom: solid {colors.notice};
97
+ }}
98
+
99
+ /* Launch warnings */
100
+ .launch-warnings-block {{
101
+ padding: 0 1;
102
+ margin: 1 0 0 0;
103
+ border-top: solid {colors.notice};
104
+ border-bottom: solid {colors.notice};
105
+ }}
106
+
107
+ /* Session info */
108
+ .session-info {{
109
+ padding: 1;
110
+ }}
111
+
112
+ /* Tool block */
113
+ .tool-block {{
114
+ padding: 0 1;
115
+ margin-top: 1;
116
+ background: transparent;
117
+ }}
118
+
119
+ .tool-block.-compact {{
120
+ margin-top: 0;
121
+ }}
122
+
123
+ .tool-block.-pending,
124
+ .tool-block.-success,
125
+ .tool-block.-error {{
126
+ background: transparent;
127
+ color: {colors.dim};
128
+ border: none;
129
+ }}
130
+
131
+ .tool-block.-approval {{
132
+ background: {approval_bg};
133
+ color: {colors.dim};
134
+ border-left: outer {colors.accent};
135
+ margin: 1 0 1 1;
136
+ padding: 1 1;
137
+ }}
138
+
139
+ .tool-block.-approval #tool-output {{
140
+ padding: 1 0 0 0;
141
+ }}
142
+
143
+ #tool-header {{
144
+ text-style: none;
145
+ }}
146
+
147
+ #tool-output,
148
+ .tool-output {{
149
+ color: {colors.dim};
150
+ padding: 0 0 0 2;
151
+ }}
152
+
153
+ #tool-output.-diff-output {{
154
+ text-wrap: nowrap;
155
+ text-overflow: clip;
156
+ }}
157
+
158
+ .tool-block.-with-details {{
159
+ padding: 0 1;
160
+ }}
161
+
162
+ #tool-output.-hidden {{
163
+ display: none;
164
+ height: 0;
165
+ }}
166
+
167
+ /* Compaction message */
168
+ .compaction-message {{
169
+ background: {colors.panel};
170
+ padding: 1 1;
171
+ margin-top: 1;
172
+ width: 100%;
173
+ }}
174
+
175
+ /* Handoff link */
176
+ .handoff-link-block {{
177
+ background: {colors.panel};
178
+ padding: 1 1;
179
+ margin: 1 0 0 0;
180
+ width: 100%;
181
+ }}
182
+
183
+ /* Aborted message */
184
+ .aborted-message {{
185
+ padding: 0 1;
186
+ margin-top: 1;
187
+ }}
188
+
189
+ /* Info message */
190
+ .info-message {{
191
+ padding: 0 1;
192
+ margin-top: 1;
193
+ }}
194
+
195
+ /* Loaded resources should not add extra top margin */
196
+ .info-message.loaded-resources {{
197
+ margin-top: 0;
198
+ }}
199
+
200
+ /* Queue display - shown above status line when messages are queued */
201
+ #queue-display {{
202
+ height: auto;
203
+ padding: 0 1 1 1;
204
+ }}
205
+
206
+ #queue-display.-hidden {{
207
+ display: none;
208
+ }}
209
+
210
+ #queue-content {{
211
+ color: {colors.dim};
212
+ width: 100%;
213
+ }}
214
+
215
+ /* Status line - vtx style with spinner */
216
+ .status-line {{
217
+ height: auto;
218
+ min-height: 1;
219
+ padding: 0 1;
220
+ color: $warning;
221
+ }}
222
+
223
+ #status-text {{
224
+ color: {colors.dim};
225
+ width: 1fr;
226
+ }}
227
+
228
+ #exit-hint {{
229
+ color: {colors.dim};
230
+ width: auto;
231
+ }}
232
+
233
+ /* Input area */
234
+ #input-box {{
235
+ background: {colors.editor};
236
+ border-top: solid {colors.editor};
237
+ border-bottom: solid {colors.editor};
238
+ border-title-color: {colors.dim};
239
+ border-subtitle-color: {colors.dim};
240
+ }}
241
+
242
+ #input-prefix {{
243
+ color: {colors.fg};
244
+ text-style: bold;
245
+ }}
246
+
247
+ #input-box.-thinking-none,
248
+ #input-box.-thinking-minimal,
249
+ #input-box.-thinking-low {{
250
+ background: {colors.editor};
251
+ border-top: solid {colors.editor};
252
+ border-bottom: solid {colors.editor};
253
+ }}
254
+
255
+ #input-box.-thinking-medium {{
256
+ background: {thinking_medium_bg};
257
+ border-top: solid {thinking_medium_bg};
258
+ border-bottom: solid {thinking_medium_bg};
259
+ }}
260
+
261
+ #input-box.-thinking-high {{
262
+ background: {thinking_high_bg};
263
+ border-top: solid {thinking_high_bg};
264
+ border-bottom: solid {thinking_high_bg};
265
+ }}
266
+
267
+ #input-box.-thinking-xhigh {{
268
+ background: {thinking_xhigh_bg};
269
+ border-top: solid {thinking_xhigh_bg};
270
+ border-bottom: solid {thinking_xhigh_bg};
271
+ }}
272
+
273
+ #input-box.-shell-command {{
274
+ background: {shell_bg};
275
+ border-top: solid {shell_bg};
276
+ border-bottom: solid {shell_bg};
277
+ }}
278
+
279
+ #input-box.-shell-command .input-textarea {{
280
+ color: {colors.success};
281
+ }}
282
+
283
+ /* Completion list - between input and info bar */
284
+ #completion-list {{
285
+ height: auto;
286
+ padding: 0 1;
287
+ }}
288
+
289
+ /* Info bar - vtx style tmux-like bottom bar with two rows */
290
+ .info-bar {{
291
+ height: 2;
292
+ color: {colors.dim};
293
+ }}
294
+
295
+ .info-bar.-completion-hidden {{
296
+ display: none;
297
+ height: 0;
298
+ }}
299
+
300
+ #info-row-1, #info-row-2 {{
301
+ height: 1;
302
+ }}
303
+
304
+ #info-cwd {{
305
+ width: 1fr;
306
+ padding: 0 1;
307
+ }}
308
+
309
+ #info-row2-left {{
310
+ width: 1fr;
311
+ padding: 0 1;
312
+ }}
313
+
314
+ #info-row1-right, #info-row2-right {{
315
+ width: auto;
316
+ padding: 0 1;
317
+ text-align: right;
318
+ }}
319
+
320
+ /* Notifications */
321
+ Notification {{
322
+ layer: notification;
323
+ }}
324
+ """
325
+
326
+
327
+ STYLES = get_styles()
vtx/ui/tool_output.py ADDED
@@ -0,0 +1,34 @@
1
+ from rich.markup import escape
2
+ from rich.text import Text
3
+
4
+ from vtx import config
5
+
6
+
7
+ def format_expand_hint(hidden_lines: int) -> Text:
8
+ colors = config.ui.colors
9
+ text = Text()
10
+ text.append(f"... ({hidden_lines} lines hidden • ", style=colors.dim)
11
+ text.append("ctrl+o", style=colors.muted)
12
+ text.append(" to expand)", style=colors.dim)
13
+ return text
14
+
15
+
16
+ def escape_tool_output_text(text: str) -> str:
17
+ return "\n".join(escape(line) for line in text.split("\n"))
18
+
19
+
20
+ def truncate_tool_output_text(
21
+ text: str, max_lines: int = 5, escape_lines: bool = True
22
+ ) -> tuple[str, bool]:
23
+ if not text:
24
+ return text, False
25
+
26
+ lines = text.split("\n")
27
+ if len(lines) <= max_lines:
28
+ return text, False
29
+
30
+ hidden = len(lines) - max_lines
31
+ visible = [escape(line) if escape_lines else line for line in lines[:max_lines]]
32
+ hint = format_expand_hint(hidden_lines=hidden)
33
+ visible.append(hint.markup)
34
+ return "\n".join(visible), True