From 22a4fc50a59260e0a4f1d9caf392e78c1ddfe187 Mon Sep 17 00:00:00 2001 From: c-d-p Date: Sat, 26 Apr 2025 12:43:19 +0200 Subject: [PATCH] fixed comments --- .../__pycache__/celery_app.cpython-312.pyc | Bin 438 -> 438 bytes .../core/__pycache__/config.cpython-312.pyc | Bin 1314 -> 1299 bytes .../core/__pycache__/database.cpython-312.pyc | Bin 1866 -> 1866 bytes backend/core/celery_app.py | 11 +- backend/core/config.py | 2 +- backend/core/database.py | 3 +- backend/main.py | 12 --- .../admin/__pycache__/api.cpython-312.pyc | Bin 1661 -> 1661 bytes .../admin/__pycache__/tasks.cpython-312.pyc | Bin 1744 -> 1742 bytes backend/modules/admin/api.py | 8 +- backend/modules/admin/services.py | 3 - backend/modules/admin/tasks.py | 3 - .../auth/__pycache__/api.cpython-312.pyc | Bin 4298 -> 4298 bytes .../__pycache__/dependencies.cpython-312.pyc | Bin 1334 -> 1334 bytes .../auth/__pycache__/schemas.cpython-312.pyc | Bin 2240 -> 2240 bytes .../auth/__pycache__/security.cpython-312.pyc | Bin 8591 -> 8177 bytes .../auth/__pycache__/services.cpython-312.pyc | Bin 1641 -> 1641 bytes backend/modules/auth/api.py | 3 +- backend/modules/auth/dependencies.py | 1 - backend/modules/auth/schemas.py | 1 - backend/modules/auth/security.py | 24 +---- backend/modules/auth/services.py | 1 - .../calendar/__pycache__/api.cpython-312.pyc | Bin 3023 -> 3023 bytes .../__pycache__/schemas.cpython-312.pyc | Bin 2906 -> 2906 bytes backend/modules/calendar/api.py | 1 - backend/modules/calendar/schemas.py | 5 +- .../nlp/__pycache__/api.cpython-312.pyc | Bin 11495 -> 11481 bytes .../nlp/__pycache__/models.cpython-312.pyc | Bin 1360 -> 1360 bytes .../nlp/__pycache__/schemas.cpython-312.pyc | Bin 687 -> 687 bytes .../nlp/__pycache__/service.cpython-312.pyc | Bin 7595 -> 7593 bytes backend/modules/nlp/api.py | 52 +-------- backend/modules/nlp/models.py | 1 - backend/modules/nlp/schemas.py | 2 - backend/modules/nlp/service.py | 2 - backend/modules/todo/__init__.py | 1 - .../todo/__pycache__/__init__.cpython-312.pyc | Bin 149 -> 149 bytes .../todo/__pycache__/api.cpython-312.pyc | Bin 3266 -> 3266 bytes .../todo/__pycache__/models.cpython-312.pyc | Bin 988 -> 988 bytes backend/modules/todo/api.py | 17 ++- backend/modules/todo/models.py | 2 +- .../user/__pycache__/api.cpython-312.pyc | Bin 4220 -> 4220 bytes backend/modules/user/api.py | 1 - interfaces/nativeapp/app.json | 11 +- interfaces/nativeapp/eas.json | 21 ++++ interfaces/nativeapp/package-lock.json | 102 ++++++++++++++++++ interfaces/nativeapp/package.json | 3 +- interfaces/nativeapp/src/api/client.ts | 12 +-- .../src/navigation/AuthNavigator.tsx | 2 +- .../nativeapp/src/screens/RegisterScreen.tsx | 6 +- 49 files changed, 165 insertions(+), 148 deletions(-) create mode 100644 interfaces/nativeapp/eas.json diff --git a/backend/core/__pycache__/celery_app.cpython-312.pyc b/backend/core/__pycache__/celery_app.cpython-312.pyc index 39f3ce1f0912c048cde07824dcd07139271fa7ad..1a911f9da2530518f5a42144bb35a31232f3237e 100644 GIT binary patch delta 40 tcmdnSyp5UfG%qg~0}%M=a%HeGZseD?G zAp=7cccp-);NTcnmk1!AdV=A5Su)Q*+Lm4UL*}7 zz{+GnELIr70b~@1PyWN~Ehs8+nMM3N3k$2{Ck7xE#`JdN2x zLl7oeBm-iB)yjcbtT2KD$S97U{E^vPR9d#dZ-Vn>7MbrXEUc2B7=T2P>||dSH$4fM l>RTMesU; Callable[[FastAPI], _AsyncGeneratorContextManager[Any]]: @asynccontextmanager @@ -29,16 +23,11 @@ def lifespan_factory() -> Callable[[FastAPI], _AsyncGeneratorContextManager[Any] lifespan = lifespan_factory() app = FastAPI(lifespan=lifespan) -# Include module router app.include_router(router) -# CORS app.add_middleware( CORSMiddleware, allow_origins=[ - "http://localhost:8081", # Keep for web testing if needed - "http://192.168.1.9:8081", # Add your mobile device/emulator origin (adjust port if needed) - "http://192.168.255.221:8081", "https://maia.depaoli.id.au", ], allow_credentials=True, @@ -47,7 +36,6 @@ app.add_middleware( ) -# Health endpoint @app.get("/api/health") def health(): return {"status": "ok"} diff --git a/backend/modules/admin/__pycache__/api.cpython-312.pyc b/backend/modules/admin/__pycache__/api.cpython-312.pyc index 7beb637cb83c4fb5e5fb8de49fb4a57f6c642070..65877700d94111986506a50642bba43176a6444c 100644 GIT binary patch delta 55 zcmey%^OuM3G%qg~0}yc8aAh4Ffy`D7G+as K!AyXZr&}IeZ{fvwfn;)>4FfwvX7G+as Kdybd)G%qg~0}wk}t;>Qs9c(wG6h1MqaB6pW-I)A?)sBr5$o{}J*@mrJQif4~g32cbAoZD_<3?Pt0m)u$x~VFR6npW2#HOXohW-UBY_i-KC01$8>uZb&J7VqoRe?(ljr`5UVp8#j>sfoHN6TeYM-qy7YyPYginGcyB| N;72APt4IZC2LOWsAN&9S diff --git a/backend/modules/admin/api.py b/backend/modules/admin/api.py index 9b3c260..876c80b 100644 --- a/backend/modules/admin/api.py +++ b/backend/modules/admin/api.py @@ -1,7 +1,7 @@ # modules/admin/api.py from typing import Annotated -from fastapi import APIRouter, Depends # Import Body -from pydantic import BaseModel # Import BaseModel +from fastapi import APIRouter, Depends +from pydantic import BaseModel from sqlalchemy.orm import Session from core.database import get_db from modules.auth.dependencies import admin_only @@ -10,7 +10,6 @@ from .tasks import cleardb router = APIRouter(prefix="/admin", tags=["admin"], dependencies=[Depends(admin_only)]) -# Define a Pydantic model for the request body class ClearDbRequest(BaseModel): hard: bool @@ -20,7 +19,6 @@ def read_admin(): return {"message": "Admin route"} -# Change to POST and use the request body model @router.post("/cleardb") def clear_db(payload: ClearDbRequest, db: Annotated[Session, Depends(get_db)]): """ @@ -28,6 +26,6 @@ def clear_db(payload: ClearDbRequest, db: Annotated[Session, Depends(get_db)]): 'hard'=True: Drop and recreate all tables. 'hard'=False: Delete data from tables except users. """ - hard = payload.hard # Get 'hard' from the payload + hard = payload.hard cleardb.delay(hard) return {"message": "Clearing database in the background", "hard": hard} diff --git a/backend/modules/admin/services.py b/backend/modules/admin/services.py index 00b45ac..57df60d 100644 --- a/backend/modules/admin/services.py +++ b/backend/modules/admin/services.py @@ -1,4 +1 @@ -# modules/admin/services.py - - ## temp diff --git a/backend/modules/admin/tasks.py b/backend/modules/admin/tasks.py index 1ba029f..d0e8943 100644 --- a/backend/modules/admin/tasks.py +++ b/backend/modules/admin/tasks.py @@ -18,16 +18,13 @@ def cleardb(hard: bool): db = SessionLocal() if hard: - # Drop and recreate all tables Base.metadata.drop_all(bind=engine) Base.metadata.create_all(bind=engine) db.commit() return {"message": "Database reset (HARD)"} else: - # Delete data from tables except users tables = Base.metadata.tables.keys() for table_name in tables: - # delete all tables that isn't the users table if table_name != "users": table = Base.metadata.tables[table_name] print(f"Deleting table: {table_name}") diff --git a/backend/modules/auth/__pycache__/api.cpython-312.pyc b/backend/modules/auth/__pycache__/api.cpython-312.pyc index fec21f8b776d920da167b6b6ced22de31b07c224..30261803586c1ba80fd4fbbd30d81db047b8fadf 100644 GIT binary patch delta 57 zcmX@5cuJA?G%qg~0}w0L2my#sB~S delta 57 zcmX@5cuJA?G%qg~0}$lPb7U;u$Xm_IsIgctDW%G%qg~0}wgctDW%G%qg~0}$lPb7Xwq$ScUi$TnG?=^-P}WJc!AjDnN5GB+}cPBv$m$S67a nB+D{Jxyc2rs~J@`%dqJ(GU`qCVvk_dn7o*M1LM=lAsjgXfI}9C diff --git a/backend/modules/auth/__pycache__/security.cpython-312.pyc b/backend/modules/auth/__pycache__/security.cpython-312.pyc index 0d639b268aa882a00a05444b48c157dbda30e8bb..bf301a3e730218719f6ec0b698330b1c3d993178 100644 GIT binary patch delta 545 zcmXw#L1+^}6o%i+WH!^p>~7P9U1XaYTa`vFLPLWswvq&_co9mK_G%BJ9wc3?g%$Ox zhg1fn;w1+`K@X9=#EZn93I%EKQV^j+uhLl~-UQ!n=p5#o_y7M4KhvlNbNWs?odjCT zx01JiWk2d|A?9g(0xBuLiX!`&GW>tyM+~Rs_tZ@}ZkT@MSR;n>G*h;`irq~r{ zRiu{65%>8(k5fv`=BV|g0z!*g6FStIuuTmJ>ViOXlLCb1l?bi)pKz)d=qLUILZgqW delta 860 zcmYk3&ubGw6vt<}*>#&=-SkJA)});%rN3-I8!V<`OB)bdC}KlHFP3dGA)%6#-R+M+ zY84M63T>TBMUa3Vg!T~GONEN@RuD=;6?zf+Cu~gd;z4IN#X5)mym{~Y9^ZLe8QB} z!V+OwlTj*xmgNVjI63lkkw2c+^>e+JLGu_bvq32w4_FaBcy$rSG#sBZN6u;4MI5S4 zi_p-NFj*vt|49)Op-ke;MUNbdVO2#Lg_=nySWWhtZSnaKn#L;0w)s;Dti_UONyQ3^ zQLimOj|{i-S){pZf}w^r+is@w{c4hc%4{G(&pw?;u zve@u;!{%d~)8H7p0yPGQO`h=1&E_)SQsrr}GP4Z9@E9x(9EI*yI3JXbMb~EctD*e$ z*CVCIzOvYFnAzZv$rHZ5%2Smw3f}!^-$WT0*d@?69vmD JyD5IUjlVm}_=*4k diff --git a/backend/modules/auth/__pycache__/services.cpython-312.pyc b/backend/modules/auth/__pycache__/services.cpython-312.pyc index 7cec1a2fe4d1f1958a6dc55f4cc1f2643f826b68..cb3b6212e13208d12fa63dad139ec68aa42e01b5 100644 GIT binary patch delta 35 pcmaFK^OA@6G%qg~0}w str: """Hash a password with Argon2 (and optional pepper).""" - peppered_password = password + settings.PEPPER # Prepend/append pepper + peppered_password = password + settings.PEPPER return password_hasher.hash(peppered_password) @@ -47,10 +47,8 @@ def authenticate_user(username: str, password: str, db: Session) -> User | None: Authenticate a user by checking username/password against the database. Returns User object if valid, None otherwise. """ - # Get user from database user = db.query(User).filter(User.username == username).first() - # If user not found or password doesn't match if not user or not verify_password(password, user.hashed_password): return None @@ -65,7 +63,6 @@ def create_access_token(data: dict, expires_delta: timedelta | None = None): expire = datetime.now(timezone.utc) + timedelta( minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES ) - # expire = datetime.now(timezone.utc) + timedelta(seconds=5) to_encode.update({"exp": expire, "token_type": TokenType.ACCESS}) return jwt.encode( to_encode, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM @@ -89,22 +86,6 @@ def create_refresh_token(data: dict, expires_delta: timedelta | None = None): def verify_token( token: str, expected_token_type: TokenType, db: Session ) -> TokenData | None: - """Verify a JWT token and return TokenData if valid. - - Parameters - ---------- - token: str - The JWT token to be verified. - expected_token_type: TokenType - The expected type of token (access or refresh) - db: Session - Database session to fetch user data. - - Returns - ------- - TokenData | None - TokenData instance if the token is valid, None otherwise. - """ is_blacklisted = ( db.query(TokenBlacklist).filter(TokenBlacklist.token == token).first() is not None @@ -137,7 +118,6 @@ def get_current_user( headers={"WWW-Authenticate": "Bearer"}, ) - # Check if the token is blacklisted is_blacklisted = ( db.query(TokenBlacklist).filter(TokenBlacklist.token == token).first() is not None @@ -178,7 +158,6 @@ def blacklist_tokens(access_token: str, refresh_token: str, db: Session) -> None ) expires_at = datetime.fromtimestamp(payload.get("exp")) - # Add the token to the blacklist blacklisted_token = TokenBlacklist(token=token, expires_at=expires_at) db.add(blacklisted_token) @@ -191,7 +170,6 @@ def blacklist_token(token: str, db: Session) -> None: ) expires_at = datetime.fromtimestamp(payload.get("exp")) - # Add the token to the blacklist blacklisted_token = TokenBlacklist(token=token, expires_at=expires_at) db.add(blacklisted_token) db.commit() diff --git a/backend/modules/auth/services.py b/backend/modules/auth/services.py index 3f50a37..0a15257 100644 --- a/backend/modules/auth/services.py +++ b/backend/modules/auth/services.py @@ -1,4 +1,3 @@ -# modules/auth/services.py from sqlalchemy.orm import Session from modules.auth.models import User from modules.auth.schemas import UserResponse diff --git a/backend/modules/calendar/__pycache__/api.cpython-312.pyc b/backend/modules/calendar/__pycache__/api.cpython-312.pyc index 0416d50d41dd3c8df49de75e4ef0e4b14db3c534..cd1869bade059ab30b1f82e81baa3a24978336ef 100644 GIT binary patch delta 60 zcmX>veqNmSG%qg~0}wveqNmSG%qg~0}$lPb7b7y$ScaqC^=b~^%SGZrypXMj kQDL(lJ0}yPi_@% diff --git a/backend/modules/calendar/api.py b/backend/modules/calendar/api.py index cdb1cf6..5564f61 100644 --- a/backend/modules/calendar/api.py +++ b/backend/modules/calendar/api.py @@ -1,4 +1,3 @@ -# modules/calendar/api.py from fastapi import APIRouter, Depends, status from sqlalchemy.orm import Session from datetime import datetime diff --git a/backend/modules/calendar/schemas.py b/backend/modules/calendar/schemas.py index 3cec1c7..3b8de61 100644 --- a/backend/modules/calendar/schemas.py +++ b/backend/modules/calendar/schemas.py @@ -1,7 +1,6 @@ -# modules/calendar/schemas.py from datetime import datetime -from pydantic import BaseModel, field_validator # Add field_validator -from typing import List, Optional # Add List and Optional +from pydantic import BaseModel, field_validator +from typing import List, Optional # Base schema for common fields, including tags diff --git a/backend/modules/nlp/__pycache__/api.cpython-312.pyc b/backend/modules/nlp/__pycache__/api.cpython-312.pyc index 91a120535a495b4e4331fc075c69cec26cf2a8dd..2ab4e8746b871cd867f4c692337276b153462b16 100644 GIT binary patch delta 626 zcmZvWOK1~e6ov1d$vpCyOeUH~+Zde5V-izr2uX+)Vw+MZrPhEh%+?kZ7Zp^L?ka9v zD2V^2f?~Qd%SfP9bm3BPlf+016%?3Wpgl55Ng1}ZgXlVamKyHg@hc)yut3iycWq|cL0{yrxRN6lVIninX{ zRvuWFTw@Ev&!Zf`8fZ>%`nRP>O^U3|@0(l%apxGq?u;P3psSE<&c{v-9_7LaYKABY-i?bnYoXveVUS- zKUlIW&tj7Vm6*OPuRO*U$%j2;CB&hP{8oZGlLOC;)UPL>1B#I(NF*3LOhp@b&u*C; zo?O+D>q8kGp3yyHvUyV;S#OW{m^e;`~D?(%$F#STw_0(N#>Agjyi2f$q1GALzH| zdPA%EbXhm8UwLjZQ1NbQW@Gg)BDwK!YMI6yHl3bWnk~_ z5%KoVfp^LU9*>c${5%FSdHy{o#F%#PHF+vJ^*TO@k9jJ<$zifCKG2z31T|+O(jxK{_T2vh~txn&9FEy2Z!x&XY5{OLY`GO@c(gz6&ei=wRsI9{MKh{}@vlg`1$%ziTOawrv(FD(^JLpgDXYUjucmk%rCqw5fg!kg7?&(Z`FHi&-adRyR*mKZunO^{mB15EGu>2H?y^9>r4C7j@;nI-2O{-4QEl= zVV&=ORrHQska&BUTn?OPSG*0l!y-rriv}fSSTQY|){R@?cs?A@K4bw&ayyo^GZ&5* zOru}K(cjc6XE1mjaV~SS=O{OpKme*i#2tv`Ayxu+3G7wqu0nqayiGwst^uqxRlsxD zzr=J4D8_}%h!(goiX}2D&DQ#+IS*F0? z>ixCTuNG=8NS!1a^2g3-F@Z%jKs9YtR&A7TBNmKg-qp2nO#|FGQtqEHBa&yKiN8|~ B#dQDx diff --git a/backend/modules/nlp/__pycache__/models.cpython-312.pyc b/backend/modules/nlp/__pycache__/models.cpython-312.pyc index f113b096f61ab290245ddc39e30b3715131f5d08..515297efc594f2ffdeb181ae0b1175fe3ee2614d 100644 GIT binary patch delta 42 xcmcb>b%BfbG%qg~0}wb%BfbG%qg~0}$lPb7cJ5$a{j3k!$lcMtLSi{>|T*)fpL|PnKgf0s#443z`4` diff --git a/backend/modules/nlp/__pycache__/schemas.cpython-312.pyc b/backend/modules/nlp/__pycache__/schemas.cpython-312.pyc index bcce691ecb9e5a85c9f51af6a64aa6f599caf3b3..d0f66b69dc36814b60b5b901c1119571e2dda376 100644 GIT binary patch delta 41 vcmZ3_x}KHqG%qg~0}wj$jCZ5gK+~R=VVEyV#d3Zdzq8~(tHYt delta 41 vcmZ3_x}KHqG%qg~0}$lPb7Z(NZsdz(WMrG1!MK5uYqBI$G2_$8y-Z2~zsm{D diff --git a/backend/modules/nlp/__pycache__/service.cpython-312.pyc b/backend/modules/nlp/__pycache__/service.cpython-312.pyc index c02a10ad48a80be4dc0cd1614391f8780085edd8..acd4ce1c71fb93a950c9c37ede6767f977466d86 100644 GIT binary patch delta 74 zcmZ2&z0#WZG%qg~0}w List[str]: if not events: return ["You have no events matching that criteria."] formatted = ["Here are the events:"] for event in events: - # Access attributes directly from the model instance start_str = ( event.start.strftime("%Y-%m-%d %H:%M") if event.start else "No start time" ) @@ -65,7 +59,6 @@ def format_calendar_events(events: List[CalendarEvent]) -> List[str]: return formatted -# Helper to format TODO items (expects list of Todo models) def format_todos(todos: List[Todo]) -> List[str]: if not todos: return ["Your TODO list is empty."] @@ -80,7 +73,6 @@ def format_todos(todos: List[Todo]) -> List[str]: return formatted -# Update the response model for the endpoint @router.post("/process-command", response_model=ProcessCommandResponse) def process_command( request_data: ProcessCommandRequest, @@ -92,34 +84,25 @@ def process_command( """ user_input = request_data.user_input - # --- Save User Message --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.USER, text=user_input ) - # ------------------------ command_data = process_request(user_input) intent = command_data["intent"] params = command_data["params"] response_text = command_data["response_text"] - responses = [response_text] # Start with the initial response + responses = [response_text] - # --- Save Initial AI Response --- - # Save the first response generated by process_request save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=response_text ) - # ----------------------------- if intent == "error": - # Don't raise HTTPException here if we want to save the error message - # Instead, return the error response directly - # save_chat_message(db, user_id=current_user.id, sender=MessageSender.AI, text=response_text) # Already saved above return ProcessCommandResponse(responses=responses) if intent == "clarification_needed" or intent == "unknown": - # save_chat_message(db, user_id=current_user.id, sender=MessageSender.AI, text=response_text) # Already saved above return ProcessCommandResponse(responses=responses) try: @@ -127,11 +110,9 @@ def process_command( case "ask_ai": ai_answer = ask_ai(**params) responses.append(ai_answer) - # --- Save Additional AI Response --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=ai_answer ) - # --------------------------------- return ProcessCommandResponse(responses=responses) case "get_calendar_events": @@ -140,12 +121,10 @@ def process_command( ) formatted_responses = format_calendar_events(events) responses.extend(formatted_responses) - # --- Save Additional AI Responses --- for resp in formatted_responses: save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=resp ) - # ---------------------------------- return ProcessCommandResponse(responses=responses) case "add_calendar_event": @@ -159,20 +138,17 @@ def process_command( title = created_event.title or "Untitled Event" add_response = f"Added: {title} starting at {start_str}." responses.append(add_response) - # --- Save Additional AI Response --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=add_response, ) - # --------------------------------- return ProcessCommandResponse(responses=responses) case "update_calendar_event": event_id = params.pop("event_id", None) if event_id is None: - # Save the error message before raising error_msg = "Event ID is required for update." save_chat_message( db, @@ -188,20 +164,17 @@ def process_command( title = updated_event.title or "Untitled Event" update_response = f"Updated event ID {updated_event.id}: {title}." responses.append(update_response) - # --- Save Additional AI Response --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=update_response, ) - # --------------------------------- return ProcessCommandResponse(responses=responses) case "delete_calendar_event": event_id = params.get("event_id") if event_id is None: - # Save the error message before raising error_msg = "Event ID is required for delete." save_chat_message( db, @@ -213,29 +186,24 @@ def process_command( delete_calendar_event(db, current_user.id, event_id) delete_response = f"Deleted event ID {event_id}." responses.append(delete_response) - # --- Save Additional AI Response --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=delete_response, ) - # --------------------------------- return ProcessCommandResponse(responses=responses) - # --- Add TODO Cases --- case "get_todos": todos: List[Todo] = todo_service.get_todos( db, user=current_user, **params ) formatted_responses = format_todos(todos) responses.extend(formatted_responses) - # --- Save Additional AI Responses --- for resp in formatted_responses: save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=resp ) - # ---------------------------------- return ProcessCommandResponse(responses=responses) case "add_todo": @@ -247,14 +215,12 @@ def process_command( f"Added TODO: '{created_todo.task}' (ID: {created_todo.id})." ) responses.append(add_response) - # --- Save Additional AI Response --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=add_response, ) - # --------------------------------- return ProcessCommandResponse(responses=responses) case "update_todo": @@ -279,14 +245,12 @@ def process_command( status = "complete" if params["complete"] else "incomplete" update_response += f" Marked as {status}." responses.append(update_response) - # --- Save Additional AI Response --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=update_response, ) - # --------------------------------- return ProcessCommandResponse(responses=responses) case "delete_todo": @@ -307,26 +271,21 @@ def process_command( f"Deleted TODO ID {deleted_todo.id}: '{deleted_todo.task}'." ) responses.append(delete_response) - # --- Save Additional AI Response --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=delete_response, ) - # --------------------------------- return ProcessCommandResponse(responses=responses) - # --- End TODO Cases --- case _: print( f"Warning: Unhandled intent '{intent}' reached api.py match statement." ) - # The initial response_text was already saved return ProcessCommandResponse(responses=responses) except HTTPException as http_exc: - # Don't save again if already saved before raising if http_exc.status_code != 400 or ("event_id" not in http_exc.detail.lower()): save_chat_message( db, @@ -340,11 +299,9 @@ def process_command( error_response = ( "Sorry, I encountered an error while trying to perform that action." ) - # --- Save Final Error AI Response --- save_chat_message( db, user_id=current_user.id, sender=MessageSender.AI, text=error_response ) - # ---------------------------------- return ProcessCommandResponse(responses=[error_response]) @@ -355,6 +312,3 @@ def read_chat_history( """Retrieves the last 50 chat messages for the current user.""" history = get_chat_history(db, user_id=current_user.id, limit=50) return history - - -# ------------------------------------- diff --git a/backend/modules/nlp/models.py b/backend/modules/nlp/models.py index 120fcee..87cd143 100644 --- a/backend/modules/nlp/models.py +++ b/backend/modules/nlp/models.py @@ -1,4 +1,3 @@ -# /home/cdp/code/MAIA/backend/modules/nlp/models.py from sqlalchemy import Column, Integer, Text, DateTime, ForeignKey, Enum as SQLEnum from sqlalchemy.orm import relationship from sqlalchemy.sql import func diff --git a/backend/modules/nlp/schemas.py b/backend/modules/nlp/schemas.py index d2a2807..bff1a12 100644 --- a/backend/modules/nlp/schemas.py +++ b/backend/modules/nlp/schemas.py @@ -1,4 +1,3 @@ -# modules/nlp/schemas.py from pydantic import BaseModel from typing import List @@ -9,5 +8,4 @@ class ProcessCommandRequest(BaseModel): class ProcessCommandResponse(BaseModel): responses: List[str] - # Optional: Keep details if needed for specific frontend logic beyond display # details: dict | None = None diff --git a/backend/modules/nlp/service.py b/backend/modules/nlp/service.py index ef4bca4..18ba6dd 100644 --- a/backend/modules/nlp/service.py +++ b/backend/modules/nlp/service.py @@ -1,5 +1,3 @@ -# modules/nlp/service.py - from sqlalchemy.orm import Session from sqlalchemy import desc # Import desc for ordering from google import genai diff --git a/backend/modules/todo/__init__.py b/backend/modules/todo/__init__.py index d6fc651..1a6df05 100644 --- a/backend/modules/todo/__init__.py +++ b/backend/modules/todo/__init__.py @@ -1,2 +1 @@ -# backend/modules/todo/__init__.py # This file makes the 'todo' directory a Python package. diff --git a/backend/modules/todo/__pycache__/__init__.cpython-312.pyc b/backend/modules/todo/__pycache__/__init__.cpython-312.pyc index 1a4f3d322e5ea7bec99ddcdd5ffe66fc002a7f8b..d61a235d3f50577b7b384ebd11fc38b6bf702ab1 100644 GIT binary patch delta 21 bcmbQrIF*t2G%qg~0}wkc}SA)G%qg~0}wCLumc8rW_n`_uv7#WQw WH*%a~wA&oO8Og|afAcCX2_^tVkr9gk delta 67 zcmX>kc}SA)G%qg~0}$lPb7b7&*vO~L$|yWJfKy^}2L6J|!;&Dval Um>B&wYw*rtWW2liDBpHQ07p|2cmMzZ delta 66 zcmeyP@JE67G%qg~0}$lPb7aig$g9Z0$iG>igQNHbr076U>X#fBK diff --git a/backend/modules/user/api.py b/backend/modules/user/api.py index 34317f7..6f54cfa 100644 --- a/backend/modules/user/api.py +++ b/backend/modules/user/api.py @@ -1,4 +1,3 @@ -# modules/user/api.py from typing import Annotated from fastapi import APIRouter, Depends from sqlalchemy.orm import Session diff --git a/interfaces/nativeapp/app.json b/interfaces/nativeapp/app.json index baa11bc..6c5c812 100644 --- a/interfaces/nativeapp/app.json +++ b/interfaces/nativeapp/app.json @@ -20,7 +20,8 @@ "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" }, - "softwareKeyboardLayoutMode": "resize" + "softwareKeyboardLayoutMode": "resize", + "package": "com.seedeep.maia" }, "web": { "favicon": "./assets/favicon.png" @@ -28,6 +29,12 @@ "plugins": [ "expo-secure-store", "expo-font" - ] + ], + "extra": { + "eas": { + "projectId": "4d7d70ce-a4d8-4307-8827-8ef713b95b78" + } + }, + "owner": "cdp202" } } diff --git a/interfaces/nativeapp/eas.json b/interfaces/nativeapp/eas.json new file mode 100644 index 0000000..4b759f9 --- /dev/null +++ b/interfaces/nativeapp/eas.json @@ -0,0 +1,21 @@ +{ + "cli": { + "version": ">= 16.3.2", + "appVersionSource": "remote" + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal" + }, + "preview": { + "distribution": "internal" + }, + "production": { + "autoIncrement": true + } + }, + "submit": { + "production": {} + } +} diff --git a/interfaces/nativeapp/package-lock.json b/interfaces/nativeapp/package-lock.json index 238de80..f262723 100644 --- a/interfaces/nativeapp/package-lock.json +++ b/interfaces/nativeapp/package-lock.json @@ -18,6 +18,7 @@ "axios": "^1.8.4", "date-fns": "^4.1.0", "expo": "^52.0.46", + "expo-dev-client": "~5.0.20", "expo-font": "~13.0.4", "expo-secure-store": "~14.0.1", "expo-splash-screen": "~0.29.24", @@ -3746,6 +3747,21 @@ "node": ">=8" } }, + "node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/anser": { "version": "1.4.10", "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", @@ -5307,6 +5323,54 @@ "react-native": "*" } }, + "node_modules/expo-dev-client": { + "version": "5.0.20", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-5.0.20.tgz", + "integrity": "sha512-bLNkHdU7V3I4UefgJbJnIDUBUL0LxIal/xYEx9BbgDd3B7wgQKY//+BpPIxBOKCQ22lkyiHY8y9tLhO903sAgg==", + "dependencies": { + "expo-dev-launcher": "5.0.35", + "expo-dev-menu": "6.0.25", + "expo-dev-menu-interface": "1.9.3", + "expo-manifests": "~0.15.8", + "expo-updates-interface": "~1.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher": { + "version": "5.0.35", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-5.0.35.tgz", + "integrity": "sha512-hEQr0ZREnUMxZ6wtQgfK1lzYnbb0zar3HqYZhmANzXmE6UEPbQ4GByLzhpfz/d+xxdBVQZsrHdtiV28KPG2sog==", + "dependencies": { + "ajv": "8.11.0", + "expo-dev-menu": "6.0.25", + "expo-manifests": "~0.15.8", + "resolve-from": "^5.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu": { + "version": "6.0.25", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-6.0.25.tgz", + "integrity": "sha512-K2m4z/I+CPWbMtHlDzU68lHaQs52De0v5gbsjAmA5ig8FrYh4MKZvPxSVANaiKENzgmtglu8qaFh7ua9Gt2TfA==", + "dependencies": { + "expo-dev-menu-interface": "1.9.3" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu-interface": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.9.3.tgz", + "integrity": "sha512-KY/dWTBE1l47i9V366JN5rC6YIdOc9hz8yAmZzkl5DrPia5l3M2WIjtnpHC9zUkNjiSiG2urYoOAq4H/uLdmyg==", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-file-system": { "version": "18.0.12", "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.0.12.tgz", @@ -5331,6 +5395,11 @@ "react": "*" } }, + "node_modules/expo-json-utils": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.14.0.tgz", + "integrity": "sha512-xjGfK9dL0B1wLnOqNkX0jM9p48Y0I5xEPzHude28LY67UmamUyAACkqhZGaPClyPNfdzczk7Ej6WaRMT3HfXvw==" + }, "node_modules/expo-keep-awake": { "version": "14.0.3", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.0.3.tgz", @@ -5340,6 +5409,18 @@ "react": "*" } }, + "node_modules/expo-manifests": { + "version": "0.15.8", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.8.tgz", + "integrity": "sha512-VuIyaMfRfLZeETNsRohqhy1l7iZ7I+HKMPfZXVL2Yn17TT0WkOhZoq1DzYwPbOHPgp1Uk6phNa86EyaHrD2DLw==", + "dependencies": { + "@expo/config": "~10.0.11", + "expo-json-utils": "~0.14.0" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-modules-autolinking": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.0.8.tgz", @@ -5427,6 +5508,14 @@ "react-native": "*" } }, + "node_modules/expo-updates-interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-1.0.0.tgz", + "integrity": "sha512-93oWtvULJOj+Pp+N/lpTcFfuREX1wNeHtp7Lwn8EbzYYmdn37MvZU3TPW2tYYCZuhzmKEXnUblYcruYoDu7IrQ==", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/exponential-backoff": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", @@ -6596,6 +6685,11 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -10308,6 +10402,14 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/use-latest-callback": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.3.tgz", diff --git a/interfaces/nativeapp/package.json b/interfaces/nativeapp/package.json index f8a2494..4c66651 100644 --- a/interfaces/nativeapp/package.json +++ b/interfaces/nativeapp/package.json @@ -33,7 +33,8 @@ "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", "react-native-vector-icons": "^10.2.0", - "react-native-web": "~0.19.13" + "react-native-web": "~0.19.13", + "expo-dev-client": "~5.0.20" }, "devDependencies": { "@babel/core": "^7.25.2", diff --git a/interfaces/nativeapp/src/api/client.ts b/interfaces/nativeapp/src/api/client.ts index 0bd4e05..1b0ce6b 100644 --- a/interfaces/nativeapp/src/api/client.ts +++ b/interfaces/nativeapp/src/api/client.ts @@ -1,15 +1,13 @@ // src/api/client.ts -import axios, { AxiosError } from 'axios'; // Import AxiosError +import axios, { AxiosError } from 'axios'; import { Platform } from 'react-native'; import * as SecureStore from 'expo-secure-store'; import AsyncStorage from '@react-native-async-storage/async-storage'; -// const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'http://192.168.255.221:8000/api'; // Use your machine's IP -// const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'http://192.168.1.9:8000/api'; // Use your machine's IP -const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'https://maia.depaoli.id.au/api'; // Use your machine's IP -const ACCESS_TOKEN_KEY = 'maia_access_token'; // Renamed for clarity -const REFRESH_TOKEN_KEY = 'maia_refresh_token'; // Key for refresh token +const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'https://maia.depaoli.id.au/api'; +const ACCESS_TOKEN_KEY = 'maia_access_token'; +const REFRESH_TOKEN_KEY = 'maia_refresh_token'; console.log("Using API Base URL:", API_BASE_URL); @@ -34,7 +32,7 @@ const deleteToken = async (key: string): Promise => { if (Platform.OS === 'web') { await AsyncStorage.removeItem(key); } else { - await SecureStore.deleteItemAsync(key).catch(() => {}); // Ignore delete error + await SecureStore.deleteItemAsync(key).catch(() => {}); } }; diff --git a/interfaces/nativeapp/src/navigation/AuthNavigator.tsx b/interfaces/nativeapp/src/navigation/AuthNavigator.tsx index a4672c5..77d2358 100644 --- a/interfaces/nativeapp/src/navigation/AuthNavigator.tsx +++ b/interfaces/nativeapp/src/navigation/AuthNavigator.tsx @@ -13,7 +13,7 @@ const AuthNavigator = () => { return ( - {/* Add Register screen */} + ); }; diff --git a/interfaces/nativeapp/src/screens/RegisterScreen.tsx b/interfaces/nativeapp/src/screens/RegisterScreen.tsx index 6be8cb9..ddc25e1 100644 --- a/interfaces/nativeapp/src/screens/RegisterScreen.tsx +++ b/interfaces/nativeapp/src/screens/RegisterScreen.tsx @@ -35,11 +35,7 @@ const RegisterScreen: React.FC = ({ navigation }) => { await register(username, password, name); console.log("[RegisterScreen] handleRegister: Registration successful (from context perspective)."); // Show success message and navigate back to Login - Alert.alert( - 'Registration Successful', - 'Your account has been created. Please log in.', - [{ text: 'OK', onPress: () => navigation.navigate('Login') }] - ); + navigation.navigate('Login'); } catch (err: any) { console.log("[RegisterScreen] handleRegister: Caught error from context register."); const errorMessage = err.response?.data?.detail ||