@@ -157,10 +65,7 @@ onUnmounted(() => { ws?.close() })
min-height: 0;
}
-.graph-container {
- padding: 16px;
- height: 100%;
-}
+.graph-container { padding: 16px; height: 100%; }
.graph-nodes {
display: flex;
@@ -208,14 +113,8 @@ onUnmounted(() => { ws?.close() })
box-shadow: 0 0 8px var(--status-live);
}
-.node-label {
- font-family: var(--font-mono);
- font-size: 13px;
-}
-
-.summary-panel {
- flex-shrink: 0;
-}
+.node-label { font-family: var(--font-mono); font-size: 13px; }
+.summary-panel { flex-shrink: 0; }
.summary {
display: flex;
diff --git a/ui/app/src/pages/OpsNotifications.vue b/ui/app/src/pages/OpsNotifications.vue
index 798f956..bd4c1bf 100644
--- a/ui/app/src/pages/OpsNotifications.vue
+++ b/ui/app/src/pages/OpsNotifications.vue
@@ -1,8 +1,9 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ Running agent...
+ Select a flight and click Run FCE.
+
-
-
-
-
- Running agent... gathering flight data, weather, crew notes...
-
-
- Select a flight and click Run FCE to generate a notification.
-
-
+
+
+
+
+
+ Running agent...
+ Click Run Handover.
+
+
-
-
-
-
-
-
-
+
+
+
+
+
Waiting for agent run...
+
+
+
+
+
+
+
+ {{ currentRun.agent }} / {{ currentRun.run_id }} / {{ entries.length }} events
-
- Running agent... scanning all hubs for active issues...
-
-
- Click Run Handover to generate a shift handover brief.
-
-
+
diff --git a/ui/app/src/pages/Settings.vue b/ui/app/src/pages/Settings.vue
new file mode 100644
index 0000000..f5788ea
--- /dev/null
+++ b/ui/app/src/pages/Settings.vue
@@ -0,0 +1,257 @@
+
+
+
+
+
+
+
diff --git a/uv.lock b/uv.lock
index 2f590f7..11e1b56 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1091,6 +1091,25 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/58/78/548fb8e07b1a341746bfbecb32f2c268470f45fa028aacdbd10d9bc73aab/numpy-2.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7", size = 10566643, upload-time = "2026-03-29T13:21:34.339Z" },
]
+[[package]]
+name = "openai"
+version = "2.31.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+ { name = "distro" },
+ { name = "httpx" },
+ { name = "jiter" },
+ { name = "pydantic" },
+ { name = "sniffio" },
+ { name = "tqdm" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/94/fe/64b3d035780b3188f86c4f6f1bc202e7bb74757ef028802112273b9dcacf/openai-2.31.0.tar.gz", hash = "sha256:43ca59a88fc973ad1848d86b98d7fac207e265ebbd1828b5e4bdfc85f79427a5", size = 684772, upload-time = "2026-04-08T21:01:41.797Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/66/bc/a8f7c3aa03452fedbb9af8be83e959adba96a6b4a35e416faffcc959c568/openai-2.31.0-py3-none-any.whl", hash = "sha256:44e1344d87e56a493d649b17e2fac519d1368cbb0745f59f1957c4c26de50a0a", size = 1153479, upload-time = "2026-04-08T21:01:39.217Z" },
+]
+
[[package]]
name = "openapi-pydantic"
version = "0.5.1"
@@ -1895,6 +1914,7 @@ dependencies = [
{ name = "langfuse" },
{ name = "langgraph" },
{ name = "mcp", extra = ["cli"] },
+ { name = "openai" },
{ name = "pydantic" },
{ name = "uvicorn", extra = ["standard"] },
{ name = "websockets" },
@@ -1921,6 +1941,7 @@ requires-dist = [
{ name = "langfuse" },
{ name = "langgraph" },
{ name = "mcp", extras = ["cli"] },
+ { name = "openai" },
{ name = "pydantic", specifier = ">=2.0" },
{ name = "pytest", marker = "extra == 'dev'" },
{ name = "pytest-asyncio", marker = "extra == 'dev'" },
@@ -1939,6 +1960,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" },
]
+[[package]]
+name = "tqdm"
+version = "4.67.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" },
+]
+
[[package]]
name = "typer"
version = "0.24.1"