yncli 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,97 @@
1
+ import os
2
+ import json
3
+ from pathlib import Path
4
+ from typing import Dict, Any, List
5
+
6
+
7
+ class WorkspaceMemory:
8
+ """
9
+ Maintains real-time in-depth memory and indexed source code of the active workspace.
10
+ """
11
+ def __init__(self, workspace_dir: str = "."):
12
+ self.workspace_dir = str(Path(workspace_dir).resolve())
13
+ self.indexed_files: Dict[str, str] = {}
14
+ self.file_tree: List[str] = []
15
+ self.project_type: str = "general"
16
+ self.refresh()
17
+
18
+ def refresh(self) -> None:
19
+ cwd = Path(self.workspace_dir)
20
+ if not cwd.exists():
21
+ return
22
+
23
+ ignore_dirs = {
24
+ "node_modules", "venv", ".venv", "__pycache__", "target", "vendor",
25
+ "dist", "build", ".git", ".idea", ".vscode", "yncli.egg-info"
26
+ }
27
+
28
+ source_exts = {
29
+ ".html", ".htm", ".css", ".js", ".jsx", ".ts", ".tsx", ".php",
30
+ ".py", ".json", ".md", ".sql", ".yaml", ".yml", ".toml", ".rs", ".go"
31
+ }
32
+
33
+ self.indexed_files = {}
34
+ self.file_tree = []
35
+
36
+ try:
37
+ for root, dirs, files in os.walk(cwd):
38
+ dirs[:] = [d for d in dirs if d not in ignore_dirs and not d.startswith(".")]
39
+ rel_root = Path(root).relative_to(cwd)
40
+
41
+ for f in sorted(files):
42
+ if f.startswith(".") and f not in (".env", ".gitignore"):
43
+ continue
44
+ rel_f = rel_root / f if str(rel_root) != "." else Path(f)
45
+ posix_path = rel_f.as_posix()
46
+ self.file_tree.append(posix_path)
47
+
48
+ full_path = cwd / rel_f
49
+ ext = full_path.suffix.lower()
50
+
51
+ # Read all small project source files up to 25KB into memory
52
+ if (ext in source_exts or f in ("Dockerfile", "Makefile")) and len(self.indexed_files) < 20:
53
+ try:
54
+ size = full_path.stat().st_size
55
+ if 0 < size < 35000:
56
+ with open(full_path, "r", encoding="utf-8", errors="replace") as fp:
57
+ self.indexed_files[posix_path] = fp.read()
58
+ except Exception:
59
+ pass
60
+ except Exception:
61
+ pass
62
+
63
+ # Detect primary project type
64
+ fset = set(self.file_tree)
65
+ if "index.html" in fset or any(f.endswith(".html") for f in fset):
66
+ self.project_type = "Web Frontend (HTML/CSS/JS)"
67
+ elif "composer.json" in fset or "artisan" in fset or any(f.endswith(".php") for f in fset):
68
+ self.project_type = "PHP / Laravel"
69
+ elif "package.json" in fset:
70
+ self.project_type = "Node.js / JavaScript"
71
+ elif "requirements.txt" in fset or "pyproject.toml" in fset or any(f.endswith(".py") for f in fset):
72
+ self.project_type = "Python"
73
+
74
+ def get_context_for_prompt(self) -> str:
75
+ """
76
+ Builds an exhaustive source code snapshot for the AI so it never needs to ask where files are.
77
+ """
78
+ lines = []
79
+ lines.append(f"### WORKSPACE LOCATION: {self.workspace_dir}")
80
+ lines.append(f"### DETECTED PROJECT TYPE: {self.project_type}")
81
+ lines.append(f"### TOTAL WORKSPACE FILES ({len(self.file_tree)}):")
82
+ for f in self.file_tree[:30]:
83
+ lines.append(f" - {f}")
84
+ if len(self.file_tree) > 30:
85
+ lines.append(f" - ... ({len(self.file_tree) - 30} other files)")
86
+
87
+ if self.indexed_files:
88
+ lines.append("\n### COMPLETE PRE-LOADED PROJECT SOURCE FILES:")
89
+ for fname, content in self.indexed_files.items():
90
+ lines.append(f"\n========================================")
91
+ lines.append(f"FILE: `{fname}` ({len(content.splitlines())} lines)")
92
+ lines.append(f"========================================")
93
+ lines.append(content)
94
+ else:
95
+ lines.append("\n(No existing project source files found in workspace directory)")
96
+
97
+ return "\n".join(lines)
@@ -0,0 +1,99 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import Dict, Any, List
4
+
5
+
6
+ def scan_workspace_deep(workspace_dir: str = ".") -> Dict[str, Any]:
7
+ """
8
+ Performs deep background workspace inspection, analyzing project structure,
9
+ key files, frameworks, and existing implementation state.
10
+ """
11
+ cwd = Path(workspace_dir).resolve()
12
+ if not cwd.exists():
13
+ return {"summary": "Workspace directory not found.", "key_files": {}, "tree": []}
14
+
15
+ ignore_dirs = {
16
+ "node_modules", "venv", ".venv", "__pycache__", "target", "vendor",
17
+ "dist", "build", ".git", ".idea", ".vscode", "yncli.egg-info"
18
+ }
19
+
20
+ files_list: List[str] = []
21
+ dirs_list: List[str] = []
22
+ key_files_content: Dict[str, str] = {}
23
+
24
+ priority_files = [
25
+ "plan.md", "README.md", "package.json", "composer.json", "requirements.txt",
26
+ "index.html", "index.php", "main.py", "app.py", "Cargo.toml", "go.mod",
27
+ "style.css", "styles.css", "script.js", "app.js", "App.tsx", "App.jsx"
28
+ ]
29
+
30
+ try:
31
+ for root, dirs, files in os.walk(cwd):
32
+ dirs[:] = [d for d in dirs if d not in ignore_dirs and not d.startswith(".")]
33
+ rel_root = Path(root).relative_to(cwd)
34
+
35
+ for d in dirs:
36
+ rel_d = rel_root / d if str(rel_root) != "." else Path(d)
37
+ dirs_list.append(f"{rel_d.as_posix()}/")
38
+
39
+ for f in sorted(files):
40
+ if f.startswith(".") and f not in (".env", ".gitignore"):
41
+ continue
42
+ rel_f = rel_root / f if str(rel_root) != "." else Path(f)
43
+ posix_path = rel_f.as_posix()
44
+ files_list.append(posix_path)
45
+
46
+ # Read key context files if small
47
+ if f in priority_files and len(key_files_content) < 6:
48
+ full_p = cwd / rel_f
49
+ try:
50
+ if full_p.stat().st_size < 30000:
51
+ with open(full_p, "r", encoding="utf-8", errors="replace") as fp:
52
+ snippet = fp.read(4000)
53
+ key_files_content[posix_path] = snippet
54
+ except Exception:
55
+ pass
56
+ except Exception as e:
57
+ return {"summary": f"Error scanning workspace: {e}", "key_files": {}, "tree": []}
58
+
59
+ return {
60
+ "cwd": str(cwd),
61
+ "total_files": len(files_list),
62
+ "total_dirs": len(dirs_list),
63
+ "files": files_list[:60],
64
+ "key_files": key_files_content
65
+ }
66
+
67
+
68
+ def format_workspace_context(scan_data: Dict[str, Any]) -> str:
69
+ """
70
+ Formats the deep scan data into an executive architectural context for LLM system prompt.
71
+ """
72
+ if not scan_data or "cwd" not in scan_data:
73
+ return "No workspace data available."
74
+
75
+ lines = []
76
+ lines.append(f"### Current Workspace: {scan_data['cwd']}")
77
+ lines.append(f"Total Detected Files: {scan_data.get('total_files', 0)} files")
78
+
79
+ files = scan_data.get("files", [])
80
+ if files:
81
+ lines.append("### Project File Structure:")
82
+ for f in files[:35]:
83
+ lines.append(f" - {f}")
84
+ if len(files) > 35:
85
+ lines.append(f" - ... ({len(files) - 35} more files)")
86
+ else:
87
+ lines.append("### Project File Structure: (Empty workspace directory)")
88
+
89
+ key_files = scan_data.get("key_files", {})
90
+ if key_files:
91
+ lines.append("\n### Key Project Files Overview:")
92
+ for fname, content in key_files.items():
93
+ lines.append(f"#### File: `{fname}`")
94
+ lines.append("```")
95
+ preview = "\n".join(content.splitlines()[:25])
96
+ lines.append(preview)
97
+ lines.append("```")
98
+
99
+ return "\n".join(lines)
@@ -0,0 +1,63 @@
1
+ Metadata-Version: 2.4
2
+ Name: yncli
3
+ Version: 1.0.0
4
+ Summary: Autonomous Polyglot AI Coding Agent & TUI
5
+ Author: YNCLI Team
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: rich>=13.7.0
9
+ Requires-Dist: prompt_toolkit>=3.0.40
10
+ Requires-Dist: requests>=2.31.0
11
+ Requires-Dist: duckduckgo-search>=6.0.0
12
+ Requires-Dist: beautifulsoup4>=4.12.0
13
+ Requires-Dist: pygments>=2.17.0
14
+ Dynamic: author
15
+ Dynamic: requires-python
16
+
17
+ # ⚡ YNCLI: World-Class Autonomous Polyglot AI Coding Agent & TUI
18
+
19
+ YNCLI adalah AI Coding Agent berbasis CLI/TUI mandiri yang mendukung:
20
+ - **Polyglot Coding Engine**: Menguasai Python, TypeScript/JavaScript, Rust, Go, C/C++, Java/Kotlin, C#/.NET, PHP, Ruby, Dart/Flutter, Swift, SQL, Shell, dan Web stack.
21
+ - **Dynamic Language & Framework Detection**: Otomatis mendeteksi arsitektur project dan menginjeksi idiomatic patterns ke dalam agent.
22
+ - **Autonomous ReAct Loop**: AI dapat membaca file, menulis file, melakukan surgical patch, mencari kode via grep, memvalidasi sintaks via compiler/linter, dan menjalankan perintah di terminal.
23
+ - **Real-Time Date & Environment Awareness**: Mengetahui waktu, tanggal, hari lokal secara real-time.
24
+ - **Thinking / Reasoning Visualizer**: Menampilkan penalaran model (seperti Gemini 3.7 Flash High / Claude 4.6 Thinking) secara live.
25
+ - **Real-time Web Search & Scraper**: DuckDuckGo search + HTML-to-markdown reader bawaan.
26
+ - **Dynamic Skills System**: Mode Architect, Debugger, Code Reviewer, Test Runner, dan Polyglot.
27
+
28
+ ## Cara Menggunakan
29
+
30
+ Cukup ketik perintah berikut di PowerShell atau Command Prompt mana saja:
31
+
32
+ ### 1. Masuk ke Mode TUI Interaktif:
33
+ ```powershell
34
+ yncli
35
+ ```
36
+
37
+ ### 2. Mode Direct Execution (Quick Query):
38
+ ```powershell
39
+ yncli "buatkan script rest api fastapi lengkap dengan jwt auth"
40
+ ```
41
+
42
+ ### 3. Opsi Tambahan:
43
+ ```powershell
44
+ # Ganti model
45
+ yncli -m ag/claude-sonnet-4-6
46
+
47
+ # Aktifkan skill tertentu
48
+ yncli -s architect
49
+
50
+ # Lihat daftar model yang tersedia di endpoint
51
+ yncli --list-models
52
+ ```
53
+
54
+ ### Slash Commands di dalam TUI:
55
+ - `/model <nama>`: Ganti model AI aktif
56
+ - `/models`: Lihat semua model AI dari endpoint
57
+ - `/skill <nama>`: Aktifkan skill (polyglot, architect, debugger, code_review, test_runner)
58
+ - `/skills`: Lihat semua skill yang tersedia
59
+ - `/tools`: Lihat daftar tools coding yang aktif
60
+ - `/clear`: Reset memory percakapan
61
+ - `/history`: Lihat ringkasan percakapan
62
+ - `/save [file]`: Export percakapan ke Markdown
63
+ - `/exit`: Keluar
@@ -0,0 +1,32 @@
1
+ yncli/__init__.py,sha256=7VvDOot5C5ccdADH58Jrm2JlCKKecHmrG_Seq-s8N3U,80
2
+ yncli/agent.py,sha256=LRjtCtqWWlbQ-mxtCosTYNv63vH06L36OjMZ5aOBwAs,12388
3
+ yncli/clean_text.py,sha256=vw95KVDrBt5rug0AGeMpv4JOFMXB0DcmbBrOMuqVjjY,2034
4
+ yncli/client.py,sha256=xaPbnghCtOv4jTFkUuNwtPKtY66QnvalXljQPl18SFE,5428
5
+ yncli/config.py,sha256=onxEobwZkon6E8UVXMScFZ0gmf4LX1OX48zfM0Ooe0Y,1301
6
+ yncli/language_detector.py,sha256=qAD5gS0CqObtvA8akD6yTDJE2w712Bxuaffmoo0Msqk,9043
7
+ yncli/main.py,sha256=mrCaVHflCcH626xws2tdpRCoE1YTtz7W3dANq6q9zS8,3956
8
+ yncli/skills_manager.py,sha256=UpXaGRpgDRycx33Ps0NKrRCG06ONXd2WRzk8FRfNaWA,2377
9
+ yncli/system_prompt.py,sha256=b5M09FrbPW10oCu6VJixh7tXxMbQJkePT3BDX6m1CKY,5911
10
+ yncli/tui.py,sha256=aZPUbYTAid800to_HVRLsMStwLoUlM1obINtEfHuu2M,24031
11
+ yncli/workspace_memory.py,sha256=_nTJ10IY9yPjcQsIIeOBQpjmVfQT6E28wWLlv8stAlQ,4119
12
+ yncli/workspace_scanner.py,sha256=V-KJG8j92AbxO2fnbN8iFCm7TF_zp9W9aY-yzC7M0Ec,3720
13
+ yncli/built_in_skills/architect.md,sha256=zr6bf71DXsguHNLUxp31q4U214Zk2hz2O0DvnnKC2t0,714
14
+ yncli/built_in_skills/code_review.md,sha256=UYRyaidGYcV2x07jZYjd7eaDUKaVA6QgxojqmnDogzI,704
15
+ yncli/built_in_skills/debug_oracle.md,sha256=7eoCA5xcg1pyZe4BuQvegofVJvxOvHoQEcdVbFLJGLs,908
16
+ yncli/built_in_skills/debugger.md,sha256=q6dcCjtk84Khvi8LYXWh3jAlGZTqjtBR1rn7Vj9OOlA,793
17
+ yncli/built_in_skills/polyglot.md,sha256=ToqMfN0IHYzm6e9RodnqIagPKWaRmyQxdvr_a1hlbTA,1545
18
+ yncli/built_in_skills/refactor_master.md,sha256=hxxccZXVqlp9rEzP7Lr5yK0K3FS3NfdHWlD1nn1ZAto,1061
19
+ yncli/built_in_skills/security_auditor.md,sha256=TQahVOfz2VfwHtHEuyZIUQPAiU_2kL9EEtj8MSkJDEo,1242
20
+ yncli/built_in_skills/system_architect.md,sha256=j0sHJqQgCBpIWLTFAYkiNL5JSi04F_h1bQ3kW40wSqY,789
21
+ yncli/built_in_skills/test_runner.md,sha256=sS-FW5y5KcZ-lCDKKXUImSiBNKxmdmELY1G8vOQ1gBQ,793
22
+ yncli/built_in_skills/ultrabrain.md,sha256=JewfCyRwzt_oev-Khj0C4iGV4cxCMjTgrNgUIe-azAo,1583
23
+ yncli/tools/__init__.py,sha256=P5HmDzhcc0O6x3uLHq9Tvh-xWXhNRgcgZOhkTwrzxu8,11674
24
+ yncli/tools/file_tools.py,sha256=qghfoKGxq-XiedEOqU0P6GU6xhlbr0hOen8a5jLfqbQ,8577
25
+ yncli/tools/polyglot_tools.py,sha256=hm2EteZ3v9PgeuCDYszmYMW7Y__Xshn18kYaddaNw6g,5470
26
+ yncli/tools/search_tools.py,sha256=EUC8mk19En3rAfHmCTbXsE3gCkYh3E-WHGMw1vMKG-s,2344
27
+ yncli/tools/system_tools.py,sha256=4PYImZUYscxQS6_rGJspa4ttX-2HRNoChLue1oXtezM,4587
28
+ yncli-1.0.0.dist-info/METADATA,sha256=8JUTPQDL53qtWWJPqT9zmriNeadE5ZpYa98yHNfoYzk,2490
29
+ yncli-1.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
30
+ yncli-1.0.0.dist-info/entry_points.txt,sha256=YvlvvcUrBuvBkCq7LZzQ-AKXY3jDnhUNFUvmhxFejyU,42
31
+ yncli-1.0.0.dist-info/top_level.txt,sha256=FBSylTcPyJt8Jur-0awK08GNAjtYqQHvRagrqMxEYIU,6
32
+ yncli-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ yncli = yncli.main:main
@@ -0,0 +1 @@
1
+ yncli