sky-dev 0.1.8__tar.gz → 0.1.9__tar.gz
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.
- {sky_dev-0.1.8 → sky_dev-0.1.9}/CHANGELOG.md +16 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/PKG-INFO +1 -1
- {sky_dev-0.1.8 → sky_dev-0.1.9}/pyproject.toml +1 -1
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/__init__.py +1 -1
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/chat.py +47 -1
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/security/guardrails_nvidia.py +47 -9
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky_dev.egg-info/PKG-INFO +1 -1
- {sky_dev-0.1.8 → sky_dev-0.1.9}/.env.example +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/CONTRIBUTING.md +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/LICENSE +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/MANIFEST.in +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/README.md +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/SECURITY.md +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/setup.cfg +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/cli.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/config/__init__.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/config/models.yaml +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/config/schema.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/__init__.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/approval.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/benchmark.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/fast_loop.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/mode_prompts.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/router.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/subagent.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/core/workflow.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/errors.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/memory/__init__.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/memory/indexer.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/memory/vectorstore.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/security/__init__.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/security/audit.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/security/detection.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/security/guardrails.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/security/prompts.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/security/rate_limit.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/security/sanitize.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/storage/__init__.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/storage/db.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/tools/__init__.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/tools/fs_tools.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/tools/git_tools.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/tools/registry.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/tools/search_tools.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky/tools/shell_tools.py +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky_dev.egg-info/SOURCES.txt +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky_dev.egg-info/dependency_links.txt +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky_dev.egg-info/entry_points.txt +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky_dev.egg-info/requires.txt +0 -0
- {sky_dev-0.1.8 → sky_dev-0.1.9}/sky_dev.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.9] - 2026-09-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Dynamic model discovery for guardrails (auto-selects available NIM models)
|
|
7
|
+
- Chat mode now has repository context awareness
|
|
8
|
+
- `_get_repo_context()` for automatic project understanding
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- EOL model issue (`meta/llama-3.1-70b-instruct` was deprecated)
|
|
12
|
+
- Chat mode no longer asks "please share your codebase"
|
|
13
|
+
- Version mismatch between pip and CLI
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Guardrails now auto-discover working models from NVIDIA NIM
|
|
17
|
+
- Chat injects current directory, files, and README snippet
|
|
18
|
+
|
|
3
19
|
## [0.1.8] - 2026-09-28
|
|
4
20
|
|
|
5
21
|
### Added
|
|
@@ -126,11 +126,57 @@ class ChatEngine:
|
|
|
126
126
|
asyncio.run(self._get_chat_response(user_input))
|
|
127
127
|
|
|
128
128
|
|
|
129
|
+
def _get_repo_context(self) -> str:
|
|
130
|
+
"""Get brief context about the current repository."""
|
|
131
|
+
try:
|
|
132
|
+
from pathlib import Path
|
|
133
|
+
import logging
|
|
134
|
+
cwd = Path.cwd()
|
|
135
|
+
|
|
136
|
+
# Get top-level files and directories
|
|
137
|
+
items = sorted([item.name for item in cwd.iterdir()
|
|
138
|
+
if not item.name.startswith('.')])[:10]
|
|
139
|
+
|
|
140
|
+
# Check for common project files
|
|
141
|
+
markers = []
|
|
142
|
+
for marker in ["README.md", "pyproject.toml", "package.json",
|
|
143
|
+
"requirements.txt", "Cargo.toml", "go.mod"]:
|
|
144
|
+
if (cwd / marker).exists():
|
|
145
|
+
markers.append(marker)
|
|
146
|
+
|
|
147
|
+
# Read README first 500 chars if available
|
|
148
|
+
readme_snippet = ""
|
|
149
|
+
readme = cwd / "README.md"
|
|
150
|
+
if readme.exists():
|
|
151
|
+
readme_snippet = readme.read_text(encoding="utf-8")[:500]
|
|
152
|
+
|
|
153
|
+
context = f"""Current working directory: {cwd.name}
|
|
154
|
+
Top-level items: {', '.join(items)}
|
|
155
|
+
Project markers: {', '.join(markers) if markers else 'none'}
|
|
156
|
+
|
|
157
|
+
README excerpt:
|
|
158
|
+
{readme_snippet}
|
|
159
|
+
"""
|
|
160
|
+
return context
|
|
161
|
+
except Exception as e:
|
|
162
|
+
import logging
|
|
163
|
+
logging.getLogger(__name__).error(f"Failed to get repo context: {e}")
|
|
164
|
+
return ""
|
|
165
|
+
|
|
129
166
|
async def _get_chat_response(self, user_input: str):
|
|
130
167
|
"""Get response from chat model."""
|
|
131
168
|
if not any(m.get("role") == "system" for m in self.messages):
|
|
132
169
|
from sky.core.mode_prompts import get_mode_prompt
|
|
133
|
-
self.
|
|
170
|
+
repo_context = self._get_repo_context()
|
|
171
|
+
chat_system_prompt = get_mode_prompt("chat")
|
|
172
|
+
system_prompt = f"""{chat_system_prompt}
|
|
173
|
+
|
|
174
|
+
## Current Repository Context
|
|
175
|
+
{repo_context}
|
|
176
|
+
|
|
177
|
+
Use this context to answer questions about the repository.
|
|
178
|
+
"""
|
|
179
|
+
self.messages.insert(0, {"role": "system", "content": system_prompt})
|
|
134
180
|
|
|
135
181
|
self.messages.append({"role": "user", "content": user_input})
|
|
136
182
|
|
|
@@ -6,12 +6,49 @@ import asyncio
|
|
|
6
6
|
from typing import Optional, Dict, Any
|
|
7
7
|
from openai import AsyncOpenAI
|
|
8
8
|
|
|
9
|
+
import httpx
|
|
10
|
+
|
|
9
11
|
logger = logging.getLogger(__name__)
|
|
10
12
|
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
# Preferred models (in order of preference)
|
|
14
|
+
PREFERRED_MODELS = [
|
|
15
|
+
"nvidia/llama-3.1-nemotron-70b-instruct", # Reliable
|
|
16
|
+
"nvidia/nemotron-3-super-120b-a12b", # Newest
|
|
17
|
+
"meta/llama-3.3-70b-instruct", # If available
|
|
18
|
+
"mistralai/mistral-large-2-instruct", # Alternative
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
def discover_guardrail_model() -> Optional[str]:
|
|
22
|
+
"""Discover an available model from NVIDIA NIM."""
|
|
23
|
+
api_key = os.getenv("NVIDIA_NIM_API_KEY")
|
|
24
|
+
if not api_key:
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
res = httpx.get(
|
|
29
|
+
"https://integrate.api.nvidia.com/v1/models",
|
|
30
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
31
|
+
timeout=10
|
|
32
|
+
)
|
|
33
|
+
available = {m["id"] for m in res.json().get("data", [])}
|
|
34
|
+
|
|
35
|
+
# Pick the first preferred model that's available
|
|
36
|
+
for model in PREFERRED_MODELS:
|
|
37
|
+
if model in available:
|
|
38
|
+
logger.info(f"Using guardrail model: {model}")
|
|
39
|
+
return model
|
|
40
|
+
|
|
41
|
+
# Fallback: any Llama or Nemotron model
|
|
42
|
+
for model_id in available:
|
|
43
|
+
if "llama" in model_id.lower() or "nemotron" in model_id.lower():
|
|
44
|
+
logger.info(f"Fallback guardrail model: {model_id}")
|
|
45
|
+
return model_id
|
|
46
|
+
|
|
47
|
+
logger.warning("No suitable guardrail model found")
|
|
48
|
+
return None
|
|
49
|
+
except Exception as e:
|
|
50
|
+
logger.error(f"Model discovery failed: {e}")
|
|
51
|
+
return None
|
|
15
52
|
|
|
16
53
|
|
|
17
54
|
class NVIDIAGuardrails:
|
|
@@ -26,18 +63,19 @@ class NVIDIAGuardrails:
|
|
|
26
63
|
return cls._instance
|
|
27
64
|
|
|
28
65
|
def __init__(self):
|
|
29
|
-
if self
|
|
66
|
+
if getattr(self, "_initialized", False):
|
|
30
67
|
return
|
|
31
68
|
|
|
32
69
|
self.client = AsyncOpenAI(
|
|
33
70
|
base_url="https://integrate.api.nvidia.com/v1",
|
|
34
71
|
api_key=os.getenv("NVIDIA_NIM_API_KEY")
|
|
35
72
|
)
|
|
73
|
+
self.model = discover_guardrail_model()
|
|
36
74
|
self._initialized = True
|
|
37
75
|
|
|
38
76
|
def is_available(self) -> bool:
|
|
39
77
|
"""Check if NVIDIA guardrails are available."""
|
|
40
|
-
return bool(
|
|
78
|
+
return bool(self.model)
|
|
41
79
|
|
|
42
80
|
async def check_input_async(self, user_input: str) -> Dict[str, Any]:
|
|
43
81
|
"""Async check for jailbreak attempts."""
|
|
@@ -46,7 +84,7 @@ class NVIDIAGuardrails:
|
|
|
46
84
|
|
|
47
85
|
try:
|
|
48
86
|
response = await self.client.chat.completions.create(
|
|
49
|
-
model=
|
|
87
|
+
model=self.model,
|
|
50
88
|
messages=[
|
|
51
89
|
{
|
|
52
90
|
"role": "system",
|
|
@@ -83,7 +121,7 @@ class NVIDIAGuardrails:
|
|
|
83
121
|
|
|
84
122
|
try:
|
|
85
123
|
response = await self.client.chat.completions.create(
|
|
86
|
-
model=
|
|
124
|
+
model=self.model,
|
|
87
125
|
messages=[
|
|
88
126
|
{
|
|
89
127
|
"role": "system",
|
|
@@ -119,7 +157,7 @@ class NVIDIAGuardrails:
|
|
|
119
157
|
|
|
120
158
|
try:
|
|
121
159
|
result = await self.client.chat.completions.create(
|
|
122
|
-
model=
|
|
160
|
+
model=self.model,
|
|
123
161
|
messages=[
|
|
124
162
|
{
|
|
125
163
|
"role": "system",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|