demeter

Autonomous Hydroponic Intelligence
commit 214a9f4f3fb4a6ae76d8bc0bce1ce03c312bf51d
parent e4a89d8ecf0850418665cc9ef7dd2ee909ff14f2
Author: maydayv7 <maydayv7@gmail.com>
Date:   Fri, 20 Mar 2026 23:15:24 +0530

Frontend Fixes

Diffstat:
Magent/sub_agents/Supervisor.py | 4++--
Mbackend/node_server/package-lock.json | 94++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mbackend/server/functions.py | 9++++++---
Mfrontend/src/components/Sidebar.jsx | 2+-
Mfrontend/src/data/mockData.js | 12+++++-------
Mfrontend/src/pages/AgentControl.jsx | 1+
Mfrontend/src/pages/Alerts.jsx | 20++------------------
Mfrontend/src/pages/Analytics.jsx | 2++
Mfrontend/src/pages/CropDetails.jsx | 1+
Mfrontend/src/utils/dataUtils.js | 4+++-
10 files changed, 73 insertions(+), 76 deletions(-)

diff --git a/agent/sub_agents/Supervisor.py b/agent/sub_agents/Supervisor.py @@ -187,7 +187,7 @@ class SupervisorAgent: result = self.app.invoke(initial_state) final_targets = result.get("merged_plan", {}) - current_sensors = fmu.metadata.get('sensor_data', {}) + current_sensors = fmu.metadata.get('sensors', {}) print(f"[{self.name}] ⚙️ Converting Targets to Actuator Commands...") @@ -213,7 +213,7 @@ class SupervisorAgent: # --- ADVISORY ONLY (Not Enforced) --- def get_strategic_goal(self, fmu): # (Same as before, but treated as advice now) - sensors = fmu.metadata.get('sensor_data', {}) + sensors = fmu.metadata.get('sensors', {}) fmu_vector = fmu.vector vis_vec1 = np.array(fmu_vector) if isinstance(fmu_vector, list) else fmu_vector vis_vec = vis_vec1[:512] if len(vis_vec1) >= 512 else None diff --git a/backend/node_server/package-lock.json b/backend/node_server/package-lock.json @@ -18,13 +18,13 @@ } }, "node_modules/@qdrant/js-client-rest": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/@qdrant/js-client-rest/-/js-client-rest-1.16.2.tgz", - "integrity": "sha512-Zm4wEZURrZ24a+Hmm4l1QQYjiz975Ep3vF0yzWR7ICGcxittNz47YK2iBOk8kb8qseCu8pg7WmO1HOIsO8alvw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@qdrant/js-client-rest/-/js-client-rest-1.17.0.tgz", + "integrity": "sha512-aZFQeirWVqWAa1a8vJ957LMzcXkFHGbsoRhzc8AkGfg6V0jtK8PlG8/eyyc2xhYsR961FDDx1Tx6nyE0K7lS+A==", "license": "Apache-2.0", "dependencies": { "@qdrant/openapi-typescript-fetch": "1.2.6", - "undici": "^6.0.0" + "undici": "^6.23.0" }, "engines": { "node": ">=18.17.0", @@ -71,10 +71,13 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/binary-extensions": { "version": "2.3.0", @@ -113,13 +116,15 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -196,12 +201,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, "node_modules/content-disposition": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", @@ -243,9 +242,9 @@ } }, "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "license": "MIT", "dependencies": { "object-assign": "^4", @@ -253,6 +252,10 @@ }, "engines": { "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/debug": { @@ -282,9 +285,9 @@ } }, "node_modules/dotenv": { - "version": "17.2.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", - "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", + "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -739,15 +742,18 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "*" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ms": { @@ -766,15 +772,15 @@ } }, "node_modules/nodemon": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.11.tgz", - "integrity": "sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", "license": "MIT", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", + "minimatch": "^10.2.1", "pstree.remy": "^1.1.8", "semver": "^7.5.3", "simple-update-notifier": "^2.0.0", @@ -895,9 +901,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -968,9 +974,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -1200,9 +1206,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", - "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", + "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", "license": "MIT", "engines": { "node": ">=18.17" diff --git a/backend/server/functions.py b/backend/server/functions.py @@ -3,7 +3,7 @@ import shutil import json import traceback import base64 -from fastapi import UploadFile +from fastapi import UploadFile, HTTPException from groq import Groq from qdrant_client.http import models from datetime import datetime @@ -257,13 +257,16 @@ async def process_search(file: UploadFile, sensors_str: str, builder): "new_fmu_id": query_fmu.id, "agent_decision": final_decision_json, "explanation": explanation_log, - "search_results": [{"id": p.id, "score": p.score, "payload": p.payload} for p in points_list], + "search_results": [ + {"id": p.id, "score": p.score, "payload": p.payload} + for p in points_list + ], } except Exception as e: print(f"❌ Pipeline Error: {e}") traceback.print_exc() - return {"status": "error", "message": str(e)} + raise HTTPException(status_code=500, detail=str(e)) finally: # Cleanup temp file diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx @@ -32,7 +32,7 @@ export default function Sidebar() { { label: "Crops", icon: LayoutGrid, path: "/dashboard" }, { label: "Analytics", icon: BarChart3, path: "/analytics" }, { label: "Alerts", icon: Bell, path: "/alerts", badge: alertCount || null }, - { label: "Agent AI", icon: Brain, path: "/control" }, + { label: "Agent Control", icon: Brain, path: "/control" }, { label: "Settings", icon: Settings, path: "/settings" }, ]; diff --git a/frontend/src/data/mockData.js b/frontend/src/data/mockData.js @@ -1,9 +1,7 @@ -// ============================================================ -// DEMETER MOCK DATA -// Set USE_MOCK_DATA = true to use local test data -// Set USE_MOCK_DATA = false to connect to the real backend API -// ============================================================ -export const USE_MOCK_DATA = true; +// MOCK DATA +// -- Set USE_MOCK_DATA = true to use local test data +// -- Set USE_MOCK_DATA = false to connect to the real backend API +export const USE_MOCK_DATA = false; // HELPERS const ts = (daysAgo, hour = 10, min = 0) => { @@ -221,7 +219,7 @@ export const MOCK_SEARCH_RESULT = { 2. **Precedent**: 3 similar past states found. In 2 of those cases, a slight EC boost improved growth rate. No disease was detected in the last 5 cycles. -3. **Logic**: EC at 1.4 is slightly below the 1.5–1.8 target for late vegetative. +3. **Logic**: EC at 1.4 is slightly below the 1.5-1.8 target for late vegetative. A small nutrient dosage increase will push it into the optimal window. Fan speed is adequate; no VPD concerns. diff --git a/frontend/src/pages/AgentControl.jsx b/frontend/src/pages/AgentControl.jsx @@ -661,6 +661,7 @@ export default function AgentControl() { overflow: "hidden", background: "var(--surface)", border: "1px solid rgba(74,222,128,0.3)", + flexShrink: 0, }} > <div diff --git a/frontend/src/pages/Alerts.jsx b/frontend/src/pages/Alerts.jsx @@ -302,24 +302,8 @@ export default function Alerts() { }} > <div> - <h1 - style={{ - fontWeight: 700, - fontSize: 18, - color: "var(--text)", - margin: 0, - }} - > - Alerts - </h1> - <p - style={{ - fontSize: 11, - fontFamily: "DM Mono, monospace", - color: "var(--text-3)", - margin: 0, - }} - > + <h1 className="page-title">Alerts</h1> + <p className="page-subtitle"> {loading ? "Analyzing sensor history…" : `${counts.total} unacknowledged · ${alerts.length} total`} diff --git a/frontend/src/pages/Analytics.jsx b/frontend/src/pages/Analytics.jsx @@ -660,6 +660,7 @@ export default function Analytics() { overflow: "hidden", background: "var(--surface)", border: "1px solid var(--border)", + flexShrink: 0, }} > <div @@ -811,6 +812,7 @@ export default function Analytics() { overflow: "hidden", background: "var(--surface)", border: "1px solid var(--border)", + flexShrink: 0, }} > <div diff --git a/frontend/src/pages/CropDetails.jsx b/frontend/src/pages/CropDetails.jsx @@ -598,6 +598,7 @@ export default function CropDetails() { overflow: "hidden", background: "var(--surface)", border: "1px solid var(--border)", + flexShrink: 0, }} > {/* Header row */} diff --git a/frontend/src/utils/dataUtils.js b/frontend/src/utils/dataUtils.js @@ -146,7 +146,9 @@ function timeAgo(isoString) { if (mins < 60) return `${mins} min ago`; const hrs = Math.floor(mins / 60); if (hrs < 24) return `${hrs} hr ago`; - return `${Math.floor(hrs / 24)} days ago`; + const days = Math.floor(hrs / 24); + if (days === 1) return "1 day ago"; + return `${days} days ago`; } export const generateAlerts = (points) => {