Files changed (1) hide show
  1. app.py +31 -18
app.py CHANGED
@@ -57,7 +57,14 @@ except Exception as e:
57
 
58
  app = Flask(__name__)
59
  CORS(app, supports_credentials=True)
60
- app.config['SECRET_KEY'] = os.environ.get("SECRET_KEY", "nexa-ai-secret-key-2026")
 
 
 
 
 
 
 
61
 
62
  # --- Database Setup ---
63
  DB_PATH = "nexa_ai.db"
@@ -107,26 +114,27 @@ def init_db():
107
  # FIXED: Ensure a default admin account exists and has the correct password
108
  try:
109
  admin_user = conn.execute('SELECT * FROM users WHERE username = ?', ('admin',)).fetchone()
110
- admin_pass_hash = pwd_context.hash("admin123")
111
  if not admin_user:
 
 
 
 
 
 
 
 
112
  conn.execute(
113
  'INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)',
114
- ('admin', 'admin@nexa.ai', admin_pass_hash)
115
- )
116
- logger.info(f"Default admin account created: admin / admin123 (Hash: {admin_pass_hash[:10]}...)")
117
- else:
118
- # Force update password hash to ensure it matches admin123
119
- conn.execute(
120
- 'UPDATE users SET password_hash = ?, email = ? WHERE username = ?',
121
- (admin_pass_hash, 'admin@nexa.ai', 'admin')
122
  )
123
- logger.info(f"Default admin account password reset to: admin123 (Hash: {admin_pass_hash[:10]}...)")
124
-
125
- # Self-verification check
126
- test_verify = pwd_context.verify("admin123", admin_pass_hash)
127
- logger.info(f"Admin self-verification test: {'PASSED' if test_verify else 'FAILED'}")
 
128
  except Exception as e:
129
- logger.error(f"Error creating/resetting default admin: {e}")
130
 
131
  conn.commit()
132
 
@@ -193,18 +201,23 @@ try:
193
  except Exception as e:
194
  logger.error(f"Failed to load Phi-3-mini model: {e}")
195
 
196
- SYSTEM_PROMPT = """You are Nexa AI, a professional technical execution engine.
 
 
 
 
197
  ### **WRITING PRINCIPLES**:
198
  1. Match response depth and length to the question. A simple question gets a short, direct answer in plain prose β€” no headers, no bullet template. A complex technical request can use structure (headers, numbered steps, tables, code blocks) where it genuinely improves clarity.
199
  2. Write in clear, natural language. Avoid filler words ("just", "really", "very", "basically") but do not strip the response down to unnatural telegraphic phrasing either.
200
  3. Never simulate dialogue, never include "AI:"/"User:" labels, never narrate what you're about to do β€” just answer.
201
  4. Don't force emoji, bold labels, or section headers onto every message. Use them only when they add real value (e.g., a multi-step technical walkthrough, a comparison table).
202
- 5. If the user asks for code, give clean, correct, runnable code with only as much explanation as is useful β€” don't pad it with restating what the code obviously does.
203
  6. Be honest about uncertainty instead of inventing confident-sounding details.
204
  ### **WHEN WEB RESULTS ARE PROVIDED**:
205
  - Synthesize the sources into your own words; cite specific claims with [N] tied to the source list.
206
  - End with a short **Reference** section listing each [N] as a markdown link.
207
  - Never cite Wikipedia.
 
208
  ### **WHEN A TOOL FAILS**:
209
  Briefly state what failed and what you'll try next (or what the user can do), in one or two sentences β€” no need for a formatted alert block.
210
  Current Date: {date}
 
57
 
58
  app = Flask(__name__)
59
  CORS(app, supports_credentials=True)
60
+ app.config['SECRET_KEY'] = os.environ.get("SECRET_KEY")
61
+ if not app.config['SECRET_KEY']:
62
+ # Generate a random key so the app still runs locally/in dev, but this
63
+ # invalidates all existing JWTs on every restart. Set SECRET_KEY in your
64
+ # environment for any deployment where sessions need to persist or where
65
+ # the app is reachable outside your own machine.
66
+ app.config['SECRET_KEY'] = os.urandom(32).hex()
67
+ logger.warning("SECRET_KEY not set in environment β€” using a random ephemeral key. Set SECRET_KEY for production.")
68
 
69
  # --- Database Setup ---
70
  DB_PATH = "nexa_ai.db"
 
114
  # FIXED: Ensure a default admin account exists and has the correct password
115
  try:
116
  admin_user = conn.execute('SELECT * FROM users WHERE username = ?', ('admin',)).fetchone()
 
117
  if not admin_user:
118
+ # Use ADMIN_PASSWORD from the environment if set; otherwise
119
+ # generate a random one-time password and print it once so
120
+ # it isn't a fixed, guessable credential baked into the code.
121
+ admin_password = os.environ.get("ADMIN_PASSWORD")
122
+ generated = admin_password is None
123
+ if generated:
124
+ admin_password = uuid.uuid4().hex
125
+ admin_pass_hash = pwd_context.hash(admin_password)
126
  conn.execute(
127
  'INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)',
128
+ ('admin', os.environ.get("ADMIN_EMAIL", "admin@nexa.ai"), admin_pass_hash)
 
 
 
 
 
 
 
129
  )
130
+ if generated:
131
+ logger.warning(f"Default admin account created with a GENERATED password (shown once): {admin_password} β€” log in and change it, or set ADMIN_PASSWORD in your environment.")
132
+ else:
133
+ logger.info("Default admin account created using ADMIN_PASSWORD from environment.")
134
+ # If the admin account already exists, leave its password alone β€”
135
+ # do not overwrite it on every restart.
136
  except Exception as e:
137
+ logger.error(f"Error creating default admin: {e}")
138
 
139
  conn.commit()
140
 
 
201
  except Exception as e:
202
  logger.error(f"Failed to load Phi-3-mini model: {e}")
203
 
204
+ SYSTEM_PROMPT = """You are Nexa AI, a professional technical execution engine built for direct, competent help across research, coding, writing, and file/media generation.
205
+ ### **SCOPE & HONESTY**:
206
+ 1. You have real tools (web search, file parsing, image/video generation, code execution) β€” only claim to have done something (searched, generated a file, run code) if the corresponding tool actually ran and returned a result this turn.
207
+ 2. If a tool is unavailable or fails, say so plainly rather than fabricating output. Never invent URLs, citations, file contents, or search results.
208
+ 3. If a request is ambiguous, make a reasonable assumption, state it briefly, and proceed β€” don't stall on clarifying questions unless genuinely necessary.
209
  ### **WRITING PRINCIPLES**:
210
  1. Match response depth and length to the question. A simple question gets a short, direct answer in plain prose β€” no headers, no bullet template. A complex technical request can use structure (headers, numbered steps, tables, code blocks) where it genuinely improves clarity.
211
  2. Write in clear, natural language. Avoid filler words ("just", "really", "very", "basically") but do not strip the response down to unnatural telegraphic phrasing either.
212
  3. Never simulate dialogue, never include "AI:"/"User:" labels, never narrate what you're about to do β€” just answer.
213
  4. Don't force emoji, bold labels, or section headers onto every message. Use them only when they add real value (e.g., a multi-step technical walkthrough, a comparison table).
214
+ 5. If the user asks for code, give clean, correct, runnable code with only as much explanation as is useful β€” don't pad it with restating what the code obviously does. Decline requests to write malware, exploits, or credential-stealing code.
215
  6. Be honest about uncertainty instead of inventing confident-sounding details.
216
  ### **WHEN WEB RESULTS ARE PROVIDED**:
217
  - Synthesize the sources into your own words; cite specific claims with [N] tied to the source list.
218
  - End with a short **Reference** section listing each [N] as a markdown link.
219
  - Never cite Wikipedia.
220
+ - Never reproduce more than a short phrase verbatim from any single source.
221
  ### **WHEN A TOOL FAILS**:
222
  Briefly state what failed and what you'll try next (or what the user can do), in one or two sentences β€” no need for a formatted alert block.
223
  Current Date: {date}