Spaces:
Running
Running
Run Open WebUI against LynxScribe in LynxKite.
Browse files- README.md +8 -5
- data/LynxScribe demo +2 -10
- server/executors/one_by_one.py +7 -6
- server/llm_ops.py +4 -1
- server/lynxkite_ops.py +1 -1
- server/lynxscribe_ops.py +93 -38
- server/main.py +14 -4
- web/package-lock.json +122 -3
- web/package.json +1 -0
- web/src/apiTypes.ts +7 -0
README.md
CHANGED
@@ -7,16 +7,13 @@ original LynxKite. The primary goals of this rewrite are:
|
|
7 |
- More extensible backend. Make it easy to add new LynxKite boxes. Make it easy to use our frontend for other purposes,
|
8 |
configuring and executing other pipelines.
|
9 |
|
10 |
-
Current status: **PROTOTYPE**
|
11 |
-
|
12 |
## Installation
|
13 |
|
14 |
To run the backend:
|
15 |
|
16 |
```bash
|
17 |
-
|
18 |
-
|
19 |
-
uvicorn server.main:app --reload
|
20 |
```
|
21 |
|
22 |
To run the frontend:
|
@@ -26,3 +23,9 @@ cd web
|
|
26 |
npm i
|
27 |
npm run dev
|
28 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
- More extensible backend. Make it easy to add new LynxKite boxes. Make it easy to use our frontend for other purposes,
|
8 |
configuring and executing other pipelines.
|
9 |
|
|
|
|
|
10 |
## Installation
|
11 |
|
12 |
To run the backend:
|
13 |
|
14 |
```bash
|
15 |
+
PYTHONPATH=. uv run pydantic2ts --module server.workspace --output ./web/src/apiTypes.ts --json2ts-cmd "npm exec --prefix web json2ts"
|
16 |
+
uv run fastapi run server/main.py --reload
|
|
|
17 |
```
|
18 |
|
19 |
To run the frontend:
|
|
|
23 |
npm i
|
24 |
npm run dev
|
25 |
```
|
26 |
+
|
27 |
+
To run a chat UI for LynxScribe workspaces:
|
28 |
+
|
29 |
+
```bash
|
30 |
+
WEBUI_AUTH=false OPENAI_API_BASE_URL=http://localhost:8000/api/service/server.lynxscribe_ops uvx open-webui serve
|
31 |
+
```
|
data/LynxScribe demo
CHANGED
@@ -580,8 +580,7 @@
|
|
580 |
"data": {
|
581 |
"title": "Truncate history",
|
582 |
"params": {
|
583 |
-
"max_tokens": 10000
|
584 |
-
"language": "English"
|
585 |
},
|
586 |
"display": null,
|
587 |
"error": null,
|
@@ -594,13 +593,6 @@
|
|
594 |
"type": {
|
595 |
"type": "<class 'int'>"
|
596 |
}
|
597 |
-
},
|
598 |
-
"language": {
|
599 |
-
"name": "language",
|
600 |
-
"default": "English",
|
601 |
-
"type": {
|
602 |
-
"type": "<class 'str'>"
|
603 |
-
}
|
604 |
}
|
605 |
},
|
606 |
"inputs": {},
|
@@ -957,4 +949,4 @@
|
|
957 |
"targetHandle": "chat_api"
|
958 |
}
|
959 |
]
|
960 |
-
}
|
|
|
580 |
"data": {
|
581 |
"title": "Truncate history",
|
582 |
"params": {
|
583 |
+
"max_tokens": 10000
|
|
|
584 |
},
|
585 |
"display": null,
|
586 |
"error": null,
|
|
|
593 |
"type": {
|
594 |
"type": "<class 'int'>"
|
595 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
596 |
}
|
597 |
},
|
598 |
"inputs": {},
|
|
|
949 |
"targetHandle": "chat_api"
|
950 |
}
|
951 |
]
|
952 |
+
}
|
server/executors/one_by_one.py
CHANGED
@@ -127,12 +127,13 @@ async def execute(ws, catalog, cache=None):
|
|
127 |
results = []
|
128 |
for task in ts:
|
129 |
try:
|
130 |
-
inputs = [
|
131 |
-
|
132 |
-
if i.position in "top or bottom"
|
133 |
-
|
134 |
-
|
135 |
-
|
|
|
136 |
if cache is not None:
|
137 |
key = make_cache_key((inputs, params))
|
138 |
if key not in cache:
|
|
|
127 |
results = []
|
128 |
for task in ts:
|
129 |
try:
|
130 |
+
inputs = []
|
131 |
+
for i in op.inputs.values():
|
132 |
+
if i.position in "top or bottom":
|
133 |
+
assert (n, i.name) in batch_inputs, f"{i.name} is missing"
|
134 |
+
inputs.append(batch_inputs[(n, i.name)])
|
135 |
+
else:
|
136 |
+
inputs.append(task)
|
137 |
if cache is not None:
|
138 |
key = make_cache_key((inputs, params))
|
139 |
if key not in cache:
|
server/llm_ops.py
CHANGED
@@ -13,7 +13,7 @@ from .executors import one_by_one
|
|
13 |
chat_client = openai.OpenAI(base_url="http://localhost:8080/v1")
|
14 |
embedding_client = openai.OpenAI(base_url="http://localhost:7997/")
|
15 |
jinja = jinja2.Environment()
|
16 |
-
chroma_client =
|
17 |
LLM_CACHE = {}
|
18 |
ENV = "LLM logic"
|
19 |
one_by_one.register(ENV)
|
@@ -178,12 +178,15 @@ def rag(
|
|
178 |
num_matches: int = 10,
|
179 |
_ctx: one_by_one.Context,
|
180 |
):
|
|
|
181 |
if engine == RagEngine.Chroma:
|
182 |
last = _ctx.last_result
|
183 |
if last:
|
184 |
collection = last["_collection"]
|
185 |
else:
|
186 |
collection_name = _ctx.node.id.replace(" ", "_")
|
|
|
|
|
187 |
for c in chroma_client.list_collections():
|
188 |
if c.name == collection_name:
|
189 |
chroma_client.delete_collection(name=collection_name)
|
|
|
13 |
chat_client = openai.OpenAI(base_url="http://localhost:8080/v1")
|
14 |
embedding_client = openai.OpenAI(base_url="http://localhost:7997/")
|
15 |
jinja = jinja2.Environment()
|
16 |
+
chroma_client = None
|
17 |
LLM_CACHE = {}
|
18 |
ENV = "LLM logic"
|
19 |
one_by_one.register(ENV)
|
|
|
178 |
num_matches: int = 10,
|
179 |
_ctx: one_by_one.Context,
|
180 |
):
|
181 |
+
global chroma_client
|
182 |
if engine == RagEngine.Chroma:
|
183 |
last = _ctx.last_result
|
184 |
if last:
|
185 |
collection = last["_collection"]
|
186 |
else:
|
187 |
collection_name = _ctx.node.id.replace(" ", "_")
|
188 |
+
if chroma_client is None:
|
189 |
+
chroma_client = chromadb.Client()
|
190 |
for c in chroma_client.list_collections():
|
191 |
if c.name == collection_name:
|
192 |
chroma_client.delete_collection(name=collection_name)
|
server/lynxkite_ops.py
CHANGED
@@ -218,7 +218,7 @@ def sql(bundle: Bundle, *, query: ops.LongStr, save_as: str = "result"):
|
|
218 |
# TODO: Currently `collect()` moves the data from cuDF to Polars. Then we convert it to Pandas,
|
219 |
# which (hopefully) puts it back into cuDF. Hopefully we will be able to keep it in cuDF.
|
220 |
else:
|
221 |
-
res = pl.SQLContext(bundle.dfs).execute(query)
|
222 |
bundle.dfs[save_as] = res
|
223 |
return bundle
|
224 |
|
|
|
218 |
# TODO: Currently `collect()` moves the data from cuDF to Polars. Then we convert it to Pandas,
|
219 |
# which (hopefully) puts it back into cuDF. Hopefully we will be able to keep it in cuDF.
|
220 |
else:
|
221 |
+
res = pl.SQLContext(bundle.dfs).execute(query).collect().to_pandas()
|
222 |
bundle.dfs[save_as] = res
|
223 |
return bundle
|
224 |
|
server/lynxscribe_ops.py
CHANGED
@@ -5,19 +5,18 @@ LynxScribe configuration and testing in LynxKite.
|
|
5 |
from lynxscribe.core.llm.base import get_llm_engine
|
6 |
from lynxscribe.core.vector_store.base import get_vector_store
|
7 |
from lynxscribe.common.config import load_config
|
8 |
-
from lynxscribe.components.
|
9 |
from lynxscribe.components.rag.rag_graph import RAGGraph
|
10 |
from lynxscribe.components.rag.knowledge_base_graph import PandasKnowledgeBaseGraph
|
11 |
from lynxscribe.components.rag.rag_chatbot import Scenario, ScenarioSelector, RAGChatbot
|
12 |
-
from lynxscribe.components.
|
13 |
-
|
14 |
MaskTemplate,
|
15 |
TruncateHistory,
|
16 |
)
|
17 |
-
from lynxscribe.components.
|
18 |
|
19 |
from . import ops
|
20 |
-
import asyncio
|
21 |
import json
|
22 |
from .executors import one_by_one
|
23 |
|
@@ -134,12 +133,8 @@ def chat_processor(processor, *, _ctx: one_by_one.Context):
|
|
134 |
|
135 |
@output_on_top
|
136 |
@op("Truncate history")
|
137 |
-
def truncate_history(*, max_tokens=10000
|
138 |
-
return {
|
139 |
-
"question_processor": TruncateHistory(
|
140 |
-
max_tokens=max_tokens, language=language.lower()
|
141 |
-
)
|
142 |
-
}
|
143 |
|
144 |
|
145 |
@output_on_top
|
@@ -224,42 +219,102 @@ def view(input):
|
|
224 |
return v
|
225 |
|
226 |
|
227 |
-
async def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
228 |
"""
|
229 |
Serves a chat endpoint that matches LynxScribe's interface.
|
230 |
To access it you need to add the "module" and "workspace"
|
231 |
parameters.
|
232 |
The workspace must contain exactly one "Chat API" node.
|
233 |
|
234 |
-
curl -X POST ${LYNXKITE_URL}/api/service \
|
235 |
-H "Content-Type: application/json" \
|
236 |
-d '{
|
237 |
-
"
|
238 |
-
"
|
239 |
-
"session_id": "b43215a0-428f-11ef-9454-0242ac120002",
|
240 |
-
"question": "what does the fox say",
|
241 |
-
"history": [],
|
242 |
-
"user_id": "x",
|
243 |
-
"meta_inputs": {}
|
244 |
}'
|
245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
import pathlib
|
247 |
from . import workspace
|
248 |
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
question=request["question"],
|
262 |
-
history=request["history"],
|
263 |
-
)
|
264 |
-
response = await chat_api.answer(request)
|
265 |
-
return response
|
|
|
5 |
from lynxscribe.core.llm.base import get_llm_engine
|
6 |
from lynxscribe.core.vector_store.base import get_vector_store
|
7 |
from lynxscribe.common.config import load_config
|
8 |
+
from lynxscribe.components.text.embedder import TextEmbedder
|
9 |
from lynxscribe.components.rag.rag_graph import RAGGraph
|
10 |
from lynxscribe.components.rag.knowledge_base_graph import PandasKnowledgeBaseGraph
|
11 |
from lynxscribe.components.rag.rag_chatbot import Scenario, ScenarioSelector, RAGChatbot
|
12 |
+
from lynxscribe.components.chat.processors import (
|
13 |
+
ChatProcessor,
|
14 |
MaskTemplate,
|
15 |
TruncateHistory,
|
16 |
)
|
17 |
+
from lynxscribe.components.chat.api import ChatAPI, ChatAPIRequest, ChatAPIResponse
|
18 |
|
19 |
from . import ops
|
|
|
20 |
import json
|
21 |
from .executors import one_by_one
|
22 |
|
|
|
133 |
|
134 |
@output_on_top
|
135 |
@op("Truncate history")
|
136 |
+
def truncate_history(*, max_tokens=10000):
|
137 |
+
return {"question_processor": TruncateHistory(max_tokens=max_tokens)}
|
|
|
|
|
|
|
|
|
138 |
|
139 |
|
140 |
@output_on_top
|
|
|
219 |
return v
|
220 |
|
221 |
|
222 |
+
async def get_chat_api(ws):
|
223 |
+
import pathlib
|
224 |
+
from . import workspace
|
225 |
+
|
226 |
+
DATA_PATH = pathlib.Path.cwd() / "data"
|
227 |
+
path = DATA_PATH / ws
|
228 |
+
assert path.is_relative_to(DATA_PATH)
|
229 |
+
assert path.exists(), f"Workspace {path} does not exist"
|
230 |
+
ws = workspace.load(path)
|
231 |
+
contexts = await ops.EXECUTORS[ENV](ws)
|
232 |
+
nodes = [op for op in ws.nodes if op.data.title == "Chat API"]
|
233 |
+
[node] = nodes
|
234 |
+
context = contexts[node.id]
|
235 |
+
return context.last_result["chat_api"]
|
236 |
+
|
237 |
+
|
238 |
+
async def stream_chat_api_response(request):
|
239 |
+
chat_api = await get_chat_api(request["model"])
|
240 |
+
chat_api_request = ChatAPIRequest(
|
241 |
+
session_id=request.get("session_id", "00000000-0000-0000-0000-000000000000"),
|
242 |
+
history=request["messages"][:-1],
|
243 |
+
question=request["messages"][-1]["content"],
|
244 |
+
)
|
245 |
+
response = await chat_api.answer(chat_api_request)
|
246 |
+
response = response.model_dump()
|
247 |
+
yield json.dumps(
|
248 |
+
{
|
249 |
+
**response,
|
250 |
+
"id": "asd",
|
251 |
+
"object": "chat.completion.chunk",
|
252 |
+
"model": request["model"],
|
253 |
+
"choices": [
|
254 |
+
{
|
255 |
+
"index": 0,
|
256 |
+
"delta": {"role": "assistant", "content": response["answer"]},
|
257 |
+
}
|
258 |
+
],
|
259 |
+
}
|
260 |
+
)
|
261 |
+
|
262 |
+
|
263 |
+
async def api_service_post(request):
|
264 |
"""
|
265 |
Serves a chat endpoint that matches LynxScribe's interface.
|
266 |
To access it you need to add the "module" and "workspace"
|
267 |
parameters.
|
268 |
The workspace must contain exactly one "Chat API" node.
|
269 |
|
270 |
+
curl -X POST ${LYNXKITE_URL}/api/service/server.lynxkite_ops \
|
271 |
-H "Content-Type: application/json" \
|
272 |
-d '{
|
273 |
+
"model": "LynxScribe demo",
|
274 |
+
"messages": [{"role": "user", "content": "what does the fox say"}]
|
|
|
|
|
|
|
|
|
|
|
275 |
}'
|
276 |
+
"""
|
277 |
+
path = "/".join(request.url.path.split("/")[4:])
|
278 |
+
request = await request.json()
|
279 |
+
if path == "chat/completions":
|
280 |
+
from sse_starlette.sse import EventSourceResponse
|
281 |
+
|
282 |
+
return EventSourceResponse(stream_chat_api_response(request))
|
283 |
+
return {"error": "Not found"}
|
284 |
+
|
285 |
+
|
286 |
+
async def api_service_get(request):
|
287 |
+
path = "/".join(request.url.path.split("/")[4:])
|
288 |
+
if path == "models":
|
289 |
+
return {
|
290 |
+
"object": "list",
|
291 |
+
"data": [
|
292 |
+
{
|
293 |
+
"id": ws,
|
294 |
+
"object": "model",
|
295 |
+
"created": 0,
|
296 |
+
"owned_by": "lynxkite",
|
297 |
+
"meta": {"profile_image_url": "https://lynxkite.com/favicon.png"},
|
298 |
+
}
|
299 |
+
for ws in get_lynxscribe_workspaces()
|
300 |
+
],
|
301 |
+
}
|
302 |
+
return {"error": "Not found"}
|
303 |
+
|
304 |
+
|
305 |
+
def get_lynxscribe_workspaces():
|
306 |
import pathlib
|
307 |
from . import workspace
|
308 |
|
309 |
+
DATA_DIR = pathlib.Path.cwd() / "data"
|
310 |
+
workspaces = []
|
311 |
+
for p in DATA_DIR.glob("**/*"):
|
312 |
+
if p.is_file():
|
313 |
+
try:
|
314 |
+
ws = workspace.load(p)
|
315 |
+
if ws.env == ENV:
|
316 |
+
workspaces.append(p.relative_to(DATA_DIR))
|
317 |
+
except Exception:
|
318 |
+
pass # Ignore files that are not valid workspaces.
|
319 |
+
workspaces.sort()
|
320 |
+
return workspaces
|
|
|
|
|
|
|
|
|
|
server/main.py
CHANGED
@@ -1,3 +1,6 @@
|
|
|
|
|
|
|
|
1 |
import dataclasses
|
2 |
import fastapi
|
3 |
import importlib
|
@@ -87,8 +90,15 @@ def make_dir(req: dict):
|
|
87 |
return list_dir(path.parent)
|
88 |
|
89 |
|
90 |
-
@app.
|
91 |
-
async def
|
92 |
"""Executors can provide extra HTTP APIs through the /api/service endpoint."""
|
93 |
-
module = lynxkite_modules[
|
94 |
-
return await module.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# TODO: Make this conditional. Until then just comment/uncomment it to use cuDF Pandas.
|
2 |
+
# import cudf.pandas
|
3 |
+
# cudf.pandas.install()
|
4 |
import dataclasses
|
5 |
import fastapi
|
6 |
import importlib
|
|
|
90 |
return list_dir(path.parent)
|
91 |
|
92 |
|
93 |
+
@app.get("/api/service/{module_path:path}")
|
94 |
+
async def service_get(req: fastapi.Request, module_path: str):
|
95 |
"""Executors can provide extra HTTP APIs through the /api/service endpoint."""
|
96 |
+
module = lynxkite_modules[module_path.split("/")[0]]
|
97 |
+
return await module.api_service_get(req)
|
98 |
+
|
99 |
+
|
100 |
+
@app.post("/api/service/{module_path:path}")
|
101 |
+
async def service_post(req: fastapi.Request, module_path: str):
|
102 |
+
"""Executors can provide extra HTTP APIs through the /api/service endpoint."""
|
103 |
+
module = lynxkite_modules[module_path.split("/")[0]]
|
104 |
+
return await module.api_service_post(req)
|
web/package-lock.json
CHANGED
@@ -20,6 +20,7 @@
|
|
20 |
"daisyui": "^4.12.20",
|
21 |
"echarts": "^5.5.1",
|
22 |
"fuse.js": "^7.0.0",
|
|
|
23 |
"react": "^18.3.1",
|
24 |
"react-dom": "^18.3.1",
|
25 |
"react-markdown": "^9.0.1",
|
@@ -97,6 +98,23 @@
|
|
97 |
"url": "https://github.com/sponsors/antfu"
|
98 |
}
|
99 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
"node_modules/@babel/code-frame": {
|
101 |
"version": "7.26.2",
|
102 |
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
|
@@ -687,6 +705,12 @@
|
|
687 |
"@jridgewell/sourcemap-codec": "^1.4.14"
|
688 |
}
|
689 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
690 |
"node_modules/@nodelib/fs.scandir": {
|
691 |
"version": "2.1.5",
|
692 |
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
@@ -1333,7 +1357,12 @@
|
|
1333 |
"version": "7.0.15",
|
1334 |
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
1335 |
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
1336 |
-
"
|
|
|
|
|
|
|
|
|
|
|
1337 |
"license": "MIT"
|
1338 |
},
|
1339 |
"node_modules/@types/mdast": {
|
@@ -3339,7 +3368,6 @@
|
|
3339 |
"version": "2.1.1",
|
3340 |
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
3341 |
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
3342 |
-
"dev": true,
|
3343 |
"license": "MIT",
|
3344 |
"engines": {
|
3345 |
"node": ">=0.10.0"
|
@@ -3359,7 +3387,6 @@
|
|
3359 |
"version": "4.0.3",
|
3360 |
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
3361 |
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
3362 |
-
"dev": true,
|
3363 |
"license": "MIT",
|
3364 |
"dependencies": {
|
3365 |
"is-extglob": "^2.1.1"
|
@@ -3486,6 +3513,29 @@
|
|
3486 |
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
3487 |
"license": "MIT"
|
3488 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3489 |
"node_modules/json-schema-traverse": {
|
3490 |
"version": "0.4.1",
|
3491 |
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
@@ -3760,6 +3810,12 @@
|
|
3760 |
"url": "https://github.com/sponsors/sindresorhus"
|
3761 |
}
|
3762 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
3763 |
"node_modules/lodash.debounce": {
|
3764 |
"version": "4.0.8",
|
3765 |
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
@@ -4452,6 +4508,15 @@
|
|
4452 |
"node": "*"
|
4453 |
}
|
4454 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4455 |
"node_modules/minipass": {
|
4456 |
"version": "7.1.2",
|
4457 |
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
@@ -4985,6 +5050,21 @@
|
|
4985 |
"node": ">= 0.8.0"
|
4986 |
}
|
4987 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4988 |
"node_modules/property-information": {
|
4989 |
"version": "6.5.0",
|
4990 |
"resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz",
|
@@ -5695,6 +5775,45 @@
|
|
5695 |
"integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==",
|
5696 |
"license": "MIT"
|
5697 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5698 |
"node_modules/to-regex-range": {
|
5699 |
"version": "5.0.1",
|
5700 |
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
|
|
20 |
"daisyui": "^4.12.20",
|
21 |
"echarts": "^5.5.1",
|
22 |
"fuse.js": "^7.0.0",
|
23 |
+
"json-schema-to-typescript": "^15.0.3",
|
24 |
"react": "^18.3.1",
|
25 |
"react-dom": "^18.3.1",
|
26 |
"react-markdown": "^9.0.1",
|
|
|
98 |
"url": "https://github.com/sponsors/antfu"
|
99 |
}
|
100 |
},
|
101 |
+
"node_modules/@apidevtools/json-schema-ref-parser": {
|
102 |
+
"version": "11.7.3",
|
103 |
+
"resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.3.tgz",
|
104 |
+
"integrity": "sha512-WApSdLdXEBb/1FUPca2lteASewEfpjEYJ8oXZP+0gExK5qSfsEKBKcA+WjY6Q4wvXwyv0+W6Kvc372pSceib9w==",
|
105 |
+
"license": "MIT",
|
106 |
+
"dependencies": {
|
107 |
+
"@jsdevtools/ono": "^7.1.3",
|
108 |
+
"@types/json-schema": "^7.0.15",
|
109 |
+
"js-yaml": "^4.1.0"
|
110 |
+
},
|
111 |
+
"engines": {
|
112 |
+
"node": ">= 16"
|
113 |
+
},
|
114 |
+
"funding": {
|
115 |
+
"url": "https://github.com/sponsors/philsturgeon"
|
116 |
+
}
|
117 |
+
},
|
118 |
"node_modules/@babel/code-frame": {
|
119 |
"version": "7.26.2",
|
120 |
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
|
|
|
705 |
"@jridgewell/sourcemap-codec": "^1.4.14"
|
706 |
}
|
707 |
},
|
708 |
+
"node_modules/@jsdevtools/ono": {
|
709 |
+
"version": "7.1.3",
|
710 |
+
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
|
711 |
+
"integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
|
712 |
+
"license": "MIT"
|
713 |
+
},
|
714 |
"node_modules/@nodelib/fs.scandir": {
|
715 |
"version": "2.1.5",
|
716 |
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
|
|
1357 |
"version": "7.0.15",
|
1358 |
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
1359 |
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
1360 |
+
"license": "MIT"
|
1361 |
+
},
|
1362 |
+
"node_modules/@types/lodash": {
|
1363 |
+
"version": "4.17.14",
|
1364 |
+
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz",
|
1365 |
+
"integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==",
|
1366 |
"license": "MIT"
|
1367 |
},
|
1368 |
"node_modules/@types/mdast": {
|
|
|
3368 |
"version": "2.1.1",
|
3369 |
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
3370 |
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
|
|
3371 |
"license": "MIT",
|
3372 |
"engines": {
|
3373 |
"node": ">=0.10.0"
|
|
|
3387 |
"version": "4.0.3",
|
3388 |
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
3389 |
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
|
|
3390 |
"license": "MIT",
|
3391 |
"dependencies": {
|
3392 |
"is-extglob": "^2.1.1"
|
|
|
3513 |
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
3514 |
"license": "MIT"
|
3515 |
},
|
3516 |
+
"node_modules/json-schema-to-typescript": {
|
3517 |
+
"version": "15.0.3",
|
3518 |
+
"resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-15.0.3.tgz",
|
3519 |
+
"integrity": "sha512-iOKdzTUWEVM4nlxpFudFsWyUiu/Jakkga4OZPEt7CGoSEsAsUgdOZqR6pcgx2STBek9Gm4hcarJpXSzIvZ/hKA==",
|
3520 |
+
"license": "MIT",
|
3521 |
+
"dependencies": {
|
3522 |
+
"@apidevtools/json-schema-ref-parser": "^11.5.5",
|
3523 |
+
"@types/json-schema": "^7.0.15",
|
3524 |
+
"@types/lodash": "^4.17.7",
|
3525 |
+
"is-glob": "^4.0.3",
|
3526 |
+
"js-yaml": "^4.1.0",
|
3527 |
+
"lodash": "^4.17.21",
|
3528 |
+
"minimist": "^1.2.8",
|
3529 |
+
"prettier": "^3.2.5",
|
3530 |
+
"tinyglobby": "^0.2.9"
|
3531 |
+
},
|
3532 |
+
"bin": {
|
3533 |
+
"json2ts": "dist/src/cli.js"
|
3534 |
+
},
|
3535 |
+
"engines": {
|
3536 |
+
"node": ">=16.0.0"
|
3537 |
+
}
|
3538 |
+
},
|
3539 |
"node_modules/json-schema-traverse": {
|
3540 |
"version": "0.4.1",
|
3541 |
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
|
|
3810 |
"url": "https://github.com/sponsors/sindresorhus"
|
3811 |
}
|
3812 |
},
|
3813 |
+
"node_modules/lodash": {
|
3814 |
+
"version": "4.17.21",
|
3815 |
+
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
3816 |
+
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
3817 |
+
"license": "MIT"
|
3818 |
+
},
|
3819 |
"node_modules/lodash.debounce": {
|
3820 |
"version": "4.0.8",
|
3821 |
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
|
|
4508 |
"node": "*"
|
4509 |
}
|
4510 |
},
|
4511 |
+
"node_modules/minimist": {
|
4512 |
+
"version": "1.2.8",
|
4513 |
+
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
4514 |
+
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
4515 |
+
"license": "MIT",
|
4516 |
+
"funding": {
|
4517 |
+
"url": "https://github.com/sponsors/ljharb"
|
4518 |
+
}
|
4519 |
+
},
|
4520 |
"node_modules/minipass": {
|
4521 |
"version": "7.1.2",
|
4522 |
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
|
|
5050 |
"node": ">= 0.8.0"
|
5051 |
}
|
5052 |
},
|
5053 |
+
"node_modules/prettier": {
|
5054 |
+
"version": "3.4.2",
|
5055 |
+
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
|
5056 |
+
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
|
5057 |
+
"license": "MIT",
|
5058 |
+
"bin": {
|
5059 |
+
"prettier": "bin/prettier.cjs"
|
5060 |
+
},
|
5061 |
+
"engines": {
|
5062 |
+
"node": ">=14"
|
5063 |
+
},
|
5064 |
+
"funding": {
|
5065 |
+
"url": "https://github.com/prettier/prettier?sponsor=1"
|
5066 |
+
}
|
5067 |
+
},
|
5068 |
"node_modules/property-information": {
|
5069 |
"version": "6.5.0",
|
5070 |
"resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz",
|
|
|
5775 |
"integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==",
|
5776 |
"license": "MIT"
|
5777 |
},
|
5778 |
+
"node_modules/tinyglobby": {
|
5779 |
+
"version": "0.2.10",
|
5780 |
+
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz",
|
5781 |
+
"integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==",
|
5782 |
+
"license": "MIT",
|
5783 |
+
"dependencies": {
|
5784 |
+
"fdir": "^6.4.2",
|
5785 |
+
"picomatch": "^4.0.2"
|
5786 |
+
},
|
5787 |
+
"engines": {
|
5788 |
+
"node": ">=12.0.0"
|
5789 |
+
}
|
5790 |
+
},
|
5791 |
+
"node_modules/tinyglobby/node_modules/fdir": {
|
5792 |
+
"version": "6.4.2",
|
5793 |
+
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz",
|
5794 |
+
"integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==",
|
5795 |
+
"license": "MIT",
|
5796 |
+
"peerDependencies": {
|
5797 |
+
"picomatch": "^3 || ^4"
|
5798 |
+
},
|
5799 |
+
"peerDependenciesMeta": {
|
5800 |
+
"picomatch": {
|
5801 |
+
"optional": true
|
5802 |
+
}
|
5803 |
+
}
|
5804 |
+
},
|
5805 |
+
"node_modules/tinyglobby/node_modules/picomatch": {
|
5806 |
+
"version": "4.0.2",
|
5807 |
+
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
5808 |
+
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
5809 |
+
"license": "MIT",
|
5810 |
+
"engines": {
|
5811 |
+
"node": ">=12"
|
5812 |
+
},
|
5813 |
+
"funding": {
|
5814 |
+
"url": "https://github.com/sponsors/jonschlinkert"
|
5815 |
+
}
|
5816 |
+
},
|
5817 |
"node_modules/to-regex-range": {
|
5818 |
"version": "5.0.1",
|
5819 |
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
web/package.json
CHANGED
@@ -22,6 +22,7 @@
|
|
22 |
"daisyui": "^4.12.20",
|
23 |
"echarts": "^5.5.1",
|
24 |
"fuse.js": "^7.0.0",
|
|
|
25 |
"react": "^18.3.1",
|
26 |
"react-dom": "^18.3.1",
|
27 |
"react-markdown": "^9.0.1",
|
|
|
22 |
"daisyui": "^4.12.20",
|
23 |
"echarts": "^5.5.1",
|
24 |
"fuse.js": "^7.0.0",
|
25 |
+
"json-schema-to-typescript": "^15.0.3",
|
26 |
"react": "^18.3.1",
|
27 |
"react-dom": "^18.3.1",
|
28 |
"react-markdown": "^9.0.1",
|
web/src/apiTypes.ts
CHANGED
@@ -5,6 +5,13 @@
|
|
5 |
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
6 |
*/
|
7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
export interface BaseConfig {
|
9 |
[k: string]: unknown;
|
10 |
}
|
|
|
5 |
/* Do not modify it by hand - just update the pydantic models and then re-run the script
|
6 |
*/
|
7 |
|
8 |
+
/* eslint-disable */
|
9 |
+
/**
|
10 |
+
* This file was automatically generated by json-schema-to-typescript.
|
11 |
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
12 |
+
* and run json-schema-to-typescript to regenerate this file.
|
13 |
+
*/
|
14 |
+
|
15 |
export interface BaseConfig {
|
16 |
[k: string]: unknown;
|
17 |
}
|