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.
Files changed (143) hide show
  1. windcode/__init__.py +6 -0
  2. windcode/__main__.py +4 -0
  3. windcode/auth/__init__.py +11 -0
  4. windcode/auth/store.py +90 -0
  5. windcode/cli.py +181 -0
  6. windcode/config/__init__.py +41 -0
  7. windcode/config/loader.py +117 -0
  8. windcode/config/models.py +203 -0
  9. windcode/config/writer.py +74 -0
  10. windcode/context/__init__.py +18 -0
  11. windcode/context/compactor.py +72 -0
  12. windcode/context/estimator.py +89 -0
  13. windcode/context/truncation.py +87 -0
  14. windcode/domain/__init__.py +1 -0
  15. windcode/domain/errors.py +33 -0
  16. windcode/domain/events.py +597 -0
  17. windcode/domain/messages.py +226 -0
  18. windcode/domain/models.py +73 -0
  19. windcode/domain/subagents.py +263 -0
  20. windcode/domain/tools.py +55 -0
  21. windcode/extensions/__init__.py +27 -0
  22. windcode/extensions/commands.py +25 -0
  23. windcode/extensions/discovery.py +139 -0
  24. windcode/extensions/events.py +58 -0
  25. windcode/extensions/hooks/__init__.py +4 -0
  26. windcode/extensions/hooks/dispatcher.py +107 -0
  27. windcode/extensions/hooks/executor.py +49 -0
  28. windcode/extensions/hooks/loader.py +101 -0
  29. windcode/extensions/hooks/models.py +109 -0
  30. windcode/extensions/mcp/__init__.py +10 -0
  31. windcode/extensions/mcp/adapter.py +101 -0
  32. windcode/extensions/mcp/catalog.py +153 -0
  33. windcode/extensions/mcp/client.py +273 -0
  34. windcode/extensions/mcp/runtime.py +144 -0
  35. windcode/extensions/mcp/tools.py +570 -0
  36. windcode/extensions/models.py +168 -0
  37. windcode/extensions/paths.py +71 -0
  38. windcode/extensions/plugins/__init__.py +3 -0
  39. windcode/extensions/plugins/installer.py +93 -0
  40. windcode/extensions/plugins/manifest.py +166 -0
  41. windcode/extensions/runtime.py +366 -0
  42. windcode/extensions/service.py +437 -0
  43. windcode/extensions/skills/__init__.py +3 -0
  44. windcode/extensions/skills/loader.py +67 -0
  45. windcode/extensions/skills/parser.py +57 -0
  46. windcode/extensions/skills/tools.py +213 -0
  47. windcode/extensions/snapshot.py +57 -0
  48. windcode/extensions/state.py +158 -0
  49. windcode/instructions/__init__.py +8 -0
  50. windcode/instructions/loader.py +50 -0
  51. windcode/memory/__init__.py +57 -0
  52. windcode/memory/extraction.py +83 -0
  53. windcode/memory/models.py +218 -0
  54. windcode/memory/refiner.py +189 -0
  55. windcode/memory/security.py +23 -0
  56. windcode/memory/service.py +179 -0
  57. windcode/memory/store.py +362 -0
  58. windcode/observability/__init__.py +4 -0
  59. windcode/observability/redaction.py +95 -0
  60. windcode/observability/trace.py +115 -0
  61. windcode/policy/__init__.py +22 -0
  62. windcode/policy/engine.py +137 -0
  63. windcode/policy/models.py +69 -0
  64. windcode/providers/__init__.py +29 -0
  65. windcode/providers/_utils.py +19 -0
  66. windcode/providers/anthropic.py +215 -0
  67. windcode/providers/base.py +46 -0
  68. windcode/providers/catalog.py +119 -0
  69. windcode/providers/errors.py +96 -0
  70. windcode/providers/openai_compat.py +231 -0
  71. windcode/providers/openai_responses.py +189 -0
  72. windcode/providers/registry.py +105 -0
  73. windcode/runtime/__init__.py +15 -0
  74. windcode/runtime/control.py +89 -0
  75. windcode/runtime/event_bus.py +67 -0
  76. windcode/runtime/loop.py +510 -0
  77. windcode/runtime/prompts.py +132 -0
  78. windcode/runtime/report.py +64 -0
  79. windcode/runtime/retry.py +73 -0
  80. windcode/runtime/scheduler.py +194 -0
  81. windcode/runtime/subagents/__init__.py +28 -0
  82. windcode/runtime/subagents/approvals.py +88 -0
  83. windcode/runtime/subagents/budgets.py +79 -0
  84. windcode/runtime/subagents/coordinator.py +714 -0
  85. windcode/runtime/subagents/factory.py +311 -0
  86. windcode/runtime/subagents/roles.py +74 -0
  87. windcode/runtime/subagents/verification.py +53 -0
  88. windcode/sandbox/__init__.py +3 -0
  89. windcode/sandbox/bwrap.py +79 -0
  90. windcode/sdk.py +1259 -0
  91. windcode/sessions/__init__.py +23 -0
  92. windcode/sessions/artifacts.py +69 -0
  93. windcode/sessions/models.py +104 -0
  94. windcode/sessions/store.py +167 -0
  95. windcode/sessions/tree.py +35 -0
  96. windcode/tools/__init__.py +10 -0
  97. windcode/tools/apply_patch.py +191 -0
  98. windcode/tools/ask_user.py +58 -0
  99. windcode/tools/builtins.py +44 -0
  100. windcode/tools/edit_file.py +54 -0
  101. windcode/tools/filesystem.py +77 -0
  102. windcode/tools/glob.py +35 -0
  103. windcode/tools/grep.py +66 -0
  104. windcode/tools/memory.py +400 -0
  105. windcode/tools/read_file.py +54 -0
  106. windcode/tools/registry.py +120 -0
  107. windcode/tools/shell.py +159 -0
  108. windcode/tools/subagents/__init__.py +31 -0
  109. windcode/tools/subagents/cancel.py +35 -0
  110. windcode/tools/subagents/integrate.py +54 -0
  111. windcode/tools/subagents/list.py +46 -0
  112. windcode/tools/subagents/spawn.py +86 -0
  113. windcode/tools/subagents/wait.py +74 -0
  114. windcode/tools/write_file.py +61 -0
  115. windcode/tui/__init__.py +3 -0
  116. windcode/tui/app.py +1015 -0
  117. windcode/tui/commands.py +90 -0
  118. windcode/tui/permission_display.py +24 -0
  119. windcode/tui/styles.tcss +591 -0
  120. windcode/tui/widgets/__init__.py +31 -0
  121. windcode/tui/widgets/approval.py +98 -0
  122. windcode/tui/widgets/command_menu.py +90 -0
  123. windcode/tui/widgets/extensions.py +48 -0
  124. windcode/tui/widgets/input.py +110 -0
  125. windcode/tui/widgets/memory.py +143 -0
  126. windcode/tui/widgets/messages.py +299 -0
  127. windcode/tui/widgets/models.py +565 -0
  128. windcode/tui/widgets/question.py +46 -0
  129. windcode/tui/widgets/sessions.py +68 -0
  130. windcode/tui/widgets/status.py +46 -0
  131. windcode/tui/widgets/subagents.py +195 -0
  132. windcode/tui/widgets/tools.py +66 -0
  133. windcode/tui/widgets/welcome.py +149 -0
  134. windcode/types.py +80 -0
  135. windcode/worktrees/__init__.py +24 -0
  136. windcode/worktrees/git.py +92 -0
  137. windcode/worktrees/manager.py +265 -0
  138. windcode/worktrees/models.py +62 -0
  139. windcode-0.1.0.dist-info/METADATA +207 -0
  140. windcode-0.1.0.dist-info/RECORD +143 -0
  141. windcode-0.1.0.dist-info/WHEEL +4 -0
  142. windcode-0.1.0.dist-info/entry_points.txt +2 -0
  143. 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
+ ![alt text](assets/image.png)
43
+ ![alt text](assets/image1.png)
44
+ ![alt text](assets/image2.png)
45
+ ![alt text](assets/image3.png)
46
+ ![alt text](assets/image4.png)
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,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any