pi-python-helper 0.1.0
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.
- package/CHANGELOG.md +60 -0
- package/CONTRIBUTING.md +77 -0
- package/LICENSE +17 -0
- package/README.md +172 -0
- package/SECURITY.md +24 -0
- package/docs/compatibility.md +64 -0
- package/docs/tools.md +518 -0
- package/extensions/index.ts +28 -0
- package/extensions/shared.ts +48 -0
- package/extensions/tools/dependencies.ts +203 -0
- package/extensions/tools/environment.ts +171 -0
- package/extensions/tools/testing.ts +350 -0
- package/extensions/tools/validation.ts +344 -0
- package/helpers/scan_project.py +777 -0
- package/package.json +73 -0
- package/skills/python-development/SKILL.md +45 -0
- package/src/build/commands.ts +65 -0
- package/src/build/discover.ts +98 -0
- package/src/build/failure.ts +452 -0
- package/src/build/pytest.ts +118 -0
- package/src/build/selection.ts +138 -0
- package/src/build/staleness.ts +117 -0
- package/src/core/result.ts +102 -0
- package/src/core/runner.ts +96 -0
- package/src/core/safety.ts +181 -0
- package/src/core/version.ts +20 -0
- package/src/dependencies/plan.ts +398 -0
- package/src/environment/discovery.ts +166 -0
- package/src/environment/tools.ts +141 -0
- package/src/project/conformance.ts +343 -0
- package/src/project/inspect.ts +351 -0
- package/src/project/installed.ts +225 -0
- package/src/project/paths.ts +74 -0
- package/src/project/root.ts +72 -0
- package/src/project/scanner.ts +243 -0
- package/src/validation/bundle.ts +65 -0
- package/src/validation/evidence.ts +33 -0
- package/src/validation/tdd.ts +62 -0
package/docs/tools.md
ADDED
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
# 도구 레퍼런스 (Tool reference)
|
|
2
|
+
|
|
3
|
+
> 이 문서는 생성된 파일입니다. 직접 편집하지 마세요.
|
|
4
|
+
>
|
|
5
|
+
> ```bash
|
|
6
|
+
> npm run docs # 이 문서와 docs/api-surface.json을 다시 생성
|
|
7
|
+
> ```
|
|
8
|
+
>
|
|
9
|
+
> 출처: `extensions/`의 도구 등록(설명·파라미터)과 `docs/api-surface.json`(반환 형태 스냅샷).
|
|
10
|
+
|
|
11
|
+
## 응답 규격 (Response envelope)
|
|
12
|
+
|
|
13
|
+
모든 도구는 동일한 `PyToolResult` 규격을 반환합니다. 반환 형태는 구조만 기록하며 값·경로·버전·소요시간은 스냅샷에서 제외합니다.
|
|
14
|
+
|
|
15
|
+
- `commands` (optional): array of
|
|
16
|
+
- `args`: array<string>
|
|
17
|
+
- `cwd`: string
|
|
18
|
+
- `executable`: string
|
|
19
|
+
- `risk`: string
|
|
20
|
+
- `data`: object
|
|
21
|
+
- `errors`: array of
|
|
22
|
+
- `code`: string
|
|
23
|
+
- `line` (optional): number
|
|
24
|
+
- `message`: string
|
|
25
|
+
- `path` (optional): string
|
|
26
|
+
- `severity`: string
|
|
27
|
+
- `evidence`: array of object
|
|
28
|
+
- `metadata`: object
|
|
29
|
+
- `cwd`: string
|
|
30
|
+
- `durationMs`: number
|
|
31
|
+
- `projectRoot` (optional): string
|
|
32
|
+
- `pythonVersion` (optional): string
|
|
33
|
+
- `toolVersion`: string
|
|
34
|
+
- `truncated`: boolean
|
|
35
|
+
- `ok`: boolean
|
|
36
|
+
- `projectRoot` (optional): string
|
|
37
|
+
- `pythonVersion` (optional): string
|
|
38
|
+
- `suggestions`: array of
|
|
39
|
+
- `command` (optional): string
|
|
40
|
+
- `confidence`: string
|
|
41
|
+
- `message`: string
|
|
42
|
+
- `summary`: string
|
|
43
|
+
- `warnings`: array of
|
|
44
|
+
- `code`: string
|
|
45
|
+
- `message`: string
|
|
46
|
+
- `path` (optional): string
|
|
47
|
+
- `severity`: string
|
|
48
|
+
|
|
49
|
+
`data`와 `evidence`의 내부 형태는 도구마다 다르며, 아래 각 도구 섹션에 기록되어 있습니다.
|
|
50
|
+
|
|
51
|
+
## 스냅샷 캡처 조건 (Capture conditions)
|
|
52
|
+
|
|
53
|
+
반환 형태는 다음 파라미터로 참조 프로젝트(`scripts/api-docs/fixture.ts`)를 진단해 캡처했습니다. 모든 호출은 읽기 전용입니다.
|
|
54
|
+
|
|
55
|
+
| 도구 | 파라미터 |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `py_environment` | `{}` |
|
|
58
|
+
| `py_project_inspect` | `{}` |
|
|
59
|
+
| `py_dependency_plan` | `{"includeUnused":true}` |
|
|
60
|
+
| `py_tdd_checkpoint` | `{"changedPaths":["src/ledger/totals.py","tests/test_other.py"]}` |
|
|
61
|
+
| `py_completion_evidence` | `{"syncExecuted":false,"syncOk":false,"testExecuted":false,"testOk":false,"stale":false,"changedPaths":["src/le…` |
|
|
62
|
+
| `py_test_select` | `{"changedPaths":["src/ledger/totals.py"]}` |
|
|
63
|
+
| `py_test` | `{"execute":false}` |
|
|
64
|
+
| `py_failure_diagnose` | `{"output":"============================= test session starts ==============================\ncollected 2 items…` |
|
|
65
|
+
| `py_sync` | `{"mode":"check","execute":false}` |
|
|
66
|
+
| `py_validation_bundle` | `{"execute":false}` |
|
|
67
|
+
|
|
68
|
+
## 도구 (Tools)
|
|
69
|
+
|
|
70
|
+
### `py_completion_evidence`
|
|
71
|
+
|
|
72
|
+
Build a conservative completion report from environment sync and test execution results. Read-only.
|
|
73
|
+
|
|
74
|
+
- 시스템 프롬프트 한 줄: `Create evidence for a Python completion report`
|
|
75
|
+
- 라벨: Python Completion Evidence
|
|
76
|
+
- 프로젝트 상태 변경: 없음 (읽기 전용)
|
|
77
|
+
|
|
78
|
+
**파라미터**
|
|
79
|
+
|
|
80
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| `changedPaths` | `array<string>` | 예 | maxItems 500 |
|
|
83
|
+
| `stale` | `boolean` | 예 | Whether stale artifacts were detected. |
|
|
84
|
+
| `syncExecuted` | `boolean` | 예 | Whether uv lock --check / uv sync actually ran. |
|
|
85
|
+
| `syncOk` | `boolean` | 예 | — |
|
|
86
|
+
| `testExecuted` | `boolean` | 예 | Whether pytest actually ran. |
|
|
87
|
+
| `testOk` | `boolean` | 예 | — |
|
|
88
|
+
|
|
89
|
+
**프롬프트 가이드라인**
|
|
90
|
+
|
|
91
|
+
- Use py_completion_evidence before claiming Python work is complete; a partial run is not evidence.
|
|
92
|
+
|
|
93
|
+
**반환 `data` 형태**
|
|
94
|
+
|
|
95
|
+
- `blockers`: array<string>
|
|
96
|
+
- `changedPaths`: array<string>
|
|
97
|
+
- `ok`: boolean
|
|
98
|
+
|
|
99
|
+
### `py_dependency_plan`
|
|
100
|
+
|
|
101
|
+
Compare imports found with ast against declared dependencies, dev groups, and uv.lock, and preview the uv commands that would fix the drift. Read-only.
|
|
102
|
+
|
|
103
|
+
- 시스템 프롬프트 한 줄: `Plan Python dependency changes from declared and imported packages`
|
|
104
|
+
- 라벨: Python Dependency Plan
|
|
105
|
+
- 프로젝트 상태 변경: 없음 (읽기 전용)
|
|
106
|
+
|
|
107
|
+
**파라미터**
|
|
108
|
+
|
|
109
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
110
|
+
|---|---|---|---|
|
|
111
|
+
| `includeUnused` | `boolean` | 아니오 | Also report declared packages that no file imports. Off by default because runtime plugins and console tools produce false positives. |
|
|
112
|
+
| `path` | `string` | 아니오 | Project directory to analyse. |
|
|
113
|
+
|
|
114
|
+
**프롬프트 가이드라인**
|
|
115
|
+
|
|
116
|
+
- Use py_dependency_plan before editing dependencies, and whenever an import fails or a package may be declared in the wrong group.
|
|
117
|
+
- Use py_dependency_plan to detect drift between pyproject.toml and uv.lock instead of reading the lockfile by hand.
|
|
118
|
+
|
|
119
|
+
**반환 `data` 형태**
|
|
120
|
+
|
|
121
|
+
- `declared`: array of
|
|
122
|
+
- `groups`: array<string>
|
|
123
|
+
- `name`: string
|
|
124
|
+
- `normalized`: string
|
|
125
|
+
- `declaredCount`: number
|
|
126
|
+
- `drift`: object
|
|
127
|
+
- `lockPresent`: boolean
|
|
128
|
+
- `missingFromLock`: array<string>
|
|
129
|
+
- `requiresPythonMismatch`: null
|
|
130
|
+
- `unsatisfiedInLock`: array of
|
|
131
|
+
- `locked`: string
|
|
132
|
+
- `name`: string
|
|
133
|
+
- `specifier`: string
|
|
134
|
+
- `misplaced`: array of
|
|
135
|
+
- `declaredIn`: array<string>
|
|
136
|
+
- `distribution`: string
|
|
137
|
+
- `import`: string
|
|
138
|
+
- `runtimeFiles`: array<string>
|
|
139
|
+
- `notes`: array of
|
|
140
|
+
- `code`: string
|
|
141
|
+
- `message`: string
|
|
142
|
+
- `severity`: string
|
|
143
|
+
- `providerMappingReliable`: boolean
|
|
144
|
+
- `suggestions`: array of
|
|
145
|
+
- `command`: string
|
|
146
|
+
- `confidence`: string
|
|
147
|
+
- `message`: string
|
|
148
|
+
- `thirdPartyImportCount`: number
|
|
149
|
+
- `undeclared`: array of
|
|
150
|
+
- `fileCount`: number
|
|
151
|
+
- `files`: array<string>
|
|
152
|
+
- `import`: string
|
|
153
|
+
- `providers`: array<…>
|
|
154
|
+
- `reason`: string
|
|
155
|
+
- `suggestedDistribution`: string
|
|
156
|
+
- `typeCheckingOnly`: boolean
|
|
157
|
+
- `unparsable`: array<…>
|
|
158
|
+
- `unused`: array of
|
|
159
|
+
- `groups`: array<string>
|
|
160
|
+
- `name`: string
|
|
161
|
+
- `normalized`: string
|
|
162
|
+
- `warnings`: array of
|
|
163
|
+
- `code`: string
|
|
164
|
+
- `message`: string
|
|
165
|
+
- `path`: string
|
|
166
|
+
- `severity`: string
|
|
167
|
+
|
|
168
|
+
### `py_environment`
|
|
169
|
+
|
|
170
|
+
Inspect the active Python interpreter, virtual environment, uv availability, and project root. Read-only.
|
|
171
|
+
|
|
172
|
+
- 시스템 프롬프트 한 줄: `Inspect the current Python interpreter and uv environment`
|
|
173
|
+
- 라벨: Python Environment
|
|
174
|
+
- 프로젝트 상태 변경: 없음 (읽기 전용)
|
|
175
|
+
|
|
176
|
+
**파라미터**
|
|
177
|
+
|
|
178
|
+
(파라미터 없음)
|
|
179
|
+
|
|
180
|
+
**프롬프트 가이드라인**
|
|
181
|
+
|
|
182
|
+
- Use py_environment before running Python commands when the active interpreter, virtual environment, or uv availability is unknown.
|
|
183
|
+
|
|
184
|
+
**반환 `data` 형태**
|
|
185
|
+
|
|
186
|
+
- `interpreter`: string
|
|
187
|
+
- `projectRoot`: string
|
|
188
|
+
- `python`: object
|
|
189
|
+
- `basePrefix`: string
|
|
190
|
+
- `candidateVenvDir`: string
|
|
191
|
+
- `condaPrefix`: null
|
|
192
|
+
- `executable`: string
|
|
193
|
+
- `implementation`: string
|
|
194
|
+
- `inVirtualEnvironment`: boolean
|
|
195
|
+
- `platform`: string
|
|
196
|
+
- `prefix`: string
|
|
197
|
+
- `stdlibModuleNames`: boolean
|
|
198
|
+
- `tomlAvailable`: boolean
|
|
199
|
+
- `version`: string
|
|
200
|
+
- `versionInfo`: array<number>
|
|
201
|
+
- `virtualEnv`: null
|
|
202
|
+
- `suggestions`: array<…>
|
|
203
|
+
- `tools`: array of
|
|
204
|
+
- `available`: boolean
|
|
205
|
+
- `declared`: boolean
|
|
206
|
+
- `executable`: string
|
|
207
|
+
- `name`: string
|
|
208
|
+
- `origin`: string
|
|
209
|
+
- `preferredInvocation`: string
|
|
210
|
+
- `version` (optional): string
|
|
211
|
+
- `versionSource`: string
|
|
212
|
+
- `uv`: object
|
|
213
|
+
- `available`: boolean
|
|
214
|
+
- `lockPresent`: boolean
|
|
215
|
+
- `version`: string
|
|
216
|
+
- `venvDir`: string
|
|
217
|
+
- `warnings`: array<…>
|
|
218
|
+
|
|
219
|
+
### `py_failure_diagnose`
|
|
220
|
+
|
|
221
|
+
Classify the first actionable cause in bounded Python, pytest, or uv output and point at the first non-library traceback frame. Read-only.
|
|
222
|
+
|
|
223
|
+
- 시스템 프롬프트 한 줄: `Diagnose the first actionable Python failure`
|
|
224
|
+
- 라벨: Python Failure Diagnose
|
|
225
|
+
- 프로젝트 상태 변경: 없음 (읽기 전용)
|
|
226
|
+
|
|
227
|
+
**파라미터**
|
|
228
|
+
|
|
229
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
230
|
+
|---|---|---|---|
|
|
231
|
+
| `output` | `string` | 예 | Bounded stdout/stderr from the failing command. |
|
|
232
|
+
| `path` | `string` | 아니오 | Project directory used to classify the missing module. |
|
|
233
|
+
|
|
234
|
+
**프롬프트 가이드라인**
|
|
235
|
+
|
|
236
|
+
- Use py_failure_diagnose on bounded command output instead of reading a full traceback in context; traceback frames inside site-packages are never the cause.
|
|
237
|
+
|
|
238
|
+
**반환 `data` 형태**
|
|
239
|
+
|
|
240
|
+
- `evidence`: array of
|
|
241
|
+
- `file`: string
|
|
242
|
+
- `line`: number
|
|
243
|
+
- `message`: string
|
|
244
|
+
- `exceptionType`: string
|
|
245
|
+
- `firstUserFrame`: object
|
|
246
|
+
- `func`: string
|
|
247
|
+
- `library`: boolean
|
|
248
|
+
- `line`: number
|
|
249
|
+
- `path`: string
|
|
250
|
+
- `frames`: array of
|
|
251
|
+
- `func`: string
|
|
252
|
+
- `library`: boolean
|
|
253
|
+
- `line`: number
|
|
254
|
+
- `path`: string
|
|
255
|
+
- `kind`: string
|
|
256
|
+
- `libraryFrameCount`: number
|
|
257
|
+
- `suggestions`: array of
|
|
258
|
+
- `confidence`: string
|
|
259
|
+
- `message`: string
|
|
260
|
+
- `summary`: string
|
|
261
|
+
- `totalFrameCount`: number
|
|
262
|
+
|
|
263
|
+
### `py_project_inspect`
|
|
264
|
+
|
|
265
|
+
Inspect pyproject.toml, uv.lock, dependency groups, layout, and tool configuration, and report lockfile drift. Read-only.
|
|
266
|
+
|
|
267
|
+
- 시스템 프롬프트 한 줄: `Inspect a Python project manifest and lockfile`
|
|
268
|
+
- 라벨: Python Project Inspect
|
|
269
|
+
- 프로젝트 상태 변경: 없음 (읽기 전용)
|
|
270
|
+
|
|
271
|
+
**파라미터**
|
|
272
|
+
|
|
273
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
274
|
+
|---|---|---|---|
|
|
275
|
+
| `path` | `string` | 아니오 | Project directory, pyproject.toml path, or uv.lock path. |
|
|
276
|
+
|
|
277
|
+
**프롬프트 가이드라인**
|
|
278
|
+
|
|
279
|
+
- Use py_project_inspect before editing pyproject.toml or uv.lock, and whenever the project layout or dependency groups are unclear.
|
|
280
|
+
|
|
281
|
+
**반환 `data` 형태**
|
|
282
|
+
|
|
283
|
+
- `buildBackend`: string
|
|
284
|
+
- `conformance`: object
|
|
285
|
+
- `checks`: object
|
|
286
|
+
- `installedScanned`: boolean
|
|
287
|
+
- `lockPresent`: boolean
|
|
288
|
+
- `projectEditable`: boolean
|
|
289
|
+
- `projectInstalled`: boolean
|
|
290
|
+
- `venvPresent`: boolean
|
|
291
|
+
- `complete`: boolean
|
|
292
|
+
- `counts`: object
|
|
293
|
+
- `conditional`: number
|
|
294
|
+
- `installedPackages`: number
|
|
295
|
+
- `lockPackages`: number
|
|
296
|
+
- `mismatched`: number
|
|
297
|
+
- `missing`: number
|
|
298
|
+
- `untracked`: number
|
|
299
|
+
- `findings`: array of
|
|
300
|
+
- `code`: string
|
|
301
|
+
- `expected`: string
|
|
302
|
+
- `message`: string
|
|
303
|
+
- `name`: string
|
|
304
|
+
- `notes`: array<…>
|
|
305
|
+
- `reason`: string
|
|
306
|
+
- `verdict`: string
|
|
307
|
+
- `warnings`: array of
|
|
308
|
+
- `code`: string
|
|
309
|
+
- `message`: string
|
|
310
|
+
- `severity`: string
|
|
311
|
+
- `dependencyCounts`: object
|
|
312
|
+
- `groups`: object
|
|
313
|
+
- `dev`: number
|
|
314
|
+
- `optional`: object
|
|
315
|
+
- `aws`: number
|
|
316
|
+
- `runtime`: number
|
|
317
|
+
- `entryPoints`: array<…>
|
|
318
|
+
- `importName`: string
|
|
319
|
+
- `installed`: object
|
|
320
|
+
- `count`: number
|
|
321
|
+
- `editableCount`: number
|
|
322
|
+
- `sitePackages`: string
|
|
323
|
+
- `layout`: string
|
|
324
|
+
- `lock`: object
|
|
325
|
+
- `packageCount`: number
|
|
326
|
+
- `path`: string
|
|
327
|
+
- `present`: boolean
|
|
328
|
+
- `modules`: array<string>
|
|
329
|
+
- `name`: string
|
|
330
|
+
- `notes`: array<…>
|
|
331
|
+
- `pyproject`: string
|
|
332
|
+
- `requirementsFiles`: array<…>
|
|
333
|
+
- `requiresPython`: string
|
|
334
|
+
- `root`: string
|
|
335
|
+
- `suggestions`: array of
|
|
336
|
+
- `command`: string
|
|
337
|
+
- `confidence`: string
|
|
338
|
+
- `message`: string
|
|
339
|
+
- `toolConfiguration`: object
|
|
340
|
+
- `coverage`: boolean
|
|
341
|
+
- `hatch`: boolean
|
|
342
|
+
- `mypy`: boolean
|
|
343
|
+
- `pyright`: boolean
|
|
344
|
+
- `pytest`: boolean
|
|
345
|
+
- `ruff`: boolean
|
|
346
|
+
- `ty`: boolean
|
|
347
|
+
- `uvLock`: string
|
|
348
|
+
- `uvSources`: array<…>
|
|
349
|
+
- `uvWorkspaceMembers`: array<…>
|
|
350
|
+
- `venvDir`: string
|
|
351
|
+
- `version`: string
|
|
352
|
+
- `warnings`: array of
|
|
353
|
+
- `code`: string
|
|
354
|
+
- `message`: string
|
|
355
|
+
- `path` (optional): string
|
|
356
|
+
- `severity`: string
|
|
357
|
+
|
|
358
|
+
### `py_sync`
|
|
359
|
+
|
|
360
|
+
Preview or run uv lock --check or uv sync --frozen. Execution is opt-in because it modifies .venv. Does not edit sources.
|
|
361
|
+
|
|
362
|
+
- 시스템 프롬프트 한 줄: `Preview or run the uv environment sync`
|
|
363
|
+
- 라벨: Python Sync
|
|
364
|
+
- 프로젝트 상태 변경: `execute: true` 옵트인 필요
|
|
365
|
+
|
|
366
|
+
**파라미터**
|
|
367
|
+
|
|
368
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
369
|
+
|---|---|---|---|
|
|
370
|
+
| `execute` | `boolean` | 아니오 | — |
|
|
371
|
+
| `mode` | `"check" | "sync"` | 아니오 | check runs uv lock --check; sync runs uv sync --frozen --all-groups. |
|
|
372
|
+
| `path` | `string` | 아니오 | — |
|
|
373
|
+
| `timeoutSeconds` | `integer` | 아니오 | 1..1800 |
|
|
374
|
+
|
|
375
|
+
**프롬프트 가이드라인**
|
|
376
|
+
|
|
377
|
+
- Use py_sync with execute=false to preview the uv command, and execute=true only when the environment must be created or refreshed.
|
|
378
|
+
|
|
379
|
+
**반환 `data` 형태**
|
|
380
|
+
|
|
381
|
+
- `command`: object
|
|
382
|
+
- `args`: array<string>
|
|
383
|
+
- `cwd`: string
|
|
384
|
+
- `executable`: string
|
|
385
|
+
- `risk`: string
|
|
386
|
+
- `executed`: boolean
|
|
387
|
+
- `lockPresent`: boolean
|
|
388
|
+
- `mode`: string
|
|
389
|
+
|
|
390
|
+
### `py_tdd_checkpoint`
|
|
391
|
+
|
|
392
|
+
Check whether production Python changes have related test changes before implementation is considered complete. Read-only.
|
|
393
|
+
|
|
394
|
+
- 시스템 프롬프트 한 줄: `Check the Python TDD checkpoint for changed files`
|
|
395
|
+
- 라벨: Python TDD Checkpoint
|
|
396
|
+
- 프로젝트 상태 변경: 없음 (읽기 전용)
|
|
397
|
+
|
|
398
|
+
**파라미터**
|
|
399
|
+
|
|
400
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
401
|
+
|---|---|---|---|
|
|
402
|
+
| `changedPaths` | `array<string>` | 아니오 | maxItems 500 |
|
|
403
|
+
| `testChangedPaths` | `array<string>` | 아니오 | maxItems 500 |
|
|
404
|
+
|
|
405
|
+
**프롬프트 가이드라인**
|
|
406
|
+
|
|
407
|
+
- Use py_tdd_checkpoint before reporting Python implementation work as complete.
|
|
408
|
+
|
|
409
|
+
**반환 `data` 형태**
|
|
410
|
+
|
|
411
|
+
- `changedPaths`: array<string>
|
|
412
|
+
- `ok`: boolean
|
|
413
|
+
- `reasons`: array<string>
|
|
414
|
+
- `source`: string
|
|
415
|
+
- `sourceChanges`: array<string>
|
|
416
|
+
- `testChanges`: array<string>
|
|
417
|
+
|
|
418
|
+
### `py_test`
|
|
419
|
+
|
|
420
|
+
Preview or run pytest through uv run --frozen and summarise failures by test, file, and first project frame. Does not modify sources.
|
|
421
|
+
|
|
422
|
+
- 시스템 프롬프트 한 줄: `Preview or run Python tests and summarise failures`
|
|
423
|
+
- 라벨: Python Test
|
|
424
|
+
- 프로젝트 상태 변경: `execute: true` 옵트인 필요
|
|
425
|
+
|
|
426
|
+
**파라미터**
|
|
427
|
+
|
|
428
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
429
|
+
|---|---|---|---|
|
|
430
|
+
| `execute` | `boolean` | 아니오 | — |
|
|
431
|
+
| `keyword` | `string` | 아니오 | pytest -k expression. |
|
|
432
|
+
| `lastFailed` | `boolean` | 아니오 | Rerun only tests that failed last time (--lf). |
|
|
433
|
+
| `maxFail` | `integer` | 아니오 | 1..1000 |
|
|
434
|
+
| `path` | `string` | 아니오 | — |
|
|
435
|
+
| `targets` | `array<string>` | 아니오 | — |
|
|
436
|
+
| `timeoutSeconds` | `integer` | 아니오 | 1..3600 |
|
|
437
|
+
|
|
438
|
+
**프롬프트 가이드라인**
|
|
439
|
+
|
|
440
|
+
- Use py_test with execute=false first; a preview is never a passing test run.
|
|
441
|
+
- Use py_test after changing Python sources; it does not rebuild anything, so run py_sync first when dependencies changed.
|
|
442
|
+
|
|
443
|
+
**반환 `data` 형태**
|
|
444
|
+
|
|
445
|
+
- `command`: object
|
|
446
|
+
- `args`: array<string>
|
|
447
|
+
- `cwd`: string
|
|
448
|
+
- `executable`: string
|
|
449
|
+
- `risk`: string
|
|
450
|
+
- `executed`: boolean
|
|
451
|
+
|
|
452
|
+
### `py_test_select`
|
|
453
|
+
|
|
454
|
+
Select focused pytest targets from changed files using pytest naming conventions, without running tests. Read-only.
|
|
455
|
+
|
|
456
|
+
- 시스템 프롬프트 한 줄: `Select focused Python tests from changed files`
|
|
457
|
+
- 라벨: Python Test Select
|
|
458
|
+
- 프로젝트 상태 변경: 없음 (읽기 전용)
|
|
459
|
+
|
|
460
|
+
**파라미터**
|
|
461
|
+
|
|
462
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
463
|
+
|---|---|---|---|
|
|
464
|
+
| `changedPaths` | `array<string>` | 아니오 | Changed paths; defaults to git diff plus untracked files. |
|
|
465
|
+
| `path` | `string` | 아니오 | Project directory to scan for test files. |
|
|
466
|
+
| `testFiles` | `array<string>` | 아니오 | Known test files; defaults to a project scan. |
|
|
467
|
+
|
|
468
|
+
**프롬프트 가이드라인**
|
|
469
|
+
|
|
470
|
+
- Use py_test_select after changing Python source to choose a focused pytest target instead of running the whole suite.
|
|
471
|
+
|
|
472
|
+
**반환 `data` 형태**
|
|
473
|
+
|
|
474
|
+
- `changedSourceFiles`: array<string>
|
|
475
|
+
- `changedTestFiles`: array<…>
|
|
476
|
+
- `consideredTestFiles`: array<string>
|
|
477
|
+
- `fellBackToAll`: boolean
|
|
478
|
+
- `pytestTargets`: array<string>
|
|
479
|
+
- `selected`: array of
|
|
480
|
+
- `path`: string
|
|
481
|
+
- `reason`: string
|
|
482
|
+
- `score`: number
|
|
483
|
+
|
|
484
|
+
### `py_validation_bundle`
|
|
485
|
+
|
|
486
|
+
Preview or run one evidence-oriented sequence: uv lock --check, uv sync --frozen, pytest, and a stale-artifact check. Execution is opt-in.
|
|
487
|
+
|
|
488
|
+
- 시스템 프롬프트 한 줄: `Run the Python sync and test validation bundle`
|
|
489
|
+
- 라벨: Python Validation Bundle
|
|
490
|
+
- 프로젝트 상태 변경: `execute: true` 옵트인 필요
|
|
491
|
+
|
|
492
|
+
**파라미터**
|
|
493
|
+
|
|
494
|
+
| 파라미터 | 타입 | 필수 | 설명 |
|
|
495
|
+
|---|---|---|---|
|
|
496
|
+
| `execute` | `boolean` | 아니오 | — |
|
|
497
|
+
| `path` | `string` | 아니오 | — |
|
|
498
|
+
| `targets` | `array<string>` | 아니오 | — |
|
|
499
|
+
| `timeoutSeconds` | `integer` | 아니오 | 1..3600 |
|
|
500
|
+
|
|
501
|
+
**프롬프트 가이드라인**
|
|
502
|
+
|
|
503
|
+
- Use py_validation_bundle with execute=false first; a preview is never a passing validation.
|
|
504
|
+
- Use py_validation_bundle as the single completion gate after changing Python sources or dependencies.
|
|
505
|
+
|
|
506
|
+
**반환 `data` 형태**
|
|
507
|
+
|
|
508
|
+
- `executed`: boolean
|
|
509
|
+
- `lockPresent`: boolean
|
|
510
|
+
- `steps`: array of
|
|
511
|
+
- `args`: array<string>
|
|
512
|
+
- `cwd`: string
|
|
513
|
+
- `executable`: string
|
|
514
|
+
- `risk`: string
|
|
515
|
+
|
|
516
|
+
## 대화형 명령어 (Commands)
|
|
517
|
+
|
|
518
|
+
- `/py-status` — Show a concise Python interpreter and uv project status
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
|
|
2
|
+
import { detectPythonEnvironment } from '../src/environment/discovery.ts';
|
|
3
|
+
import { registerDependencyTools } from './tools/dependencies.ts';
|
|
4
|
+
import { registerEnvironmentTools } from './tools/environment.ts';
|
|
5
|
+
import { registerTestingTools } from './tools/testing.ts';
|
|
6
|
+
import { registerValidationTools } from './tools/validation.ts';
|
|
7
|
+
|
|
8
|
+
export default function (pi: ExtensionAPI): void {
|
|
9
|
+
registerEnvironmentTools(pi);
|
|
10
|
+
registerDependencyTools(pi);
|
|
11
|
+
registerTestingTools(pi);
|
|
12
|
+
registerValidationTools(pi);
|
|
13
|
+
|
|
14
|
+
pi.registerCommand('py-status', {
|
|
15
|
+
description: 'Show a concise Python interpreter and uv project status',
|
|
16
|
+
handler: async (_args, ctx) => {
|
|
17
|
+
const environment = await detectPythonEnvironment(ctx.cwd);
|
|
18
|
+
const python = environment.python;
|
|
19
|
+
const ok = Boolean(environment.interpreter);
|
|
20
|
+
ctx.ui.notify(
|
|
21
|
+
`Python ${python?.version ?? 'unavailable'} · ${python?.inVirtualEnvironment ? 'virtual environment' : 'system interpreter'} · uv ${
|
|
22
|
+
environment.uv.available ? (environment.uv.version ?? 'ready') : 'missing'
|
|
23
|
+
} · ${environment.projectRoot ?? 'no project root'}`,
|
|
24
|
+
ok ? 'info' : 'warning',
|
|
25
|
+
);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';
|
|
2
|
+
import { basename, dirname, resolve } from 'node:path';
|
|
3
|
+
import { findProjectRoot, isDirectory, isFile } from '../src/project/root.ts';
|
|
4
|
+
|
|
5
|
+
export type Pi = ExtensionAPI;
|
|
6
|
+
export type Ctx = ExtensionContext;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Every tool returns JSON text plus the same object in `details`, so the UI can
|
|
10
|
+
* render structured results while the model reads a single stable document.
|
|
11
|
+
*/
|
|
12
|
+
export function text(value: unknown): {
|
|
13
|
+
content: { type: 'text'; text: string }[];
|
|
14
|
+
details: unknown;
|
|
15
|
+
} {
|
|
16
|
+
return {
|
|
17
|
+
content: [{ type: 'text' as const, text: JSON.stringify(value, null, 2) }],
|
|
18
|
+
details: value,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Accept a project directory, a `pyproject.toml` path, or nothing (the current
|
|
24
|
+
* directory). Never assume the caller passed a directory.
|
|
25
|
+
*/
|
|
26
|
+
export async function resolveProjectRoot(
|
|
27
|
+
cwd: string,
|
|
28
|
+
requested?: string,
|
|
29
|
+
): Promise<string | undefined> {
|
|
30
|
+
if (!requested) return findProjectRoot(cwd);
|
|
31
|
+
const candidate = resolve(cwd, requested);
|
|
32
|
+
if ((await isFile(candidate)) && basename(candidate) === 'pyproject.toml') {
|
|
33
|
+
return dirname(candidate);
|
|
34
|
+
}
|
|
35
|
+
if ((await isFile(candidate)) && basename(candidate) === 'uv.lock') {
|
|
36
|
+
return dirname(candidate);
|
|
37
|
+
}
|
|
38
|
+
if (await isDirectory(candidate)) return (await findProjectRoot(candidate)) ?? candidate;
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function hasDirectory(path: string): Promise<boolean> {
|
|
43
|
+
return isDirectory(path);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function messageOf(error: unknown): string {
|
|
47
|
+
return error instanceof Error ? error.message : String(error);
|
|
48
|
+
}
|