axnwork-cli 0.2.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.
axon/providers.py ADDED
@@ -0,0 +1,44 @@
1
+ """Fetch available models from LLM provider APIs."""
2
+ import httpx
3
+
4
+
5
+ def fetch_models(provider: str, api_key: str, api_base: str = "") -> list[dict]:
6
+ """Fetch models from provider. Returns list of {label, value}."""
7
+ try:
8
+ if provider == "anthropic" and api_key:
9
+ resp = httpx.get("https://api.anthropic.com/v1/models", headers={
10
+ "x-api-key": api_key, "anthropic-version": "2023-06-01",
11
+ }, timeout=10)
12
+ if resp.status_code == 200:
13
+ models = [m["id"] for m in resp.json().get("data", [])]
14
+ models = [m for m in models if "claude-2" not in m and "instant" not in m]
15
+ models.sort(reverse=True)
16
+ return [{"label": m, "value": f"anthropic/{m}"} for m in models]
17
+
18
+ if provider == "openai" and api_key:
19
+ resp = httpx.get("https://api.openai.com/v1/models", headers={
20
+ "Authorization": f"Bearer {api_key}",
21
+ }, timeout=10)
22
+ if resp.status_code == 200:
23
+ prefixes = ("gpt-", "o1", "o3", "o4", "gpt4", "gpt5", "chatgpt")
24
+ models = [m["id"] for m in resp.json().get("data", []) if m["id"].startswith(prefixes)]
25
+ models.sort(reverse=True)
26
+ return [{"label": m, "value": f"openai/{m}"} for m in models]
27
+
28
+ if provider == "deepseek" and api_key:
29
+ resp = httpx.get("https://api.deepseek.com/v1/models", headers={
30
+ "Authorization": f"Bearer {api_key}",
31
+ }, timeout=10)
32
+ if resp.status_code == 200:
33
+ models = sorted(m["id"] for m in resp.json().get("data", []))
34
+ return [{"label": m, "value": f"deepseek/{m}"} for m in models]
35
+
36
+ if provider == "ollama":
37
+ base = api_base or "http://localhost:11434"
38
+ resp = httpx.get(f"{base}/api/tags", timeout=5)
39
+ if resp.status_code == 200:
40
+ models = sorted(m["name"] for m in resp.json().get("models", []))
41
+ return [{"label": m, "value": f"ollama/{m}"} for m in models]
42
+ except Exception:
43
+ pass
44
+ return []
axon/session.py ADDED
@@ -0,0 +1,26 @@
1
+ """Mining session persistence."""
2
+ import json
3
+
4
+ from axon.config import AXON_HOME
5
+
6
+ SESSIONS_DIR = AXON_HOME / "sessions"
7
+
8
+
9
+ def load_session(task_id: str) -> dict | None:
10
+ path = SESSIONS_DIR / f"{task_id}.json"
11
+ if not path.exists():
12
+ return None
13
+ try:
14
+ return json.loads(path.read_text())
15
+ except Exception:
16
+ return None
17
+
18
+
19
+ def save_session(task_id: str, data: dict):
20
+ SESSIONS_DIR.mkdir(parents=True, exist_ok=True)
21
+ (SESSIONS_DIR / f"{task_id}.json").write_text(json.dumps(data, indent=2))
22
+
23
+
24
+ def delete_session(task_id: str):
25
+ path = SESSIONS_DIR / f"{task_id}.json"
26
+ path.unlink(missing_ok=True)
axon/wallet.py ADDED
@@ -0,0 +1,45 @@
1
+ """ETH wallet — generate, load, sign."""
2
+ import json
3
+
4
+ from eth_account import Account
5
+ from eth_account.messages import encode_defunct
6
+
7
+ from axon.config import AXON_HOME
8
+
9
+ WALLET_FILE = AXON_HOME / "wallet.json"
10
+
11
+
12
+ def generate_wallet() -> dict:
13
+ """Generate a new ETH wallet. Returns {address, private_key}."""
14
+ acct = Account.create()
15
+ return {"address": acct.address, "private_key": acct.key.hex()}
16
+
17
+
18
+ def save_wallet(wallet: dict):
19
+ """Save wallet to ~/.axon/wallet.json"""
20
+ WALLET_FILE.parent.mkdir(parents=True, exist_ok=True)
21
+ WALLET_FILE.write_text(json.dumps(wallet, indent=2) + "\n")
22
+ WALLET_FILE.chmod(0o600) # owner-only read/write
23
+
24
+
25
+ def load_wallet() -> dict | None:
26
+ """Load wallet from disk. Returns {address, private_key} or None."""
27
+ if not WALLET_FILE.exists():
28
+ return None
29
+ try:
30
+ return json.loads(WALLET_FILE.read_text())
31
+ except Exception:
32
+ return None
33
+
34
+
35
+ def sign_message(message: str, private_key: str) -> str:
36
+ """Sign a message with private key. Returns hex signature."""
37
+ msg = encode_defunct(text=message)
38
+ signed = Account.sign_message(msg, private_key=private_key)
39
+ return signed.signature.hex()
40
+
41
+
42
+ def get_address() -> str:
43
+ """Get wallet address or empty string."""
44
+ wallet = load_wallet()
45
+ return wallet["address"] if wallet else ""