@nghiapt/kit 1.0.4 → 1.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/bin/index.js CHANGED
@@ -12,7 +12,7 @@ if (process.stdin.isTTY) {
12
12
 
13
13
  const HEADER = `
14
14
  ==========================================
15
- Antigravity Kit Setup
15
+ Antigravity Kit Setup by NghiaPT
16
16
  ==========================================
17
17
  `;
18
18
 
@@ -26,17 +26,14 @@ const LOCAL_DEST = path.join(process.cwd(), '.agent', 'workflows');
26
26
  const OPTIONS = [
27
27
  {
28
28
  label: 'Install Global (Recommended)',
29
- desc: 'Copies to ~/.gemini/antigravity/global_workflows',
30
29
  action: async () => await installWorkflows(GLOBAL_DEST, 'Global')
31
30
  },
32
31
  {
33
- label: 'Install Only on Context Project',
34
- desc: 'Copies to ./.agent/workflows',
32
+ label: 'Install Only on Current Project',
35
33
  action: async () => await installWorkflows(LOCAL_DEST, 'Local Project')
36
34
  },
37
35
  {
38
36
  label: 'Exit',
39
- desc: 'Close the setup wizard',
40
37
  action: () => process.exit(0)
41
38
  }
42
39
  ];
package/index.js CHANGED
@@ -26,7 +26,6 @@ const LOCAL_DEST = path.join(process.cwd(), '.agent', 'workflows');
26
26
  const OPTIONS = [
27
27
  {
28
28
  label: 'Install Global (Recommended)',
29
- desc: 'Copies to ~/.gemini/antigravity/global_workflows',
30
29
  action: async () => {
31
30
  await installWorkflows(GLOBAL_DEST, 'Global');
32
31
  process.exit(0);
@@ -34,7 +33,6 @@ const OPTIONS = [
34
33
  },
35
34
  {
36
35
  label: 'Install Only on Context Project',
37
- desc: 'Copies to ./.agent/workflows',
38
36
  action: async () => {
39
37
  await installWorkflows(LOCAL_DEST, 'Local Project');
40
38
  process.exit(0);
@@ -42,7 +40,6 @@ const OPTIONS = [
42
40
  },
43
41
  {
44
42
  label: 'Exit',
45
- desc: 'Close the setup wizard',
46
43
  action: () => process.exit(0)
47
44
  }
48
45
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nghiapt/kit",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "The 'Native Gemini' Agentic Framework. Turn your IDE into an autonomous coding partner.",
5
5
  "main": "./bin/index.js",
6
6
  "bin": {
@@ -1,32 +0,0 @@
1
- import os
2
- import re
3
- from pathlib import Path
4
-
5
- def check_workflows():
6
- workflows_dir = Path(r"d:\antigravity-kit\workflows")
7
- print(f"Checking workflows in {workflows_dir}...")
8
-
9
- passed = 0
10
- failed = 0
11
-
12
- for f in workflows_dir.glob("*.md"):
13
- content = f.read_text(encoding='utf-8', errors='ignore')
14
-
15
- # Check for Frontmatter
16
- has_frontmatter = content.strip().startswith("---")
17
-
18
- # Check for Role/Task (Antigravity Native indicators)
19
- has_role = "# Role" in content or "Role:" in content
20
- has_task = "# Task" in content or "Task:" in content or "# Process" in content
21
-
22
- if has_frontmatter:
23
- # print(f"✅ {f.name}: Valid Frontmatter")
24
- passed += 1
25
- else:
26
- print(f"⚠️ {f.name}: MISSING Frontmatter (Legacy?)")
27
- failed += 1
28
-
29
- print(f"\nSummary: {passed} Passed, {failed} Potential Legacy Format")
30
-
31
- if __name__ == "__main__":
32
- check_workflows()
package/core/context.py DELETED
@@ -1,70 +0,0 @@
1
- import os
2
- from pathlib import Path
3
- from typing import List, Set
4
- # No external deps if possible, or use standard lib
5
-
6
- # Default ignores
7
- IGNORED_DIRS = {
8
- '.git', '.idea', '.vscode', '__pycache__', 'node_modules',
9
- 'venv', 'env', 'dist', 'build', 'coverage', '.next', '.nuxt',
10
- '.output', 'target', 'bin', 'obj'
11
- }
12
-
13
- IGNORED_EXTS = {
14
- '.pyc', '.pyo', '.pyd', '.so', '.dll', '.exe', '.bin',
15
- '.jpg', '.jpeg', '.png', '.gif', '.ico', '.svg', '.mp4',
16
- '.mp3', '.pdf', '.zip', '.tar', '.gz', '.7z', '.rar',
17
- '.db', '.sqlite', '.sqlite3', '.pkl', '.lock'
18
- }
19
-
20
- IGNORED_FILES = {
21
- 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'poetry.lock',
22
- 'Gemfile.lock', 'composer.lock', 'cargo.lock'
23
- }
24
-
25
- def is_ignored(path: Path) -> bool:
26
- if path.name in IGNORED_FILES:
27
- return True
28
- if path.suffix in IGNORED_EXTS:
29
- return True
30
- # Check parts for ignored dirs
31
- if any(part in IGNORED_DIRS for part in path.parts):
32
- return True
33
- return False
34
-
35
- def get_project_files(root_dir: str) -> List[Path]:
36
- """Scans the project for text files, respecting ignore rules."""
37
- root = Path(root_dir)
38
- files = []
39
-
40
- # Simple walk
41
- for dirpath, dirnames, filenames in os.walk(root):
42
- # Modify dirnames in-place to prune ignored dirs
43
- dirnames[:] = [d for d in dirnames if d not in IGNORED_DIRS and not d.startswith('.')]
44
-
45
- for f in filenames:
46
- p = Path(dirpath) / f
47
- if not is_ignored(p):
48
- files.append(p)
49
-
50
- return files
51
-
52
- def get_context_string(root_dir: str) -> str:
53
- """Generates a massive string containing all project code."""
54
- files = get_project_files(root_dir)
55
- context = []
56
-
57
- context.append(f"Project Context (Root: {root_dir})\n")
58
- context.append("="*50 + "\n")
59
-
60
- for f in files:
61
- try:
62
- relative_path = f.relative_to(root_dir)
63
- content = f.read_text(encoding='utf-8', errors='ignore')
64
-
65
- context.append(f"\n--- FILE: {relative_path} ---\n")
66
- context.append(content)
67
- except Exception:
68
- pass # Skip unreadable
69
-
70
- return "\n".join(context)
package/core/engine.py DELETED
@@ -1,173 +0,0 @@
1
- import re
2
- import json
3
- import os
4
- import argparse
5
- from google import genai
6
- from google.genai import types
7
- from pathlib import Path
8
-
9
- try:
10
- from .context import get_context_string
11
- from .ops import read_file, write_file
12
- except ImportError:
13
- from context import get_context_string
14
- from ops import read_file, write_file
15
-
16
- def clean_json(text: str) -> str:
17
- # Remove markdown fences ```json ... ```
18
- text = re.sub(r"^```json\s*", "", text, flags=re.MULTILINE)
19
- text = re.sub(r"^```\s*", "", text, flags=re.MULTILINE)
20
- text = re.sub(r"```$", "", text, flags=re.MULTILINE)
21
- return text.strip()
22
-
23
-
24
- # Load Config
25
- CONFIG_PATH = Path(__file__).parent.parent / ".antigravity" / "config.json"
26
- try:
27
- with open(CONFIG_PATH, 'r') as f:
28
- CONFIG = json.load(f)
29
- API_KEY = CONFIG.get("api_key") or os.getenv("GEMINI_API_KEY")
30
- MODEL_NAME = CONFIG.get("model", "gemini-2.0-flash-exp")
31
- except Exception:
32
- API_KEY = os.getenv("GEMINI_API_KEY")
33
- MODEL_NAME = "gemini-2.0-flash-exp"
34
-
35
- def parse_workflow(content: str) -> tuple[dict, str]:
36
- if content.startswith("---"):
37
- parts = re.split(r"^---$", content, maxsplit=2, flags=re.MULTILINE)
38
- if len(parts) >= 3:
39
- try:
40
- metadata = {}
41
- for line in parts[1].strip().split('\n'):
42
- if ':' in line:
43
- k, v = line.split(':', 1)
44
- metadata[k.strip()] = v.strip()
45
- return metadata, parts[2].strip()
46
- except Exception:
47
- pass
48
- return {}, content.strip()
49
-
50
-
51
- # RUNTIME INJECTION: Turns Docs into Agents
52
- ANTIGRAVITY_PROTOCOL = """
53
- # ANTIGRAVITY AGENT PROTOCOL (SYSTEM OVERRIDE)
54
-
55
- You are an autonomous AI Agent running inside the Antigravity Kit.
56
- The text below is not just documentation; it is your **OPERATIONAL MANUAL**.
57
-
58
- ## YOUR MANDATE:
59
- 1. **ACT, DON'T JUST READ**: If the user instruction is a command (e.g., "Build this"), execute it using the Manual's best practices.
60
- 2. **CONTEXT ACCESS**: You have full access to `[PROJECT CONTEXT]`. Read it to understand the codebase.
61
- - **Do NOT** ask for file permissions.
62
- - **Do NOT** hallucinate paths. Use `list_dir` to confirm.
63
- 3. **TOOLS**: Use `run_command` to install/build, `write_to_file` to code.
64
- 4. **CHAINING**: If a task is too complex, output a request to chain another agent using `python core/engine.py [workflow]`.
65
-
66
- ## MANUAL CONTENT START
67
- --------------------------------------------------
68
- {workflow_content}
69
- --------------------------------------------------
70
- ## MANUAL CONTENT END
71
- """
72
-
73
- def load_workflow(name: str) -> tuple[dict, str]:
74
- base_dir = Path(__file__).parent.parent
75
- path = base_dir / "workflows" / f"{name}.md"
76
- if not path.exists():
77
- return {}, f"Error: Workflow '{name}' not found."
78
-
79
- raw_content = read_file(str(path))
80
- metadata, stripped_content = parse_workflow(raw_content)
81
-
82
- # INJECT PROTOCOL
83
- system_prompt = ANTIGRAVITY_PROTOCOL.format(workflow_content=stripped_content)
84
-
85
- return metadata, system_prompt
86
-
87
-
88
- def call_gemini(system_instruction: str, user_prompt: str, json_mode: bool = False) -> str:
89
- if not API_KEY:
90
- return "Error: GEMINI_API_KEY environment variable not set."
91
- try:
92
- client = genai.Client(api_key=API_KEY)
93
-
94
- config = types.GenerateContentConfig(
95
- system_instruction=system_instruction
96
- )
97
-
98
- if json_mode:
99
- config.response_mime_type = "application/json"
100
-
101
- response = client.models.generate_content(
102
- model=MODEL_NAME,
103
- contents=user_prompt,
104
- config=config
105
- )
106
- return response.text
107
- except Exception as e:
108
- return f"Error calling Gemini: {e}"
109
-
110
- def execute_workflow(workflow_name: str, user_request: str, project_context: str) -> str:
111
- print(f"\n🚀 Executing Workflow: {workflow_name}...")
112
- metadata, system_prompt = load_workflow(workflow_name)
113
- if "Error" in system_prompt:
114
- return system_prompt
115
-
116
- full_prompt = f"""
117
- [PROJECT CONTEXT]
118
- {project_context}
119
-
120
- [USER REQUEST]
121
- {user_request}
122
- """
123
-
124
- json_mode = metadata.get("output", "").lower() == "json"
125
- response = call_gemini(system_prompt, full_prompt, json_mode=json_mode)
126
- print(f"✅ {workflow_name} Completed.")
127
- return response
128
-
129
- def main():
130
- parser = argparse.ArgumentParser(description="Antigravity Universal Runner")
131
- parser.add_argument("workflow", help="Name of the workflow (or 'orchestrator')")
132
- parser.add_argument("prompt", help="User Input")
133
- args = parser.parse_args()
134
-
135
- cwd = os.getcwd()
136
- print(f"Loading Context from {cwd}...")
137
- context = get_context_string(cwd)
138
-
139
- # ORCHESTRATOR LOGIC
140
- if args.workflow == "orchestrator":
141
- plan_json = execute_workflow("orchestrator", args.prompt, context)
142
- try:
143
- # Clean before parsing
144
- cleaned_json = clean_json(plan_json)
145
- plan = json.loads(cleaned_json)
146
-
147
- print(f"\n📋 Orchestrator Plan: {plan.get('thought_process', '')}")
148
-
149
- # Chain Execution
150
- previous_output = ""
151
- for step in plan.get("steps", []):
152
-
153
- step_workflow = step.get("workflow")
154
- step_instruction = step.get("instruction")
155
-
156
- # Append previous output to history/instruction
157
- if previous_output:
158
- step_instruction += f"\n\n[PREVIOUS AGENT OUTPUT]\n{previous_output}"
159
-
160
- output = execute_workflow(step_workflow, step_instruction, context)
161
- previous_output = output # Chain it
162
-
163
- print(f"\n--- Output of {step_workflow} ---\n{output[:500]}...\n")
164
-
165
- except json.JSONDecodeError:
166
- print("Error: Orchestrator failed to return valid JSON.")
167
- print(plan_json)
168
- else:
169
- # SINGLE RUN
170
- print(execute_workflow(args.workflow, args.prompt, context))
171
-
172
- if __name__ == "__main__":
173
- main()
package/core/ops.py DELETED
@@ -1,39 +0,0 @@
1
- import os
2
- import subprocess
3
- from pathlib import Path
4
-
5
- def read_file(path: str) -> str:
6
- """Reads a file and returns its content. Returns error string if failed."""
7
- try:
8
- with open(path, 'r', encoding='utf-8') as f:
9
- return f.read()
10
- except Exception as e:
11
- return f"Error reading {path}: {e}"
12
-
13
- def write_file(path: str, content: str) -> bool:
14
- """Writes content to a file. Creates parent directories if needed."""
15
- try:
16
- p = Path(path)
17
- p.parent.mkdir(parents=True, exist_ok=True)
18
- with open(p, 'w', encoding='utf-8') as f:
19
- f.write(content)
20
- return True
21
- except Exception as e:
22
- print(f"Error writing {path}: {e}")
23
- return False
24
-
25
- def run_command(command: str, cwd: str = ".") -> tuple[str, str, int]:
26
- """Runs a shell command and returns (stdout, stderr, return_code)."""
27
- try:
28
- result = subprocess.run(
29
- command,
30
- cwd=cwd,
31
- shell=True,
32
- capture_output=True,
33
- text=True,
34
- encoding='utf-8',
35
- errors='replace'
36
- )
37
- return result.stdout, result.stderr, result.returncode
38
- except Exception as e:
39
- return "", str(e), -1
@@ -1,45 +0,0 @@
1
- import os
2
- import re
3
- from pathlib import Path
4
-
5
- def optimize_file(path: Path):
6
- content = path.read_text(encoding='utf-8', errors='ignore')
7
- original_content = content
8
-
9
- # 1. Branding Replacement
10
- content = content.replace("Claude" + "Kit", "Antigravity Kit")
11
- content = content.replace("ported from Claude Kit", "Native Gemini Framework")
12
- content = content.replace(".claude/", ".antigravity/")
13
-
14
- # 2. Frontmatter Injection
15
- if not content.strip().startswith("---"):
16
- # Synthesize frontmatter
17
- description = "Antigravity Workflow"
18
- # Try to grab first line description if available
19
- lines = content.strip().split('\n')
20
- if lines and lines[0].startswith('# '):
21
- # Skip title
22
- pass
23
-
24
- content = f"---\ndescription: {description}\noutput: markdown\n---\n\n" + content
25
-
26
- # 3. Role Injection (If missing)
27
- if not ("# Role" in content or "Role:" in content):
28
- content = content.replace("---\n\n", "---\n\n# Role\nYou are an expert AI agent specializing in this workflow.\n\n")
29
-
30
- # 4. Save if changed
31
- if content != original_content:
32
- path.write_text(content, encoding='utf-8')
33
- print(f"✅ Optimized: {path.name}")
34
- else:
35
- print(f"Start: {path.name} (No changes)")
36
-
37
- def main():
38
- workflows_dir = Path(r"d:\antigravity-kit\workflows")
39
- print("Starting Bulk Optimization...")
40
- for f in workflows_dir.glob("*.md"):
41
- optimize_file(f)
42
- print("Optimization Complete.")
43
-
44
- if __name__ == "__main__":
45
- main()
@@ -1,38 +0,0 @@
1
- import os
2
- import json
3
- import tempfile
4
- from pathlib import Path
5
-
6
- STATE_FILE = Path(tempfile.gettempdir()) / "antigravity_state.json"
7
-
8
- def load_state():
9
- if not STATE_FILE.exists():
10
- return {}
11
- try:
12
- with open(STATE_FILE, 'r') as f:
13
- return json.load(f)
14
- except:
15
- return {}
16
-
17
- def save_state(state):
18
- with open(STATE_FILE, 'w') as f:
19
- json.dump(state, f, indent=2)
20
-
21
- def set_active_plan(plan_path):
22
- state = load_state()
23
- state["active_plan"] = str(Path(plan_path).resolve())
24
- save_state(state)
25
- print(f"Active plan set to: {state['active_plan']}")
26
-
27
- def get_active_plan():
28
- state = load_state()
29
- return state.get("active_plan")
30
-
31
- if __name__ == "__main__":
32
- import sys
33
- if len(sys.argv) > 2 and sys.argv[1] == "set":
34
- set_active_plan(sys.argv[2])
35
- elif len(sys.argv) > 1 and sys.argv[1] == "get":
36
- print(get_active_plan() or "None")
37
- else:
38
- print("Usage: python state_manager.py [set <path> | get]")
@@ -1,50 +0,0 @@
1
- import os
2
- from pathlib import Path
3
-
4
- # The Header that turns any doc into an Agent
5
- ANTIGRAVITY_HEADER = """
6
- # Antigravity Native Protocol
7
- > **SYSTEM OVERRIDE**: Use the following rules as your Primary Directive.
8
-
9
- 1. **Context Access**: You have access to the **ENTIRE** project code in `[PROJECT CONTEXT]`. Read it to understand the codebase. Do not ask for files.
10
- 2. **Agentic Behavior**: You are NOT a documentation reader. You are an **ACTOR**.
11
- - If the user asks for code, **WRITE IT**.
12
- - If the user asks for a fix, **RUN THE TEST** and **FIX IT**.
13
- 3. **Automation**: Use `run_command` freely to install, build, and test.
14
- 4. **Chaining**: If you need to switch modes (e.g., from Planning to Coding), use `python core/engine.py [workflow_name]`.
15
-
16
- ---
17
- """
18
-
19
- def upgrade_workflows():
20
- workflows_dir = Path(r"d:\antigravity-kit\workflows")
21
-
22
- # Files we already manually fixed or shouldn't touch
23
- skip_list = ["template_agent.md", "backend-development.md", "fix-bugs.md", "orchestrator.md", "planning.md", "router.md"]
24
-
25
- for f in workflows_dir.glob("*.md"):
26
- if f.name in skip_list:
27
- continue
28
-
29
- content = f.read_text(encoding='utf-8', errors='ignore')
30
-
31
- # Avoid double injection
32
- if "# Antigravity Native Protocol" in content:
33
- print(f"Skipping {f.name} (Already Upgraded)")
34
- continue
35
-
36
- # Inject after Frontmatter
37
- if content.startswith("---"):
38
- # Find end of frontmatter
39
- parts = content.split("---", 2)
40
- if len(parts) >= 3:
41
- new_content = f"---{parts[1]}---\n{ANTIGRAVITY_HEADER}\n{parts[2]}"
42
- f.write_text(new_content, encoding='utf-8')
43
- print(f"🚀 Upgraded: {f.name}")
44
- else:
45
- # No frontmatter? Just prepend.
46
- f.write_text(ANTIGRAVITY_HEADER + content, encoding='utf-8')
47
- print(f"🚀 Upgraded: {f.name}")
48
-
49
- if __name__ == "__main__":
50
- upgrade_workflows()
package/rules/.clinerules DELETED
@@ -1,17 +0,0 @@
1
- # Antigravity Kit - Default Rules
2
-
3
- This file defines the operating procedures for this project, powered by Antigravity Kit.
4
-
5
- ## 1. Context Intelligence
6
- - **Rule:** Before reading any massive folder, run `context-optimizer`.
7
- - **Action:** Use `python ~/.gemini/antigravity/antigravity-kit/core/context_scout.py .` to see what you are dealing with.
8
-
9
- ## 2. Smart Routing
10
- - **Rule:** If unsure which workflow to use, use the router.
11
- - **Action:** `/router`
12
-
13
- ## 3. State Management
14
- - **Rule:** Always check if there is an active plan before starting.
15
- - **Action:** `python ~/.gemini/antigravity/antigravity-kit/core/state_manager.py get`
16
- - **Rule:** When creating a plan, register it.
17
- - **Action:** `python ~/.gemini/antigravity/antigravity-kit/core/state_manager.py set "path/to/plan.md"`
@@ -1,45 +0,0 @@
1
- # Antigravity Global Rules
2
-
3
- I am an Antigravity Agent, powered by Gemini. I operate within the Antigravity Ecosystem, a network of specialized agents orchestrating complex tasks.
4
-
5
- ## 1. Identity & Context
6
- - **I am "Antigravity Native":** I prioritize Gemini's strengths (Long Context, Multimodality).
7
- - **I am a Node:** I may be working alone or as part of a chain (orchestrated by `workflows/orchestrator.md`).
8
- - **Context Awareness:**
9
- - Always check for `memory-bank/activeContext.md` to understand the bigger picture.
10
- - If I see `[PREVIOUS AGENT OUTPUT]` in my prompt, I treat it as the absolute source of truth for my inputs.
11
-
12
- ## 2. Multi-Agent Coordination Protocol
13
- When working on a complex task, I do NOT try to do everything at once. I Delegate.
14
-
15
- ### Using the Engine
16
- To perform specialized tasks, I use the Antigravity Engine:
17
- ```bash
18
- python core/engine.py [workflow] "[instruction]"
19
- ```
20
-
21
- **Common Workflows:**
22
- - `orchestrator`: For complex, multi-step goals. ("Build a X feature")
23
- - `planner`: For architectural decisions. ("How should we structure X?")
24
- - `builder`: For implementation. ("Write the code for X plan")
25
- - `code-review`: For auditing. ("Check this file for bugs")
26
-
27
- ### The "Chain" Mindset
28
- - **Output:** My final response should be clear and structured so the *next* agent can parse it.
29
- - **State:** I verify `memory-bank/progress.md` before claiming a task is done.
30
-
31
- ## 3. Tech Stack & Best Practices
32
- - **Frontend:** React, Tailwind CSS, Shadcn UI (unless specified otherwise).
33
- - **Backend:** Python (FastAPI) or Node.js (Next.js API Routes).
34
- - **Files:**
35
- - verify file existence before editing.
36
- - use `python core/engine.py builder` for large-scale scaffolding.
37
-
38
- ## 4. "One Shot" reliability
39
- - **Think before acting:** If a user request is vague, use `/research` or `/planner` first.
40
- - **Verify:** Always run a quick test (or `python core/engine.py debugging`) after writing code.
41
- - **No Hallucinations:** I do not guess file paths. I use `list_dir` or `view_file` to confirm.
42
-
43
- ## 5. Security & IP
44
- - I NEVER output code containing proprietary markers from the legacy port.
45
- - I maintain strict adherence to the **Antigravity Native** architecture.