intelligence-suite 0.2.7__tar.gz → 0.2.8__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.
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/PKG-INFO +1 -1
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/config.py +4 -3
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_suite.egg-info/PKG-INFO +1 -1
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_suite.egg-info/SOURCES.txt +1 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_suite.egg-info/entry_points.txt +1 -0
- intelligence_suite-0.2.8/intelligence_ui/launcher.py +385 -0
- intelligence_suite-0.2.8/intelligence_ui/templates.py +547 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/pyproject.toml +2 -1
- intelligence_suite-0.2.7/intelligence_ui/templates.py +0 -396
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/embed_chunks.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/parse_repo.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/parsers/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/parsers/go_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/parsers/markdown_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/parsers/python_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/parsers/sql_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/parsers/typescript_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/parsers/yaml_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/CodeIntelligence/rag_server.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/doc_server.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/embed_docs.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/ingest_docs.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/parsers/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/parsers/docx_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/parsers/markdown_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/parsers/pdf_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/parsers/txt_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/DocIntelligence/parsers/xlsx_parser.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/LICENSE +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/content/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/content/ingest_practices.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/content/path_templates.json +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/mentor_server.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/orchestrator.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/path_builder.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/profile_detector.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/MentorIntelligence/session_manager.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/README.md +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/chunk.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/embedder.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/escalation.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/llm/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/llm/claude.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/llm/ollama.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/llm/openai_compat.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/llm/protocol.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/retriever.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/server_base.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_core/store.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_suite.egg-info/dependency_links.txt +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_suite.egg-info/requires.txt +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_suite.egg-info/top_level.txt +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_ui/__init__.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_ui/chat_app.py +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/setup.cfg +0 -0
- {intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/tests/test_intelligence_suite.py +0 -0
|
@@ -80,9 +80,10 @@ class Settings(BaseSettings):
|
|
|
80
80
|
mi_llm_api_key: str = ""
|
|
81
81
|
|
|
82
82
|
# ── Server ports (one per module, avoids conflicts when running together) ──
|
|
83
|
-
ci_port:
|
|
84
|
-
di_port:
|
|
85
|
-
mi_port:
|
|
83
|
+
ci_port: int = 8080 # CodeIntelligence
|
|
84
|
+
di_port: int = 8081 # DocIntelligence
|
|
85
|
+
mi_port: int = 8082 # MentorIntelligence
|
|
86
|
+
launcher_port: int = 8079 # Launcher dashboard
|
|
86
87
|
|
|
87
88
|
# ── Shared server settings ─────────────────────────────────────────────────
|
|
88
89
|
api_host: str = "0.0.0.0"
|
{intelligence_suite-0.2.7 → intelligence_suite-0.2.8}/intelligence_suite.egg-info/entry_points.txt
RENAMED
|
@@ -5,5 +5,6 @@ ci-serve = CodeIntelligence.rag_server:main
|
|
|
5
5
|
di-embed = DocIntelligence.embed_docs:main
|
|
6
6
|
di-ingest = DocIntelligence.ingest_docs:main
|
|
7
7
|
di-serve = DocIntelligence.doc_server:main
|
|
8
|
+
is-launch = intelligence_ui.launcher:main
|
|
8
9
|
mi-ingest = MentorIntelligence.content.ingest_practices:main
|
|
9
10
|
mi-serve = MentorIntelligence.mentor_server:main
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
"""IntelligenceSuite Launcher — start/stop/monitor all three modules from one page."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
import logging
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import httpx
|
|
10
|
+
import uvicorn
|
|
11
|
+
from fastapi import FastAPI
|
|
12
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
13
|
+
from fastapi.responses import HTMLResponse, JSONResponse
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
# ── Module registry ─────────────────────────────────────────────────────────
|
|
18
|
+
MODULES: dict[str, dict] = {
|
|
19
|
+
"code": {
|
|
20
|
+
"name": "Code Intelligence",
|
|
21
|
+
"description": "Ask questions about your source code in natural language",
|
|
22
|
+
"icon": "💻",
|
|
23
|
+
"port": 8080,
|
|
24
|
+
"color": "#6366f1",
|
|
25
|
+
"cli": "ci-serve",
|
|
26
|
+
"module": "CodeIntelligence.rag_server",
|
|
27
|
+
"chunks_cmd": "ci-parse",
|
|
28
|
+
},
|
|
29
|
+
"doc": {
|
|
30
|
+
"name": "Doc Intelligence",
|
|
31
|
+
"description": "Query documents, PDFs, DOCX, XLSX in any language",
|
|
32
|
+
"icon": "📄",
|
|
33
|
+
"port": 8081,
|
|
34
|
+
"color": "#06b6d4",
|
|
35
|
+
"cli": "di-serve",
|
|
36
|
+
"module": "DocIntelligence.doc_server",
|
|
37
|
+
"chunks_cmd": "di-ingest",
|
|
38
|
+
},
|
|
39
|
+
"mentor": {
|
|
40
|
+
"name": "Mentor Intelligence",
|
|
41
|
+
"description": "Adaptive onboarding with session-based learning paths",
|
|
42
|
+
"icon": "🎓",
|
|
43
|
+
"port": 8082,
|
|
44
|
+
"color": "#ec4899",
|
|
45
|
+
"cli": "mi-serve",
|
|
46
|
+
"module": "MentorIntelligence.mentor_server",
|
|
47
|
+
"chunks_cmd": "mi-ingest",
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# In-memory process handles (module key → Popen)
|
|
52
|
+
_procs: dict[str, subprocess.Popen] = {}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ── FastAPI app ──────────────────────────────────────────────────────────────
|
|
56
|
+
app = FastAPI(title="IntelligenceSuite Launcher", docs_url=None, redoc_url=None)
|
|
57
|
+
app.add_middleware(
|
|
58
|
+
CORSMiddleware,
|
|
59
|
+
allow_origins=["*"], allow_methods=["*"], allow_headers=["*"],
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# ── Helpers ──────────────────────────────────────────────────────────────────
|
|
64
|
+
def _alive(key: str) -> bool:
|
|
65
|
+
"""True if we started the process and it's still running."""
|
|
66
|
+
p = _procs.get(key)
|
|
67
|
+
return p is not None and p.poll() is None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _health_url(port: int) -> str:
|
|
71
|
+
return f"http://localhost:{port}/health"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _start(key: str) -> dict:
|
|
75
|
+
mod = MODULES[key]
|
|
76
|
+
if _alive(key):
|
|
77
|
+
return {"status": "already_running"}
|
|
78
|
+
|
|
79
|
+
# Try CLI command first, then python -m fallback
|
|
80
|
+
for cmd in ([mod["cli"]], [sys.executable, "-m", mod["module"]]):
|
|
81
|
+
try:
|
|
82
|
+
p = subprocess.Popen(
|
|
83
|
+
cmd,
|
|
84
|
+
stdout=subprocess.DEVNULL,
|
|
85
|
+
stderr=subprocess.DEVNULL,
|
|
86
|
+
cwd=str(Path.cwd()),
|
|
87
|
+
)
|
|
88
|
+
_procs[key] = p
|
|
89
|
+
return {"status": "starting", "pid": p.pid, "port": mod["port"]}
|
|
90
|
+
except FileNotFoundError:
|
|
91
|
+
continue
|
|
92
|
+
return {"status": "error", "detail": f"Cannot find {mod['cli']} or {mod['module']}"}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _stop(key: str) -> dict:
|
|
96
|
+
p = _procs.pop(key, None)
|
|
97
|
+
if p is None:
|
|
98
|
+
return {"status": "not_managed"}
|
|
99
|
+
p.terminate()
|
|
100
|
+
return {"status": "stopped"}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# ── REST endpoints ───────────────────────────────────────────────────────────
|
|
104
|
+
@app.get("/api/status")
|
|
105
|
+
def status():
|
|
106
|
+
result = {}
|
|
107
|
+
for key, mod in MODULES.items():
|
|
108
|
+
running = False
|
|
109
|
+
chunks = 0
|
|
110
|
+
try:
|
|
111
|
+
r = httpx.get(_health_url(mod["port"]), timeout=1.5)
|
|
112
|
+
if r.status_code == 200:
|
|
113
|
+
running = True
|
|
114
|
+
chunks = r.json().get("chunks_indexed", 0)
|
|
115
|
+
except Exception:
|
|
116
|
+
pass
|
|
117
|
+
result[key] = {
|
|
118
|
+
"running": running,
|
|
119
|
+
"managed": _alive(key),
|
|
120
|
+
"port": mod["port"],
|
|
121
|
+
"chunks": chunks,
|
|
122
|
+
"url": f"http://localhost:{mod['port']}",
|
|
123
|
+
}
|
|
124
|
+
return JSONResponse(result)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@app.post("/api/start/{key}")
|
|
128
|
+
def start(key: str):
|
|
129
|
+
if key not in MODULES:
|
|
130
|
+
return JSONResponse({"error": "unknown module"}, status_code=400)
|
|
131
|
+
return JSONResponse(_start(key))
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@app.post("/api/stop/{key}")
|
|
135
|
+
def stop(key: str):
|
|
136
|
+
if key not in MODULES:
|
|
137
|
+
return JSONResponse({"error": "unknown module"}, status_code=400)
|
|
138
|
+
return JSONResponse(_stop(key))
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@app.post("/api/start-all")
|
|
142
|
+
def start_all():
|
|
143
|
+
return JSONResponse({k: _start(k) for k in MODULES})
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# ── Launcher HTML ────────────────────────────────────────────────────────────
|
|
147
|
+
_LAUNCHER_HTML = """\
|
|
148
|
+
<!DOCTYPE html>
|
|
149
|
+
<html lang="en">
|
|
150
|
+
<head>
|
|
151
|
+
<meta charset="UTF-8">
|
|
152
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
153
|
+
<title>IntelligenceSuite — Launcher</title>
|
|
154
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
155
|
+
<style>
|
|
156
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
|
|
157
|
+
.card { transition: transform .2s, box-shadow .2s; }
|
|
158
|
+
.card:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(0,0,0,.35); }
|
|
159
|
+
.dot-pulse { animation: pulse 2s cubic-bezier(.4,0,.6,1) infinite; }
|
|
160
|
+
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.4} }
|
|
161
|
+
.btn { transition: all .15s; }
|
|
162
|
+
</style>
|
|
163
|
+
</head>
|
|
164
|
+
<body class="bg-gray-950 text-white min-h-screen flex flex-col">
|
|
165
|
+
|
|
166
|
+
<!-- Header -->
|
|
167
|
+
<header class="border-b border-gray-800 px-8 py-5 flex items-center justify-between">
|
|
168
|
+
<div class="flex items-center gap-4">
|
|
169
|
+
<span class="text-3xl">🧠</span>
|
|
170
|
+
<div>
|
|
171
|
+
<h1 class="text-lg font-bold tracking-tight">IntelligenceSuite</h1>
|
|
172
|
+
<p class="text-xs text-gray-500">On-premise knowledge retrieval · Local AI</p>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
<button onclick="startAll()"
|
|
176
|
+
class="btn bg-indigo-600 hover:bg-indigo-500 px-5 py-2.5 rounded-xl
|
|
177
|
+
text-sm font-semibold flex items-center gap-2">
|
|
178
|
+
▶ Start All
|
|
179
|
+
</button>
|
|
180
|
+
</header>
|
|
181
|
+
|
|
182
|
+
<!-- Cards grid -->
|
|
183
|
+
<main class="flex-1 flex items-center justify-center px-8 py-12">
|
|
184
|
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 w-full max-w-5xl" id="cards">
|
|
185
|
+
|
|
186
|
+
<!-- Code Intelligence -->
|
|
187
|
+
<div class="card bg-gray-900 border border-gray-800 rounded-2xl p-7 flex flex-col gap-5"
|
|
188
|
+
id="card-code">
|
|
189
|
+
<div class="flex items-start justify-between">
|
|
190
|
+
<div class="text-4xl">💻</div>
|
|
191
|
+
<div class="flex items-center gap-2" id="badge-code">
|
|
192
|
+
<div class="w-2 h-2 rounded-full bg-gray-600 dot-pulse" id="dot-code"></div>
|
|
193
|
+
<span class="text-xs text-gray-500" id="label-code">checking…</span>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
<div>
|
|
197
|
+
<h2 class="font-bold text-base mb-1" style="color:#818cf8">Code Intelligence</h2>
|
|
198
|
+
<p class="text-xs text-gray-400 leading-relaxed">
|
|
199
|
+
Ask questions about your source code in natural language. Supports Python, TS, Go, SQL, YAML.
|
|
200
|
+
</p>
|
|
201
|
+
</div>
|
|
202
|
+
<div class="text-xs text-gray-600 font-mono">localhost:8080</div>
|
|
203
|
+
<div class="text-xs text-gray-500" id="chunks-code">— chunks indexed</div>
|
|
204
|
+
<div class="flex gap-2 mt-auto">
|
|
205
|
+
<a href="http://localhost:8080" target="_blank"
|
|
206
|
+
class="btn flex-1 text-center bg-gray-800 hover:bg-gray-700 text-sm
|
|
207
|
+
py-2 rounded-lg font-medium">
|
|
208
|
+
Open →
|
|
209
|
+
</a>
|
|
210
|
+
<button onclick="toggle('code')" id="btn-code"
|
|
211
|
+
class="btn flex-1 bg-indigo-700 hover:bg-indigo-600 text-sm
|
|
212
|
+
py-2 rounded-lg font-medium">
|
|
213
|
+
Start
|
|
214
|
+
</button>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
|
|
218
|
+
<!-- Doc Intelligence -->
|
|
219
|
+
<div class="card bg-gray-900 border border-gray-800 rounded-2xl p-7 flex flex-col gap-5"
|
|
220
|
+
id="card-doc">
|
|
221
|
+
<div class="flex items-start justify-between">
|
|
222
|
+
<div class="text-4xl">📄</div>
|
|
223
|
+
<div class="flex items-center gap-2" id="badge-doc">
|
|
224
|
+
<div class="w-2 h-2 rounded-full bg-gray-600 dot-pulse" id="dot-doc"></div>
|
|
225
|
+
<span class="text-xs text-gray-500" id="label-doc">checking…</span>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
<div>
|
|
229
|
+
<h2 class="font-bold text-base mb-1" style="color:#22d3ee">Doc Intelligence</h2>
|
|
230
|
+
<p class="text-xs text-gray-400 leading-relaxed">
|
|
231
|
+
Query company documents in any language. PDF (with OCR fallback), DOCX, XLSX, Markdown.
|
|
232
|
+
</p>
|
|
233
|
+
</div>
|
|
234
|
+
<div class="text-xs text-gray-600 font-mono">localhost:8081</div>
|
|
235
|
+
<div class="text-xs text-gray-500" id="chunks-doc">— chunks indexed</div>
|
|
236
|
+
<div class="flex gap-2 mt-auto">
|
|
237
|
+
<a href="http://localhost:8081" target="_blank"
|
|
238
|
+
class="btn flex-1 text-center bg-gray-800 hover:bg-gray-700 text-sm
|
|
239
|
+
py-2 rounded-lg font-medium">
|
|
240
|
+
Open →
|
|
241
|
+
</a>
|
|
242
|
+
<button onclick="toggle('doc')" id="btn-doc"
|
|
243
|
+
class="btn flex-1 bg-cyan-700 hover:bg-cyan-600 text-sm
|
|
244
|
+
py-2 rounded-lg font-medium">
|
|
245
|
+
Start
|
|
246
|
+
</button>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
|
|
250
|
+
<!-- Mentor Intelligence -->
|
|
251
|
+
<div class="card bg-gray-900 border border-gray-800 rounded-2xl p-7 flex flex-col gap-5"
|
|
252
|
+
id="card-mentor">
|
|
253
|
+
<div class="flex items-start justify-between">
|
|
254
|
+
<div class="text-4xl">🎓</div>
|
|
255
|
+
<div class="flex items-center gap-2" id="badge-mentor">
|
|
256
|
+
<div class="w-2 h-2 rounded-full bg-gray-600 dot-pulse" id="dot-mentor"></div>
|
|
257
|
+
<span class="text-xs text-gray-500" id="label-mentor">checking…</span>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
<div>
|
|
261
|
+
<h2 class="font-bold text-base mb-1" style="color:#f472b6">Mentor Intelligence</h2>
|
|
262
|
+
<p class="text-xs text-gray-400 leading-relaxed">
|
|
263
|
+
Adaptive onboarding with profile detection, session management and cross-domain retrieval.
|
|
264
|
+
</p>
|
|
265
|
+
</div>
|
|
266
|
+
<div class="text-xs text-gray-600 font-mono">localhost:8082</div>
|
|
267
|
+
<div class="text-xs text-gray-500" id="chunks-mentor">— chunks indexed</div>
|
|
268
|
+
<div class="flex gap-2 mt-auto">
|
|
269
|
+
<a href="http://localhost:8082" target="_blank"
|
|
270
|
+
class="btn flex-1 text-center bg-gray-800 hover:bg-gray-700 text-sm
|
|
271
|
+
py-2 rounded-lg font-medium">
|
|
272
|
+
Open →
|
|
273
|
+
</a>
|
|
274
|
+
<button onclick="toggle('mentor')" id="btn-mentor"
|
|
275
|
+
class="btn flex-1 bg-pink-700 hover:bg-pink-600 text-sm
|
|
276
|
+
py-2 rounded-lg font-medium">
|
|
277
|
+
Start
|
|
278
|
+
</button>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
</div>
|
|
283
|
+
</main>
|
|
284
|
+
|
|
285
|
+
<!-- Footer -->
|
|
286
|
+
<footer class="border-t border-gray-800 px-8 py-3 text-center text-xs text-gray-700">
|
|
287
|
+
IntelligenceSuite Launcher · <span id="footer-status">polling…</span>
|
|
288
|
+
</footer>
|
|
289
|
+
|
|
290
|
+
<script>
|
|
291
|
+
const MODULES = ['code', 'doc', 'mentor'];
|
|
292
|
+
const COLORS = { code:'bg-green-400', doc:'bg-green-400', mentor:'bg-green-400' };
|
|
293
|
+
|
|
294
|
+
async function poll() {
|
|
295
|
+
try {
|
|
296
|
+
const res = await fetch('/api/status');
|
|
297
|
+
const data = await res.json();
|
|
298
|
+
let allOk = true;
|
|
299
|
+
for (const [key, s] of Object.entries(data)) {
|
|
300
|
+
const dot = document.getElementById('dot-' + key);
|
|
301
|
+
const label = document.getElementById('label-' + key);
|
|
302
|
+
const btn = document.getElementById('btn-' + key);
|
|
303
|
+
const chnk = document.getElementById('chunks-' + key);
|
|
304
|
+
|
|
305
|
+
if (s.running) {
|
|
306
|
+
dot.className = 'w-2 h-2 rounded-full bg-green-400';
|
|
307
|
+
label.textContent = '● online';
|
|
308
|
+
label.className = 'text-xs text-green-400';
|
|
309
|
+
btn.textContent = 'Stop';
|
|
310
|
+
btn.className = btn.className.replace(/bg-\\w+-700 hover:bg-\\w+-600/,
|
|
311
|
+
'bg-gray-700 hover:bg-gray-600');
|
|
312
|
+
chnk.textContent = s.chunks + ' chunks indexed';
|
|
313
|
+
} else {
|
|
314
|
+
dot.className = 'w-2 h-2 rounded-full bg-gray-600';
|
|
315
|
+
label.textContent = '○ offline';
|
|
316
|
+
label.className = 'text-xs text-gray-500';
|
|
317
|
+
const colors = { code:'bg-indigo-700 hover:bg-indigo-600',
|
|
318
|
+
doc:'bg-cyan-700 hover:bg-cyan-600',
|
|
319
|
+
mentor:'bg-pink-700 hover:bg-pink-600' };
|
|
320
|
+
btn.textContent = 'Start';
|
|
321
|
+
btn.className = 'btn flex-1 ' + colors[key] + ' text-sm py-2 rounded-lg font-medium';
|
|
322
|
+
chnk.textContent = '— chunks indexed';
|
|
323
|
+
allOk = false;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
document.getElementById('footer-status').textContent =
|
|
327
|
+
allOk ? 'All modules online' : 'Some modules offline';
|
|
328
|
+
} catch(e) {
|
|
329
|
+
document.getElementById('footer-status').textContent = 'Launcher error: ' + e.message;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
async function toggle(key) {
|
|
334
|
+
const btn = document.getElementById('btn-' + key);
|
|
335
|
+
const starting = btn.textContent.trim() === 'Start';
|
|
336
|
+
btn.disabled = true;
|
|
337
|
+
btn.textContent = starting ? 'Starting…' : 'Stopping…';
|
|
338
|
+
await fetch('/api/' + (starting ? 'start' : 'stop') + '/' + key, { method: 'POST' });
|
|
339
|
+
// Poll a few times quickly to reflect new state
|
|
340
|
+
for (let i = 0; i < 6; i++) {
|
|
341
|
+
await new Promise(r => setTimeout(r, 800));
|
|
342
|
+
await poll();
|
|
343
|
+
}
|
|
344
|
+
btn.disabled = false;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
async function startAll() {
|
|
348
|
+
await fetch('/api/start-all', { method: 'POST' });
|
|
349
|
+
for (let i = 0; i < 8; i++) {
|
|
350
|
+
await new Promise(r => setTimeout(r, 700));
|
|
351
|
+
await poll();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Initial + recurring poll
|
|
356
|
+
poll();
|
|
357
|
+
setInterval(poll, 4000);
|
|
358
|
+
</script>
|
|
359
|
+
</body>
|
|
360
|
+
</html>
|
|
361
|
+
"""
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
@app.get("/", response_class=HTMLResponse)
|
|
365
|
+
def index():
|
|
366
|
+
return HTMLResponse(_LAUNCHER_HTML)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
# ── Entry point ──────────────────────────────────────────────────────────────
|
|
370
|
+
def main():
|
|
371
|
+
from intelligence_core.config import settings
|
|
372
|
+
port = getattr(settings, "launcher_port", 8079)
|
|
373
|
+
|
|
374
|
+
import threading, webbrowser, time
|
|
375
|
+
def _open():
|
|
376
|
+
time.sleep(1.2)
|
|
377
|
+
webbrowser.open(f"http://localhost:{port}")
|
|
378
|
+
threading.Thread(target=_open, daemon=True).start()
|
|
379
|
+
|
|
380
|
+
print(f" 🧠 IntelligenceSuite Launcher → http://localhost:{port}")
|
|
381
|
+
uvicorn.run(app, host=settings.api_host, port=port, log_level="warning")
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
if __name__ == "__main__":
|
|
385
|
+
main()
|