ghostcode-canary 0.1.25-canary.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/LICENSE +201 -0
- package/PAT.txt +1 -0
- package/README.md +95 -0
- package/cli.js +92 -0
- package/error/err1.txt +12 -0
- package/package.json +31 -0
- package/setup.js +67 -0
- package/src/ghostcode/__init__.py +3 -0
- package/src/ghostcode/__main__.py +3 -0
- package/src/ghostcode/_version.py +17 -0
- package/src/ghostcode/agents/__init__.py +20 -0
- package/src/ghostcode/agents/code.py +104 -0
- package/src/ghostcode/agents/explore.py +50 -0
- package/src/ghostcode/ai/__init__.py +0 -0
- package/src/ghostcode/ai/anthropic_client.py +8 -0
- package/src/ghostcode/ai/base.py +33 -0
- package/src/ghostcode/ai/factory.py +38 -0
- package/src/ghostcode/ai/groq_client.py +7 -0
- package/src/ghostcode/ai/nvidia_client.py +7 -0
- package/src/ghostcode/ai/ollama_client.py +7 -0
- package/src/ghostcode/ai/openai_client.py +7 -0
- package/src/ghostcode/ai/openai_compat.py +139 -0
- package/src/ghostcode/ai/opencode_go_client.py +7 -0
- package/src/ghostcode/ai/opencode_zen_client.py +7 -0
- package/src/ghostcode/ai/openrouter_client.py +7 -0
- package/src/ghostcode/ai/registry.py +169 -0
- package/src/ghostcode/app.py +148 -0
- package/src/ghostcode/config.py +24 -0
- package/src/ghostcode/core/__init__.py +5 -0
- package/src/ghostcode/core/commands.py +55 -0
- package/src/ghostcode/core/file_ops.py +127 -0
- package/src/ghostcode/core/hooks.py +122 -0
- package/src/ghostcode/core/memory.py +137 -0
- package/src/ghostcode/core/prompt.py +73 -0
- package/src/ghostcode/core/reminders.py +61 -0
- package/src/ghostcode/core/security.py +119 -0
- package/src/ghostcode/core/tasks.py +125 -0
- package/src/ghostcode/tools/__init__.py +2 -0
- package/src/ghostcode/tools/defs.py +325 -0
- package/src/ghostcode/tools/executor.py +261 -0
- package/src/ghostcode/tui/__init__.py +0 -0
- package/src/ghostcode/tui/app.py +12 -0
- package/src/ghostcode/tui/dialogs.py +241 -0
- package/src/ghostcode/tui/screens.py +799 -0
- package/src/ghostcode/tui/widgets.py +32 -0
- package/src/ghostcode/utils/__init__.py +0 -0
- package/src/ghostcode/utils/config_loader.py +102 -0
- package/src/ghostcode/utils/logger.py +16 -0
- package/src/pyproject.toml +18 -0
- package/token.txt +1 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from rich.markdown import Markdown
|
|
4
|
+
from textual.widgets import Static
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
CODE_BLOCK_RE = re.compile(r"```(\w+)?\n(.*?)```", re.DOTALL)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def render_chat_content(content: str) -> Markdown:
|
|
11
|
+
return Markdown(content, code_theme="monokai")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def dim_text(text: str) -> str:
|
|
15
|
+
return text.replace("[dim]", "").replace("[/dim]", "")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Message(Static):
|
|
19
|
+
def __init__(self, role: str, content: str, *args, **kwargs):
|
|
20
|
+
self.role = role
|
|
21
|
+
self.content = content
|
|
22
|
+
super().__init__(*args, **kwargs)
|
|
23
|
+
self.update(render_chat_content(content))
|
|
24
|
+
|
|
25
|
+
def on_mount(self):
|
|
26
|
+
self.styles.margin = (0, 1)
|
|
27
|
+
if self.role == "user":
|
|
28
|
+
self.styles.background = "$surface"
|
|
29
|
+
self.styles.border = ("round", "$primary")
|
|
30
|
+
else:
|
|
31
|
+
self.styles.background = "$background"
|
|
32
|
+
self.styles.border = ("round", "$success")
|
|
File without changes
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from dotenv import load_dotenv
|
|
6
|
+
|
|
7
|
+
CONFIG_DIR = Path.home() / ".ghostcode"
|
|
8
|
+
CONFIG_PATH = CONFIG_DIR / "config.json"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def ensure_config():
|
|
12
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
13
|
+
if not CONFIG_PATH.exists():
|
|
14
|
+
CONFIG_PATH.write_text(json.dumps({
|
|
15
|
+
"default_provider": "nvidia",
|
|
16
|
+
"api_keys": {},
|
|
17
|
+
}, indent=2))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def load_config() -> dict:
|
|
21
|
+
ensure_config()
|
|
22
|
+
return json.loads(CONFIG_PATH.read_text())
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def save_config(cfg: dict):
|
|
26
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
27
|
+
CONFIG_PATH.write_text(json.dumps(cfg, indent=2))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_api_key(provider: str) -> str:
|
|
31
|
+
cfg = load_config()
|
|
32
|
+
return cfg.get("api_keys", {}).get(provider.lower(), "")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def set_api_key(provider: str, key: str):
|
|
36
|
+
cfg = load_config()
|
|
37
|
+
cfg.setdefault("api_keys", {})
|
|
38
|
+
cfg["api_keys"][provider.lower()] = key
|
|
39
|
+
save_config(cfg)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_default_provider() -> str:
|
|
43
|
+
cfg = load_config()
|
|
44
|
+
return cfg.get("default_provider", "nvidia")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def set_default_provider(provider: str):
|
|
48
|
+
cfg = load_config()
|
|
49
|
+
cfg["default_provider"] = provider
|
|
50
|
+
save_config(cfg)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_last_model(provider: str) -> str | None:
|
|
54
|
+
cfg = load_config()
|
|
55
|
+
return cfg.get("models", {}).get(provider.lower())
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def set_last_model(provider: str, model: str):
|
|
59
|
+
cfg = load_config()
|
|
60
|
+
cfg.setdefault("models", {})
|
|
61
|
+
cfg["models"][provider.lower()] = model
|
|
62
|
+
save_config(cfg)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def find_and_load_env():
|
|
66
|
+
paths = [
|
|
67
|
+
Path(".env"),
|
|
68
|
+
CONFIG_DIR / ".env",
|
|
69
|
+
Path(__file__).resolve().parent.parent.parent / ".env",
|
|
70
|
+
]
|
|
71
|
+
for p in paths:
|
|
72
|
+
if p.exists():
|
|
73
|
+
load_dotenv(p)
|
|
74
|
+
return str(p)
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def migrate_env_keys_to_config():
|
|
79
|
+
key_map = {
|
|
80
|
+
"NVIDIA_API_KEY": "nvidia",
|
|
81
|
+
"OPENAI_API_KEY": "openai",
|
|
82
|
+
"GROQ_API_KEY": "groq",
|
|
83
|
+
"ANTHROPIC_API_KEY": "anthropic",
|
|
84
|
+
"OPENROUTER_API_KEY": "openrouter",
|
|
85
|
+
}
|
|
86
|
+
cfg = load_config()
|
|
87
|
+
changed = False
|
|
88
|
+
for env_var, provider_id in key_map.items():
|
|
89
|
+
val = os.getenv(env_var, "")
|
|
90
|
+
if val and provider_id not in cfg.get("api_keys", {}):
|
|
91
|
+
cfg.setdefault("api_keys", {})
|
|
92
|
+
cfg["api_keys"][provider_id] = val
|
|
93
|
+
changed = True
|
|
94
|
+
opencode_key = os.getenv("OPENCODE_API_KEY", "")
|
|
95
|
+
if opencode_key:
|
|
96
|
+
for pid in ("opencode-zen", "opencode-go"):
|
|
97
|
+
if pid not in cfg.get("api_keys", {}):
|
|
98
|
+
cfg.setdefault("api_keys", {})
|
|
99
|
+
cfg["api_keys"][pid] = opencode_key
|
|
100
|
+
changed = True
|
|
101
|
+
if changed:
|
|
102
|
+
save_config(cfg)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def setup_logger(name: str = "ghostcode", level: str = "WARNING") -> logging.Logger:
|
|
6
|
+
logger = logging.getLogger(name)
|
|
7
|
+
logger.setLevel(getattr(logging, level.upper(), logging.WARNING))
|
|
8
|
+
|
|
9
|
+
if not logger.handlers:
|
|
10
|
+
handler = logging.StreamHandler(sys.stderr)
|
|
11
|
+
handler.setFormatter(logging.Formatter(
|
|
12
|
+
"%(asctime)s [%(levelname)s] %(name)s: %(message)s"
|
|
13
|
+
))
|
|
14
|
+
logger.addHandler(handler)
|
|
15
|
+
|
|
16
|
+
return logger
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ghostcode-cli"
|
|
3
|
+
version = "0.1.25"
|
|
4
|
+
requires-python = ">=3.8"
|
|
5
|
+
dependencies = [
|
|
6
|
+
"textual>=8.0.0",
|
|
7
|
+
"httpx>=0.28.0",
|
|
8
|
+
"python-dotenv>=1.0.0",
|
|
9
|
+
"pygments>=2.15.0",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[tool.setuptools.packages.find]
|
|
13
|
+
where = ["."]
|
|
14
|
+
include = ["ghostcode*"]
|
|
15
|
+
|
|
16
|
+
[build-system]
|
|
17
|
+
requires = ["setuptools>=64", "wheel"]
|
|
18
|
+
build-backend = "setuptools.build_meta"
|
package/token.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
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
|