voidx 1.0.0__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 (126) hide show
  1. voidx/__init__.py +3 -0
  2. voidx/agent/__init__.py +0 -0
  3. voidx/agent/agents.py +439 -0
  4. voidx/agent/attachments.py +235 -0
  5. voidx/agent/graph.py +463 -0
  6. voidx/agent/graph_components/__init__.py +1 -0
  7. voidx/agent/graph_components/compaction.py +268 -0
  8. voidx/agent/graph_components/permissions.py +139 -0
  9. voidx/agent/graph_components/run_loop.py +532 -0
  10. voidx/agent/graph_components/runtime.py +14 -0
  11. voidx/agent/graph_components/streaming.py +351 -0
  12. voidx/agent/graph_components/subagent.py +278 -0
  13. voidx/agent/graph_components/tool_execution.py +208 -0
  14. voidx/agent/runtime_context.py +368 -0
  15. voidx/agent/slash.py +466 -0
  16. voidx/agent/slash_components/__init__.py +1 -0
  17. voidx/agent/slash_components/code_ide.py +68 -0
  18. voidx/agent/slash_components/lsp.py +105 -0
  19. voidx/agent/slash_components/mcp.py +332 -0
  20. voidx/agent/slash_components/model.py +419 -0
  21. voidx/agent/slash_components/runtime.py +55 -0
  22. voidx/agent/slash_components/skills.py +94 -0
  23. voidx/agent/state.py +32 -0
  24. voidx/agent/task_state.py +278 -0
  25. voidx/agent/tool_filters.py +27 -0
  26. voidx/config.py +707 -0
  27. voidx/llm/__init__.py +0 -0
  28. voidx/llm/catalog.py +188 -0
  29. voidx/llm/compaction.py +267 -0
  30. voidx/llm/context.py +43 -0
  31. voidx/llm/instruction.py +220 -0
  32. voidx/llm/provider.py +312 -0
  33. voidx/llm/usage.py +341 -0
  34. voidx/lsp/__init__.py +30 -0
  35. voidx/lsp/client.py +259 -0
  36. voidx/lsp/config.py +172 -0
  37. voidx/lsp/detector.py +512 -0
  38. voidx/lsp/errors.py +19 -0
  39. voidx/lsp/manager.py +280 -0
  40. voidx/lsp/schema.py +179 -0
  41. voidx/lsp/service.py +103 -0
  42. voidx/main.py +154 -0
  43. voidx/mcp/__init__.py +33 -0
  44. voidx/mcp/client.py +458 -0
  45. voidx/mcp/manager.py +267 -0
  46. voidx/mcp/schema.py +112 -0
  47. voidx/mcp/tool.py +122 -0
  48. voidx/mcp_servers/__init__.py +1 -0
  49. voidx/mcp_servers/web.py +104 -0
  50. voidx/memory/__init__.py +0 -0
  51. voidx/memory/context_frames.py +188 -0
  52. voidx/memory/model_profiles.py +98 -0
  53. voidx/memory/runtime_state.py +240 -0
  54. voidx/memory/session.py +272 -0
  55. voidx/memory/store.py +245 -0
  56. voidx/memory/transcript.py +137 -0
  57. voidx/permission/__init__.py +28 -0
  58. voidx/permission/engine.py +430 -0
  59. voidx/permission/evaluate.py +114 -0
  60. voidx/permission/sandbox.py +280 -0
  61. voidx/permission/schema.py +24 -0
  62. voidx/permission/service.py +314 -0
  63. voidx/permission/wildcard.py +34 -0
  64. voidx/skills/__init__.py +18 -0
  65. voidx/skills/bundled/superpowers/receiving-code-review/SKILL.md +30 -0
  66. voidx/skills/bundled/superpowers/requesting-code-review/SKILL.md +27 -0
  67. voidx/skills/bundled/superpowers/systematic-debugging/SKILL.md +36 -0
  68. voidx/skills/bundled/superpowers/test-driven-development/SKILL.md +33 -0
  69. voidx/skills/bundled/superpowers/verification-before-completion/SKILL.md +31 -0
  70. voidx/skills/bundled/superpowers/writing-plans/SKILL.md +27 -0
  71. voidx/skills/policy.py +97 -0
  72. voidx/skills/registry.py +162 -0
  73. voidx/skills/schema.py +47 -0
  74. voidx/skills/service.py +199 -0
  75. voidx/tools/__init__.py +0 -0
  76. voidx/tools/agent.py +81 -0
  77. voidx/tools/base.py +86 -0
  78. voidx/tools/bash.py +105 -0
  79. voidx/tools/file_ops.py +193 -0
  80. voidx/tools/lsp.py +155 -0
  81. voidx/tools/registry.py +104 -0
  82. voidx/tools/repomap.py +238 -0
  83. voidx/tools/search.py +162 -0
  84. voidx/tools/task_status.py +57 -0
  85. voidx/tools/task_tracker.py +81 -0
  86. voidx/tools/todo.py +82 -0
  87. voidx/tools/web_content.py +357 -0
  88. voidx/tools/web_mcp.py +107 -0
  89. voidx/tools/webfetch.py +155 -0
  90. voidx/tools/websearch.py +276 -0
  91. voidx/ui/__init__.py +0 -0
  92. voidx/ui/app.py +1033 -0
  93. voidx/ui/app_components/__init__.py +1 -0
  94. voidx/ui/app_components/clipboard_image.py +245 -0
  95. voidx/ui/app_components/commands.py +18 -0
  96. voidx/ui/app_components/controls.py +29 -0
  97. voidx/ui/app_components/file_picker.py +115 -0
  98. voidx/ui/app_components/formatting.py +187 -0
  99. voidx/ui/app_components/git_changes.py +51 -0
  100. voidx/ui/app_components/rendering.py +1169 -0
  101. voidx/ui/browse.py +160 -0
  102. voidx/ui/capture.py +169 -0
  103. voidx/ui/code_ide.py +251 -0
  104. voidx/ui/commands.py +83 -0
  105. voidx/ui/console.py +381 -0
  106. voidx/ui/console_components/__init__.py +1 -0
  107. voidx/ui/console_components/formatting.py +96 -0
  108. voidx/ui/console_components/streaming.py +253 -0
  109. voidx/ui/diff.py +331 -0
  110. voidx/ui/dock.py +372 -0
  111. voidx/ui/dock_components/__init__.py +1 -0
  112. voidx/ui/dock_components/formatting.py +123 -0
  113. voidx/ui/dock_components/nodes.py +401 -0
  114. voidx/ui/dock_components/state.py +51 -0
  115. voidx/ui/event_components/__init__.py +1 -0
  116. voidx/ui/event_components/schema.py +249 -0
  117. voidx/ui/events.py +341 -0
  118. voidx/ui/session_changes.py +163 -0
  119. voidx/ui/startup.py +161 -0
  120. voidx/ui/transcript.py +148 -0
  121. voidx/ui/tree.py +316 -0
  122. voidx-1.0.0.dist-info/METADATA +59 -0
  123. voidx-1.0.0.dist-info/RECORD +126 -0
  124. voidx-1.0.0.dist-info/WHEEL +5 -0
  125. voidx-1.0.0.dist-info/entry_points.txt +2 -0
  126. voidx-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,278 @@
1
+ """Multi-turn task intent state."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+
7
+ from enum import Enum
8
+
9
+ from pydantic import BaseModel
10
+
11
+ from voidx.agent.runtime_context import (
12
+ InteractionMode,
13
+ TaskIntent,
14
+ implementation_allowed_for_intent,
15
+ infer_task_intent,
16
+ )
17
+
18
+
19
+ _APPROVAL_ONLY_HINTS = {
20
+ "ok",
21
+ "okay",
22
+ "yes",
23
+ "yeah",
24
+ "yep",
25
+ "sure",
26
+ "confirm",
27
+ "confirmed",
28
+ "approve",
29
+ "goahead",
30
+ "go",
31
+ "yesgo",
32
+ "\u597d",
33
+ "\u597d\u7684",
34
+ "\u884c",
35
+ "\u53ef\u4ee5",
36
+ "\u53ef\u4ee5\u7684",
37
+ "\u53ef\u4ee5\u4e86",
38
+ "\u5bf9\u53ef\u4ee5",
39
+ "\u5bf9\u7684",
40
+ "\u5bf9",
41
+ "\u55ef",
42
+ "\u786e\u8ba4",
43
+ "\u786e\u8ba4\u4e86",
44
+ "\u662f\u7684",
45
+ "\u540c\u610f",
46
+ "\u6279\u51c6",
47
+ "\u6ca1\u95ee\u9898",
48
+ "\u6ca1\u95ee\u9898\u4e86",
49
+ "\u5f00\u59cb\u5427",
50
+ "\u505a\u5427",
51
+ "\u6309\u8fd9\u4e2a\u505a",
52
+ "\u5c31\u8fd9\u6837",
53
+ }
54
+
55
+ _DIRECT_IMPLEMENT_COMMANDS = {
56
+ "change",
57
+ "edit",
58
+ "fix",
59
+ "implement",
60
+ "modify",
61
+ "patch",
62
+ "doit",
63
+ "goaheadandchange",
64
+ "\u6539",
65
+ "\u6539\u5427",
66
+ "\u4fee\u6539",
67
+ "\u4fee\u6539\u5427",
68
+ "\u4fee",
69
+ "\u4fee\u5427",
70
+ "\u4fee\u590d",
71
+ "\u4fee\u590d\u5427",
72
+ "\u5b9e\u73b0",
73
+ "\u5b9e\u73b0\u5427",
74
+ "\u505a",
75
+ "\u505a\u5427",
76
+ "\u5f00\u59cb\u6539",
77
+ "\u5f00\u59cb\u505a",
78
+ }
79
+
80
+
81
+ class TaskPhase(str, Enum):
82
+ CLARIFY = "clarify"
83
+ INSPECT = "inspect"
84
+ DESIGN = "design"
85
+ IMPLEMENT = "implement"
86
+ VERIFY = "verify"
87
+ REVIEW = "review"
88
+ DONE = "done"
89
+
90
+
91
+ class TaskRunStatus(str, Enum):
92
+ IDLE = "idle"
93
+ ACTIVE = "active"
94
+ DONE = "done"
95
+
96
+
97
+ class TaskRun(BaseModel):
98
+ goal: str = ""
99
+ phase: TaskPhase = TaskPhase.CLARIFY
100
+ status: TaskRunStatus = TaskRunStatus.IDLE
101
+ approved_scope: str = ""
102
+ awaiting_implementation_approval: bool = False
103
+ turn_count: int = 0
104
+
105
+ @property
106
+ def active(self) -> bool:
107
+ return self.status == TaskRunStatus.ACTIVE and bool(self.goal)
108
+
109
+ def set_goal(self, goal: str) -> None:
110
+ self.goal = _summarize_scope(goal)
111
+ self.phase = TaskPhase.CLARIFY
112
+ self.status = TaskRunStatus.ACTIVE if self.goal else TaskRunStatus.IDLE
113
+ self.approved_scope = ""
114
+ self.awaiting_implementation_approval = False
115
+ self.turn_count = 0
116
+
117
+ def clear(self) -> None:
118
+ self.goal = ""
119
+ self.phase = TaskPhase.CLARIFY
120
+ self.status = TaskRunStatus.IDLE
121
+ self.approved_scope = ""
122
+ self.awaiting_implementation_approval = False
123
+ self.turn_count = 0
124
+
125
+ def update_after_turn(
126
+ self,
127
+ resolution: "IntentResolution",
128
+ user_text: str,
129
+ *,
130
+ scope_text: str | None = None,
131
+ ) -> None:
132
+ if not self.goal:
133
+ self.set_goal(scope_text or user_text)
134
+ if not self.goal:
135
+ return
136
+
137
+ self.status = TaskRunStatus.ACTIVE
138
+ self.turn_count += 1
139
+ self.phase = _phase_for_intent(resolution.intent)
140
+
141
+ if resolution.intent == TaskIntent.DESIGN:
142
+ self.awaiting_implementation_approval = True
143
+ self.approved_scope = _summarize_scope(scope_text or self.goal or user_text)
144
+ return
145
+
146
+ if resolution.intent == TaskIntent.IMPLEMENT:
147
+ self.awaiting_implementation_approval = False
148
+ self.approved_scope = ""
149
+ return
150
+
151
+ if resolution.intent != TaskIntent.AMBIGUOUS:
152
+ self.awaiting_implementation_approval = False
153
+ self.approved_scope = ""
154
+
155
+
156
+ class TaskState(BaseModel):
157
+ current_intent: TaskIntent = TaskIntent.CHAT
158
+ previous_intent: TaskIntent | None = None
159
+ current_goal: str = ""
160
+ awaiting_implementation_approval: bool = False
161
+ approved_scope: str = ""
162
+ last_plan_summary: str = ""
163
+
164
+ def update_after_turn(
165
+ self,
166
+ resolution: "IntentResolution",
167
+ user_text: str,
168
+ *,
169
+ scope_text: str | None = None,
170
+ ) -> None:
171
+ self.previous_intent = self.current_intent
172
+ self.current_intent = resolution.intent
173
+ self.current_goal = _summarize_scope(scope_text or user_text)
174
+
175
+ if resolution.intent == TaskIntent.DESIGN:
176
+ scope = _summarize_scope(scope_text or user_text)
177
+ self.awaiting_implementation_approval = True
178
+ self.approved_scope = scope
179
+ self.last_plan_summary = scope
180
+ return
181
+
182
+ if resolution.intent == TaskIntent.IMPLEMENT:
183
+ self.awaiting_implementation_approval = False
184
+ self.approved_scope = ""
185
+ return
186
+
187
+ if resolution.intent != TaskIntent.AMBIGUOUS:
188
+ self.awaiting_implementation_approval = False
189
+ self.approved_scope = ""
190
+
191
+
192
+ class IntentResolution(BaseModel):
193
+ intent: TaskIntent
194
+ implementation_allowed: bool
195
+ reason: str
196
+ awaiting_implementation_approval: bool = False
197
+ approved_scope: str = ""
198
+
199
+
200
+ def resolve_turn_intent(
201
+ text: str,
202
+ interaction_mode: str | InteractionMode | None = None,
203
+ task_state: TaskState | None = None,
204
+ ) -> IntentResolution:
205
+ mode = InteractionMode.parse(interaction_mode)
206
+ state = task_state or TaskState()
207
+
208
+ if mode == InteractionMode.PLAN:
209
+ return _resolution(TaskIntent.DESIGN, "interaction mode forces design")
210
+
211
+ if _is_approval_only(text):
212
+ if state.awaiting_implementation_approval:
213
+ return _resolution(
214
+ TaskIntent.IMPLEMENT,
215
+ "user confirmed the pending implementation plan",
216
+ awaiting_implementation_approval=True,
217
+ approved_scope=state.approved_scope,
218
+ )
219
+ return _resolution(
220
+ TaskIntent.AMBIGUOUS,
221
+ "approval phrase without a pending implementation plan",
222
+ )
223
+
224
+ if _is_direct_implementation_command(text):
225
+ return _resolution(
226
+ TaskIntent.IMPLEMENT,
227
+ "direct short command asks to modify the current task",
228
+ )
229
+
230
+ intent = infer_task_intent(text, mode)
231
+ return _resolution(intent, f"single-turn classifier matched {intent.value}")
232
+
233
+
234
+ def _resolution(
235
+ intent: TaskIntent,
236
+ reason: str,
237
+ *,
238
+ awaiting_implementation_approval: bool = False,
239
+ approved_scope: str = "",
240
+ ) -> IntentResolution:
241
+ return IntentResolution(
242
+ intent=intent,
243
+ implementation_allowed=implementation_allowed_for_intent(intent),
244
+ reason=reason,
245
+ awaiting_implementation_approval=awaiting_implementation_approval,
246
+ approved_scope=approved_scope,
247
+ )
248
+
249
+
250
+ def _is_approval_only(text: str) -> bool:
251
+ return _normalize_approval_text(text) in _APPROVAL_ONLY_HINTS
252
+
253
+
254
+ def _is_direct_implementation_command(text: str) -> bool:
255
+ return _normalize_approval_text(text) in _DIRECT_IMPLEMENT_COMMANDS
256
+
257
+
258
+ def _normalize_approval_text(text: str) -> str:
259
+ return re.sub(r"[\s,.;:!?,。;:!?、]+", "", text.strip().lower())
260
+
261
+
262
+ def _summarize_scope(text: str) -> str:
263
+ first_line = text.strip().splitlines()[0] if text.strip() else ""
264
+ return first_line[:160]
265
+
266
+
267
+ def _phase_for_intent(intent: TaskIntent) -> TaskPhase:
268
+ if intent == TaskIntent.INSPECT:
269
+ return TaskPhase.INSPECT
270
+ if intent == TaskIntent.DESIGN:
271
+ return TaskPhase.DESIGN
272
+ if intent == TaskIntent.IMPLEMENT:
273
+ return TaskPhase.IMPLEMENT
274
+ if intent == TaskIntent.REVIEW:
275
+ return TaskPhase.REVIEW
276
+ if intent == TaskIntent.DEBUG:
277
+ return TaskPhase.INSPECT
278
+ return TaskPhase.CLARIFY
@@ -0,0 +1,27 @@
1
+ """Tool definition filters shared by primary and worker-role loops."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ def filter_unavailable_lsp_tools(tool_defs: list[dict], lsp_manager: Any | None) -> list[dict]:
9
+ if _has_available_lsp_server(lsp_manager):
10
+ return tool_defs
11
+ return [
12
+ tool
13
+ for tool in tool_defs
14
+ if not str(tool.get("function", {}).get("name", "")).startswith("lsp_")
15
+ ]
16
+
17
+
18
+ def _has_available_lsp_server(lsp_manager: Any | None) -> bool:
19
+ if lsp_manager is None or not hasattr(lsp_manager, "doctor"):
20
+ return False
21
+ try:
22
+ return any(
23
+ getattr(check, "enabled", False) and getattr(check, "available", False)
24
+ for check in lsp_manager.doctor()
25
+ )
26
+ except Exception:
27
+ return False