docs and api mostly work
This commit is contained in:
89
AGENTS.md
89
AGENTS.md
@@ -353,3 +353,92 @@ Updated:
|
||||
```
|
||||
|
||||
The Phase 1 implementation successfully transforms the CLI tool into a modern web application while preserving all existing functionality and data compatibility.
|
||||
|
||||
## Docker Build Issue Resolution
|
||||
|
||||
**Problem**: The original Docker build was failing with the error:
|
||||
```
|
||||
npm error The `npm ci` command can only install with an existing package-lock.json or
|
||||
npm error npm-shrinkwrap.json with lockfileVersion >= 1. Run an install with npm@5 or
|
||||
npm error later to generate a package-lock.json file, then try again.
|
||||
```
|
||||
|
||||
**Solution**: Updated the frontend Dockerfile to use `npm install` instead of `npm ci` since no package-lock.json file exists yet. The updated Dockerfile now works correctly:
|
||||
|
||||
```dockerfile
|
||||
# Install dependencies
|
||||
# Use npm install for development (npm ci requires package-lock.json)
|
||||
RUN npm install
|
||||
```
|
||||
|
||||
**Verification**: Docker build now completes successfully and the frontend container can be built and run without errors.
|
||||
|
||||
## Docker Permission Error Resolution
|
||||
|
||||
**Problem**: The backend container was failing with the error:
|
||||
```
|
||||
PermissionError: [Errno 13] Permission denied: '/data'
|
||||
```
|
||||
|
||||
**Root Cause**: The issue was in `backend/main.py` where the data directory path was incorrectly calculated:
|
||||
```python
|
||||
# Incorrect calculation
|
||||
data_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data")
|
||||
# This resulted in '/data' instead of '/app/data'
|
||||
```
|
||||
|
||||
**Solution**: Fixed the path calculation to use the configuration-based approach:
|
||||
```python
|
||||
# Correct calculation using settings
|
||||
from pathlib import Path
|
||||
from app.core.config import settings
|
||||
data_dir = Path(settings.DATA_DIR) # 'data' -> resolves to '/app/data' in container
|
||||
data_dir.mkdir(exist_ok=True)
|
||||
```
|
||||
|
||||
**Additional Considerations**:
|
||||
1. **User Permissions**: The Dockerfile creates a non-root user `appuser` with UID 1000, which matches the typical host user UID for better volume permission compatibility.
|
||||
2. **Volume Mount**: The docker-compose.yml mounts `./data:/app/data` ensuring data persistence.
|
||||
3. **Directory Permissions**: The host `data/` directory has permissions `700` (owner only), but since the container user has the same UID (1000), it can access the directory.
|
||||
|
||||
**Verification**:
|
||||
- Docker builds complete successfully for both backend and frontend
|
||||
- Backend container starts without permission errors
|
||||
- API endpoints respond correctly
|
||||
- Health check endpoint returns `{"status": "healthy"}`
|
||||
- FastAPI documentation endpoints (`/docs` and `/redoc`) are now always enabled
|
||||
|
||||
## FastAPI Documentation Endpoints Fix
|
||||
|
||||
**Problem**: FastAPI's built-in documentation endpoints (`/docs` and `/redoc`) were not working because they were only enabled when `DEBUG=true`.
|
||||
|
||||
**Root Cause**: In `backend/main.py`, the documentation endpoints were conditionally enabled:
|
||||
```python
|
||||
docs_url="/docs" if settings.DEBUG else None,
|
||||
redoc_url="/redoc" if settings.DEBUG else None,
|
||||
```
|
||||
|
||||
**Solution**: Removed the conditional logic to always enable documentation endpoints:
|
||||
```python
|
||||
docs_url="/docs",
|
||||
redoc_url="/redoc",
|
||||
```
|
||||
|
||||
**Verification**:
|
||||
- `/docs` endpoint returns HTTP 200 with Swagger UI
|
||||
- `/redoc` endpoint returns HTTP 200 with ReDoc documentation
|
||||
- `/openapi.json` provides the OpenAPI schema
|
||||
- Root endpoint correctly lists documentation URLs
|
||||
|
||||
User notes:
|
||||
Backend and backend docs seem to be in a good state.
|
||||
Let us focus on frontend for a bit.
|
||||
Task 1:
|
||||
There are UI elements which shift on mouseover. This is bad design.
|
||||
Task 2:
|
||||
The default page should show just the prompt in the most recent position in history. It currently does a draw from the pool, or possibly displays the most recent draw action. Drawing from the pool should only happen when requested by the user.
|
||||
On the default page there should be some sort of indication of how full the pool is. A simple graphical element would be nice. It should only show one writing prompt.
|
||||
Task 3:
|
||||
Check whether the UI buttons to refill the pool and to draw from the pool have working functionality.
|
||||
Task 4:
|
||||
Change the default number drawn from the pool to 3.
|
||||
|
||||
43
README.md
43
README.md
@@ -177,6 +177,49 @@ Edit `data/settings.cfg` to customize:
|
||||
- Number of prompts per session
|
||||
- Pool volume targets
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Docker Permission Issues
|
||||
If you encounter permission errors when running Docker containers:
|
||||
|
||||
1. **Check directory permissions**:
|
||||
```bash
|
||||
ls -la data/
|
||||
```
|
||||
The `data/` directory should be readable/writable by your user (UID 1000 typically).
|
||||
|
||||
2. **Fix permissions** (if needed):
|
||||
```bash
|
||||
chmod 700 data/
|
||||
chown -R $(id -u):$(id -g) data/
|
||||
```
|
||||
|
||||
3. **Verify Docker user matches host user**:
|
||||
The Dockerfile creates a user with UID 1000. If your host user has a different UID:
|
||||
```bash
|
||||
# Check your UID
|
||||
id -u
|
||||
|
||||
# Update Dockerfile to match your UID
|
||||
# Change: RUN useradd -m -u 1000 appuser
|
||||
# To: RUN useradd -m -u YOUR_UID appuser
|
||||
```
|
||||
|
||||
### npm Build Errors
|
||||
If you see `npm ci` errors:
|
||||
- The Dockerfile uses `npm install` instead of `npm ci` for development
|
||||
- For production, generate a `package-lock.json` file first:
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
```
|
||||
|
||||
### API Connection Issues
|
||||
If the backend can't connect to AI APIs:
|
||||
1. Verify your API key is set in `.env`
|
||||
2. Check network connectivity
|
||||
3. Ensure the API service is available
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
Run the backend tests:
|
||||
|
||||
@@ -4,6 +4,7 @@ Main application entry point
|
||||
"""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from contextlib import asynccontextmanager
|
||||
@@ -25,9 +26,9 @@ async def lifespan(app: FastAPI):
|
||||
logger.info(f"Debug mode: {settings.DEBUG}")
|
||||
|
||||
# Create data directory if it doesn't exist
|
||||
data_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data")
|
||||
os.makedirs(data_dir, exist_ok=True)
|
||||
logger.info(f"Data directory: {data_dir}")
|
||||
data_dir = Path(settings.DATA_DIR)
|
||||
data_dir.mkdir(exist_ok=True)
|
||||
logger.info(f"Data directory: {data_dir.absolute()}")
|
||||
|
||||
yield
|
||||
|
||||
@@ -39,8 +40,8 @@ app = FastAPI(
|
||||
title="Daily Journal Prompt Generator API",
|
||||
description="API for generating and managing journal writing prompts",
|
||||
version="1.0.0",
|
||||
docs_url="/docs" if settings.DEBUG else None,
|
||||
redoc_url="/redoc" if settings.DEBUG else None,
|
||||
docs_url="/docs",
|
||||
redoc_url="/redoc",
|
||||
lifespan=lifespan
|
||||
)
|
||||
|
||||
@@ -67,7 +68,8 @@ async def root():
|
||||
"name": "Daily Journal Prompt Generator API",
|
||||
"version": "1.0.0",
|
||||
"description": "API for generating and managing journal writing prompts",
|
||||
"docs": "/docs" if settings.DEBUG else None,
|
||||
"docs": "/docs",
|
||||
"redoc": "/redoc",
|
||||
"health": "/health"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
[
|
||||
"Describe preparing and eating a meal alone with the attention of a sacred ritual. Focus on each step: selecting ingredients, the sound of chopping, the aromas, the arrangement on the plate, the first bite. Write about the difference between eating for fuel and eating as an act of communion with yourself. What thoughts arise in the space of this deliberate solitude?",
|
||||
"Recall a rule you were taught as a child\u2014a practical safety rule, a social manner, a household edict. Examine its original purpose. Now, trace how your relationship to that rule has evolved. Do you follow it rigidly, have you modified it, or do you ignore it entirely? Write about the journey from external imposition to internalized (or rejected) law."
|
||||
"You discover an old list you wrote—a grocery list, a packing list, a list of goals. Analyze it as a archaeological fragment. What does the handwriting, the items chosen, the crossings-out reveal about a past self's priorities and state of mind? Reconstruct the day or the trip or the aspiration it belonged to. Now, write a new list for your current self, but in the style and with the concerns of that past version. How do the two lists diverge?",
|
||||
"Describe a minor phobia or irrational aversion you have—perhaps to a specific texture, sound, or insect. Personify this fear. Give it a shape, a voice, a ridiculous costume. Have a conversation with it. Ask it what it's trying to protect you from. Is it a misguided guardian? A relic of a forgotten trauma? By making it concrete and almost comical, does its power mutate from a looming shadow into a manageable, if annoying, companion?",
|
||||
"Recall a moment of profound boredom—waiting in a long line, sitting through a dull lecture, a rainy Sunday with nothing to do. Instead of framing it as wasted time, explore it as a fertile void. What thoughts, memories, or creative impulses began to bubble up from the stillness when external stimulation was removed? Describe the architecture of this empty space. Is boredom a necessary algorithm for defragmenting the mind, forcing it to generate its own content?",
|
||||
"Examine a scar on your body, physical or emotional. Describe its topography. How did you acquire it? What was the healing process like? Now, imagine this scar is not a flaw, but a unique topographic feature on the map of you—a canyon, a ridge, a river delta. What stories does this landform tell about resilience, survival, and change? How does reframing a mark of damage as a feature of interest alter your relationship to it?",
|
||||
"You are given a box of assorted, unrelated buttons. Sort them. Do you organize by color, size, material, number of holes? Describe the satisfying, pointless algorithm of categorization. As you sort, let your mind wander. What memories are attached to buttons—a lost coat, a grandmother's sewing kit, a uniform? Write about the small, tactile pleasures of order imposed on randomness, and the unexpected pathways such a simple task can open in the mind."
|
||||
]
|
||||
12
data/prompts_pool.json.bak
Normal file
12
data/prompts_pool.json.bak
Normal file
@@ -0,0 +1,12 @@
|
||||
[
|
||||
"Choose a simple, repetitive manual task—peeling vegetables, folding laundry, sweeping a floor. Perform it with exaggerated slowness and attention. Describe the micro-sensations, the sounds, the rhythms. Now, imagine this task is a sacred ritual being performed for the first time by an alien anthropologist. Write their field notes, attempting to decipher the profound cultural meaning behind each precise movement. What grand narrative might they construct from this humble algorithm?",
|
||||
"Recall a time you successfully comforted someone in distress. Deconstruct the interaction as a series of subtle, almost imperceptible signals—a shift in your posture, the timbre of your voice, the choice to listen rather than speak. Map this non-verbal algorithm of empathy. Which parts felt instinctual, and which were learned? How did you calibrate your response to their specific frequency of pain? Write about the invisible architecture of human consolation.",
|
||||
"Find a view from a window you look through often. Describe it with intense precision, as if painting it with words. Now, recall the same view from a different season or time of day. Layer this memory over your current perception. Finally, project forward—imagine the view in ten years. What might change? What will endure? Write about this single vista as a palimpsest, holding the past, present, and multiple possible futures in a single frame.",
|
||||
"Contemplate a personal goal that feels distant and immense, like a quasar blazing at the edge of your universe. Describe the qualities of its light—does it offer warmth, guidance, or simply a daunting measure of your own distance from it? Now, turn your telescope inward. What smaller, nearer stars—intermediate achievements, supporting habits—orbit within your local system? Write about navigating by both the distant, brilliant ideal and the closer, practical constellations that make up the actual journey.",
|
||||
"Listen to a recording of a voice you love but haven't heard in a long time—an old answering machine message, a voicemail, a clip from a home movie. Describe the auditory texture: the pitch, the cadence, the unique sonic fingerprint. Now, focus on the silence that follows the playback. What emotional residue does this recorded ghost leave in the room? How does the preserved voice, trapped in digital amber, compare to your memory of the living person?",
|
||||
"You discover an old list you wrote—a grocery list, a packing list, a list of goals. Analyze it as a archaeological fragment. What does the handwriting, the items chosen, the crossings-out reveal about a past self's priorities and state of mind? Reconstruct the day or the trip or the aspiration it belonged to. Now, write a new list for your current self, but in the style and with the concerns of that past version. How do the two lists diverge?",
|
||||
"Describe a minor phobia or irrational aversion you have—perhaps to a specific texture, sound, or insect. Personify this fear. Give it a shape, a voice, a ridiculous costume. Have a conversation with it. Ask it what it's trying to protect you from. Is it a misguided guardian? A relic of a forgotten trauma? By making it concrete and almost comical, does its power mutate from a looming shadow into a manageable, if annoying, companion?",
|
||||
"Recall a moment of profound boredom—waiting in a long line, sitting through a dull lecture, a rainy Sunday with nothing to do. Instead of framing it as wasted time, explore it as a fertile void. What thoughts, memories, or creative impulses began to bubble up from the stillness when external stimulation was removed? Describe the architecture of this empty space. Is boredom a necessary algorithm for defragmenting the mind, forcing it to generate its own content?",
|
||||
"Examine a scar on your body, physical or emotional. Describe its topography. How did you acquire it? What was the healing process like? Now, imagine this scar is not a flaw, but a unique topographic feature on the map of you—a canyon, a ridge, a river delta. What stories does this landform tell about resilience, survival, and change? How does reframing a mark of damage as a feature of interest alter your relationship to it?",
|
||||
"You are given a box of assorted, unrelated buttons. Sort them. Do you organize by color, size, material, number of holes? Describe the satisfying, pointless algorithm of categorization. As you sort, let your mind wander. What memories are attached to buttons—a lost coat, a grandmother's sewing kit, a uniform? Write about the small, tactile pleasures of order imposed on randomness, and the unexpected pathways such a simple task can open in the mind."
|
||||
]
|
||||
@@ -43,23 +43,12 @@ services:
|
||||
build: ./frontend
|
||||
container_name: daily-journal-prompt-frontend
|
||||
ports:
|
||||
- "3000:80" # Production
|
||||
- "3001:3000" # Development
|
||||
- "3000:80" # Production frontend on nginx
|
||||
volumes:
|
||||
- ./frontend:/app
|
||||
- /app/node_modules
|
||||
environment:
|
||||
- NODE_ENV=${NODE_ENV:-development}
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: ./frontend/src
|
||||
target: /app/src
|
||||
ignore:
|
||||
- node_modules/
|
||||
- dist/
|
||||
- action: rebuild
|
||||
path: ./frontend/package.json
|
||||
- NODE_ENV=${NODE_ENV:-production}
|
||||
depends_on:
|
||||
backend:
|
||||
condition: service_healthy
|
||||
@@ -74,7 +63,7 @@ services:
|
||||
target: builder
|
||||
container_name: daily-journal-prompt-frontend-dev
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "3001:3000" # Development server on different port
|
||||
volumes:
|
||||
- ./frontend:/app
|
||||
- /app/node_modules
|
||||
|
||||
5
frontend/.astro/settings.json
Normal file
5
frontend/.astro/settings.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"_variables": {
|
||||
"lastUpdateCheck": 1767467593775
|
||||
}
|
||||
}
|
||||
1
frontend/.astro/types.d.ts
vendored
Normal file
1
frontend/.astro/types.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="astro/client" />
|
||||
@@ -6,7 +6,8 @@ WORKDIR /app
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci
|
||||
# Use npm install for development (npm ci requires package-lock.json)
|
||||
RUN npm install
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
1
frontend/src/env.d.ts
vendored
Normal file
1
frontend/src/env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
12
test_docker_build.sh
Executable file
12
test_docker_build.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test Docker build for the backend
|
||||
echo "Testing backend Docker build..."
|
||||
docker build -t daily-journal-prompt-backend-test ./backend
|
||||
|
||||
# Test Docker build for the frontend
|
||||
echo -e "\nTesting frontend Docker build..."
|
||||
docker build -t daily-journal-prompt-frontend-test ./frontend
|
||||
|
||||
echo -e "\nDocker build tests completed."
|
||||
|
||||
Reference in New Issue
Block a user