File size: 6,306 Bytes
494c89b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
"""
System API - Kiro status, paths, configuration
"""

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from typing import Optional, List
import platform
import os

from services.kiro_service import KiroService
from core.kiro_config import get_kiro_info, get_kiro_version, get_machine_id
from core.paths import get_paths
from core.config import get_config

router = APIRouter()
kiro_service = KiroService()


class KiroStatus(BaseModel):
    installed: bool
    running: bool
    version: Optional[str] = None
    installPath: Optional[str] = None
    currentAccount: Optional[str] = None
    tokenValid: bool = False


class SystemInfo(BaseModel):
    platform: str
    osVersion: str
    kiroVersion: str
    machineId: str
    userAgent: str
    storagePath: Optional[str] = None
    tokensPath: str
    backupsPath: str


class PathsInfo(BaseModel):
    tokensDir: str
    backupsDir: str
    kiroStorage: Optional[str] = None
    kiroStateDb: Optional[str] = None
    customMachineIdFile: str


@router.get("/kiro/status", response_model=KiroStatus)
async def get_kiro_status():
    """Get Kiro IDE status"""
    status = kiro_service.get_status()
    
    return KiroStatus(
        installed=status.installed,
        running=status.running,
        version=status.version,
        installPath=str(status.install_path) if status.install_path else None,
        currentAccount=status.current_account,
        tokenValid=status.token_valid
    )


@router.post("/kiro/start")
async def start_kiro():
    """Start Kiro IDE"""
    try:
        kiro_service.start()
        return {"success": True, "message": "Kiro started"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/kiro/stop")
async def stop_kiro():
    """Stop Kiro IDE"""
    if kiro_service.stop():
        return {"success": True, "message": "Kiro stopped"}
    else:
        raise HTTPException(status_code=500, detail="Failed to stop Kiro")


@router.post("/kiro/restart")
async def restart_kiro():
    """Restart Kiro IDE"""
    try:
        kiro_service.restart()
        return {"success": True, "message": "Kiro restarted"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/info", response_model=SystemInfo)
async def get_system_info():
    """Get system and Kiro configuration info"""
    paths = get_paths()
    kiro_info = get_kiro_info()
    
    return SystemInfo(
        platform=platform.system(),
        osVersion=platform.version(),
        kiroVersion=kiro_info['version'],
        machineId=kiro_info['machine_id'],
        userAgent=kiro_info['user_agent'],
        storagePath=kiro_info['storage_path'],
        tokensPath=str(paths.tokens_dir),
        backupsPath=str(paths.backups_dir)
    )


@router.get("/paths", response_model=PathsInfo)
async def get_paths_info():
    """Get all relevant paths"""
    paths = get_paths()
    from core.kiro_config import get_custom_machine_id_path
    
    return PathsInfo(
        tokensDir=str(paths.tokens_dir),
        backupsDir=str(paths.backups_dir),
        kiroStorage=str(paths.kiro_storage_json) if paths.kiro_storage_json else None,
        kiroStateDb=str(paths.kiro_state_db) if paths.kiro_state_db else None,
        customMachineIdFile=str(get_custom_machine_id_path())
    )


@router.get("/health")
async def health_check():
    """Health check with detailed status"""
    paths = get_paths()
    kiro_status = kiro_service.get_status()
    
    return {
        "status": "ok",
        "kiro": {
            "installed": kiro_status.installed,
            "running": kiro_status.running,
            "version": kiro_status.version
        },
        "paths": {
            "tokensExist": paths.tokens_dir.exists(),
            "backupsExist": paths.backups_dir.exists()
        }
    }


class ImapSettings(BaseModel):
    server: str
    user: str
    password: str
    domain: str
    hasDefaults: bool


@router.get("/imap-defaults", response_model=ImapSettings)
async def get_imap_defaults():
    """
    Get default IMAP settings from .env file.
    Used when user hasn't configured their own catch-all.
    """
    config = get_config()
    
    # Get from environment (loaded from .env)
    server = os.environ.get('IMAP_SERVER', config.imap.host)
    user = os.environ.get('IMAP_USER', config.imap.email)
    password = os.environ.get('IMAP_PASSWORD', config.imap.password)
    domain = os.environ.get('EMAIL_DOMAIN', config.registration.email_domain)
    
    has_defaults = bool(server and user and password and domain)
    
    return ImapSettings(
        server=server or '',
        user=user or '',
        password=password or '',
        domain=domain or '',
        hasDefaults=has_defaults
    )


class ImapSettingsUpdate(BaseModel):
    server: str
    user: str
    password: str
    domain: str


@router.post("/imap-settings")
async def save_imap_settings(settings: ImapSettingsUpdate):
    """
    Save IMAP settings to .env file.
    This allows web UI to persist settings.
    """
    from pathlib import Path
    
    # Get .env path
    autoreg_dir = Path(__file__).parent.parent.parent
    env_file = autoreg_dir / '.env'
    
    # Read existing .env or create new
    env_content = {}
    if env_file.exists():
        with open(env_file, 'r') as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith('#') and '=' in line:
                    key, value = line.split('=', 1)
                    env_content[key.strip()] = value.strip()
    
    # Update with new settings
    env_content['IMAP_SERVER'] = settings.server
    env_content['IMAP_USER'] = settings.user
    env_content['IMAP_PASSWORD'] = settings.password
    env_content['EMAIL_DOMAIN'] = settings.domain
    
    # Write back
    with open(env_file, 'w') as f:
        for key, value in env_content.items():
            f.write(f'{key}={value}\n')
    
    # Update environment variables for current session
    os.environ['IMAP_SERVER'] = settings.server
    os.environ['IMAP_USER'] = settings.user
    os.environ['IMAP_PASSWORD'] = settings.password
    os.environ['EMAIL_DOMAIN'] = settings.domain
    
    return {"success": True, "message": "Settings saved"}