adelie-ai 0.3.0 → 0.3.1
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/adelie/__init__.py +1 -1
- package/adelie/agents/coder_ai.py +10 -3
- package/adelie/agents/expert_ai.py +118 -2
- package/package.json +1 -1
package/adelie/__init__.py
CHANGED
|
@@ -81,7 +81,11 @@ def _read_existing_files(workspace_root: Path, filepaths: list[str]) -> str:
|
|
|
81
81
|
|
|
82
82
|
# Auto-include key config files if not already in the list
|
|
83
83
|
key_configs = [
|
|
84
|
-
"package.json", "tsconfig.json",
|
|
84
|
+
"package.json", "tsconfig.json",
|
|
85
|
+
"vite.config.ts", "vite.config.js",
|
|
86
|
+
"next.config.js", "next.config.mjs", "next.config.ts",
|
|
87
|
+
"nuxt.config.ts", "nuxt.config.js",
|
|
88
|
+
"svelte.config.js", "remix.config.js", "angular.json",
|
|
85
89
|
"index.html", "requirements.txt", "pyproject.toml",
|
|
86
90
|
]
|
|
87
91
|
filepath_set = set(filepaths)
|
|
@@ -249,8 +253,11 @@ def run_coder(
|
|
|
249
253
|
continue
|
|
250
254
|
|
|
251
255
|
# Sanitize — prevent writing outside staging area
|
|
252
|
-
# Check
|
|
253
|
-
|
|
256
|
+
# Check absolute paths and genuine parent-directory traversal.
|
|
257
|
+
# Use Path.parts for segment-level check so bracket paths like
|
|
258
|
+
# [..nextauth] or [...slug] (Next.js catch-all routes) are allowed.
|
|
259
|
+
parts = Path(filepath).parts
|
|
260
|
+
if filepath.startswith("/") or ".." in parts:
|
|
254
261
|
console.print(
|
|
255
262
|
f"[yellow]⚠️ Skipped unsafe path: {filepath}[/yellow]"
|
|
256
263
|
)
|
|
@@ -199,6 +199,62 @@ Source files found:
|
|
|
199
199
|
|
|
200
200
|
{advice}"""
|
|
201
201
|
|
|
202
|
+
def _detect_framework(project_root) -> str:
|
|
203
|
+
"""
|
|
204
|
+
Detect the JS/TS framework used in the project.
|
|
205
|
+
Returns one of: 'nextjs', 'nuxt', 'remix', 'sveltekit', 'angular', 'vite', 'unknown'.
|
|
206
|
+
"""
|
|
207
|
+
# Next.js: next.config.js / next.config.mjs / next.config.ts
|
|
208
|
+
for ext in (".js", ".mjs", ".ts"):
|
|
209
|
+
if (project_root / f"next.config{ext}").exists():
|
|
210
|
+
return "nextjs"
|
|
211
|
+
|
|
212
|
+
# Nuxt: nuxt.config.ts / nuxt.config.js
|
|
213
|
+
for ext in (".ts", ".js"):
|
|
214
|
+
if (project_root / f"nuxt.config{ext}").exists():
|
|
215
|
+
return "nuxt"
|
|
216
|
+
|
|
217
|
+
# Remix: remix.config.js
|
|
218
|
+
if (project_root / "remix.config.js").exists():
|
|
219
|
+
return "remix"
|
|
220
|
+
|
|
221
|
+
# SvelteKit: svelte.config.js
|
|
222
|
+
if (project_root / "svelte.config.js").exists():
|
|
223
|
+
return "sveltekit"
|
|
224
|
+
|
|
225
|
+
# Angular: angular.json
|
|
226
|
+
if (project_root / "angular.json").exists():
|
|
227
|
+
return "angular"
|
|
228
|
+
|
|
229
|
+
# Check package.json dependencies as fallback
|
|
230
|
+
pkg_path = project_root / "package.json"
|
|
231
|
+
if pkg_path.exists():
|
|
232
|
+
try:
|
|
233
|
+
pkg = json.loads(pkg_path.read_text(encoding="utf-8"))
|
|
234
|
+
all_deps = set(pkg.get("dependencies", {}).keys())
|
|
235
|
+
all_deps |= set(pkg.get("devDependencies", {}).keys())
|
|
236
|
+
|
|
237
|
+
if "next" in all_deps:
|
|
238
|
+
return "nextjs"
|
|
239
|
+
if "nuxt" in all_deps:
|
|
240
|
+
return "nuxt"
|
|
241
|
+
if "@remix-run/react" in all_deps:
|
|
242
|
+
return "remix"
|
|
243
|
+
if "@sveltejs/kit" in all_deps:
|
|
244
|
+
return "sveltekit"
|
|
245
|
+
if "@angular/core" in all_deps:
|
|
246
|
+
return "angular"
|
|
247
|
+
except Exception:
|
|
248
|
+
pass
|
|
249
|
+
|
|
250
|
+
# Vite: vite.config.ts / vite.config.js
|
|
251
|
+
for ext in (".ts", ".js"):
|
|
252
|
+
if (project_root / f"vite.config{ext}").exists():
|
|
253
|
+
return "vite"
|
|
254
|
+
|
|
255
|
+
return "unknown"
|
|
256
|
+
|
|
257
|
+
|
|
202
258
|
def _get_scaffolding_need() -> str:
|
|
203
259
|
"""
|
|
204
260
|
프로젝트 진입 파일 존재 여부 검사.
|
|
@@ -225,12 +281,72 @@ def _get_scaffolding_need() -> str:
|
|
|
225
281
|
# Define scaffolding checks per project type
|
|
226
282
|
checks: list[dict] = []
|
|
227
283
|
|
|
228
|
-
# React/Vite project detection
|
|
229
284
|
has_tsx = any(f.suffix in (".tsx", ".jsx") for f in project_root.rglob("*") if f.is_file())
|
|
230
285
|
has_ts = any(f.suffix == ".ts" for f in project_root.rglob("*") if f.is_file())
|
|
231
286
|
has_pkg = "package.json" in existing
|
|
232
287
|
|
|
233
|
-
|
|
288
|
+
# ── Framework-aware scaffolding checks ────────────────────────────
|
|
289
|
+
framework = _detect_framework(project_root)
|
|
290
|
+
|
|
291
|
+
if framework == "nextjs":
|
|
292
|
+
# Next.js needs: package.json, next.config.*, src/app/layout.tsx or pages/
|
|
293
|
+
entry_files = {
|
|
294
|
+
"package.json": "Node.js dependencies and scripts (npm run dev, npm run build)",
|
|
295
|
+
}
|
|
296
|
+
# Check for app router or pages router
|
|
297
|
+
has_app_router = (
|
|
298
|
+
(src_dir / "app" / "layout.tsx").exists()
|
|
299
|
+
or (src_dir / "app" / "layout.ts").exists()
|
|
300
|
+
or (src_dir / "app" / "layout.jsx").exists()
|
|
301
|
+
or (project_root / "app" / "layout.tsx").exists()
|
|
302
|
+
)
|
|
303
|
+
has_pages_router = (
|
|
304
|
+
(src_dir / "pages").exists()
|
|
305
|
+
or (project_root / "pages").exists()
|
|
306
|
+
)
|
|
307
|
+
if not has_app_router and not has_pages_router:
|
|
308
|
+
entry_files["src/app/layout.tsx"] = "Next.js App Router root layout"
|
|
309
|
+
entry_files["src/app/page.tsx"] = "Next.js App Router home page"
|
|
310
|
+
|
|
311
|
+
for fname, desc in entry_files.items():
|
|
312
|
+
path = project_root / fname
|
|
313
|
+
if not path.exists():
|
|
314
|
+
checks.append({"file": fname, "desc": desc})
|
|
315
|
+
|
|
316
|
+
elif framework == "nuxt":
|
|
317
|
+
entry_files = {
|
|
318
|
+
"package.json": "Node.js dependencies and scripts",
|
|
319
|
+
}
|
|
320
|
+
has_app_vue = (project_root / "app.vue").exists()
|
|
321
|
+
has_pages = (project_root / "pages").exists()
|
|
322
|
+
if not has_app_vue and not has_pages:
|
|
323
|
+
entry_files["app.vue"] = "Nuxt root App component"
|
|
324
|
+
|
|
325
|
+
for fname, desc in entry_files.items():
|
|
326
|
+
path = project_root / fname
|
|
327
|
+
if not path.exists():
|
|
328
|
+
checks.append({"file": fname, "desc": desc})
|
|
329
|
+
|
|
330
|
+
elif framework == "sveltekit":
|
|
331
|
+
entry_files = {
|
|
332
|
+
"package.json": "Node.js dependencies and scripts",
|
|
333
|
+
}
|
|
334
|
+
has_routes = (src_dir / "routes").exists()
|
|
335
|
+
if not has_routes:
|
|
336
|
+
entry_files["src/routes/+page.svelte"] = "SvelteKit root page"
|
|
337
|
+
|
|
338
|
+
for fname, desc in entry_files.items():
|
|
339
|
+
path = project_root / fname
|
|
340
|
+
if not path.exists():
|
|
341
|
+
checks.append({"file": fname, "desc": desc})
|
|
342
|
+
|
|
343
|
+
elif framework in ("remix", "angular"):
|
|
344
|
+
# Minimal checks — just package.json
|
|
345
|
+
if not (project_root / "package.json").exists():
|
|
346
|
+
checks.append({"file": "package.json", "desc": "Node.js dependencies and scripts"})
|
|
347
|
+
|
|
348
|
+
elif has_tsx or has_ts or has_pkg:
|
|
349
|
+
# Default: Vite / vanilla React project (original behavior)
|
|
234
350
|
entry_files = {
|
|
235
351
|
"index.html": "Vite entry point — must reference src/main.tsx",
|
|
236
352
|
"package.json": "Node.js dependencies and scripts (npm run build, npm run dev)",
|