epsimo-agent 0.1.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 +21 -0
- package/SKILL.md +85 -0
- package/assets/example_asset.txt +24 -0
- package/epsimo/__init__.py +3 -0
- package/epsimo/__main__.py +4 -0
- package/epsimo/auth.py +143 -0
- package/epsimo/cli.py +586 -0
- package/epsimo/client.py +53 -0
- package/epsimo/resources/assistants.py +47 -0
- package/epsimo/resources/credits.py +16 -0
- package/epsimo/resources/db.py +31 -0
- package/epsimo/resources/files.py +39 -0
- package/epsimo/resources/projects.py +30 -0
- package/epsimo/resources/threads.py +83 -0
- package/epsimo/templates/components/AuthModal/AuthModal.module.css +39 -0
- package/epsimo/templates/components/AuthModal/AuthModal.tsx +138 -0
- package/epsimo/templates/components/BuyCredits/BuyCreditsModal.module.css +96 -0
- package/epsimo/templates/components/BuyCredits/BuyCreditsModal.tsx +132 -0
- package/epsimo/templates/components/BuyCredits/CreditsDisplay.tsx +101 -0
- package/epsimo/templates/components/ThreadChat/ThreadChat.module.css +551 -0
- package/epsimo/templates/components/ThreadChat/ThreadChat.tsx +862 -0
- package/epsimo/templates/components/ThreadChat/components/ToolRenderers.module.css +509 -0
- package/epsimo/templates/components/ThreadChat/components/ToolRenderers.tsx +322 -0
- package/epsimo/templates/next-mvp/app/globals.css.tmpl +20 -0
- package/epsimo/templates/next-mvp/app/layout.tsx.tmpl +22 -0
- package/epsimo/templates/next-mvp/app/page.module.css.tmpl +84 -0
- package/epsimo/templates/next-mvp/app/page.tsx.tmpl +43 -0
- package/epsimo/templates/next-mvp/epsimo.yaml.tmpl +12 -0
- package/epsimo/templates/next-mvp/package.json.tmpl +26 -0
- package/epsimo/tools/library.yaml +51 -0
- package/package.json +27 -0
- package/references/api_reference.md +34 -0
- package/references/virtual_db_guide.md +57 -0
- package/requirements.txt +2 -0
- package/scripts/assistant.py +165 -0
- package/scripts/auth.py +195 -0
- package/scripts/credits.py +107 -0
- package/scripts/debug_run.py +41 -0
- package/scripts/example.py +19 -0
- package/scripts/files.py +73 -0
- package/scripts/find_thread.py +55 -0
- package/scripts/project.py +60 -0
- package/scripts/run.py +75 -0
- package/scripts/test_all_skills.py +387 -0
- package/scripts/test_sdk.py +83 -0
- package/scripts/test_streaming.py +167 -0
- package/scripts/test_vdb.py +65 -0
- package/scripts/thread.py +77 -0
- package/scripts/verify_skill.py +87 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 EpsimoAI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: epsimo-agent
|
|
3
|
+
description: Comprehensive framework for building AI applications using EpsimoAI. Manage agents, projects, threads, and persistent state (Virtual Database). Includes CLI tools, Python SDK for automation, and React components for frontend integration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Epsimo Agent Framework (Beta)
|
|
7
|
+
|
|
8
|
+
> [!NOTE]
|
|
9
|
+
> This is a **Beta** version of the Epsimo Agent Framework. Features and APIs may be subject to change.
|
|
10
|
+
|
|
11
|
+
The Epsimo Agent Framework allows you to build sophisticated AI-powered applications with agents, persistent threads, and a "Virtual Database" state layer. It provides a unified **CLI**, a **Python SDK**, and a **React UI Kit**.
|
|
12
|
+
|
|
13
|
+
**Base URL:** `https://api.epsimoagents.com`
|
|
14
|
+
**Frontend URL:** `https://app.epsimoagents.com`
|
|
15
|
+
|
|
16
|
+
## 🛠️ Unified CLI (`epsimo`)
|
|
17
|
+
|
|
18
|
+
The `epsimo` CLI is the main tool for managing your agents and data.
|
|
19
|
+
|
|
20
|
+
### Authentication
|
|
21
|
+
```bash
|
|
22
|
+
python3 -m epsimo.cli auth login
|
|
23
|
+
python3 -m epsimo.cli whoami
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Project Scaffolding
|
|
27
|
+
- `python3 -m epsimo.cli create <name>`: Scaffolds a full Next.js application with Epsimo integrated.
|
|
28
|
+
- `python3 -m epsimo.cli init`: Links a local directory to an Epsimo project.
|
|
29
|
+
- `python3 -m epsimo.cli deploy`: Syncs your `epsimo.yaml` configuration to the platform.
|
|
30
|
+
|
|
31
|
+
### Virtual Database
|
|
32
|
+
Threads can serve as a persistent structured storage layer.
|
|
33
|
+
- `python3 -m epsimo.cli db query --project-id <P_ID> --thread-id <T_ID>`: View structured thread state.
|
|
34
|
+
- `python3 -m epsimo.cli db set --project-id <P_ID> --thread-id <T_ID> --key <K> --value <V>`: Seed state.
|
|
35
|
+
|
|
36
|
+
### Credits
|
|
37
|
+
- `python3 -m epsimo.cli credits balance`: Check current token balance.
|
|
38
|
+
- `python3 -m epsimo.cli credits buy --quantity <N>`: Generate a Stripe checkout URL.
|
|
39
|
+
|
|
40
|
+
## 📦 Python SDK
|
|
41
|
+
|
|
42
|
+
The framework includes a powerful Python SDK for automation or backend services.
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from epsimo import EpsimoClient
|
|
46
|
+
|
|
47
|
+
c = EpsimoClient(api_key="your-token")
|
|
48
|
+
|
|
49
|
+
# Virtual DB Access
|
|
50
|
+
user_pref = c.db.get(project_id, thread_id, "user_preferences")
|
|
51
|
+
|
|
52
|
+
# Conversation Streaming
|
|
53
|
+
for chunk in c.threads.run_stream(project_id, thread_id, assistant_id, "Hello!"):
|
|
54
|
+
print(chunk)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 🎨 React UI Kit
|
|
58
|
+
|
|
59
|
+
The UI Kit provides high-level components for immediate integration. Found in `.agent/skills/epsimo-agent/epsimo/templates/components`.
|
|
60
|
+
|
|
61
|
+
- **`ThreadChat`**: A modern, dark-themed chat interface with streaming and tool support.
|
|
62
|
+
- **`useChat`**: A headless hook for managing conversation state.
|
|
63
|
+
|
|
64
|
+
### Implementation Patterns
|
|
65
|
+
See `references/api_reference.md` for detailed frontend implementation patterns and API schemas.
|
|
66
|
+
|
|
67
|
+
## 🧪 Verification
|
|
68
|
+
Ensure your environment is correctly configured:
|
|
69
|
+
```bash
|
|
70
|
+
python3 .agent/skills/epsimo-agent/scripts/verify_skill.py
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 📚 Bundled Resources
|
|
74
|
+
|
|
75
|
+
### Scripts (`scripts/`)
|
|
76
|
+
- `auth.py`: Interactive and environment-based login.
|
|
77
|
+
- `project.py`, `assistant.py`, `thread.py`, `run.py`: Low-level API interaction scripts.
|
|
78
|
+
- `credits.py`: Balance check and credit purchasing.
|
|
79
|
+
|
|
80
|
+
### Templates (`epsimo/templates/`)
|
|
81
|
+
- `components/`: Ready-to-use React components (ThreadChat, AuthModal, BuyCredits).
|
|
82
|
+
|
|
83
|
+
### References (`references/`)
|
|
84
|
+
- `api_reference.md`: Detailed API documentation and schemas.
|
|
85
|
+
- `virtual_db_guide.md`: Comprehensive guide for managing persistent state.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Example Asset File
|
|
2
|
+
|
|
3
|
+
This placeholder represents where asset files would be stored.
|
|
4
|
+
Replace with actual asset files (templates, images, fonts, etc.) or delete if not needed.
|
|
5
|
+
|
|
6
|
+
Asset files are NOT intended to be loaded into context, but rather used within
|
|
7
|
+
the output Claude produces.
|
|
8
|
+
|
|
9
|
+
Example asset files from other skills:
|
|
10
|
+
- Brand guidelines: logo.png, slides_template.pptx
|
|
11
|
+
- Frontend builder: hello-world/ directory with HTML/React boilerplate
|
|
12
|
+
- Typography: custom-font.ttf, font-family.woff2
|
|
13
|
+
- Data: sample_data.csv, test_dataset.json
|
|
14
|
+
|
|
15
|
+
## Common Asset Types
|
|
16
|
+
|
|
17
|
+
- Templates: .pptx, .docx, boilerplate directories
|
|
18
|
+
- Images: .png, .jpg, .svg, .gif
|
|
19
|
+
- Fonts: .ttf, .otf, .woff, .woff2
|
|
20
|
+
- Boilerplate code: Project directories, starter files
|
|
21
|
+
- Icons: .ico, .svg
|
|
22
|
+
- Data files: .csv, .json, .xml, .yaml
|
|
23
|
+
|
|
24
|
+
Note: This is a text placeholder. Actual assets can be any file type.
|
package/epsimo/auth.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
import time
|
|
5
|
+
import requests
|
|
6
|
+
import getpass
|
|
7
|
+
import sys
|
|
8
|
+
import subprocess
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
# Configuration
|
|
12
|
+
API_BASE_URL = os.environ.get("EPSIMO_API_URL", "https://api.epsimoagents.com")
|
|
13
|
+
TOKEN_FILE = Path.home() / "code/epsimo-frontend/.epsimo_token" # Keeping the same path for compatibility for now
|
|
14
|
+
|
|
15
|
+
def get_token():
|
|
16
|
+
"""Retrieve a valid JWT token, refreshing if necessary."""
|
|
17
|
+
|
|
18
|
+
# Check if token file exists
|
|
19
|
+
if TOKEN_FILE.exists():
|
|
20
|
+
try:
|
|
21
|
+
with open(TOKEN_FILE, 'r') as f:
|
|
22
|
+
data = json.load(f)
|
|
23
|
+
return data.get('access_token') or data.get('token') or data.get('jwt_token')
|
|
24
|
+
except json.JSONDecodeError:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
# Try logging in with env vars if file doesn't exist/is invalid
|
|
28
|
+
if os.environ.get("EPSIMO_EMAIL") and os.environ.get("EPSIMO_PASSWORD"):
|
|
29
|
+
return perform_login(os.environ.get("EPSIMO_EMAIL"), os.environ.get("EPSIMO_PASSWORD"))
|
|
30
|
+
|
|
31
|
+
# Return None instead of raising Error to let caller handle it (e.g. prompt login)
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
def perform_signup(email, password):
|
|
35
|
+
"""Register a new user."""
|
|
36
|
+
print(f"Attempting to register new user: {email}")
|
|
37
|
+
url = f"{API_BASE_URL}/auth/signup"
|
|
38
|
+
payload = {
|
|
39
|
+
"email": email,
|
|
40
|
+
"password": password
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
response = requests.post(url, json=payload)
|
|
45
|
+
response.raise_for_status()
|
|
46
|
+
print("✅ Signup successful! Logging in...")
|
|
47
|
+
return perform_login(email, password)
|
|
48
|
+
except requests.exceptions.HTTPError as e:
|
|
49
|
+
if e.response.status_code == 400: # Usually "User already exists" or validation error
|
|
50
|
+
print(f"⚠️ Signup failed: {e.response.text}")
|
|
51
|
+
else:
|
|
52
|
+
print(f"❌ Signup failed: {e}")
|
|
53
|
+
raise
|
|
54
|
+
|
|
55
|
+
def get_input_via_applescript(prompt, hidden=False):
|
|
56
|
+
"""Get input using macOS native dialog."""
|
|
57
|
+
try:
|
|
58
|
+
script = f'display dialog "{prompt}" default answer ""'
|
|
59
|
+
if hidden:
|
|
60
|
+
script += ' with hidden answer'
|
|
61
|
+
script += ' buttons {"Cancel", "OK"} default button "OK"'
|
|
62
|
+
|
|
63
|
+
cmd = ['osascript', '-e', script]
|
|
64
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
65
|
+
# Parse result: button returned:OK, text returned:foobar
|
|
66
|
+
output = result.stdout.strip()
|
|
67
|
+
if "text returned:" in output:
|
|
68
|
+
return output.split("text returned:")[-1]
|
|
69
|
+
return ""
|
|
70
|
+
except subprocess.CalledProcessError:
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
def login_interactive():
|
|
74
|
+
"""Interactive login flow."""
|
|
75
|
+
use_modal = os.environ.get("USE_GUI_PROMPT") == "1"
|
|
76
|
+
|
|
77
|
+
email = None
|
|
78
|
+
if use_modal and sys.platform == 'darwin':
|
|
79
|
+
email = get_input_via_applescript("Enter your Epsimo Email:")
|
|
80
|
+
else:
|
|
81
|
+
email = input("Email: ")
|
|
82
|
+
|
|
83
|
+
if not email:
|
|
84
|
+
print("Email is required.")
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
password = None
|
|
88
|
+
if 'EPSIMO_PASSWORD' in os.environ:
|
|
89
|
+
password = os.environ['EPSIMO_PASSWORD']
|
|
90
|
+
elif use_modal and sys.platform == 'darwin':
|
|
91
|
+
password = get_input_via_applescript("Enter your Epsimo Password:", hidden=True)
|
|
92
|
+
else:
|
|
93
|
+
password = getpass.getpass("Password: ")
|
|
94
|
+
|
|
95
|
+
if not password:
|
|
96
|
+
print("Password is required.")
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
perform_login(email, password, attempt_signup_on_fail=True)
|
|
101
|
+
except Exception:
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
def perform_login(email, password, attempt_signup_on_fail=False):
|
|
105
|
+
"""Login logic."""
|
|
106
|
+
if not email or not password:
|
|
107
|
+
raise ValueError("Email and password are required.")
|
|
108
|
+
|
|
109
|
+
url = f"{API_BASE_URL}/auth/login"
|
|
110
|
+
payload = {
|
|
111
|
+
"email": email,
|
|
112
|
+
"password": password
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
response = requests.post(url, json=payload)
|
|
117
|
+
response.raise_for_status()
|
|
118
|
+
|
|
119
|
+
data = response.json()
|
|
120
|
+
token = data.get('access_token') or data.get('token') or data.get('jwt_token')
|
|
121
|
+
|
|
122
|
+
if not token:
|
|
123
|
+
raise ValueError("Failed to obtain access token from login response.")
|
|
124
|
+
|
|
125
|
+
# Save token
|
|
126
|
+
# Create dir if not exists?
|
|
127
|
+
# TOKEN_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
128
|
+
# For now assume path exists as per user setup
|
|
129
|
+
|
|
130
|
+
with open(TOKEN_FILE, 'w') as f:
|
|
131
|
+
json.dump(data, f)
|
|
132
|
+
|
|
133
|
+
print(f"✅ Successfully logged in as {email}")
|
|
134
|
+
return token
|
|
135
|
+
|
|
136
|
+
except requests.exceptions.HTTPError as e:
|
|
137
|
+
print(f"❌ Login failed: {e}")
|
|
138
|
+
if attempt_signup_on_fail:
|
|
139
|
+
print("\nUser might not exist or password is wrong.")
|
|
140
|
+
choice = input("Do you want to create a new account with these credentials? (y/n): ")
|
|
141
|
+
if choice.lower() == 'y':
|
|
142
|
+
return perform_signup(email, password)
|
|
143
|
+
raise
|