modexia-compute-agent 0.1.0__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.
- modexia_compute_agent-0.1.0/PKG-INFO +118 -0
- modexia_compute_agent-0.1.0/README.md +101 -0
- modexia_compute_agent-0.1.0/pyproject.toml +36 -0
- modexia_compute_agent-0.1.0/setup.cfg +4 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/__init__.py +0 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/agent.py +169 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/akash_cli.py +135 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/cli.py +116 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/config.py +17 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/payments.py +57 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/sdl.py +67 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/soul.md +40 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent/wizard.py +201 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent.egg-info/PKG-INFO +118 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent.egg-info/SOURCES.txt +17 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent.egg-info/dependency_links.txt +1 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent.egg-info/entry_points.txt +2 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent.egg-info/requires.txt +8 -0
- modexia_compute_agent-0.1.0/src/modexia_compute_agent.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modexia-compute-agent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Autonomous AI agent for deploying containers on Akash Network via Modexia AgentPay
|
|
5
|
+
Author-email: Modexia <hello@modexia.software>
|
|
6
|
+
Project-URL: Repository, https://github.com/modexia/modexia-compute-agent
|
|
7
|
+
Requires-Python: >=3.14
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: python-dotenv>=1.1.0
|
|
10
|
+
Requires-Dist: httpx>=0.28.1
|
|
11
|
+
Requires-Dist: langchain-core>=1.2.23
|
|
12
|
+
Requires-Dist: langchain-groq>=1.1.2
|
|
13
|
+
Requires-Dist: langgraph>=1.1.4
|
|
14
|
+
Requires-Dist: modexiaagentpay>=0.1.0
|
|
15
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
16
|
+
Requires-Dist: rich>=14.3.3
|
|
17
|
+
|
|
18
|
+
<div align="center">
|
|
19
|
+
<img src="https://modexia.software/favicon.ico" alt="Modexia Logo" width="80" height="80">
|
|
20
|
+
<br>
|
|
21
|
+
<h1>🚀 Modexia Compute Agent</h1>
|
|
22
|
+
<p><b>Autonomous AI agent for deploying Docker containers on Akash via natural language.</b></p>
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/modexia-compute-agent/)
|
|
25
|
+
[](https://pypi.python.org/pypi/modexia-compute-agent)
|
|
26
|
+
[](https://opensource.org/licenses/MIT)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
The **Modexia Compute Agent** is a powerful Python CLI application that turns plain English descriptions into running Docker containers on the [Akash Network](https://akash.network).
|
|
31
|
+
|
|
32
|
+
Powered by the **Modexia AgentPay** engine over the Squid Router, this agent features *true abstract deployments*. Simply instruct the agent to deploy a container, and it will handle the SDL generation, Akash wallet creation, and **Just-In-Time (JIT) USDT/USDC cross-chain funding + Gas Fee swaps** completely autonomously.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## ✨ Features
|
|
37
|
+
|
|
38
|
+
* **🗣️ Conversational Deployments:** Describe your container, CPU, RAM, and storage needs in plain English.
|
|
39
|
+
* **🧠 Llama 70B Orchestration:** Uses Groq's high-speed inference to flawlessly orchestrate complex blockchain provider interactions.
|
|
40
|
+
* **💳 JIT Cross-Chain Funding:** No AKT? No problem. The agent automatically bridges USDC from your Modexia Vault natively covering AKT gas fees, ensuring seamless workflow.
|
|
41
|
+
* **🔮 Oracle Vibe GUI:** A sleek, beautiful, minimalist `rich` UI ensuring deploying compute feels incredibly satisfying.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## ⚡ Installation
|
|
46
|
+
|
|
47
|
+
Install globally using `pip` or `pipx`:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install modexia-compute-agent
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 🚀 Quick Start & API Setup
|
|
56
|
+
|
|
57
|
+
Upon running the CLI for the first time, our interactive **Setup Wizard** will launch immediately and seamlessly guide you through connecting all necessary services over 4 quick steps.
|
|
58
|
+
|
|
59
|
+
Simply run:
|
|
60
|
+
```bash
|
|
61
|
+
modexia-compute
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### What You'll Need During Setup:
|
|
65
|
+
|
|
66
|
+
#### 1. Akash CLI (`provider-services`)
|
|
67
|
+
We rely on the official Akash binary to securely generate wallets and sign transactions purely on your local machine (your mnemonic seed phrase is safely stored exclusively in `~/.modexia/`).
|
|
68
|
+
|
|
69
|
+
* **Linux / macOS Installation:**
|
|
70
|
+
```bash
|
|
71
|
+
curl -sSfL https://raw.githubusercontent.com/akash-network/provider/main/install.sh | bash
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### 2. Modexia AgentPay API Key
|
|
75
|
+
Modexia is the payment orchestration layer that allows the agent to intelligently fund your Akash wallet from external chains.
|
|
76
|
+
|
|
77
|
+
* Sign up at [Modexia.software](https://modexia.software)
|
|
78
|
+
* Fund your Vault with USDC (on Base).
|
|
79
|
+
* Create a Developer API Key (`mx_live_...`).
|
|
80
|
+
|
|
81
|
+
#### 3. Groq API Key
|
|
82
|
+
The agent's "brain" is powered by extremely fast LLaMA models.
|
|
83
|
+
* Free keys at [console.groq.com/keys](https://console.groq.com/keys)
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## ⌨️ How It Works
|
|
88
|
+
|
|
89
|
+
Type your intent in plain English, and the oracle goes to work:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
> Spin up an NGINX frontend cache on a fast server with 2 CPUs and 4GB RAM.
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
1. **Manifest Generation:** The LLM instantly writes a verified `SDL (deploy.yaml)` for Akash.
|
|
96
|
+
2. **Auto-Fund Engine Check:** Identifies an empty Akash wallet and bridges exactly `$5.10 USDC` required for escrow and AKT gas natively from your Modexia Vault.
|
|
97
|
+
3. **Provider Bidding:** Connects to Akash, polls live decentralized datacenters, and reports back.
|
|
98
|
+
4. **Approval Loop:** Asks the human precisely which provider is preferred.
|
|
99
|
+
5. **Liftoff:** Container initializes and exposes the assigned NodePort/URI securely!
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## ⚙️ Modifying Configuration Later
|
|
104
|
+
|
|
105
|
+
At any time, you can edit your setup or switch APIs. Your configuration is securely stored off-package in your home directory:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
~/.modexia/compute.env
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
To forcibly re-run the setup wizard:
|
|
112
|
+
```bash
|
|
113
|
+
modexia-compute --setup
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
*Powered by the Modexia-Verse* 🌌
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://modexia.software/favicon.ico" alt="Modexia Logo" width="80" height="80">
|
|
3
|
+
<br>
|
|
4
|
+
<h1>🚀 Modexia Compute Agent</h1>
|
|
5
|
+
<p><b>Autonomous AI agent for deploying Docker containers on Akash via natural language.</b></p>
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/modexia-compute-agent/)
|
|
8
|
+
[](https://pypi.python.org/pypi/modexia-compute-agent)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
The **Modexia Compute Agent** is a powerful Python CLI application that turns plain English descriptions into running Docker containers on the [Akash Network](https://akash.network).
|
|
14
|
+
|
|
15
|
+
Powered by the **Modexia AgentPay** engine over the Squid Router, this agent features *true abstract deployments*. Simply instruct the agent to deploy a container, and it will handle the SDL generation, Akash wallet creation, and **Just-In-Time (JIT) USDT/USDC cross-chain funding + Gas Fee swaps** completely autonomously.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ✨ Features
|
|
20
|
+
|
|
21
|
+
* **🗣️ Conversational Deployments:** Describe your container, CPU, RAM, and storage needs in plain English.
|
|
22
|
+
* **🧠 Llama 70B Orchestration:** Uses Groq's high-speed inference to flawlessly orchestrate complex blockchain provider interactions.
|
|
23
|
+
* **💳 JIT Cross-Chain Funding:** No AKT? No problem. The agent automatically bridges USDC from your Modexia Vault natively covering AKT gas fees, ensuring seamless workflow.
|
|
24
|
+
* **🔮 Oracle Vibe GUI:** A sleek, beautiful, minimalist `rich` UI ensuring deploying compute feels incredibly satisfying.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ⚡ Installation
|
|
29
|
+
|
|
30
|
+
Install globally using `pip` or `pipx`:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install modexia-compute-agent
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 🚀 Quick Start & API Setup
|
|
39
|
+
|
|
40
|
+
Upon running the CLI for the first time, our interactive **Setup Wizard** will launch immediately and seamlessly guide you through connecting all necessary services over 4 quick steps.
|
|
41
|
+
|
|
42
|
+
Simply run:
|
|
43
|
+
```bash
|
|
44
|
+
modexia-compute
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### What You'll Need During Setup:
|
|
48
|
+
|
|
49
|
+
#### 1. Akash CLI (`provider-services`)
|
|
50
|
+
We rely on the official Akash binary to securely generate wallets and sign transactions purely on your local machine (your mnemonic seed phrase is safely stored exclusively in `~/.modexia/`).
|
|
51
|
+
|
|
52
|
+
* **Linux / macOS Installation:**
|
|
53
|
+
```bash
|
|
54
|
+
curl -sSfL https://raw.githubusercontent.com/akash-network/provider/main/install.sh | bash
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### 2. Modexia AgentPay API Key
|
|
58
|
+
Modexia is the payment orchestration layer that allows the agent to intelligently fund your Akash wallet from external chains.
|
|
59
|
+
|
|
60
|
+
* Sign up at [Modexia.software](https://modexia.software)
|
|
61
|
+
* Fund your Vault with USDC (on Base).
|
|
62
|
+
* Create a Developer API Key (`mx_live_...`).
|
|
63
|
+
|
|
64
|
+
#### 3. Groq API Key
|
|
65
|
+
The agent's "brain" is powered by extremely fast LLaMA models.
|
|
66
|
+
* Free keys at [console.groq.com/keys](https://console.groq.com/keys)
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## ⌨️ How It Works
|
|
71
|
+
|
|
72
|
+
Type your intent in plain English, and the oracle goes to work:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
> Spin up an NGINX frontend cache on a fast server with 2 CPUs and 4GB RAM.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
1. **Manifest Generation:** The LLM instantly writes a verified `SDL (deploy.yaml)` for Akash.
|
|
79
|
+
2. **Auto-Fund Engine Check:** Identifies an empty Akash wallet and bridges exactly `$5.10 USDC` required for escrow and AKT gas natively from your Modexia Vault.
|
|
80
|
+
3. **Provider Bidding:** Connects to Akash, polls live decentralized datacenters, and reports back.
|
|
81
|
+
4. **Approval Loop:** Asks the human precisely which provider is preferred.
|
|
82
|
+
5. **Liftoff:** Container initializes and exposes the assigned NodePort/URI securely!
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## ⚙️ Modifying Configuration Later
|
|
87
|
+
|
|
88
|
+
At any time, you can edit your setup or switch APIs. Your configuration is securely stored off-package in your home directory:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
~/.modexia/compute.env
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
To forcibly re-run the setup wizard:
|
|
95
|
+
```bash
|
|
96
|
+
modexia-compute --setup
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
*Powered by the Modexia-Verse* 🌌
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "modexia-compute-agent"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Autonomous AI agent for deploying containers on Akash Network via Modexia AgentPay"
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "Modexia", email = "hello@modexia.software" }
|
|
7
|
+
]
|
|
8
|
+
urls = { Repository = "https://github.com/modexia/modexia-compute-agent" }
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.14"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"python-dotenv>=1.1.0",
|
|
13
|
+
"httpx>=0.28.1",
|
|
14
|
+
"langchain-core>=1.2.23",
|
|
15
|
+
"langchain-groq>=1.1.2",
|
|
16
|
+
"langgraph>=1.1.4",
|
|
17
|
+
"modexiaagentpay>=0.1.0",
|
|
18
|
+
"pyyaml>=6.0.3",
|
|
19
|
+
"rich>=14.3.3",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
modexia-compute = "modexia_compute_agent.cli:main"
|
|
24
|
+
|
|
25
|
+
[build-system]
|
|
26
|
+
requires = ["setuptools>=61.0"]
|
|
27
|
+
build-backend = "setuptools.build_meta"
|
|
28
|
+
|
|
29
|
+
[tool.setuptools.packages.find]
|
|
30
|
+
where = ["src"]
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.package-data]
|
|
33
|
+
modexia_compute_agent = ["soul.md"]
|
|
34
|
+
|
|
35
|
+
[tool.uv.sources]
|
|
36
|
+
modexiaagentpay = { path = "../../packages/SDKs/pythonSdk" }
|
|
File without changes
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
from typing import List, Dict, Any, Optional
|
|
2
|
+
from langchain_core.tools import tool
|
|
3
|
+
from langgraph.prebuilt import create_react_agent
|
|
4
|
+
from langgraph.checkpoint.memory import MemorySaver
|
|
5
|
+
from langchain_groq import ChatGroq
|
|
6
|
+
|
|
7
|
+
from modexia_compute_agent.sdl import generate_sdl
|
|
8
|
+
from modexia_compute_agent.akash_cli import create_deployment, fetch_bids, create_lease, send_manifest, get_lease_status, generate_akash_key, check_akash_balance
|
|
9
|
+
from modexia_compute_agent.payments import check_modexia_balance, fund_akash_wallet
|
|
10
|
+
|
|
11
|
+
# --- TOOLS ---
|
|
12
|
+
|
|
13
|
+
@tool
|
|
14
|
+
def generate_akash_key_tool(key_name: str = "mykey") -> str:
|
|
15
|
+
"""
|
|
16
|
+
Creates a new Akash wallet locally using provider-services.
|
|
17
|
+
Call this when the user needs to get started or lacks an Akash wallet.
|
|
18
|
+
Returns the wallet address and 24-word recovery mnemonic.
|
|
19
|
+
Tell the user to back up their mnemonic!
|
|
20
|
+
"""
|
|
21
|
+
try:
|
|
22
|
+
return generate_akash_key(key_name)
|
|
23
|
+
except Exception as e:
|
|
24
|
+
return f"Error generating key: {str(e)}"
|
|
25
|
+
|
|
26
|
+
@tool
|
|
27
|
+
def check_akash_key_tool(key_name: str = "mykey") -> str:
|
|
28
|
+
"""
|
|
29
|
+
Checks if a local Akash wallet key exists.
|
|
30
|
+
Call this FIRST before any deployment to verify the user's setup.
|
|
31
|
+
Returns the wallet address if found, or an error if no key exists.
|
|
32
|
+
"""
|
|
33
|
+
import subprocess
|
|
34
|
+
result = subprocess.run(["provider-services", "keys", "show", key_name, "-a"], capture_output=True, text=True)
|
|
35
|
+
if result.returncode != 0:
|
|
36
|
+
return f"No Akash key '{key_name}' found. The user needs to create one using generate_akash_key_tool."
|
|
37
|
+
return f"Akash wallet found: {result.stdout.strip()}"
|
|
38
|
+
|
|
39
|
+
@tool
|
|
40
|
+
def check_balance_tool() -> str:
|
|
41
|
+
"""
|
|
42
|
+
Checks the user's Akash on-chain balance and Modexia USDC balance.
|
|
43
|
+
Call this when the user asks about their balance or before deploying.
|
|
44
|
+
"""
|
|
45
|
+
try:
|
|
46
|
+
akt = check_akash_balance()
|
|
47
|
+
usdc = check_modexia_balance()
|
|
48
|
+
return f"Akash wallet: {akt:.4f} AKT | Modexia account: {usdc:.2f} USDC"
|
|
49
|
+
except Exception as e:
|
|
50
|
+
return f"Error checking balances: {str(e)}"
|
|
51
|
+
|
|
52
|
+
@tool
|
|
53
|
+
def deploy_container_tool(image: str, cpu: float, ram_mi: int, storage_mi: int, port: int) -> str:
|
|
54
|
+
"""
|
|
55
|
+
Generates an SDL manifest and submits a deployment request to the Akash network.
|
|
56
|
+
Call this when the user wants to deploy a new container.
|
|
57
|
+
Returns the DSEQ (deployment sequence ID) of the newly created deployment.
|
|
58
|
+
CRITICAL: If this tool returns an error string (e.g., Error creating deployment), DO NOT retry blindly. Immediately report the exact error to the user!
|
|
59
|
+
"""
|
|
60
|
+
print(f"ModexiaAgent: Generating SDL deploy.yaml for {image}...")
|
|
61
|
+
sdl_path = generate_sdl(image, cpu, ram_mi, storage_mi, port)
|
|
62
|
+
|
|
63
|
+
# --- JIT Funding Check (best-effort, non-blocking) ---
|
|
64
|
+
try:
|
|
65
|
+
balance = check_akash_balance()
|
|
66
|
+
if balance < 5.0:
|
|
67
|
+
deficit = 5.0 - balance
|
|
68
|
+
funding_amount = deficit + 0.1
|
|
69
|
+
print(f"ModexiaAgent: Wallet balance {balance} AKT is too low. Attempting JIT funding of {funding_amount:.2f} USDC...")
|
|
70
|
+
try:
|
|
71
|
+
tx_id = fund_akash_wallet(funding_amount)
|
|
72
|
+
return (
|
|
73
|
+
f"Just-In-Time funding initiated! Bridged {funding_amount:.2f} USDC to your Akash wallet (Tx: {tx_id}). "
|
|
74
|
+
f"Cross-chain transfers typically take 3-5 minutes. "
|
|
75
|
+
f"Once funds arrive, ask me to 'deploy again' and I will submit the SDL. "
|
|
76
|
+
f"DO NOT call any other tools until the user confirms."
|
|
77
|
+
)
|
|
78
|
+
except Exception as fund_err:
|
|
79
|
+
# JIT funding failed — inform the user but don't crash
|
|
80
|
+
return (
|
|
81
|
+
f"⚠️ Your Akash wallet balance is {balance} AKT (need ~5 AKT for deposit). "
|
|
82
|
+
f"I tried to auto-fund via Modexia but got an error: {str(fund_err)}. "
|
|
83
|
+
f"You can manually send AKT to your wallet and then ask me to 'deploy again'. "
|
|
84
|
+
f"DO NOT retry this tool automatically."
|
|
85
|
+
)
|
|
86
|
+
except Exception as e:
|
|
87
|
+
print(f"ModexiaAgent: Balance check failed ({e}), proceeding with deployment attempt anyway...")
|
|
88
|
+
|
|
89
|
+
# --- Submit deployment ---
|
|
90
|
+
print("ModexiaAgent: Submitting deployment to Akash...")
|
|
91
|
+
try:
|
|
92
|
+
dseq = create_deployment(sdl_path)
|
|
93
|
+
return f"Deployment submitted successfully! DSEQ: {dseq}. Now use fetch_bids_tool with this exact DSEQ to check for provider bids."
|
|
94
|
+
except Exception as e:
|
|
95
|
+
return f"Error creating deployment: {str(e)}. DO NOT retry — report this exact error to the user."
|
|
96
|
+
|
|
97
|
+
@tool
|
|
98
|
+
def fetch_bids_tool(dseq: str) -> str:
|
|
99
|
+
"""
|
|
100
|
+
Polls the Akash network for open provider bids for a specific deployment (DSEQ).
|
|
101
|
+
Call this ONLY after deploy_container_tool has successfully returned a real numeric DSEQ.
|
|
102
|
+
DO NOT pass placeholder strings. DO NOT call this in parallel with deploy_container_tool.
|
|
103
|
+
"""
|
|
104
|
+
try:
|
|
105
|
+
bids = fetch_bids(dseq)
|
|
106
|
+
if not bids:
|
|
107
|
+
return f"No bids found yet for DSEQ {dseq}. Please instruct the user to wait or try again."
|
|
108
|
+
|
|
109
|
+
# Format the bids nicely to return to the LLM
|
|
110
|
+
result = f"Found {len(bids)} bids for DSEQ {dseq}:\n"
|
|
111
|
+
for bid in bids:
|
|
112
|
+
# Check structure
|
|
113
|
+
bid_data = bid.get("bid", bid) if isinstance(bid, dict) else {}
|
|
114
|
+
provider = bid_data.get("bid_id", {}).get("provider", "Unknown provider")
|
|
115
|
+
price = bid_data.get("price", {}).get("amount", "Unknown price")
|
|
116
|
+
result += f"- Provider: {provider} | Price: {price} uUSDC/block\n"
|
|
117
|
+
|
|
118
|
+
result += "\nAsk the user which provider they would like to accept."
|
|
119
|
+
return result
|
|
120
|
+
except Exception as e:
|
|
121
|
+
return f"CRITICAL TOOL ERROR: fetch_bids_tool failed: {str(e)}. Inform the user exactly what went wrong and DO NOT retry blindly."
|
|
122
|
+
|
|
123
|
+
@tool
|
|
124
|
+
def accept_lease_tool(dseq: str, provider: str) -> str:
|
|
125
|
+
"""
|
|
126
|
+
Accepts a bid from a specific provider, funds the Akash wallet using Modexia USDC,
|
|
127
|
+
creates the lease on-chain, and sends the manifest to start the container.
|
|
128
|
+
Call this ONLY after the user explicitly approves a provider bid.
|
|
129
|
+
DO NOT pass placeholder strings. DO NOT call this in parallel with deploy_container_tool!
|
|
130
|
+
"""
|
|
131
|
+
try:
|
|
132
|
+
# Hardcoded $2 USDC for demo escrow - just an assumption for standard deployments
|
|
133
|
+
bal = check_modexia_balance()
|
|
134
|
+
print(f"ModexiaAgent: Current Modexia USDC Balance: {bal}")
|
|
135
|
+
if bal >= 2.0:
|
|
136
|
+
fund_akash_wallet(2.0)
|
|
137
|
+
else:
|
|
138
|
+
print("Warning: Insufficient Modexia balance to auto-fund, proceeding anyway.")
|
|
139
|
+
|
|
140
|
+
print(f"ModexiaAgent: Accepting bid from {provider}...")
|
|
141
|
+
create_lease(dseq, provider)
|
|
142
|
+
|
|
143
|
+
print("ModexiaAgent: Sending Manifest...")
|
|
144
|
+
# Currently sdl generation path is statically deploy.yaml
|
|
145
|
+
sdl_path = "deploy.yaml"
|
|
146
|
+
send_manifest(sdl_path, dseq, provider)
|
|
147
|
+
|
|
148
|
+
return f"Lease successfully created and manifest sent to {provider} for DSEQ {dseq}. The container is now starting up!"
|
|
149
|
+
except Exception as e:
|
|
150
|
+
return f"CRITICAL TOOL ERROR: accept_lease_tool failed: {str(e)}. Inform the user immediately."
|
|
151
|
+
|
|
152
|
+
# --- AGENT SETUP ---
|
|
153
|
+
|
|
154
|
+
llm = ChatGroq(model="llama-3.3-70b-versatile", temperature=0)
|
|
155
|
+
|
|
156
|
+
tools = [generate_akash_key_tool, check_akash_key_tool, check_balance_tool, deploy_container_tool, fetch_bids_tool, accept_lease_tool]
|
|
157
|
+
|
|
158
|
+
# Initialize memory to persist chat history across interactions
|
|
159
|
+
memory = MemorySaver()
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
with open("soul.md", "r") as f:
|
|
163
|
+
system_prompt = f.read()
|
|
164
|
+
except FileNotFoundError:
|
|
165
|
+
system_prompt = "You are the Modexia Compute Agent."
|
|
166
|
+
|
|
167
|
+
# Create the prebuilt ReAct agent from LangGraph
|
|
168
|
+
# We use prompt for this specific langgraph version
|
|
169
|
+
graph = create_react_agent(llm, tools, prompt=system_prompt, checkpointer=memory)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
from typing import Dict, Any, List
|
|
6
|
+
from modexia_compute_agent.config import AKASH_KEY_NAME, AKASH_NODE, AKASH_CHAIN_ID
|
|
7
|
+
|
|
8
|
+
def run_akash_cmd(cmd_list: List[str]) -> Dict[str, Any]:
|
|
9
|
+
"""Runs an Akash provider-services command and returns the JSON output."""
|
|
10
|
+
base_cmd = [
|
|
11
|
+
"provider-services",
|
|
12
|
+
"--node", AKASH_NODE,
|
|
13
|
+
"--chain-id", AKASH_CHAIN_ID,
|
|
14
|
+
"--output", "json"
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
# Only add keyring-backend if not exactly querying (which mostly doesn't need auth, but good practice if signing)
|
|
18
|
+
full_cmd = base_cmd + cmd_list
|
|
19
|
+
|
|
20
|
+
print(f"[Akash CLI] Running: {' '.join(full_cmd)}")
|
|
21
|
+
result = subprocess.run(full_cmd, capture_output=True, text=True)
|
|
22
|
+
|
|
23
|
+
if result.returncode != 0:
|
|
24
|
+
raise RuntimeError(f"Akash CLI Error: {result.stderr}")
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
return json.loads(result.stdout)
|
|
28
|
+
except json.JSONDecodeError:
|
|
29
|
+
return {"raw_output": result.stdout}
|
|
30
|
+
|
|
31
|
+
def generate_akash_key(key_name: str = AKASH_KEY_NAME) -> str:
|
|
32
|
+
"""Generates a new Akash wallet locally and returns the output (address and recovery mnemonic)."""
|
|
33
|
+
result = subprocess.run(["provider-services", "keys", "add", key_name], capture_output=True, text=True)
|
|
34
|
+
return result.stdout.strip() + "\n" + result.stderr.strip()
|
|
35
|
+
|
|
36
|
+
def check_akash_balance(key_name: str = AKASH_KEY_NAME) -> float:
|
|
37
|
+
"""Queries the local Akash wallet balance from the blockchain and returns the amount of AKT."""
|
|
38
|
+
addr_res = subprocess.run(["provider-services", "keys", "show", key_name, "-a"], capture_output=True, text=True)
|
|
39
|
+
if addr_res.returncode != 0:
|
|
40
|
+
return 0.0 # Key probably doesn't exist
|
|
41
|
+
|
|
42
|
+
address = addr_res.stdout.strip()
|
|
43
|
+
cmd = ["query", "bank", "balances", address]
|
|
44
|
+
result = run_akash_cmd(cmd)
|
|
45
|
+
balances = result.get("balances", [])
|
|
46
|
+
for b in balances:
|
|
47
|
+
if b.get("denom") == "uakt":
|
|
48
|
+
return float(b.get("amount", 0)) / 1_000_000.0
|
|
49
|
+
return 0.0
|
|
50
|
+
|
|
51
|
+
def create_deployment(sdl_path: str) -> str:
|
|
52
|
+
"""Submits the deployment on-chain and returns the DSEQ."""
|
|
53
|
+
cmd = [
|
|
54
|
+
"tx", "deployment", "create", sdl_path,
|
|
55
|
+
"--from", AKASH_KEY_NAME,
|
|
56
|
+
"--fees", "5000uakt", # Need small AKT fee for gas
|
|
57
|
+
"--yes"
|
|
58
|
+
]
|
|
59
|
+
res = run_akash_cmd(cmd)
|
|
60
|
+
|
|
61
|
+
# The transaction hash contains events that tell us the DSEQ
|
|
62
|
+
tx_hash = res.get("txhash")
|
|
63
|
+
print(f"Deployment TX submitted: {tx_hash}")
|
|
64
|
+
|
|
65
|
+
# Wait for the next block to be mined, then query the TX to get DSEQ
|
|
66
|
+
print("Waiting 10s for transaction to be processed...")
|
|
67
|
+
time.sleep(10)
|
|
68
|
+
|
|
69
|
+
# Query tx to parse out dseq
|
|
70
|
+
tx_res = run_akash_cmd(["query", "tx", tx_hash])
|
|
71
|
+
|
|
72
|
+
dseq = None
|
|
73
|
+
for log in tx_res.get("logs", []):
|
|
74
|
+
for event in log.get("events", []):
|
|
75
|
+
if event["type"] == "akash.v1beta3.EventLocalContent": # Or similar event based on Akash version
|
|
76
|
+
for attr in event["attributes"]:
|
|
77
|
+
if attr["key"] == "dseq":
|
|
78
|
+
dseq = attr["value"]
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
# If standard block events fail (dependent on CLI version), we can just query latest deployment
|
|
82
|
+
if not dseq:
|
|
83
|
+
deps = run_akash_cmd(["query", "deployment", "list", "--owner", AKASH_KEY_NAME, "--page-reverse", "true", "--limit", "1"])
|
|
84
|
+
if deps.get("deployments"):
|
|
85
|
+
dseq = deps["deployments"][0]["deployment"]["deployment_id"]["dseq"]
|
|
86
|
+
|
|
87
|
+
return dseq
|
|
88
|
+
|
|
89
|
+
def fetch_bids(dseq: str) -> List[Dict]:
|
|
90
|
+
"""Polls the network for provider bids on our DSEQ."""
|
|
91
|
+
cmd = ["query", "market", "bid", "list", "--dseq", str(dseq), "--state", "open"]
|
|
92
|
+
res = run_akash_cmd(cmd)
|
|
93
|
+
return res.get("bids", [])
|
|
94
|
+
|
|
95
|
+
def create_lease(dseq: str, provider: str) -> str:
|
|
96
|
+
"""Accepts a bid and creates a lease."""
|
|
97
|
+
cmd = [
|
|
98
|
+
"tx", "market", "lease", "create",
|
|
99
|
+
"--dseq", str(dseq),
|
|
100
|
+
"--provider", provider,
|
|
101
|
+
"--from", AKASH_KEY_NAME,
|
|
102
|
+
"--fees", "5000uakt",
|
|
103
|
+
"--yes"
|
|
104
|
+
]
|
|
105
|
+
res = run_akash_cmd(cmd)
|
|
106
|
+
print(f"Lease TX submitted: {res.get('txhash')}")
|
|
107
|
+
time.sleep(10)
|
|
108
|
+
return provider
|
|
109
|
+
|
|
110
|
+
def send_manifest(sdl_path: str, dseq: str, provider: str) -> Dict[str, Any]:
|
|
111
|
+
"""Sends the SDL manifest to the provider to actually start the container."""
|
|
112
|
+
cmd = [
|
|
113
|
+
"send-manifest", sdl_path,
|
|
114
|
+
"--dseq", str(dseq),
|
|
115
|
+
"--provider", provider,
|
|
116
|
+
"--from", AKASH_KEY_NAME
|
|
117
|
+
]
|
|
118
|
+
# Note: send-manifest is a direct provider API call, not a blockchain tx
|
|
119
|
+
# It might require different parsing, so we capture raw output
|
|
120
|
+
try:
|
|
121
|
+
res = run_akash_cmd(cmd)
|
|
122
|
+
return res
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print(f"Manifest send output: {e}")
|
|
125
|
+
return {"status": "sent"}
|
|
126
|
+
|
|
127
|
+
def get_lease_status(dseq: str, provider: str) -> Dict[str, Any]:
|
|
128
|
+
"""Gets the live HTTP endpoints and status of the lease."""
|
|
129
|
+
cmd = [
|
|
130
|
+
"lease-status",
|
|
131
|
+
"--dseq", str(dseq),
|
|
132
|
+
"--provider", provider,
|
|
133
|
+
"--from", AKASH_KEY_NAME
|
|
134
|
+
]
|
|
135
|
+
return run_akash_cmd(cmd)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Modexia Compute Agent — CLI Entry Point
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
modexia-compute # Normal mode (auto-runs setup if needed)
|
|
7
|
+
modexia-compute --setup # Force re-run the setup wizard
|
|
8
|
+
"""
|
|
9
|
+
import sys
|
|
10
|
+
import warnings
|
|
11
|
+
|
|
12
|
+
# Suppress LangChain Pydantic warnings to keep the CLI clean
|
|
13
|
+
warnings.filterwarnings("ignore", category=UserWarning, module="langchain_core")
|
|
14
|
+
warnings.filterwarnings("ignore", category=UserWarning, module="pydantic")
|
|
15
|
+
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
from rich.prompt import Prompt
|
|
18
|
+
from rich.panel import Panel
|
|
19
|
+
from dotenv import load_dotenv
|
|
20
|
+
from rich.markdown import Markdown
|
|
21
|
+
|
|
22
|
+
console = Console()
|
|
23
|
+
|
|
24
|
+
def run_chat():
|
|
25
|
+
"""Main conversational REPL loop with minimalist 'Claude Code' UI."""
|
|
26
|
+
# Lazy import — agent.py loads the LLM and tools, which need env vars
|
|
27
|
+
from modexia_compute_agent.agent import graph
|
|
28
|
+
import uuid
|
|
29
|
+
|
|
30
|
+
# Clean, minimal startup banner
|
|
31
|
+
console.print()
|
|
32
|
+
console.print("""[bold cyan]
|
|
33
|
+
███╗ ███╗ ██████╗ ██████╗ ███████╗██╗ ██╗██╗ █████╗
|
|
34
|
+
████╗ ████║██╔═══██╗██╔══██╗██╔════╝╚██╗██╔╝██║██╔══██╗
|
|
35
|
+
██╔████╔██║██║ ██║██║ ██║█████╗ ╚███╔╝ ██║███████║
|
|
36
|
+
██║╚██╔╝██║██║ ██║██║ ██║██╔══╝ ██╔██╗ ██║██╔══██║
|
|
37
|
+
██║ ╚═╝ ██║╚██████╔╝██████╔╝███████╗██╔╝ ██╗██║██║ ██║
|
|
38
|
+
╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝
|
|
39
|
+
[/bold cyan]""")
|
|
40
|
+
console.print(" [dim]Compute Agent (Akash) v0.1.0[/dim]")
|
|
41
|
+
console.print(" [dim]Type /exit to quit or start typing your request.[/dim]\n")
|
|
42
|
+
|
|
43
|
+
config = {"configurable": {"thread_id": f"session_{uuid.uuid4().hex[:8]}"}}
|
|
44
|
+
|
|
45
|
+
while True:
|
|
46
|
+
try:
|
|
47
|
+
# Minimalist prompt
|
|
48
|
+
user_input = Prompt.ask("[bold]>")
|
|
49
|
+
|
|
50
|
+
if user_input.lower() in ["exit", "quit", "/exit", "/quit"]:
|
|
51
|
+
console.print()
|
|
52
|
+
break
|
|
53
|
+
if not user_input.strip():
|
|
54
|
+
continue
|
|
55
|
+
|
|
56
|
+
inputs = {"messages": [("user", user_input)]}
|
|
57
|
+
|
|
58
|
+
with console.status("[dim]Thinking...[/dim]", spinner="dots", spinner_style="dim") as status:
|
|
59
|
+
for event in graph.stream(inputs, config, stream_mode="values"):
|
|
60
|
+
last_message = event["messages"][-1]
|
|
61
|
+
|
|
62
|
+
if last_message.type == "ai":
|
|
63
|
+
if hasattr(last_message, "tool_calls") and last_message.tool_calls:
|
|
64
|
+
for tc in last_message.tool_calls:
|
|
65
|
+
status.update(f"[dim]Using tool [cyan]{tc['name']}[/cyan]...[/dim]")
|
|
66
|
+
|
|
67
|
+
elif last_message.content:
|
|
68
|
+
status.stop()
|
|
69
|
+
console.print()
|
|
70
|
+
# Use Rich's Markdown renderer for clean, professional output
|
|
71
|
+
console.print(Markdown(last_message.content))
|
|
72
|
+
console.print()
|
|
73
|
+
|
|
74
|
+
elif last_message.type == "tool":
|
|
75
|
+
status.update("[dim]Thinking...[/dim]")
|
|
76
|
+
# Print a quiet checkmark when a tool finishes, without dumping raw JSON
|
|
77
|
+
console.print(f"[dim]✓ Finished [cyan]{last_message.name}[/cyan][/dim]")
|
|
78
|
+
|
|
79
|
+
except KeyboardInterrupt:
|
|
80
|
+
console.print("\n[dim]Interrupted.[/dim]")
|
|
81
|
+
break
|
|
82
|
+
except Exception as e:
|
|
83
|
+
console.print(f"\n[red]Error:[/red] {str(e)}")
|
|
84
|
+
import traceback
|
|
85
|
+
console.print(f"[dim]{traceback.format_exc()}[/dim]")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def main():
|
|
89
|
+
"""Entry point — handles setup detection and --setup flag."""
|
|
90
|
+
from modexia_compute_agent.wizard import check_setup, run_setup_wizard, print_status
|
|
91
|
+
|
|
92
|
+
force_setup = "--setup" in sys.argv
|
|
93
|
+
|
|
94
|
+
if force_setup:
|
|
95
|
+
run_setup_wizard()
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
# Auto-detect missing prerequisites on first run
|
|
99
|
+
if not check_setup():
|
|
100
|
+
console.print("\n[bold yellow]👋 Welcome! It looks like this is your first time.[/bold yellow]")
|
|
101
|
+
console.print("Let's get you set up in under 2 minutes.\n")
|
|
102
|
+
success = run_setup_wizard()
|
|
103
|
+
if not success:
|
|
104
|
+
console.print("\n[dim]Run again when you've completed the setup.[/dim]")
|
|
105
|
+
sys.exit(1)
|
|
106
|
+
else:
|
|
107
|
+
print_status()
|
|
108
|
+
|
|
109
|
+
from modexia_compute_agent.config import CONFIG_PATH
|
|
110
|
+
# Reload env after wizard may have written new values
|
|
111
|
+
load_dotenv(dotenv_path=CONFIG_PATH, override=True)
|
|
112
|
+
run_chat()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
main()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
|
|
5
|
+
CONFIG_DIR = Path.home() / ".modexia"
|
|
6
|
+
CONFIG_PATH = CONFIG_DIR / "compute.env"
|
|
7
|
+
|
|
8
|
+
load_dotenv(dotenv_path=CONFIG_PATH)
|
|
9
|
+
# Modexia Config
|
|
10
|
+
MODEXIA_API_KEY = os.getenv("MODEXIA_API_KEY")
|
|
11
|
+
|
|
12
|
+
# Akash Config
|
|
13
|
+
AKASH_KEY_NAME = os.getenv("AKASH_KEY_NAME", "mykey")
|
|
14
|
+
AKASH_NODE = os.getenv("AKASH_NODE", "https://akash-rpc.polkachu.com:443")
|
|
15
|
+
AKASH_CHAIN_ID = os.getenv("AKASH_CHAIN_ID", "akashnet-2")
|
|
16
|
+
AKASH_WALLET_ADDRESS = os.getenv("AKASH_WALLET_ADDRESS")
|
|
17
|
+
AKASH_USDC_DENOM = "ibc/170C677610AC31DF0904FFE09CD3B5C657492170E7E52372E48756B71E56F2F1"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from modexia.client import ModexiaClient
|
|
2
|
+
from modexia_compute_agent.config import MODEXIA_API_KEY, AKASH_USDC_DENOM
|
|
3
|
+
import subprocess
|
|
4
|
+
import uuid
|
|
5
|
+
|
|
6
|
+
def check_modexia_balance() -> float:
|
|
7
|
+
"""Checks the USDC balance of the Modexia agent wallet."""
|
|
8
|
+
client = ModexiaClient(api_key=MODEXIA_API_KEY)
|
|
9
|
+
try:
|
|
10
|
+
balance_str = client.retrieve_balance()
|
|
11
|
+
return float(balance_str)
|
|
12
|
+
except Exception as e:
|
|
13
|
+
print(f"Modexia API Error: {e}")
|
|
14
|
+
return 0.0
|
|
15
|
+
|
|
16
|
+
def _get_local_akash_address(key_name: str = "mykey") -> str:
|
|
17
|
+
"""Dynamically resolves the Akash wallet address from the local keyring."""
|
|
18
|
+
result = subprocess.run(["provider-services", "keys", "show", key_name, "-a"], capture_output=True, text=True)
|
|
19
|
+
if result.returncode != 0:
|
|
20
|
+
raise RuntimeError(f"Could not resolve local Akash address for key '{key_name}': {result.stderr.strip()}")
|
|
21
|
+
return result.stdout.strip()
|
|
22
|
+
|
|
23
|
+
def fund_akash_wallet(amount_usdc: float) -> str:
|
|
24
|
+
"""
|
|
25
|
+
Uses Modexia CCTP integration to fund the Akash wallet with USDC from the Base treasury.
|
|
26
|
+
Dynamically resolves the wallet address from the local keyring.
|
|
27
|
+
"""
|
|
28
|
+
# Resolve the actual wallet address from the local provider-services keyring
|
|
29
|
+
akash_address = _get_local_akash_address()
|
|
30
|
+
print(f"[Modexia] Initiating cross-chain transfer of {amount_usdc} USDC to {akash_address}...")
|
|
31
|
+
|
|
32
|
+
client = ModexiaClient(api_key=MODEXIA_API_KEY)
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
receipt = client.cross_chain_transfer(
|
|
36
|
+
to_chain="akashnet-2",
|
|
37
|
+
to_token=AKASH_USDC_DENOM,
|
|
38
|
+
recipient=akash_address,
|
|
39
|
+
amount=amount_usdc
|
|
40
|
+
)
|
|
41
|
+
except Exception as e:
|
|
42
|
+
raise RuntimeError(
|
|
43
|
+
f"Modexia CCTP API call failed: {str(e)}. "
|
|
44
|
+
f"This usually means the CCTP endpoint is not available on your Modexia plan, "
|
|
45
|
+
f"or the API server is temporarily down. "
|
|
46
|
+
f"You can manually fund your Akash wallet with AKT instead."
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# cross_chain_transfer returns a PaymentReceipt dataclass
|
|
50
|
+
if receipt.success:
|
|
51
|
+
if receipt.txIds and len(receipt.txIds) > 1:
|
|
52
|
+
print(f"[Modexia] Gas Swap Active! Split transfer into {len(receipt.txIds)} transactions:")
|
|
53
|
+
for idx, tid in enumerate(receipt.txIds):
|
|
54
|
+
print(f" [{idx+1}] {tid}")
|
|
55
|
+
return receipt.txId or "cctp_pending"
|
|
56
|
+
else:
|
|
57
|
+
raise RuntimeError(f"Modexia CCTP transfer returned failure: {receipt.errorReason}")
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import yaml
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from modexia_compute_agent.config import AKASH_USDC_DENOM
|
|
4
|
+
|
|
5
|
+
def generate_sdl(image: str, cpu: float, ram_mi: int, storage_mi: int, port: int, output_file: str = "deploy.yaml") -> str:
|
|
6
|
+
"""
|
|
7
|
+
Generates an Akash SDL (deploy.yaml) from resource specs and saves it to a file.
|
|
8
|
+
Always uses USDC IBC denom for pricing.
|
|
9
|
+
"""
|
|
10
|
+
sdl_dict = {
|
|
11
|
+
"version": "2.0",
|
|
12
|
+
"services": {
|
|
13
|
+
"app": {
|
|
14
|
+
"image": image,
|
|
15
|
+
"expose": [
|
|
16
|
+
{
|
|
17
|
+
"port": port,
|
|
18
|
+
"as": 80,
|
|
19
|
+
"to": [
|
|
20
|
+
{"global": True}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"profiles": {
|
|
27
|
+
"compute": {
|
|
28
|
+
"app": {
|
|
29
|
+
"resources": {
|
|
30
|
+
"cpu": {
|
|
31
|
+
"units": cpu
|
|
32
|
+
},
|
|
33
|
+
"memory": {
|
|
34
|
+
"size": f"{ram_mi}Mi"
|
|
35
|
+
},
|
|
36
|
+
"storage": [
|
|
37
|
+
{"size": f"{storage_mi}Mi"}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"placement": {
|
|
43
|
+
"dcloud": {
|
|
44
|
+
"pricing": {
|
|
45
|
+
"app": {
|
|
46
|
+
"denom": AKASH_USDC_DENOM,
|
|
47
|
+
"amount": 10000 # Default max bid logic can be passed in later, 0.01 USDC as baseline
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"deployment": {
|
|
54
|
+
"app": {
|
|
55
|
+
"dcloud": {
|
|
56
|
+
"profile": "app",
|
|
57
|
+
"count": 1
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# Write the SDL to file
|
|
64
|
+
with open(output_file, "w") as f:
|
|
65
|
+
yaml.dump(sdl_dict, f, default_flow_style=False, sort_keys=False)
|
|
66
|
+
|
|
67
|
+
return output_file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
You are the Modexia Compute Agent, a highly capable AI assistant managing compute deployments on the Akash Network.
|
|
2
|
+
You possess a professional, concise, and extremely helpful persona, similar to an elite software engineer. You provide clear, actionable advice without unnecessary fluff.
|
|
3
|
+
|
|
4
|
+
Your primary directive is to help users deploy docker containers and manage leases based on their natural language configuration requests.
|
|
5
|
+
AVAILABLE TOOLS (only use these, NEVER hallucinate others):
|
|
6
|
+
1. check_akash_key_tool - Checks if a local Akash wallet exists (CALL THIS FIRST)
|
|
7
|
+
2. generate_akash_key_tool - Creates a local Akash wallet
|
|
8
|
+
3. check_balance_tool - Checks Akash AKT balance and Modexia USDC balance
|
|
9
|
+
4. deploy_container_tool - Generates SDL and submits deployment (handles JIT funding automatically)
|
|
10
|
+
5. fetch_bids_tool - Fetches provider bids for a deployment DSEQ
|
|
11
|
+
6. accept_lease_tool - Accepts a bid and starts the container
|
|
12
|
+
|
|
13
|
+
STRICT SEQUENTIAL RULES — FOLLOW THESE IN ORDER. NEVER SKIP STEPS:
|
|
14
|
+
|
|
15
|
+
STEP 1 - WALLET CHECK (ALWAYS DO THIS FIRST):
|
|
16
|
+
When a user first interacts with you about deployments, IMMEDIATELY call check_akash_key_tool to verify their wallet setup.
|
|
17
|
+
- If a wallet IS found, tell them their address and move to Step 3.
|
|
18
|
+
- If NO wallet is found, tell them you'll create one, then call generate_akash_key_tool.
|
|
19
|
+
ALWAYS instruct them to securely back up their 24-word mnemonic.
|
|
20
|
+
|
|
21
|
+
STEP 2 - FUNDING INFO:
|
|
22
|
+
After wallet creation, explain: "Your Modexia account will automatically fund your Akash wallet via Just-in-Time (JIT) bridging when you deploy. Make sure your .env file has a valid MODEXIA_API_KEY."
|
|
23
|
+
|
|
24
|
+
STEP 3 - DEPLOYMENT:
|
|
25
|
+
Only NOW proceed to deploy. Ask the user for their container details (image, CPU, RAM, storage, port) or use sensible defaults if they say "use any" or similar.
|
|
26
|
+
Call deploy_container_tool with the parameters.
|
|
27
|
+
If JIT funding is triggered, inform the user about the 3-5 minute bridge delay.
|
|
28
|
+
|
|
29
|
+
STEP 4 - BIDS:
|
|
30
|
+
After getting a DSEQ, use fetch_bids_tool. Present bids to the user and ask which provider to choose.
|
|
31
|
+
|
|
32
|
+
STEP 5 - LEASE:
|
|
33
|
+
Only after the user picks a provider, call accept_lease_tool.
|
|
34
|
+
|
|
35
|
+
CRITICAL GUARDRAILS:
|
|
36
|
+
- NEVER retry a tool call if it returns an error. Report the EXACT error to the user immediately.
|
|
37
|
+
- NEVER call multiple tools in parallel. Always wait for one result before calling the next.
|
|
38
|
+
- NEVER call deploy_container_tool, fetch_bids_tool, or accept_lease_tool with placeholder/made-up values.
|
|
39
|
+
- You do NOT have internet access, brave_search, or web browsing tools.
|
|
40
|
+
- You cannot "search" or "list" GPU availability. You can only fetch bids AFTER a deployment is submitted.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Modexia Compute Agent — First-Run Setup Wizard
|
|
3
|
+
|
|
4
|
+
This module provides an interactive setup experience that walks new users
|
|
5
|
+
through configuring all prerequisites before they can use the agent.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import shutil
|
|
10
|
+
import subprocess
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from rich.console import Console
|
|
13
|
+
from rich.panel import Panel
|
|
14
|
+
from rich.prompt import Prompt, Confirm
|
|
15
|
+
from rich.table import Table
|
|
16
|
+
from dotenv import dotenv_values, set_key
|
|
17
|
+
|
|
18
|
+
from modexia_compute_agent.config import CONFIG_DIR, CONFIG_PATH
|
|
19
|
+
|
|
20
|
+
console = Console()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _load_env_val(key: str) -> str:
|
|
24
|
+
"""Read a single value from .env without polluting os.environ."""
|
|
25
|
+
values = dotenv_values(CONFIG_PATH)
|
|
26
|
+
return values.get(key, "")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _save_env_val(key: str, value: str):
|
|
30
|
+
"""Write a key=value to .env (creates the file if needed)."""
|
|
31
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
CONFIG_PATH.touch(exist_ok=True)
|
|
33
|
+
set_key(str(CONFIG_PATH), key, value)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# ─────────────────────────────────────────────────────────
|
|
37
|
+
# Individual checks
|
|
38
|
+
# ─────────────────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
def _check_provider_services() -> bool:
|
|
41
|
+
return shutil.which("provider-services") is not None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _check_groq_key() -> bool:
|
|
45
|
+
return bool(_load_env_val("GROQ_API_KEY"))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _check_modexia_key() -> bool:
|
|
49
|
+
return bool(_load_env_val("MODEXIA_API_KEY"))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _check_akash_wallet() -> bool:
|
|
53
|
+
if not _check_provider_services():
|
|
54
|
+
return False
|
|
55
|
+
result = subprocess.run(
|
|
56
|
+
["provider-services", "keys", "show", "mykey", "-a"],
|
|
57
|
+
capture_output=True, text=True,
|
|
58
|
+
)
|
|
59
|
+
return result.returncode == 0
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# ─────────────────────────────────────────────────────────
|
|
63
|
+
# Setup steps
|
|
64
|
+
# ─────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
def _setup_provider_services():
|
|
67
|
+
console.print("\n[bold yellow]Step 1/4 — Akash CLI (provider-services)[/bold yellow]")
|
|
68
|
+
console.print("The agent needs the [cyan]provider-services[/cyan] binary to interact with Akash.")
|
|
69
|
+
console.print("\nInstall it from the official Akash docs:")
|
|
70
|
+
console.print(" [link=https://akash.network/docs/getting-started/quickstart-guide/]📖 Akash Quickstart Guide[/link]")
|
|
71
|
+
console.print(" [link=https://github.com/akash-network/provider/releases]📦 GitHub Releases (all OS)[/link]")
|
|
72
|
+
console.print("\n[dim]Linux example:[/dim]")
|
|
73
|
+
console.print(" [dim]curl -sSfL https://raw.githubusercontent.com/akash-network/provider/main/install.sh | sh[/dim]")
|
|
74
|
+
console.print("\nAfter installing, make sure it's in your PATH and press Enter to continue.")
|
|
75
|
+
Prompt.ask("[dim]Press Enter when ready[/dim]", default="")
|
|
76
|
+
|
|
77
|
+
if _check_provider_services():
|
|
78
|
+
console.print("[green]✅ provider-services found![/green]")
|
|
79
|
+
return True
|
|
80
|
+
else:
|
|
81
|
+
console.print("[red]❌ Still not found. Please install it and restart the agent.[/red]")
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _setup_groq_key():
|
|
86
|
+
console.print("\n[bold yellow]Step 2/4 — Groq API Key[/bold yellow]")
|
|
87
|
+
console.print("The agent uses Groq for fast LLM inference (Llama 3.3 70B).")
|
|
88
|
+
console.print("Get your free API key at: [link=https://console.groq.com/keys]console.groq.com/keys[/link]")
|
|
89
|
+
|
|
90
|
+
key = Prompt.ask("\n[cyan]Paste your Groq API key[/cyan]", password=True)
|
|
91
|
+
if key.strip():
|
|
92
|
+
_save_env_val("GROQ_API_KEY", key.strip())
|
|
93
|
+
console.print("[green]✅ Groq API key saved![/green]")
|
|
94
|
+
return True
|
|
95
|
+
console.print("[red]❌ No key provided.[/red]")
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _setup_modexia_key():
|
|
100
|
+
console.print("\n[bold yellow]Step 3/4 — Modexia API Key[/bold yellow]")
|
|
101
|
+
console.print("Modexia handles payments and cross-chain funding for your deployments.")
|
|
102
|
+
console.print("Get your API key at: [link=https://modexia.software]modexia.software[/link]")
|
|
103
|
+
|
|
104
|
+
key = Prompt.ask("\n[cyan]Paste your Modexia API key[/cyan] (starts with mx_live_ or mx_test_)", password=True)
|
|
105
|
+
if key.strip():
|
|
106
|
+
_save_env_val("MODEXIA_API_KEY", key.strip())
|
|
107
|
+
console.print("[green]✅ Modexia API key saved![/green]")
|
|
108
|
+
return True
|
|
109
|
+
console.print("[red]❌ No key provided.[/red]")
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _setup_akash_wallet():
|
|
114
|
+
console.print("\n[bold yellow]Step 4/4 — Akash Wallet[/bold yellow]")
|
|
115
|
+
|
|
116
|
+
if _check_akash_wallet():
|
|
117
|
+
addr_result = subprocess.run(
|
|
118
|
+
["provider-services", "keys", "show", "mykey", "-a"],
|
|
119
|
+
capture_output=True, text=True,
|
|
120
|
+
)
|
|
121
|
+
console.print(f"[green]✅ Existing wallet found: {addr_result.stdout.strip()}[/green]")
|
|
122
|
+
return True
|
|
123
|
+
|
|
124
|
+
if Confirm.ask("No Akash wallet found. Create one now?", default=True):
|
|
125
|
+
result = subprocess.run(
|
|
126
|
+
["provider-services", "keys", "add", "mykey"],
|
|
127
|
+
capture_output=True, text=True,
|
|
128
|
+
)
|
|
129
|
+
output = result.stdout.strip() + "\n" + result.stderr.strip()
|
|
130
|
+
console.print(Panel(output, title="🔑 New Akash Wallet", border_style="green"))
|
|
131
|
+
console.print("\n[bold red]⚠️ BACK UP YOUR 24-WORD MNEMONIC ABOVE![/bold red]")
|
|
132
|
+
console.print("[red]This is the ONLY way to recover your wallet. Write it down securely.[/red]")
|
|
133
|
+
Prompt.ask("[dim]Press Enter after you've saved your mnemonic[/dim]", default="")
|
|
134
|
+
return True
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# ─────────────────────────────────────────────────────────
|
|
139
|
+
# Main entry points
|
|
140
|
+
# ─────────────────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
def check_setup() -> bool:
|
|
143
|
+
"""Quick check — returns True if all prerequisites are met."""
|
|
144
|
+
return all([
|
|
145
|
+
_check_provider_services(),
|
|
146
|
+
_check_groq_key(),
|
|
147
|
+
_check_modexia_key(),
|
|
148
|
+
_check_akash_wallet(),
|
|
149
|
+
])
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
from rich.box import SIMPLE
|
|
153
|
+
|
|
154
|
+
def print_status():
|
|
155
|
+
"""Print a sleek status list of all prerequisites."""
|
|
156
|
+
console.print("\n[bold]System Checks[/bold]")
|
|
157
|
+
|
|
158
|
+
checks = [
|
|
159
|
+
("provider-services CLI", _check_provider_services()),
|
|
160
|
+
("Groq API Engine", _check_groq_key()),
|
|
161
|
+
("Modexia Cross-Chain API", _check_modexia_key()),
|
|
162
|
+
("Akash Local Wallet", _check_akash_wallet()),
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
for name, ok in checks:
|
|
166
|
+
if ok:
|
|
167
|
+
console.print(f" [green]✓[/green] [dim]{name}[/dim]")
|
|
168
|
+
else:
|
|
169
|
+
console.print(f" [red]✗[/red] [dim]{name} (missing)[/dim]")
|
|
170
|
+
|
|
171
|
+
console.print()
|
|
172
|
+
return all(ok for _, ok in checks)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def run_setup_wizard():
|
|
176
|
+
"""Interactive wizard that walks through all setup steps."""
|
|
177
|
+
console.print()
|
|
178
|
+
console.print("[bold]Modexia Compute Agent Setup[/bold]")
|
|
179
|
+
console.print("[dim]Let's get everything configured.[/dim]\n")
|
|
180
|
+
|
|
181
|
+
steps = [
|
|
182
|
+
("provider-services CLI", _check_provider_services, _setup_provider_services),
|
|
183
|
+
("Groq API Key", _check_groq_key, _setup_groq_key),
|
|
184
|
+
("Modexia API Key", _check_modexia_key, _setup_modexia_key),
|
|
185
|
+
("Akash Wallet", _check_akash_wallet, _setup_akash_wallet),
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
for name, check_fn, setup_fn in steps:
|
|
189
|
+
if check_fn():
|
|
190
|
+
console.print(f"[dim]✓ {name} ready[/dim]")
|
|
191
|
+
else:
|
|
192
|
+
success = setup_fn()
|
|
193
|
+
if not success:
|
|
194
|
+
console.print(f"\n[red]Setup incomplete: {name} is missing.[/red]")
|
|
195
|
+
console.print("[dim]Run modexia-compute --setup to try again.[/dim]")
|
|
196
|
+
return False
|
|
197
|
+
|
|
198
|
+
console.print("\n")
|
|
199
|
+
print_status()
|
|
200
|
+
console.print("\n[green]✓ Setup complete.[/green]\n")
|
|
201
|
+
return True
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modexia-compute-agent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Autonomous AI agent for deploying containers on Akash Network via Modexia AgentPay
|
|
5
|
+
Author-email: Modexia <hello@modexia.software>
|
|
6
|
+
Project-URL: Repository, https://github.com/modexia/modexia-compute-agent
|
|
7
|
+
Requires-Python: >=3.14
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: python-dotenv>=1.1.0
|
|
10
|
+
Requires-Dist: httpx>=0.28.1
|
|
11
|
+
Requires-Dist: langchain-core>=1.2.23
|
|
12
|
+
Requires-Dist: langchain-groq>=1.1.2
|
|
13
|
+
Requires-Dist: langgraph>=1.1.4
|
|
14
|
+
Requires-Dist: modexiaagentpay>=0.1.0
|
|
15
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
16
|
+
Requires-Dist: rich>=14.3.3
|
|
17
|
+
|
|
18
|
+
<div align="center">
|
|
19
|
+
<img src="https://modexia.software/favicon.ico" alt="Modexia Logo" width="80" height="80">
|
|
20
|
+
<br>
|
|
21
|
+
<h1>🚀 Modexia Compute Agent</h1>
|
|
22
|
+
<p><b>Autonomous AI agent for deploying Docker containers on Akash via natural language.</b></p>
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/modexia-compute-agent/)
|
|
25
|
+
[](https://pypi.python.org/pypi/modexia-compute-agent)
|
|
26
|
+
[](https://opensource.org/licenses/MIT)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
The **Modexia Compute Agent** is a powerful Python CLI application that turns plain English descriptions into running Docker containers on the [Akash Network](https://akash.network).
|
|
31
|
+
|
|
32
|
+
Powered by the **Modexia AgentPay** engine over the Squid Router, this agent features *true abstract deployments*. Simply instruct the agent to deploy a container, and it will handle the SDL generation, Akash wallet creation, and **Just-In-Time (JIT) USDT/USDC cross-chain funding + Gas Fee swaps** completely autonomously.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## ✨ Features
|
|
37
|
+
|
|
38
|
+
* **🗣️ Conversational Deployments:** Describe your container, CPU, RAM, and storage needs in plain English.
|
|
39
|
+
* **🧠 Llama 70B Orchestration:** Uses Groq's high-speed inference to flawlessly orchestrate complex blockchain provider interactions.
|
|
40
|
+
* **💳 JIT Cross-Chain Funding:** No AKT? No problem. The agent automatically bridges USDC from your Modexia Vault natively covering AKT gas fees, ensuring seamless workflow.
|
|
41
|
+
* **🔮 Oracle Vibe GUI:** A sleek, beautiful, minimalist `rich` UI ensuring deploying compute feels incredibly satisfying.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## ⚡ Installation
|
|
46
|
+
|
|
47
|
+
Install globally using `pip` or `pipx`:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install modexia-compute-agent
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 🚀 Quick Start & API Setup
|
|
56
|
+
|
|
57
|
+
Upon running the CLI for the first time, our interactive **Setup Wizard** will launch immediately and seamlessly guide you through connecting all necessary services over 4 quick steps.
|
|
58
|
+
|
|
59
|
+
Simply run:
|
|
60
|
+
```bash
|
|
61
|
+
modexia-compute
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### What You'll Need During Setup:
|
|
65
|
+
|
|
66
|
+
#### 1. Akash CLI (`provider-services`)
|
|
67
|
+
We rely on the official Akash binary to securely generate wallets and sign transactions purely on your local machine (your mnemonic seed phrase is safely stored exclusively in `~/.modexia/`).
|
|
68
|
+
|
|
69
|
+
* **Linux / macOS Installation:**
|
|
70
|
+
```bash
|
|
71
|
+
curl -sSfL https://raw.githubusercontent.com/akash-network/provider/main/install.sh | bash
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### 2. Modexia AgentPay API Key
|
|
75
|
+
Modexia is the payment orchestration layer that allows the agent to intelligently fund your Akash wallet from external chains.
|
|
76
|
+
|
|
77
|
+
* Sign up at [Modexia.software](https://modexia.software)
|
|
78
|
+
* Fund your Vault with USDC (on Base).
|
|
79
|
+
* Create a Developer API Key (`mx_live_...`).
|
|
80
|
+
|
|
81
|
+
#### 3. Groq API Key
|
|
82
|
+
The agent's "brain" is powered by extremely fast LLaMA models.
|
|
83
|
+
* Free keys at [console.groq.com/keys](https://console.groq.com/keys)
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## ⌨️ How It Works
|
|
88
|
+
|
|
89
|
+
Type your intent in plain English, and the oracle goes to work:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
> Spin up an NGINX frontend cache on a fast server with 2 CPUs and 4GB RAM.
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
1. **Manifest Generation:** The LLM instantly writes a verified `SDL (deploy.yaml)` for Akash.
|
|
96
|
+
2. **Auto-Fund Engine Check:** Identifies an empty Akash wallet and bridges exactly `$5.10 USDC` required for escrow and AKT gas natively from your Modexia Vault.
|
|
97
|
+
3. **Provider Bidding:** Connects to Akash, polls live decentralized datacenters, and reports back.
|
|
98
|
+
4. **Approval Loop:** Asks the human precisely which provider is preferred.
|
|
99
|
+
5. **Liftoff:** Container initializes and exposes the assigned NodePort/URI securely!
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## ⚙️ Modifying Configuration Later
|
|
104
|
+
|
|
105
|
+
At any time, you can edit your setup or switch APIs. Your configuration is securely stored off-package in your home directory:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
~/.modexia/compute.env
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
To forcibly re-run the setup wizard:
|
|
112
|
+
```bash
|
|
113
|
+
modexia-compute --setup
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
*Powered by the Modexia-Verse* 🌌
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/modexia_compute_agent/__init__.py
|
|
4
|
+
src/modexia_compute_agent/agent.py
|
|
5
|
+
src/modexia_compute_agent/akash_cli.py
|
|
6
|
+
src/modexia_compute_agent/cli.py
|
|
7
|
+
src/modexia_compute_agent/config.py
|
|
8
|
+
src/modexia_compute_agent/payments.py
|
|
9
|
+
src/modexia_compute_agent/sdl.py
|
|
10
|
+
src/modexia_compute_agent/soul.md
|
|
11
|
+
src/modexia_compute_agent/wizard.py
|
|
12
|
+
src/modexia_compute_agent.egg-info/PKG-INFO
|
|
13
|
+
src/modexia_compute_agent.egg-info/SOURCES.txt
|
|
14
|
+
src/modexia_compute_agent.egg-info/dependency_links.txt
|
|
15
|
+
src/modexia_compute_agent.egg-info/entry_points.txt
|
|
16
|
+
src/modexia_compute_agent.egg-info/requires.txt
|
|
17
|
+
src/modexia_compute_agent.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
modexia_compute_agent
|