geomind-ai 1.0.4__tar.gz → 1.0.6__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.
- {geomind_ai-1.0.4/geomind_ai.egg-info → geomind_ai-1.0.6}/PKG-INFO +1 -1
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind/__init__.py +1 -1
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind/agent.py +26 -41
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind/cli.py +71 -2
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind/config.py +1 -4
- {geomind_ai-1.0.4 → geomind_ai-1.0.6/geomind_ai.egg-info}/PKG-INFO +1 -1
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/pyproject.toml +1 -1
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/LICENSE +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/MANIFEST.in +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/README.md +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind/tools/__init__.py +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind/tools/geocoding.py +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind/tools/processing.py +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind/tools/stac_search.py +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind_ai.egg-info/SOURCES.txt +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind_ai.egg-info/dependency_links.txt +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind_ai.egg-info/entry_points.txt +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind_ai.egg-info/requires.txt +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/geomind_ai.egg-info/top_level.txt +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/requirements.txt +0 -0
- {geomind_ai-1.0.4 → geomind_ai-1.0.6}/setup.cfg +0 -0
|
@@ -12,13 +12,10 @@ from datetime import datetime
|
|
|
12
12
|
|
|
13
13
|
from openai import OpenAI
|
|
14
14
|
|
|
15
|
-
import requests
|
|
16
|
-
|
|
17
15
|
from .config import (
|
|
18
16
|
OPENROUTER_API_KEY,
|
|
19
17
|
OPENROUTER_API_URL,
|
|
20
18
|
OPENROUTER_MODEL,
|
|
21
|
-
GEOMIND_PROXY_URL,
|
|
22
19
|
)
|
|
23
20
|
from .tools import (
|
|
24
21
|
geocode_location,
|
|
@@ -249,25 +246,27 @@ class GeoMindAgent:
|
|
|
249
246
|
|
|
250
247
|
Args:
|
|
251
248
|
model: Model name (default: xiaomi/mimo-v2-flash:free)
|
|
252
|
-
api_key: OpenRouter API key
|
|
249
|
+
api_key: OpenRouter API key (required).
|
|
253
250
|
"""
|
|
254
251
|
self.provider = "openrouter"
|
|
255
252
|
self.api_key = api_key or OPENROUTER_API_KEY
|
|
256
253
|
self.model_name = model or OPENROUTER_MODEL
|
|
257
|
-
self.
|
|
258
|
-
|
|
259
|
-
if self.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
254
|
+
self.base_url = OPENROUTER_API_URL
|
|
255
|
+
|
|
256
|
+
if not self.api_key:
|
|
257
|
+
raise ValueError(
|
|
258
|
+
"OpenRouter API key required.\n"
|
|
259
|
+
"Get your FREE API key at: https://openrouter.ai/settings/keys\n\n"
|
|
260
|
+
"Then provide it in one of these ways:\n"
|
|
261
|
+
"1. Run: geomind --api-key YOUR_KEY\n"
|
|
262
|
+
"2. Set environment variable: OPENROUTER_API_KEY=YOUR_KEY\n"
|
|
263
|
+
"3. Create .env file with: OPENROUTER_API_KEY=YOUR_KEY"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
print(f"🚀 GeoMind Agent initialized with {self.model_name}")
|
|
267
|
+
|
|
268
|
+
# Create OpenAI-compatible client
|
|
269
|
+
self.client = OpenAI(base_url=self.base_url, api_key=self.api_key)
|
|
271
270
|
|
|
272
271
|
# Chat history
|
|
273
272
|
self.history = []
|
|
@@ -301,29 +300,15 @@ When users ask for imagery:
|
|
|
301
300
|
Always explain what you're doing and interpret results in a helpful way."""
|
|
302
301
|
|
|
303
302
|
def _call_llm(self, messages: list, tools: list) -> dict:
|
|
304
|
-
"""Call LLM via
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
314
|
-
response = requests.post(self.base_url, json=payload, timeout=120)
|
|
315
|
-
response.raise_for_status()
|
|
316
|
-
return response.json()
|
|
317
|
-
else:
|
|
318
|
-
# Use OpenAI client directly
|
|
319
|
-
response = self.client.chat.completions.create(
|
|
320
|
-
model=self.model_name,
|
|
321
|
-
messages=messages,
|
|
322
|
-
tools=tools,
|
|
323
|
-
tool_choice="auto",
|
|
324
|
-
max_tokens=4096,
|
|
325
|
-
)
|
|
326
|
-
return response.model_dump()
|
|
303
|
+
"""Call LLM via OpenAI-compatible client."""
|
|
304
|
+
response = self.client.chat.completions.create(
|
|
305
|
+
model=self.model_name,
|
|
306
|
+
messages=messages,
|
|
307
|
+
tools=tools,
|
|
308
|
+
tool_choice="auto",
|
|
309
|
+
max_tokens=4096,
|
|
310
|
+
)
|
|
311
|
+
return response.model_dump()
|
|
327
312
|
|
|
328
313
|
def _execute_function(self, name: str, args: dict) -> dict:
|
|
329
314
|
"""Execute a function call and return the result."""
|
|
@@ -3,12 +3,39 @@ Command-line interface for GeoMind.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import sys
|
|
6
|
+
import os
|
|
6
7
|
import argparse
|
|
8
|
+
from pathlib import Path
|
|
7
9
|
from typing import Optional
|
|
8
10
|
|
|
9
11
|
from .agent import GeoMindAgent
|
|
10
12
|
|
|
11
13
|
|
|
14
|
+
# Config file path for storing API key
|
|
15
|
+
CONFIG_DIR = Path.home() / ".geomind"
|
|
16
|
+
CONFIG_FILE = CONFIG_DIR / "config"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_saved_api_key() -> Optional[str]:
|
|
20
|
+
"""Get API key saved on user's PC."""
|
|
21
|
+
if CONFIG_FILE.exists():
|
|
22
|
+
try:
|
|
23
|
+
return CONFIG_FILE.read_text().strip()
|
|
24
|
+
except Exception:
|
|
25
|
+
return None
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def save_api_key(api_key: str) -> bool:
|
|
30
|
+
"""Save API key to user's PC."""
|
|
31
|
+
try:
|
|
32
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
33
|
+
CONFIG_FILE.write_text(api_key)
|
|
34
|
+
return True
|
|
35
|
+
except Exception:
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
|
|
12
39
|
def main():
|
|
13
40
|
"""Main CLI entry point for the geomind package."""
|
|
14
41
|
parser = argparse.ArgumentParser(
|
|
@@ -28,6 +55,9 @@ Examples:
|
|
|
28
55
|
# With API key
|
|
29
56
|
geomind --api-key "your-openrouter-api-key"
|
|
30
57
|
|
|
58
|
+
# Clear saved API key
|
|
59
|
+
geomind --clear-key
|
|
60
|
+
|
|
31
61
|
Environment Variables:
|
|
32
62
|
OPENROUTER_API_KEY Your OpenRouter API key
|
|
33
63
|
OPENROUTER_MODEL Model to use (default: xiaomi/mimo-v2-flash:free)
|
|
@@ -56,9 +86,20 @@ Environment Variables:
|
|
|
56
86
|
parser.add_argument(
|
|
57
87
|
"--version", "-v", action="store_true", help="Show version and exit"
|
|
58
88
|
)
|
|
89
|
+
parser.add_argument(
|
|
90
|
+
"--clear-key", action="store_true", help="Clear saved API key"
|
|
91
|
+
)
|
|
59
92
|
|
|
60
93
|
args = parser.parse_args()
|
|
61
94
|
|
|
95
|
+
if args.clear_key:
|
|
96
|
+
if CONFIG_FILE.exists():
|
|
97
|
+
CONFIG_FILE.unlink()
|
|
98
|
+
print("✅ Saved API key cleared.")
|
|
99
|
+
else:
|
|
100
|
+
print("ℹ️ No saved API key found.")
|
|
101
|
+
sys.exit(0)
|
|
102
|
+
|
|
62
103
|
if args.version:
|
|
63
104
|
from . import __version__
|
|
64
105
|
|
|
@@ -68,8 +109,12 @@ Environment Variables:
|
|
|
68
109
|
# Start interactive or single-query mode
|
|
69
110
|
try:
|
|
70
111
|
if args.query:
|
|
71
|
-
# Single query mode
|
|
72
|
-
|
|
112
|
+
# Single query mode - also use saved key
|
|
113
|
+
api_key = args.api_key or get_saved_api_key()
|
|
114
|
+
if not api_key:
|
|
115
|
+
print("❌ No API key found. Run 'geomind' first to set up.")
|
|
116
|
+
sys.exit(1)
|
|
117
|
+
agent = GeoMindAgent(model=args.model, api_key=api_key)
|
|
73
118
|
agent.chat(args.query)
|
|
74
119
|
else:
|
|
75
120
|
# Interactive mode
|
|
@@ -95,6 +140,30 @@ def run_interactive(model: Optional[str] = None, api_key: Optional[str] = None):
|
|
|
95
140
|
print("Type 'reset' to start a new conversation")
|
|
96
141
|
print("=" * 60)
|
|
97
142
|
|
|
143
|
+
# Check for API key in order: argument > env > saved file
|
|
144
|
+
from .config import OPENROUTER_API_KEY
|
|
145
|
+
|
|
146
|
+
if not api_key:
|
|
147
|
+
api_key = OPENROUTER_API_KEY
|
|
148
|
+
|
|
149
|
+
if not api_key:
|
|
150
|
+
api_key = get_saved_api_key()
|
|
151
|
+
|
|
152
|
+
if not api_key:
|
|
153
|
+
print("\n🔑 OpenRouter API key required (FREE)")
|
|
154
|
+
print(" Get yours at: https://openrouter.ai/settings/keys\n")
|
|
155
|
+
api_key = input(" Enter your API key: ").strip()
|
|
156
|
+
|
|
157
|
+
if not api_key:
|
|
158
|
+
print("\n❌ No API key provided. Exiting.")
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
# Save the key for future use
|
|
162
|
+
if save_api_key(api_key):
|
|
163
|
+
print(" ✅ API key saved! You won't need to enter it again.\n")
|
|
164
|
+
else:
|
|
165
|
+
print(" ⚠️ Could not save API key. You'll need to enter it next time.\n")
|
|
166
|
+
|
|
98
167
|
agent = GeoMindAgent(model=model, api_key=api_key)
|
|
99
168
|
|
|
100
169
|
while True:
|
|
@@ -49,10 +49,7 @@ OUTPUT_DIR.mkdir(exist_ok=True)
|
|
|
49
49
|
GEOCODER_USER_AGENT = "geomind_agent_v0.1"
|
|
50
50
|
|
|
51
51
|
# OpenRouter API Configuration
|
|
52
|
-
#
|
|
53
|
-
GEOMIND_PROXY_URL = "https://geomind-proxy.harshinde.workers.dev"
|
|
54
|
-
|
|
55
|
-
# Users can optionally provide their own OpenRouter key to bypass proxy
|
|
52
|
+
# Get your free API key at: https://openrouter.ai/settings/keys
|
|
56
53
|
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY", "")
|
|
57
54
|
OPENROUTER_API_URL = os.getenv("OPENROUTER_API_URL", "https://openrouter.ai/api/v1")
|
|
58
55
|
OPENROUTER_MODEL = os.getenv("OPENROUTER_MODEL", "xiaomi/mimo-v2-flash:free")
|
|
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
|