windcode 0.1.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.
- windcode/__init__.py +6 -0
- windcode/__main__.py +4 -0
- windcode/auth/__init__.py +11 -0
- windcode/auth/store.py +90 -0
- windcode/cli.py +181 -0
- windcode/config/__init__.py +41 -0
- windcode/config/loader.py +117 -0
- windcode/config/models.py +203 -0
- windcode/config/writer.py +74 -0
- windcode/context/__init__.py +18 -0
- windcode/context/compactor.py +72 -0
- windcode/context/estimator.py +89 -0
- windcode/context/truncation.py +87 -0
- windcode/domain/__init__.py +1 -0
- windcode/domain/errors.py +33 -0
- windcode/domain/events.py +597 -0
- windcode/domain/messages.py +226 -0
- windcode/domain/models.py +73 -0
- windcode/domain/subagents.py +263 -0
- windcode/domain/tools.py +55 -0
- windcode/extensions/__init__.py +27 -0
- windcode/extensions/commands.py +25 -0
- windcode/extensions/discovery.py +139 -0
- windcode/extensions/events.py +58 -0
- windcode/extensions/hooks/__init__.py +4 -0
- windcode/extensions/hooks/dispatcher.py +107 -0
- windcode/extensions/hooks/executor.py +49 -0
- windcode/extensions/hooks/loader.py +101 -0
- windcode/extensions/hooks/models.py +109 -0
- windcode/extensions/mcp/__init__.py +10 -0
- windcode/extensions/mcp/adapter.py +101 -0
- windcode/extensions/mcp/catalog.py +153 -0
- windcode/extensions/mcp/client.py +273 -0
- windcode/extensions/mcp/runtime.py +144 -0
- windcode/extensions/mcp/tools.py +570 -0
- windcode/extensions/models.py +168 -0
- windcode/extensions/paths.py +71 -0
- windcode/extensions/plugins/__init__.py +3 -0
- windcode/extensions/plugins/installer.py +93 -0
- windcode/extensions/plugins/manifest.py +166 -0
- windcode/extensions/runtime.py +366 -0
- windcode/extensions/service.py +437 -0
- windcode/extensions/skills/__init__.py +3 -0
- windcode/extensions/skills/loader.py +67 -0
- windcode/extensions/skills/parser.py +57 -0
- windcode/extensions/skills/tools.py +213 -0
- windcode/extensions/snapshot.py +57 -0
- windcode/extensions/state.py +158 -0
- windcode/instructions/__init__.py +8 -0
- windcode/instructions/loader.py +50 -0
- windcode/memory/__init__.py +57 -0
- windcode/memory/extraction.py +83 -0
- windcode/memory/models.py +218 -0
- windcode/memory/refiner.py +189 -0
- windcode/memory/security.py +23 -0
- windcode/memory/service.py +179 -0
- windcode/memory/store.py +362 -0
- windcode/observability/__init__.py +4 -0
- windcode/observability/redaction.py +95 -0
- windcode/observability/trace.py +115 -0
- windcode/policy/__init__.py +22 -0
- windcode/policy/engine.py +137 -0
- windcode/policy/models.py +69 -0
- windcode/providers/__init__.py +29 -0
- windcode/providers/_utils.py +19 -0
- windcode/providers/anthropic.py +215 -0
- windcode/providers/base.py +46 -0
- windcode/providers/catalog.py +119 -0
- windcode/providers/errors.py +96 -0
- windcode/providers/openai_compat.py +231 -0
- windcode/providers/openai_responses.py +189 -0
- windcode/providers/registry.py +105 -0
- windcode/runtime/__init__.py +15 -0
- windcode/runtime/control.py +89 -0
- windcode/runtime/event_bus.py +67 -0
- windcode/runtime/loop.py +510 -0
- windcode/runtime/prompts.py +132 -0
- windcode/runtime/report.py +64 -0
- windcode/runtime/retry.py +73 -0
- windcode/runtime/scheduler.py +194 -0
- windcode/runtime/subagents/__init__.py +28 -0
- windcode/runtime/subagents/approvals.py +88 -0
- windcode/runtime/subagents/budgets.py +79 -0
- windcode/runtime/subagents/coordinator.py +714 -0
- windcode/runtime/subagents/factory.py +311 -0
- windcode/runtime/subagents/roles.py +74 -0
- windcode/runtime/subagents/verification.py +53 -0
- windcode/sandbox/__init__.py +3 -0
- windcode/sandbox/bwrap.py +79 -0
- windcode/sdk.py +1259 -0
- windcode/sessions/__init__.py +23 -0
- windcode/sessions/artifacts.py +69 -0
- windcode/sessions/models.py +104 -0
- windcode/sessions/store.py +167 -0
- windcode/sessions/tree.py +35 -0
- windcode/tools/__init__.py +10 -0
- windcode/tools/apply_patch.py +191 -0
- windcode/tools/ask_user.py +58 -0
- windcode/tools/builtins.py +44 -0
- windcode/tools/edit_file.py +54 -0
- windcode/tools/filesystem.py +77 -0
- windcode/tools/glob.py +35 -0
- windcode/tools/grep.py +66 -0
- windcode/tools/memory.py +400 -0
- windcode/tools/read_file.py +54 -0
- windcode/tools/registry.py +120 -0
- windcode/tools/shell.py +159 -0
- windcode/tools/subagents/__init__.py +31 -0
- windcode/tools/subagents/cancel.py +35 -0
- windcode/tools/subagents/integrate.py +54 -0
- windcode/tools/subagents/list.py +46 -0
- windcode/tools/subagents/spawn.py +86 -0
- windcode/tools/subagents/wait.py +74 -0
- windcode/tools/write_file.py +61 -0
- windcode/tui/__init__.py +3 -0
- windcode/tui/app.py +1015 -0
- windcode/tui/commands.py +90 -0
- windcode/tui/permission_display.py +24 -0
- windcode/tui/styles.tcss +591 -0
- windcode/tui/widgets/__init__.py +31 -0
- windcode/tui/widgets/approval.py +98 -0
- windcode/tui/widgets/command_menu.py +90 -0
- windcode/tui/widgets/extensions.py +48 -0
- windcode/tui/widgets/input.py +110 -0
- windcode/tui/widgets/memory.py +143 -0
- windcode/tui/widgets/messages.py +299 -0
- windcode/tui/widgets/models.py +565 -0
- windcode/tui/widgets/question.py +46 -0
- windcode/tui/widgets/sessions.py +68 -0
- windcode/tui/widgets/status.py +46 -0
- windcode/tui/widgets/subagents.py +195 -0
- windcode/tui/widgets/tools.py +66 -0
- windcode/tui/widgets/welcome.py +149 -0
- windcode/types.py +80 -0
- windcode/worktrees/__init__.py +24 -0
- windcode/worktrees/git.py +92 -0
- windcode/worktrees/manager.py +265 -0
- windcode/worktrees/models.py +62 -0
- windcode-0.1.0.dist-info/METADATA +207 -0
- windcode-0.1.0.dist-info/RECORD +143 -0
- windcode-0.1.0.dist-info/WHEEL +4 -0
- windcode-0.1.0.dist-info/entry_points.txt +2 -0
- windcode-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import re
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from windcode.domain.subagents import SubagentRecord
|
|
8
|
+
from windcode.worktrees.git import GitRunner
|
|
9
|
+
from windcode.worktrees.models import (
|
|
10
|
+
CleanupResult,
|
|
11
|
+
GitBaseline,
|
|
12
|
+
GitErrorCategory,
|
|
13
|
+
IntegrationResult,
|
|
14
|
+
WorktreeError,
|
|
15
|
+
WorktreeLease,
|
|
16
|
+
WorktreeResult,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
_SAFE_COMPONENT = re.compile(r"[^a-zA-Z0-9_.-]+")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _safe_component(value: str) -> str:
|
|
23
|
+
cleaned = _SAFE_COMPONENT.sub("-", value).strip(".-")
|
|
24
|
+
return cleaned[:48] or "task"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _resolve(path: Path) -> Path:
|
|
28
|
+
return path.expanduser().resolve()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _exists(path: Path) -> bool:
|
|
32
|
+
return path.exists()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _mkdir(path: Path) -> None:
|
|
36
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class WorktreeManager:
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
*,
|
|
43
|
+
runner: GitRunner | None = None,
|
|
44
|
+
worktrees_root: Path | None = None,
|
|
45
|
+
) -> None:
|
|
46
|
+
self.runner = runner or GitRunner()
|
|
47
|
+
self.worktrees_root = _resolve(worktrees_root) if worktrees_root else None
|
|
48
|
+
self._lock = asyncio.Lock()
|
|
49
|
+
|
|
50
|
+
async def validate_parent(self, workspace: Path) -> GitBaseline:
|
|
51
|
+
workspace = _resolve(workspace)
|
|
52
|
+
try:
|
|
53
|
+
repository_result = await self.runner.run(
|
|
54
|
+
("rev-parse", "--show-toplevel"), cwd=workspace
|
|
55
|
+
)
|
|
56
|
+
except FileNotFoundError as exc:
|
|
57
|
+
raise WorktreeError(
|
|
58
|
+
GitErrorCategory.WORKTREE_UNAVAILABLE, "Git is unavailable"
|
|
59
|
+
) from exc
|
|
60
|
+
repository = _resolve(Path(repository_result.stdout.strip()))
|
|
61
|
+
branch_result = await self.runner.run(
|
|
62
|
+
("symbolic-ref", "--quiet", "--short", "HEAD"), cwd=repository, check=False
|
|
63
|
+
)
|
|
64
|
+
if branch_result.returncode != 0 or not branch_result.stdout.strip():
|
|
65
|
+
raise WorktreeError(
|
|
66
|
+
GitErrorCategory.DETACHED_HEAD,
|
|
67
|
+
"write subagents require the parent workspace to be on a branch",
|
|
68
|
+
)
|
|
69
|
+
commit = (await self.runner.run(("rev-parse", "HEAD"), cwd=repository)).stdout.strip()
|
|
70
|
+
await self.runner.run(("worktree", "list", "--porcelain"), cwd=repository)
|
|
71
|
+
status = (
|
|
72
|
+
await self.runner.run(
|
|
73
|
+
("status", "--porcelain=v1", "--untracked-files=all"), cwd=repository
|
|
74
|
+
)
|
|
75
|
+
).stdout
|
|
76
|
+
if status.strip():
|
|
77
|
+
details = ", ".join(line.strip() for line in status.splitlines()[:5])
|
|
78
|
+
raise WorktreeError(
|
|
79
|
+
GitErrorCategory.DIRTY_WORKSPACE,
|
|
80
|
+
f"parent workspace is not clean: {details}",
|
|
81
|
+
)
|
|
82
|
+
return GitBaseline(
|
|
83
|
+
repository=repository, branch=branch_result.stdout.strip(), commit=commit
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
async def create(
|
|
87
|
+
self,
|
|
88
|
+
subagent_id: str,
|
|
89
|
+
task_name: str,
|
|
90
|
+
baseline: GitBaseline,
|
|
91
|
+
*,
|
|
92
|
+
parent_run_id: str = "run",
|
|
93
|
+
) -> WorktreeLease:
|
|
94
|
+
safe_run = _safe_component(parent_run_id)
|
|
95
|
+
safe_task = _safe_component(task_name)
|
|
96
|
+
safe_id = _safe_component(subagent_id)
|
|
97
|
+
branch = f"windcode/subagents/{safe_run}/{safe_task}-{safe_id[:12]}"
|
|
98
|
+
root = self.worktrees_root or (
|
|
99
|
+
baseline.repository.parent / f".{baseline.repository.name}-windcode-worktrees"
|
|
100
|
+
)
|
|
101
|
+
path = _resolve(root / f"{safe_task}-{safe_id[:12]}")
|
|
102
|
+
if path.is_relative_to(baseline.repository):
|
|
103
|
+
raise WorktreeError(
|
|
104
|
+
GitErrorCategory.INVALID_PATH,
|
|
105
|
+
"subagent Worktree must be outside the parent repository",
|
|
106
|
+
)
|
|
107
|
+
async with self._lock:
|
|
108
|
+
_mkdir(root)
|
|
109
|
+
if _exists(path):
|
|
110
|
+
raise WorktreeError(
|
|
111
|
+
GitErrorCategory.INVALID_PATH, f"Worktree path already exists: {path}"
|
|
112
|
+
)
|
|
113
|
+
await self.runner.run(
|
|
114
|
+
("worktree", "add", "-b", branch, str(path), baseline.commit),
|
|
115
|
+
cwd=baseline.repository,
|
|
116
|
+
)
|
|
117
|
+
lease = WorktreeLease(subagent_id, path, branch, baseline.commit)
|
|
118
|
+
try:
|
|
119
|
+
await self._validate_lease(lease)
|
|
120
|
+
except BaseException:
|
|
121
|
+
await self.runner.run(
|
|
122
|
+
("worktree", "remove", "--force", str(path)),
|
|
123
|
+
cwd=baseline.repository,
|
|
124
|
+
check=False,
|
|
125
|
+
)
|
|
126
|
+
await self.runner.run(
|
|
127
|
+
("branch", "-D", branch), cwd=baseline.repository, check=False
|
|
128
|
+
)
|
|
129
|
+
raise
|
|
130
|
+
return lease
|
|
131
|
+
|
|
132
|
+
async def _validate_lease(self, lease: WorktreeLease) -> Path:
|
|
133
|
+
if not _exists(lease.path):
|
|
134
|
+
raise WorktreeError(
|
|
135
|
+
GitErrorCategory.INVALID_PATH, f"Worktree path does not exist: {lease.path}"
|
|
136
|
+
)
|
|
137
|
+
root = _resolve(
|
|
138
|
+
Path(
|
|
139
|
+
(
|
|
140
|
+
await self.runner.run(("rev-parse", "--show-toplevel"), cwd=lease.path)
|
|
141
|
+
).stdout.strip()
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
if root != _resolve(lease.path):
|
|
145
|
+
raise WorktreeError(GitErrorCategory.INVALID_PATH, "Worktree path ownership mismatch")
|
|
146
|
+
branch = (
|
|
147
|
+
await self.runner.run(("branch", "--show-current"), cwd=lease.path)
|
|
148
|
+
).stdout.strip()
|
|
149
|
+
if branch != lease.branch:
|
|
150
|
+
raise WorktreeError(GitErrorCategory.INVALID_PATH, "Worktree branch mismatch")
|
|
151
|
+
return root
|
|
152
|
+
|
|
153
|
+
async def inspect(self, lease: WorktreeLease) -> WorktreeResult:
|
|
154
|
+
await self._validate_lease(lease)
|
|
155
|
+
status = (
|
|
156
|
+
await self.runner.run(
|
|
157
|
+
("status", "--porcelain=v1", "--untracked-files=all"), cwd=lease.path
|
|
158
|
+
)
|
|
159
|
+
).stdout
|
|
160
|
+
head = (await self.runner.run(("rev-parse", "HEAD"), cwd=lease.path)).stdout.strip()
|
|
161
|
+
commit = head if head != lease.base_commit else None
|
|
162
|
+
changed_files: tuple[str, ...] = ()
|
|
163
|
+
diff_stat = ""
|
|
164
|
+
if commit is not None:
|
|
165
|
+
names = (
|
|
166
|
+
await self.runner.run(
|
|
167
|
+
("diff", "--name-only", f"{lease.base_commit}..{commit}"), cwd=lease.path
|
|
168
|
+
)
|
|
169
|
+
).stdout
|
|
170
|
+
changed_files = tuple(line for line in names.splitlines() if line)
|
|
171
|
+
diff_stat = (
|
|
172
|
+
await self.runner.run(
|
|
173
|
+
("diff", "--stat", f"{lease.base_commit}..{commit}"), cwd=lease.path
|
|
174
|
+
)
|
|
175
|
+
).stdout.strip()
|
|
176
|
+
return WorktreeResult(not status.strip(), commit, changed_files, diff_stat)
|
|
177
|
+
|
|
178
|
+
async def integrate(self, lease: WorktreeLease, parent_workspace: Path) -> IntegrationResult:
|
|
179
|
+
worktree = await self.inspect(lease)
|
|
180
|
+
if not worktree.clean or worktree.commit is None:
|
|
181
|
+
raise WorktreeError(
|
|
182
|
+
GitErrorCategory.DIRTY_WORKSPACE,
|
|
183
|
+
"only a clean Worktree with a new commit can be integrated",
|
|
184
|
+
)
|
|
185
|
+
async with self._lock:
|
|
186
|
+
baseline = await self.validate_parent(parent_workspace)
|
|
187
|
+
before = baseline.commit
|
|
188
|
+
cherry_pick = await self.runner.run(
|
|
189
|
+
("cherry-pick", worktree.commit), cwd=baseline.repository, check=False
|
|
190
|
+
)
|
|
191
|
+
if cherry_pick.returncode == 0:
|
|
192
|
+
after = (
|
|
193
|
+
await self.runner.run(("rev-parse", "HEAD"), cwd=baseline.repository)
|
|
194
|
+
).stdout.strip()
|
|
195
|
+
return IntegrationResult(True, before, after)
|
|
196
|
+
|
|
197
|
+
conflicts = (
|
|
198
|
+
await self.runner.run(
|
|
199
|
+
("diff", "--name-only", "--diff-filter=U"),
|
|
200
|
+
cwd=baseline.repository,
|
|
201
|
+
check=False,
|
|
202
|
+
)
|
|
203
|
+
).stdout
|
|
204
|
+
abort = await self.runner.run(
|
|
205
|
+
("cherry-pick", "--abort"), cwd=baseline.repository, check=False
|
|
206
|
+
)
|
|
207
|
+
restored = (
|
|
208
|
+
await self.runner.run(("rev-parse", "HEAD"), cwd=baseline.repository)
|
|
209
|
+
).stdout.strip()
|
|
210
|
+
if abort.returncode != 0 or restored != before:
|
|
211
|
+
raise WorktreeError(
|
|
212
|
+
GitErrorCategory.COMMAND_FAILED,
|
|
213
|
+
"failed to abort conflicting integration and restore the parent HEAD",
|
|
214
|
+
)
|
|
215
|
+
return IntegrationResult(
|
|
216
|
+
False,
|
|
217
|
+
before,
|
|
218
|
+
restored,
|
|
219
|
+
tuple(line for line in conflicts.splitlines() if line),
|
|
220
|
+
cherry_pick.stderr.strip() or cherry_pick.stdout.strip(),
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
async def cleanup(
|
|
224
|
+
self,
|
|
225
|
+
lease: WorktreeLease,
|
|
226
|
+
repository: Path,
|
|
227
|
+
*,
|
|
228
|
+
integrated: bool,
|
|
229
|
+
) -> CleanupResult:
|
|
230
|
+
if not integrated:
|
|
231
|
+
return CleanupResult(False, lease.path, "task has not been successfully integrated")
|
|
232
|
+
try:
|
|
233
|
+
result = await self.inspect(lease)
|
|
234
|
+
except WorktreeError as exc:
|
|
235
|
+
return CleanupResult(False, lease.path, str(exc))
|
|
236
|
+
if not result.clean:
|
|
237
|
+
return CleanupResult(False, lease.path, "Worktree contains uncommitted changes")
|
|
238
|
+
async with self._lock:
|
|
239
|
+
removed = await self.runner.run(
|
|
240
|
+
("worktree", "remove", str(lease.path)), cwd=repository, check=False
|
|
241
|
+
)
|
|
242
|
+
if removed.returncode != 0:
|
|
243
|
+
return CleanupResult(False, lease.path, removed.stderr.strip() or "remove failed")
|
|
244
|
+
branch = await self.runner.run(
|
|
245
|
+
("branch", "-d", lease.branch), cwd=repository, check=False
|
|
246
|
+
)
|
|
247
|
+
if branch.returncode != 0:
|
|
248
|
+
return CleanupResult(False, None, branch.stderr.strip() or "branch cleanup failed")
|
|
249
|
+
return CleanupResult(True)
|
|
250
|
+
|
|
251
|
+
async def recover(self, record: SubagentRecord) -> WorktreeLease | None:
|
|
252
|
+
if record.worktree_path is None or not _exists(record.worktree_path):
|
|
253
|
+
return None
|
|
254
|
+
if record.branch is None or record.base_commit is None:
|
|
255
|
+
raise WorktreeError(
|
|
256
|
+
GitErrorCategory.INVALID_PATH, "persisted Worktree record is incomplete"
|
|
257
|
+
)
|
|
258
|
+
lease = WorktreeLease(
|
|
259
|
+
record.subagent_id,
|
|
260
|
+
_resolve(record.worktree_path),
|
|
261
|
+
record.branch,
|
|
262
|
+
record.base_commit,
|
|
263
|
+
)
|
|
264
|
+
await self._validate_lease(lease)
|
|
265
|
+
return lease
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from enum import StrEnum
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class GitErrorCategory(StrEnum):
|
|
9
|
+
NOT_REPOSITORY = "not_repository"
|
|
10
|
+
DIRTY_WORKSPACE = "dirty_workspace"
|
|
11
|
+
DETACHED_HEAD = "detached_head"
|
|
12
|
+
WORKTREE_UNAVAILABLE = "worktree_unavailable"
|
|
13
|
+
COMMAND_FAILED = "command_failed"
|
|
14
|
+
TIMEOUT = "timeout"
|
|
15
|
+
CANCELLED = "cancelled"
|
|
16
|
+
CONFLICT = "conflict"
|
|
17
|
+
INVALID_PATH = "invalid_path"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class WorktreeError(RuntimeError):
|
|
21
|
+
def __init__(self, category: GitErrorCategory, message: str) -> None:
|
|
22
|
+
self.category = category
|
|
23
|
+
super().__init__(message)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True, slots=True)
|
|
27
|
+
class GitBaseline:
|
|
28
|
+
repository: Path
|
|
29
|
+
branch: str
|
|
30
|
+
commit: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True, slots=True)
|
|
34
|
+
class WorktreeLease:
|
|
35
|
+
subagent_id: str
|
|
36
|
+
path: Path
|
|
37
|
+
branch: str
|
|
38
|
+
base_commit: str
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(frozen=True, slots=True)
|
|
42
|
+
class WorktreeResult:
|
|
43
|
+
clean: bool
|
|
44
|
+
commit: str | None
|
|
45
|
+
changed_files: tuple[str, ...]
|
|
46
|
+
diff_stat: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True, slots=True)
|
|
50
|
+
class IntegrationResult:
|
|
51
|
+
integrated: bool
|
|
52
|
+
parent_commit_before: str
|
|
53
|
+
parent_commit_after: str
|
|
54
|
+
conflict_files: tuple[str, ...] = ()
|
|
55
|
+
error_message: str | None = None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True, slots=True)
|
|
59
|
+
class CleanupResult:
|
|
60
|
+
removed: bool
|
|
61
|
+
retained_path: Path | None = None
|
|
62
|
+
reason: str | None = None
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: windcode
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A safe, extensible terminal coding agent
|
|
5
|
+
Project-URL: Homepage, https://github.com/tingfeng347/windcode
|
|
6
|
+
Project-URL: Repository, https://github.com/tingfeng347/windcode
|
|
7
|
+
Project-URL: Issues, https://github.com/tingfeng347/windcode/issues
|
|
8
|
+
Author: Tingfeng347
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent,ai,cli,coding-assistant,mcp,tui
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Natural Language :: Chinese (Simplified)
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development
|
|
21
|
+
Classifier: Topic :: Terminals
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: aiohttp>=3.12.0
|
|
24
|
+
Requires-Dist: anthropic[aiohttp]>=0.98.0
|
|
25
|
+
Requires-Dist: httpx<1,>=0.28.0
|
|
26
|
+
Requires-Dist: jsonschema<5,>=4.25.0
|
|
27
|
+
Requires-Dist: mcp<2,>=1.10.0
|
|
28
|
+
Requires-Dist: openai[aiohttp]>=2.34.0
|
|
29
|
+
Requires-Dist: platformdirs>=4.3.0
|
|
30
|
+
Requires-Dist: pydantic>=2.11.0
|
|
31
|
+
Requires-Dist: pyyaml<7,>=6.0.2
|
|
32
|
+
Requires-Dist: textual>=6.0.0
|
|
33
|
+
Requires-Dist: tomli-w>=1.2.0
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# Windcode
|
|
37
|
+
|
|
38
|
+
Windcode 是一个Coding Agent。它可以在本地
|
|
39
|
+
工作区中读取和修改代码、执行命令、运行测试、恢复会话,并通过权限策略与 Linux 沙箱控制
|
|
40
|
+
高风险操作。
|
|
41
|
+
|
|
42
|
+

|
|
43
|
+

|
|
44
|
+

|
|
45
|
+

|
|
46
|
+

|
|
47
|
+
|
|
48
|
+
## 功能
|
|
49
|
+
|
|
50
|
+
- Textual 终端工作台与 Python SDK
|
|
51
|
+
- Anthropic Messages、OpenAI Responses 和 OpenAI-compatible 模型协议
|
|
52
|
+
- 流式输出、工具调用、审批、取消、重试与显式模型回退
|
|
53
|
+
- 会话恢复、历史回退、上下文压缩和本地 trace
|
|
54
|
+
- 多子智能体并行执行与独立 Worktree
|
|
55
|
+
- 项目级长期记忆:用户画像、项目事实、经验、SOP 与主动查询
|
|
56
|
+
- MCP Server、Skills、Hooks 和本地插件扩展
|
|
57
|
+
- 四种权限模式与可选 bubblewrap 沙箱
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## 快速开始
|
|
61
|
+
|
|
62
|
+
环境要求:Linux、Python 3.12+、[uv](https://docs.astral.sh/uv/)。bubblewrap 可选。
|
|
63
|
+
|
|
64
|
+
从 PyPI 安装命令行工具:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
uv tool install windcode
|
|
68
|
+
windcode /path/to/project
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
也可以安装到当前 Python 环境:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv pip install windcode
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
从源码运行:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
uv sync --frozen --all-groups
|
|
81
|
+
cp .windcode/config.toml.example .windcode/config.toml
|
|
82
|
+
uv run windcode /path/to/project
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
最小模型配置:
|
|
86
|
+
|
|
87
|
+
```toml
|
|
88
|
+
primary_provider = "primary"
|
|
89
|
+
|
|
90
|
+
[providers.primary]
|
|
91
|
+
protocol = "openai_compatible"
|
|
92
|
+
model = "your-model"
|
|
93
|
+
base_url = "https://example.com/v1"
|
|
94
|
+
api_key_env = "MODEL_API_KEY"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
密钥应通过环境变量或 Windcode 凭据存储提供,不要写入项目配置。
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
export MODEL_API_KEY="..."
|
|
101
|
+
uv run windcode .
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
常用启动参数:
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
--config FILE
|
|
108
|
+
--model PROVIDER_OR_MODEL
|
|
109
|
+
--resume SESSION_ID
|
|
110
|
+
--permission-mode plan|default|accept_edits|full_access
|
|
111
|
+
--sandbox / --no-sandbox
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 常用命令
|
|
115
|
+
|
|
116
|
+
```text
|
|
117
|
+
/new 新建会话
|
|
118
|
+
/resume [SESSION_ID] 恢复会话
|
|
119
|
+
/history 查看历史节点
|
|
120
|
+
/rewind RECORD_ID 回退到历史记录
|
|
121
|
+
/model 管理模型与 Provider
|
|
122
|
+
/mode MODE 切换权限模式
|
|
123
|
+
/memory 管理长期记忆
|
|
124
|
+
/extensions 管理扩展
|
|
125
|
+
/compact 压缩当前上下文
|
|
126
|
+
/agents 查看子智能体
|
|
127
|
+
/status 查看运行状态
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## MCP Server
|
|
131
|
+
|
|
132
|
+
```toml
|
|
133
|
+
[extensions]
|
|
134
|
+
enabled = true
|
|
135
|
+
|
|
136
|
+
[extensions.mcp_servers.example]
|
|
137
|
+
transport = "streamable_http"
|
|
138
|
+
url = "https://example.com/mcp"
|
|
139
|
+
enable = true
|
|
140
|
+
required = false
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`enable = false` 的服务器不会连接、不会参与工具搜索,也不会注入模型上下文。`required` 只在
|
|
144
|
+
服务器启用时表示启动阶段必须连接成功。
|
|
145
|
+
|
|
146
|
+
## 本地状态
|
|
147
|
+
|
|
148
|
+
Windcode 将记忆、会话、trace、扩展状态和 Worktree 统一存放在选定的状态根下:
|
|
149
|
+
|
|
150
|
+
```toml
|
|
151
|
+
[storage]
|
|
152
|
+
project_state_root = ".windcode/state"
|
|
153
|
+
user_storage_root = "~/.local/state/windcode/state"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
配置项目状态根时优先使用项目目录;未配置时使用用户状态目录。`.windcode/config.toml` 和
|
|
157
|
+
`.windcode/state/` 都不应提交到 Git。
|
|
158
|
+
|
|
159
|
+
## 开发
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
uv run ruff format --check .
|
|
163
|
+
uv run ruff check .
|
|
164
|
+
uv run pyright
|
|
165
|
+
uv run pytest -q
|
|
166
|
+
uv build
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 构建与发布
|
|
170
|
+
|
|
171
|
+
发布前更新 `pyproject.toml` 和 `src/windcode/__init__.py` 中的版本号,并完成完整检查:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
uv sync --frozen --all-groups
|
|
175
|
+
uv run ruff format --check .
|
|
176
|
+
uv run ruff check .
|
|
177
|
+
uv run pyright
|
|
178
|
+
uv run pytest -q
|
|
179
|
+
uv build --no-sources
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
可以先发布到 TestPyPI 验证:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
uv publish \
|
|
186
|
+
--publish-url https://test.pypi.org/legacy/ \
|
|
187
|
+
--token "$TEST_PYPI_TOKEN"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
正式版本通过 GitHub Release 自动发布:创建与项目版本一致的标签,例如 `v0.1.0`,然后发布
|
|
191
|
+
GitHub Release。`.github/workflows/publish.yml` 会验证标签、运行测试、构建发行包,并使用
|
|
192
|
+
PyPI Trusted Publishing 发布。首次发布前需要在 PyPI 配置以下 Trusted Publisher:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
Owner: tingfeng347
|
|
196
|
+
Repository: windcode
|
|
197
|
+
Workflow: publish.yml
|
|
198
|
+
Environment: pypi
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
PyPI 不允许覆盖已经发布的同名版本;重新发布前必须增加版本号。
|
|
202
|
+
|
|
203
|
+
生产代码位于 `src/windcode/`。本地 `tests/` 与 `spec/` 目录由 Git 忽略,仅用于开发和规格管理。
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
[Apache-2.0](LICENSE)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
windcode/__init__.py,sha256=73wLpWuYXhUY0sqNdusxtTx1u0NqSzlBo9Kg2uzxwjg,112
|
|
2
|
+
windcode/__main__.py,sha256=eVJiCQBfl2fHUaa2hkQOWBdUMwXKeAPCV9yY-20rvpg,69
|
|
3
|
+
windcode/cli.py,sha256=ummnlFAzPA6g05vCKic1ztJKA-bvYoUo72ajIaYD_-U,6844
|
|
4
|
+
windcode/sdk.py,sha256=aw4SZvfFiDzllVI8iUGpUPYlQOLochP4jL4dwM5QllQ,53055
|
|
5
|
+
windcode/types.py,sha256=G5pI3aW5THKom4nlQJzeUtLkaVMoC88t_q2c5BoZsIo,1792
|
|
6
|
+
windcode/auth/__init__.py,sha256=s5qLbtQu4C32u1KdubMDD1xGQH9wulJC168f1xaW2sE,201
|
|
7
|
+
windcode/auth/store.py,sha256=aJ_qpdZN0SsI6gfm5jTfZCzAu3E025AkUTmf8GLodQA,3417
|
|
8
|
+
windcode/config/__init__.py,sha256=KvwUx9yljb4AO5bcAgSHcBF_XOQH4wjNoTftq_cz3ho,932
|
|
9
|
+
windcode/config/loader.py,sha256=wGINWvpTI5Z8rZs00byMTwwxSOQsFoKvJHsBCUUE-jA,4734
|
|
10
|
+
windcode/config/models.py,sha256=xKrGcjz-s1VhExHHKcn0kWyl2PETzcCqJ0pUYh1pT-E,7923
|
|
11
|
+
windcode/config/writer.py,sha256=oE-18hbuCR6Q-8ePhRsr3H7xzw1Wa1s5yPo4cFywfhU,2512
|
|
12
|
+
windcode/context/__init__.py,sha256=Dzjn41dbOox4xe1flx1S4VOvoIICwnAuxNU6Ks8xIt4,491
|
|
13
|
+
windcode/context/compactor.py,sha256=P-_xMyiykiE1GAhS_Th60hT1GfJKfSNdt7w4rQlGo40,2365
|
|
14
|
+
windcode/context/estimator.py,sha256=zBv-9hOI2gr85AV4TxN-QShf2VssVmu1zN0QTOy85P8,2995
|
|
15
|
+
windcode/context/truncation.py,sha256=MtO37hxODCa8ghePY5NEN1Tg-zfj1QlF55_0BaaYG_s,2888
|
|
16
|
+
windcode/domain/__init__.py,sha256=0YMP7bBLEIS9xp-c9_HgAuy60dfETgDLiwvfoAj0FH8,40
|
|
17
|
+
windcode/domain/errors.py,sha256=DkALAm8lIceCo_cjEfF7jU_P4QyUQl96q10lAtRLucM,927
|
|
18
|
+
windcode/domain/events.py,sha256=4FlZIl4wSW88tab91GOEnhT01BN6kUlxfgJfqmdijGE,19414
|
|
19
|
+
windcode/domain/messages.py,sha256=O0vVd9Uih1hchi-LsKME30vi7-6XeivvVbV6yBwdlDE,7618
|
|
20
|
+
windcode/domain/models.py,sha256=OA6u9GTIP0f9qnf0mGvCXGH8vKpBYHyuk5fZLRo01cE,1560
|
|
21
|
+
windcode/domain/subagents.py,sha256=zbLbSBSPrvKdNoy5QuVE0EzEibsgoj_vbzffpQUmuR4,9537
|
|
22
|
+
windcode/domain/tools.py,sha256=af5Fr5qG3aoHZnFULknBQHOAd0MfCSFX5hMBMfruaSc,1365
|
|
23
|
+
windcode/extensions/__init__.py,sha256=VzVoqNKQ8vJmKcAC4CQyHE5GnKkeZk0FVi7BBKFJvBw,554
|
|
24
|
+
windcode/extensions/commands.py,sha256=CIniu1MFSWS5ysy6EwGLx00LwUEnty0yqz5qBk9LhE8,892
|
|
25
|
+
windcode/extensions/discovery.py,sha256=2ZDsgkAZt-ropUsW51HuIN90vwaMKsIHgSlhvogh68w,5380
|
|
26
|
+
windcode/extensions/events.py,sha256=0pkMqldCjl0KxLeUPZv3ya8NvUgqO77dmjCApgCwWP0,1410
|
|
27
|
+
windcode/extensions/models.py,sha256=ZE7wyIXj_wL3PXaucLv6FRzA6Ihuyl5VCtoFo8kjp18,4562
|
|
28
|
+
windcode/extensions/paths.py,sha256=bvyDE7Weka3yKKxkJXSMDIwDP5zndzXZgOb0UL9_540,2886
|
|
29
|
+
windcode/extensions/runtime.py,sha256=0MWCYbaUvV1aEc-VEGjcs4OrGPWyinA7XhdSi0hzUn8,13254
|
|
30
|
+
windcode/extensions/service.py,sha256=RF9EHX8Nt5oS-f1djfQ3AUZxf_UWkeyaAi2VBNwdZsU,17583
|
|
31
|
+
windcode/extensions/snapshot.py,sha256=_llJ28td26FET9Ug33L9rf4Ej07hhQTeyoMTHVoRZpo,1836
|
|
32
|
+
windcode/extensions/state.py,sha256=j4q2vBNVts2cAN6N5YALyaKSIZNMdg9nHWEjnkwJt4w,5636
|
|
33
|
+
windcode/extensions/hooks/__init__.py,sha256=--8uqNAykerTXedXCepSJvjiCFFP1Ps8HbD5oAv2dUc,224
|
|
34
|
+
windcode/extensions/hooks/dispatcher.py,sha256=fsOiLaxbABucJEIcualz2fgLJ5_ZkU6LKtKtj3Slrhc,4336
|
|
35
|
+
windcode/extensions/hooks/executor.py,sha256=dmy00Hj-fBxfkREDCUq8MPOQV8nCP6gtPUesCEKk3eg,1988
|
|
36
|
+
windcode/extensions/hooks/loader.py,sha256=JlW48HFsZPnxh3T9wZGHoMgd6kHzTF7NPIZXm8KbJSU,3764
|
|
37
|
+
windcode/extensions/hooks/models.py,sha256=9xALSmQi-XN15MtWAwpXpi0uBZUwzhKI9VH0oDkd-V4,2676
|
|
38
|
+
windcode/extensions/mcp/__init__.py,sha256=3h9LzjXWoHe2HHYj8N5b__-X7fyfjZ3_IoIUX42mYwQ,290
|
|
39
|
+
windcode/extensions/mcp/adapter.py,sha256=D_kVsqAWxlZXpYveOWBNRTqzGMBeT1uEtPONkLL2Ihw,3887
|
|
40
|
+
windcode/extensions/mcp/catalog.py,sha256=EhS91ecxvWia-pi-yeDcu8_c0etB7BkeetkxFUgIvbQ,4576
|
|
41
|
+
windcode/extensions/mcp/client.py,sha256=wkL-faWX0P6VYg6PePF-vOFqSKJdntKjrvPOZKZxb0M,10141
|
|
42
|
+
windcode/extensions/mcp/runtime.py,sha256=a6VAlfPgGCzVDC0-TfLgNmWNmeAIgwORLJeFfNLCEGw,5167
|
|
43
|
+
windcode/extensions/mcp/tools.py,sha256=STKfXZbneMH0E2iE4q64mvSuXPOO8F1FD2-G9bBFNtg,21819
|
|
44
|
+
windcode/extensions/plugins/__init__.py,sha256=5KRKp7Nr4OsOUScuqAIEbzOU7sVgMEBJ7XESAqrJBb8,142
|
|
45
|
+
windcode/extensions/plugins/installer.py,sha256=5KNhFasFCqaG3dsTOSE7F3RSKH_tgRtwEc-sCh9aM08,3521
|
|
46
|
+
windcode/extensions/plugins/manifest.py,sha256=9Wv5f3sHBB8nEyIF6LEXsD8f0BcOnxYO_aKyaAMeoNI,5869
|
|
47
|
+
windcode/extensions/skills/__init__.py,sha256=NT3NhaXelyagOdHmSAvDOSPLnZhNzbH1Z3BBqvQc85I,135
|
|
48
|
+
windcode/extensions/skills/loader.py,sha256=ZYNhQCL1n2zs3cEHQ5GpVD9UdeEpt5j46WTNhlHzqr0,2339
|
|
49
|
+
windcode/extensions/skills/parser.py,sha256=5Jrccyck9fZigTnbXGIkrm8NCHqeh8mOkj1qWlSdUbE,2222
|
|
50
|
+
windcode/extensions/skills/tools.py,sha256=zTvg7Gwnhb8f4Ysh0mkS8MAn_tr5GsVdRWQr5dQi0EA,7284
|
|
51
|
+
windcode/instructions/__init__.py,sha256=Ac91uGe_kIFNNVDBEqaY2yxWFOpD7U-y3BGA8G-sNVA,235
|
|
52
|
+
windcode/instructions/loader.py,sha256=arxc1nPrCxsbgyzOua57oqrAjmpQdZJTJQa42L9QJaY,1533
|
|
53
|
+
windcode/memory/__init__.py,sha256=wx2qSTiqfm7axiioaaN9K3WDDKU06_g35xP93-tW6Hc,1465
|
|
54
|
+
windcode/memory/extraction.py,sha256=dMRy8gNKjaScjFxWPs-kgsD3IZ3F0LopJW8xAEo1ADg,3195
|
|
55
|
+
windcode/memory/models.py,sha256=nuGlr6WWlENbCjN2OqgVh-0Fxsb3L219uA-pPYnfh1Q,7108
|
|
56
|
+
windcode/memory/refiner.py,sha256=EAsyT-TxgFmA-o5cVJoXE7o0ESIkZ_wO1Btwd9h2xkw,7767
|
|
57
|
+
windcode/memory/security.py,sha256=nHis2UVbrDPm0begJGuvOyKo4GgJWJVyUbu9ACRV_84,725
|
|
58
|
+
windcode/memory/service.py,sha256=_Tzy-LaNgmWPD2-3po4a_DOdRiW9QQDbLsDwH9jS4Ew,6876
|
|
59
|
+
windcode/memory/store.py,sha256=yoj3UXQZ2LzNxX0x4heKGFHGG94iWtXsDwt_AiY9BsM,14880
|
|
60
|
+
windcode/observability/__init__.py,sha256=prUyTItCGwIIp5Ifxah8dDEVoqOTrc1jaW-wxfmo2Dw,198
|
|
61
|
+
windcode/observability/redaction.py,sha256=J6PkyUQmepZWqicNH7SuQAW3QtTk-lBrvCf3IEvNfWI,2770
|
|
62
|
+
windcode/observability/trace.py,sha256=DvoodmkwF2pybAA5Mr04OLE6t_HLIP-nXuV7lCv1Hs0,4169
|
|
63
|
+
windcode/policy/__init__.py,sha256=TFMwfmK5hAsKA_sdF23_MmklBpJg4gd7_MsloOiLKEs,456
|
|
64
|
+
windcode/policy/engine.py,sha256=0_iZM4r5Mh-u1o2Ie1vTRyoUein-iw9J5sbONllKSxc,4500
|
|
65
|
+
windcode/policy/models.py,sha256=BuKFGhAKjPNw687wNkXopUv7JWHhBE9OxdymhkrYVjg,1538
|
|
66
|
+
windcode/providers/__init__.py,sha256=cstn8SUyy7sCHi2DYzfyY9VrOoaO4I2JUVJmFO2Sx5M,936
|
|
67
|
+
windcode/providers/_utils.py,sha256=7keNdXfhbhrryWLNp5-zrs5h5DpPDtEjkFJb7kt2X44,602
|
|
68
|
+
windcode/providers/anthropic.py,sha256=jSpXYv_n4hbOJNfXQHvKf4pxSPkayVp6pwFR7Mtytso,7837
|
|
69
|
+
windcode/providers/base.py,sha256=CtX-waVXtVVxrH9HVdsR5bO_qYDzvu926Sq5X3wge40,1262
|
|
70
|
+
windcode/providers/catalog.py,sha256=CF3v0cGFXMCwdL7L9rFNFG43p_D94JAm4h0ClmT52Mw,3277
|
|
71
|
+
windcode/providers/errors.py,sha256=HtEZnI1ymHEb4czLDSxR__mjTI6xMi6Uf_hvySYMzDk,3353
|
|
72
|
+
windcode/providers/openai_compat.py,sha256=EYvUaHdLDgpphw8BI_SnjxQex1lszNiZGtkPoa7t-48,9512
|
|
73
|
+
windcode/providers/openai_responses.py,sha256=7ZHy7huY0LHS2l9OkZEcGHIjRhq78w_TkZ_N-_alG9I,7451
|
|
74
|
+
windcode/providers/registry.py,sha256=3Bd3m3LJD2wMkzoWh5uPiQtAbm5U3TCSgKfGqf6oZ_Q,4079
|
|
75
|
+
windcode/runtime/__init__.py,sha256=VLN8SipzhTcBKIPdpsJI_uBBl-SB0rItdeTK7MtpOiI,424
|
|
76
|
+
windcode/runtime/control.py,sha256=q74TpwB-Hu3bEDdv4xtn86k_vaqcIsV-EJ8IaxbtKe8,2845
|
|
77
|
+
windcode/runtime/event_bus.py,sha256=B_pvhx1QTnyVbG9-36DyVemxcQNeD1lug3NPiL6O8i0,2581
|
|
78
|
+
windcode/runtime/loop.py,sha256=xtfWTgOg86zYCsXh3bZx6-ZI51rYg8EN9oEdJCJYwOY,21063
|
|
79
|
+
windcode/runtime/prompts.py,sha256=Hn5dI6mXrMlSEQcvubsa0VNiAvO93RDXAotFYoU3uII,7812
|
|
80
|
+
windcode/runtime/report.py,sha256=TmPnxyVK4UUZ5jzQnvsOQfzFeZI_qx3XAgjlSZrNpe8,2272
|
|
81
|
+
windcode/runtime/retry.py,sha256=zuFeNOzMx8Frw7jsaO3ETxnssLnQMYPH8BWb9OxYE0E,2898
|
|
82
|
+
windcode/runtime/scheduler.py,sha256=0pJfjTbPLB870e-cDhMOXdcjTSXLXI8dD9ZuMZ8R8VQ,7345
|
|
83
|
+
windcode/runtime/subagents/__init__.py,sha256=OkW6oY4IqyGXx7biK7E_xyNMXM-iwOwHrOR74zVeyIA,848
|
|
84
|
+
windcode/runtime/subagents/approvals.py,sha256=EyPl3ILWKJL0VysZ1IPOBQpKX90NBFxeyTOFz9ulXbc,2961
|
|
85
|
+
windcode/runtime/subagents/budgets.py,sha256=zVEzgPLP68RPRYi2q-1xgxF8UEEuml-lggPVePnIfdk,2532
|
|
86
|
+
windcode/runtime/subagents/coordinator.py,sha256=6rh_xS47nNPhNFFaH_plr8RG0zV_fiFmldcd6HK74I0,28653
|
|
87
|
+
windcode/runtime/subagents/factory.py,sha256=G5bmnzUkYbZjR8H5NvtAus7FF_BPSgl4pLmJ_SKoVDQ,11802
|
|
88
|
+
windcode/runtime/subagents/roles.py,sha256=2Ms-cFJMRSG8DGCMtMOy5GDaTYTuDWza2pEeKoJ45DQ,2462
|
|
89
|
+
windcode/runtime/subagents/verification.py,sha256=gDev-qdbOChmL5lpmhCqKp_w5ZZ1FT4pQdg5cGEULvI,1772
|
|
90
|
+
windcode/sandbox/__init__.py,sha256=TGFwBECIHg2nwpOqzY3ApW3pE_k0Q105rJ0Jm77SAaM,158
|
|
91
|
+
windcode/sandbox/bwrap.py,sha256=MnSc5mTAleV05BhBqvEn8gu0xNqDa9PrglSdhviXk2c,2640
|
|
92
|
+
windcode/sessions/__init__.py,sha256=LZA6wHfqTpzNsofCU1cq6F-pK1qFp5Krzn5k8otc8ME,572
|
|
93
|
+
windcode/sessions/artifacts.py,sha256=OMk2tUxjdLDf7tUQ7lYH4xiVGbyGfW0mmobUaOyavvA,2505
|
|
94
|
+
windcode/sessions/models.py,sha256=wyLWj_3TM87S-QCiqEDNiqAWEARpO7IzXRPwbRBquOY,3342
|
|
95
|
+
windcode/sessions/store.py,sha256=swq6mY-6pREOPRx3ODDjhhh3jn86qOlao017UzlBjAo,6569
|
|
96
|
+
windcode/sessions/tree.py,sha256=vcBHSrsbX68Xc2zVMIZfVdjvGw3ekzuRK16Uj_FWWdk,1100
|
|
97
|
+
windcode/tools/__init__.py,sha256=zVLg_n61sgfAR-oJ5iLVoyuMIjVKeEyf0-DjlooeJVU,306
|
|
98
|
+
windcode/tools/apply_patch.py,sha256=PL-ji6xlvrTmCzXZ6l-WbUkgxc9P531hbp_cFwBmmG8,7636
|
|
99
|
+
windcode/tools/ask_user.py,sha256=LHrkMbpfaLUoPJZU1sM71wCd1-MSgR0L3azUN49X40s,2184
|
|
100
|
+
windcode/tools/builtins.py,sha256=431H9OAX6KdSnpM46WljHhw7jvdxjIq_cue8zbtEA0I,1349
|
|
101
|
+
windcode/tools/edit_file.py,sha256=FnnYw8NFhj2GaFITVBU5vdJPREogSRoCLdk_N8tc_zA,1990
|
|
102
|
+
windcode/tools/filesystem.py,sha256=6sNCYzAUmvm_y3BbTBMYPPxtvM27XRJtYbKfwbTe7IY,2350
|
|
103
|
+
windcode/tools/glob.py,sha256=VjLcXKVeh-Yjrfy-tovo0_yK2PLal1aOk0A3PE7jbbk,1139
|
|
104
|
+
windcode/tools/grep.py,sha256=cTF1ht4aWKtQr3rutCezBlTRbZ6JpnSH8LxuCpJ3UH8,2471
|
|
105
|
+
windcode/tools/memory.py,sha256=VOm9u9BbPYo4NywHMPpJjSvIH-8yPCtiP6TUV8ABme4,14228
|
|
106
|
+
windcode/tools/read_file.py,sha256=FnqiTUT5Ae2jtSnE7H_v-WEnsu4UJcZAmcydo8xeQVw,1965
|
|
107
|
+
windcode/tools/registry.py,sha256=utCUpCMJtuCkM35tDYEgw28ZPimz_1KPEQeYDAjOwEw,4264
|
|
108
|
+
windcode/tools/shell.py,sha256=1z36qZ0uzgJ9okifSWhYx-VX8zwihFQiGTUTG20WzSc,5586
|
|
109
|
+
windcode/tools/write_file.py,sha256=ZeJHJ2FLAmSSi3cZt-bHS1dysAQOJ-3gUp7vLtcvX4g,2163
|
|
110
|
+
windcode/tools/subagents/__init__.py,sha256=QqbVbEZKknzphsl-ecIKeX1FDfoifqI5W067YNtjOJE,983
|
|
111
|
+
windcode/tools/subagents/cancel.py,sha256=iVMAoZcVg0ufxoHsvgDeC8wGHQNcUwWFwwSlzGitHIM,1279
|
|
112
|
+
windcode/tools/subagents/integrate.py,sha256=XteXqMJ8CEAVhx8YfKhBOjJzoClV_hAeDB8MoxHjyt4,2034
|
|
113
|
+
windcode/tools/subagents/list.py,sha256=7mGQEh_Jz2UyRZLbTpTYot6ZFXdXbWQixG3yTWzFZDo,1643
|
|
114
|
+
windcode/tools/subagents/spawn.py,sha256=6CpovAguSZFAvBBJvBFPpzdLdRQoCGTDnrqjBLhtsLE,3038
|
|
115
|
+
windcode/tools/subagents/wait.py,sha256=EJ_b-_JN7b_vdpdp8ly6Hc0176YAIxkcsJKiokCiR9Q,2859
|
|
116
|
+
windcode/tui/__init__.py,sha256=K0DprxN5miNlExKuhffx1pkIxpUoEx7Iw1WKRn6RqGQ,68
|
|
117
|
+
windcode/tui/app.py,sha256=O24oXLuwG3B-gSKRmyu0tE0FZp2jK5n9a80GiyI3UzA,45811
|
|
118
|
+
windcode/tui/commands.py,sha256=8hRutDmxCD89jJRxhaMmS03D7zZBsBJS_QBWzE3W2P0,2826
|
|
119
|
+
windcode/tui/permission_display.py,sha256=gRVJ_OEXYGtgFx5Glv3aIdF0ybQO-J5s1ZkeLGu4j3U,565
|
|
120
|
+
windcode/tui/styles.tcss,sha256=fn9PKO6AbAn1a3Iu5oTrijXE3Fn3PNVjQkBB90OzjH0,8244
|
|
121
|
+
windcode/tui/widgets/__init__.py,sha256=jj-Y7yj9xg4yqtEv-bCOVrUqAXhL4MWsq7zRZmd0FE8,1056
|
|
122
|
+
windcode/tui/widgets/approval.py,sha256=iVoZeK6VIrz3dAFm_69UMD0k6kDoFzdYiOM-cEszV2A,3694
|
|
123
|
+
windcode/tui/widgets/command_menu.py,sha256=EJ1io5WGMKVzH9dOcBOIpp772wgkUkKnQadm08PXSBQ,2716
|
|
124
|
+
windcode/tui/widgets/extensions.py,sha256=OvjEPkuBZ58mpfLI6mnWB0pThOBjwEcQxP1-ElvcZMc,1680
|
|
125
|
+
windcode/tui/widgets/input.py,sha256=6vrVknp0dF-vtZ7w_MQGI2y-0aQ6x8a1J2RR-zpX38Y,3552
|
|
126
|
+
windcode/tui/widgets/memory.py,sha256=h8nv_nHTpy9eOHMjjQ4M8jj_QE9TcMJMoCHavNqs5to,6162
|
|
127
|
+
windcode/tui/widgets/messages.py,sha256=u7eKTSellYlKzKP5dKvI3kH0odZw8OuRoV6psgI1NQw,12143
|
|
128
|
+
windcode/tui/widgets/models.py,sha256=CPeRoxyOuLEucgCbAWLV9Hxb3-ZpJADxS6fIR81Oo0Y,24732
|
|
129
|
+
windcode/tui/widgets/question.py,sha256=cg_upTlZlfC9l_82UnS5cAchaUE7PPo3CLfQB5SYUX8,1819
|
|
130
|
+
windcode/tui/widgets/sessions.py,sha256=qO1CmgzCqbA-H0ms8lLs0WdPep7MZ-c6WwVo8nmLBgk,2343
|
|
131
|
+
windcode/tui/widgets/status.py,sha256=93lJxxhFHV5d3TJrjQQSwk__iCovVqh9tQidUnRoG8M,1670
|
|
132
|
+
windcode/tui/widgets/subagents.py,sha256=eFynAb6nkT87c0p7VZ6k3X4NOABAOd0uCM8QRs3leb0,7147
|
|
133
|
+
windcode/tui/widgets/tools.py,sha256=hTSTUTnINmdKOgwpRyPie4-3nVfu1Czdtt_AuYPxVwM,2356
|
|
134
|
+
windcode/tui/widgets/welcome.py,sha256=ZBOCMfW54wXfMZNgFmw85Fr_-31wNH0Db7qJeur3KYg,5510
|
|
135
|
+
windcode/worktrees/__init__.py,sha256=q3bfRMdZgECXrZfm-zwgNsHry3hpSsQDY3KltgnE4eE,531
|
|
136
|
+
windcode/worktrees/git.py,sha256=QNJO2qjdAIu33QM1ySHgwxxk6wed2j8t1VtJqNv1Lk8,3111
|
|
137
|
+
windcode/worktrees/manager.py,sha256=eItN4zDogWX_lWP3QWpSVyH2u7oMdk2UoDfoJoM4MRs,10271
|
|
138
|
+
windcode/worktrees/models.py,sha256=o3lR_SF5IwiBKmCqE9UThZffexW75TAShc7gvcnppVQ,1408
|
|
139
|
+
windcode-0.1.0.dist-info/METADATA,sha256=N_TJo1w7sWLZRsEL76YtRDpmHUGwUkzzoiM8BnPk-9k,5662
|
|
140
|
+
windcode-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
141
|
+
windcode-0.1.0.dist-info/entry_points.txt,sha256=kZES599OUKWaEE7_wmuWPvWtfaaNFup1qggmQbxaXMg,47
|
|
142
|
+
windcode-0.1.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
143
|
+
windcode-0.1.0.dist-info/RECORD,,
|