Getting Started
Requirements
- GitHub and Vercel accounts.
- A LINE Developers Messaging API channel.
- An OpenAI Platform API key with API billing.
- SerpAPI for default-on search (or set
ENABLE_SEARCH=false) and an optional Vercel Blob store for GPT Image. - Required in 6.0: Supabase Postgres; Google Calendar/Tasks also need a Google Cloud project and OAuth client.
Deploy to Vercel
- Fork SanHsien/gpt-ai-assistant.
- Import the fork into Vercel.
- Add at least these environment variables:
APP_DEBUG=false
OPENAI_API_KEY=...
LINE_CHANNEL_ACCESS_TOKEN=...
LINE_CHANNEL_SECRET=...
- Set the LINE webhook URL to your stable Vercel domain plus
/webhook. - Enable Use webhook and disable LINE Auto-reply and Greeting messages.
- Verify the webhook and test a text message.
LINE_CHANNEL_SECRET must not be empty. The service intentionally fails closed when it is missing.
Optional LINE rich menu
Quick replies appear with bot messages as one horizontally scrollable row. For a persistent two-row launcher on mobile, create a large 3×2 rich menu manually in LINE Official Account Manager. This is optional channel configuration and needs no environment variable.
| Top left | Top center | Top right | Bottom left | Bottom center | Bottom right |
|---|---|---|---|---|---|
Add eventSchedule | My eventsMy events | WeatherWeather | Add taskAdd task | My tasksMy tasks | MoreCommand |
Use text actions for all six areas. Keep it collapsed by default for chat-first use or expanded for newcomer discovery. Do not configure matching keyword Auto-replies, which may reply alongside the webhook bot. Rich menus appear only on iOS/Android LINE, not Windows/macOS; a Messaging API per-user/default rich menu can also override the Manager default. See LINE's quick-reply guide, rich-menu overview, and rich-menu API reference.
Enable image generation
The default gpt-image-2 model returns base64 data:
- Connect a private Vercel Blob store to the project.
- Vercel normally injects
BLOB_STORE_IDand uses OIDC. - If logs report
No blob credentials found, addBLOB_READ_WRITE_TOKENas a fallback.
The application uploads privately and gives LINE a temporary signed URL. Do not change the store to public.
Configure the durable-only runtime and events
- Create Supabase Postgres and use its serverless transaction-pooler URL.
- Add
DATABASE_URL,DATABASE_SSL_CA, andDATA_ENCRYPTION_KEYto Vercel Production as Sensitive variables. - Put those three values in the fork's untracked local
.env, then runnpm ciandnpm run db:migratefrom the repository root. - Run
npm run db:preflight, then verify thatschema_migrationsends at0019_calendar_sync_query_version.sql. The runner records SHA-256 checksums and safely skips matching migrations. - Enable
ENABLE_SCHEDULE=true,ENABLE_TASKS=true, andENABLE_WEATHER=trueas needed, then redeploy. Version 6.0 always uses the durable queue and has noAPP_WEBHOOK_QUEUEflag.
Migration 0010 adds weather subscriptions, 0011 Google Tasks outbound, 0012/0013 Calendar inbound, 0014/0016 Tasks inbound, 0015/0017 consolidate reminder indexes, 0018 moves bot-source activation to Postgres, and 0019 versions Calendar inbound for non-expanded series sync. Apply migrations before deploying 6.0.
Before enabling ENABLE_GOOGLE_TASKS=true, enable Google Tasks API in the same Google Cloud project that owns the Web OAuth client; granting the Tasks scope does not enable the API. Existing Calendar-only users must run "Connect Google Calendar" again to grant the scope. If sync previously failed because the API was disabled, enable it and reconnect; rc.5 safely revives the same dead sync job without creating another task.
Enable the per-minute worker and due reminders
- Generate a random
REMINDER_CRON_SECRETof at least 32 characters and store it as a Vercel Production Sensitive variable. - Temporarily set the same secret, database settings, and
REMINDER_CRON_URL=https://your-production-domain/cron/reminderslocally. - Run
npm run db:configure-reminders. It stores the URL and secret in Supabase Vault and schedules a per-minute Cron call. The worker drains reminders, Google Calendar retries, and final status delivery. - Set
ENABLE_REMINDERS=trueand redeploy. Timed events remind at their start; all-day events remind at 09:00. - In Supabase Cron Jobs/History, verify that
gpt-ai-assistant-remindersis active and successfully calls Production every minute.
Reminder delivery uses LINE Push and counts against the monthly quota. Never paste the secret into SQL, documentation, issues, or chat.
Reminder preferences include the localized commands for pause, resume, and quiet hours such as 22:00-07:00. Reminders due while paused are skipped rather than backfilled; resuming affects future due reminders.
Enable Google Calendar
- In the Google Cloud project that owns the Web OAuth client, enable Google Calendar API and separately enable Google Tasks API when task synchronization is wanted. Verify both under Enabled APIs and services. Configure an External OAuth consent screen. Testing can use an allowlisted test user, but Calendar grants and refresh tokens expire after seven days. Publish a persistent deployment as In Production. A personal-use app with fewer than 100 users may remain unverified, with an unverified-app warning and a 100-new-user cap.
- Create a Web application OAuth client. Set the authorized redirect URI to
https://your-production-domain/oauth/google/callback. - Add
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET, andGOOGLE_OAUTH_REDIRECT_URIto Vercel Production as Sensitive variables. - Verify
0004_google_calendar.sql; Tasks outbound additionally needs0011, Tasks inbound needs0014/0016, and Calendar inbound needs0012/0013/0019. - Set
ENABLE_GOOGLE_CALENDAR=true; optionally setENABLE_GOOGLE_TASKS=trueandENABLE_GOOGLE_CALENDAR_INBOUND=true, then redeploy. - Send
Connect Google Calendarin LINE and use the authorization button. Reconnect whenever a new scope is enabled so Tasks authorization and backfill can run. - Keep the per-minute worker enabled for retries, final status delivery, and Calendar inbound polling. Inbound changes normally appear within about five to six minutes.
Never put real keys, client secrets, database URLs, CAs, encryption keys, or tokens in docs, issues, commits, or chat transcripts.
Production checklist
- The stable root URL returns
200with the expected version. - LINE webhook verification succeeds and a text message receives one reply.
schema_migrationsends at the repository's latest migration, and Supabase Cron History succeeds every minute.- Production was redeployed after every environment change, with no DB TLS, OAuth, or cron
401/503errors. - Reconnect Google in LINE, then create one test event and one test task; verify exactly one item in Google Calendar and Google Tasks respectively.
AI-operated LINE PC acceptance
The maintainer may explicitly authorize an AI agent to operate the LINE Windows client for the final Production round trip. This is supervised desktop acceptance, not a fixed macro suitable for blind CI replay: every action must rediscover and activate the single intended LINE window, locate controls from a fresh screen capture, send one message, and verify the bot response before the next state transition.
Create an acceptance manifest first with the time window, unique prefixes, local audio paths, and resulting data IDs. Cross-check LINE results in Google Calendar/Tasks, Supabase jobs, and Vercel logs. After release, review the entire release cycle rather than only the last successful batch: remove precisely identified events, tasks, confirmations, related jobs/runs/processed events, and local temporary audio, then check for pending reminders whose event no longer exists. Preserve recurring inbound cron/cursor history, real data, and platform-controlled logs, and never claim that uncontrollable traces were erased.
See the authoritative docs/DEVELOPMENT.md runbook.
Local development
Node.js 24 is required to match CI, Vercel, and the Docker image.
git clone https://github.com/SanHsien/gpt-ai-assistant.git
cd gpt-ai-assistant
npm ci
cp .env.example .env
npm run dev
Expose port 3000 through an HTTPS tunnel for LINE webhook testing. Before submitting changes, run:
npx eslint .
npm test
The repository includes a Node 24 Dockerfile and Compose setup. Create an untracked .env from .env.example, fill every required value, then run docker compose up --build --detach; Compose injects that file and defaults a missing or blank APP_PORT to 3000. The image installs production dependencies only, runs as a non-root user, and includes a /health/live healthcheck. Confirm healthy with docker compose ps, then open http://127.0.0.1:3000/health/live. restart: unless-stopped only restarts an exited main process; it does not recycle a container solely because it is unhealthy, so automatic recovery requires platform/orchestrator monitoring. Containers still require a public HTTPS webhook, Supabase, and the same LINE/OpenAI credentials.
Updates
Vercel redeploys when the connected main branch is pushed. Review the application changelog and redeploy after changing environment variables.