claudenv 1.3.0 → 1.3.2
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/README.md +80 -2
- package/bin/cli.js +296 -0
- package/package.json +1 -1
- package/scaffold/.claude/skills/dynamic-workflows/SKILL.md +105 -0
- package/scaffold/global/.claude/commands/add-source.md +31 -0
- package/scaffold/global/.claude/commands/claudenv.md +3 -1
- package/scaffold/global/.claude/commands/harness.md +29 -0
- package/scaffold/global/.claude/skills/claudenv/scaffold/.claude/skills/dynamic-workflows/SKILL.md +105 -0
- package/scaffold/global/.claude/skills/harness/SKILL.md +148 -0
- package/scaffold/global/.claude/skills/source-connector/SKILL.md +128 -0
- package/src/bundled-catalog.js +165 -0
- package/src/capabilities.js +164 -0
- package/src/doctor.js +57 -0
- package/src/installer.js +4 -0
- package/src/kimi.js +43 -0
- package/src/loop.js +27 -1
- package/src/memory-context.js +37 -2
- package/src/memory-paths.js +61 -0
- package/src/skills-registry.js +447 -0
- package/src/sources.js +78 -0
- package/src/workspaces.js +129 -0
- package/templates/connector-mssql.ejs +62 -0
- package/templates/connector-rest.ejs +59 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Коннектор к MSSQL: <%= name %> (host <%= host %>, db <%= database %>).
|
|
5
|
+
Сгенерирован claudenv (skill source-connector).
|
|
6
|
+
|
|
7
|
+
Креды читаются из .env.local (gitignored), НЕ хардкодятся:
|
|
8
|
+
<%= userEnv %>=<логин>
|
|
9
|
+
<%= passwordEnv %>=<пароль>
|
|
10
|
+
|
|
11
|
+
Зависимости: pip install pymssql sqlalchemy pandas
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
from urllib.parse import quote_plus
|
|
17
|
+
|
|
18
|
+
import pandas as pd
|
|
19
|
+
from sqlalchemy import create_engine
|
|
20
|
+
|
|
21
|
+
HOST = os.getenv("<%= name.toUpperCase().replace(/[^A-Z0-9]/g, '_') %>_HOST", "<%= host %>")
|
|
22
|
+
PORT = os.getenv("<%= name.toUpperCase().replace(/[^A-Z0-9]/g, '_') %>_PORT", "<%= port || 1433 %>")
|
|
23
|
+
DATABASE = os.getenv("<%= name.toUpperCase().replace(/[^A-Z0-9]/g, '_') %>_DB", "<%= database %>")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def load_env_local(path=".env.local"):
|
|
27
|
+
env = {}
|
|
28
|
+
if os.path.exists(path):
|
|
29
|
+
with open(path, encoding="utf-8") as fh:
|
|
30
|
+
for line in fh:
|
|
31
|
+
line = line.strip()
|
|
32
|
+
if line and not line.startswith("#") and "=" in line:
|
|
33
|
+
k, _, v = line.partition("=")
|
|
34
|
+
env[k.strip()] = v.strip()
|
|
35
|
+
return env
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
_env = load_env_local()
|
|
39
|
+
USER = _env.get("<%= userEnv %>") or os.getenv("<%= userEnv %>")
|
|
40
|
+
PASSWORD = _env.get("<%= passwordEnv %>") or os.getenv("<%= passwordEnv %>")
|
|
41
|
+
|
|
42
|
+
if not USER or not PASSWORD:
|
|
43
|
+
sys.exit("Нет кред в .env.local: <%= userEnv %> / <%= passwordEnv %>")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def engine():
|
|
47
|
+
# пароль экранируем - в нём могут быть спецсимволы (@ : ~ и т.п.)
|
|
48
|
+
url = f"mssql+pymssql://{quote_plus(USER)}:{quote_plus(PASSWORD)}@{HOST}:{PORT}/{DATABASE}"
|
|
49
|
+
return create_engine(url)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def query(sql):
|
|
53
|
+
"""Выполнить SELECT, вернуть DataFrame."""
|
|
54
|
+
return pd.read_sql(sql, engine())
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if __name__ == "__main__":
|
|
58
|
+
sql = sys.argv[1] if len(sys.argv) > 1 else "SELECT 1 AS ok"
|
|
59
|
+
df = query(sql)
|
|
60
|
+
print(f"Строк: {len(df)}")
|
|
61
|
+
with pd.option_context("display.max_columns", None, "display.width", 200):
|
|
62
|
+
print(df.head(20).to_string(index=False))
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Коннектор к REST API: <%= name %> (base <%= host %>).
|
|
5
|
+
Сгенерирован claudenv (skill source-connector).
|
|
6
|
+
|
|
7
|
+
Токен читается из .env.local (gitignored), НЕ хардкодится:
|
|
8
|
+
<%= tokenEnv %>=<токен>
|
|
9
|
+
|
|
10
|
+
Зависимости: pip install requests
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
|
|
16
|
+
import requests
|
|
17
|
+
|
|
18
|
+
BASE = os.getenv("<%= name.toUpperCase().replace(/[^A-Z0-9]/g, '_') %>_BASE", "<%= host %>")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def load_env_local(path=".env.local"):
|
|
22
|
+
env = {}
|
|
23
|
+
if os.path.exists(path):
|
|
24
|
+
with open(path, encoding="utf-8") as fh:
|
|
25
|
+
for line in fh:
|
|
26
|
+
line = line.strip()
|
|
27
|
+
if line and not line.startswith("#") and "=" in line:
|
|
28
|
+
k, _, v = line.partition("=")
|
|
29
|
+
env[k.strip()] = v.strip()
|
|
30
|
+
return env
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
_env = load_env_local()
|
|
34
|
+
TOKEN = _env.get("<%= tokenEnv %>") or os.getenv("<%= tokenEnv %>")
|
|
35
|
+
|
|
36
|
+
if not TOKEN:
|
|
37
|
+
sys.exit("Нет токена в .env.local: <%= tokenEnv %>")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def client():
|
|
41
|
+
s = requests.Session()
|
|
42
|
+
s.headers.update({
|
|
43
|
+
"Authorization": f"Bearer {TOKEN}",
|
|
44
|
+
"Accept": "application/json",
|
|
45
|
+
})
|
|
46
|
+
return s
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get(path, **params):
|
|
50
|
+
"""GET к API, вернуть JSON. path - относительный (/api/...)."""
|
|
51
|
+
r = client().get(f"{BASE}{path}", params=params, timeout=30)
|
|
52
|
+
r.raise_for_status()
|
|
53
|
+
return r.json()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if __name__ == "__main__":
|
|
57
|
+
path = sys.argv[1] if len(sys.argv) > 1 else "/"
|
|
58
|
+
import json
|
|
59
|
+
print(json.dumps(get(path), ensure_ascii=False, indent=2)[:2000])
|