Skip to content

Commit

Permalink
Removed feedback button expiry/reset, and a number of squashed messag…
Browse files Browse the repository at this point in the history
…es (#1)

* Removed feedback button expiry/reset

Early in development, I came under the impression that the initial
interaction token for a discord interaction, meant that updates couldn't
be made to the interaction, even in response to a component button
click. I tried using the component interaction's token, and the
original interaction token, and both failed. Turns out, I need to
use the "Update" interaction type, rather than attempting to edit
it, or defer it + respond.

So, the feedback system's been updated to remove the Undo/Reset button,
and to never set buttons as disabled. Now, the number of `UserFeedback`
entries by type are counted for the associated `ChatCommand`, and
the button labels are updated to reflect the number of times they've
been selected. Also, except for the "Other" modal, a user clicking
the same feedback button more than once has no effect.

Updated `README.md` and tests to reflect this

Minor bugfixes, cleanup, expanded tests

Fixed an issue where `DisConcierge.requestQueue.requestCh` could
panic due to sending on a closed channel, in cases where `Run()` was
stopped via context and then started again in the same process.

Added tests to expand coverage

Removed `ChatCommand.mu` as it was basically vestigial

Simplified `DisConcierge.Run` and `DisConcierge.shutdown`

Updated the frontend `ChatCommand` model to reflect the newly-removed
feedback columns

Cleaning up config, interrupt/resume handling, shutdowns, etc

Fixed an issue where a `CreateRun()` call that returned an error due
to the context being cancelled, would cause a `ChatCommand` to report
as failed, and not resume after a restart.

Fixed an issue where a `ChatCommand` that had an associated OpenAI
run wouldn't resume on restart, if the bot started again later than
`max_age`, but before the discord interaction token expired, causing
the interaction to show the 'thinking...' message permanently, instead
of polling for the final run status.

Switched the app config to only work off envvars and dotenv files,
which should simplify configuration and  make it more consistent
when defining things in dockerfiles or compose.

Simplified/tidied up the shutdown logic/ordering, and updated
the HTTP servers to hard-close on shutdown timeout

Bumped up the default TLS version for the HTTP servers

Moved `APIConfig.Development` onto the top-level `Config` struct

Removed some unused structs and moved some magic durations into
variables/consts

Fixed an issue where an invalid webhook server public key would
cause startup to fail, even if the webhook server was disabled

Improved propagation of shutdown signals, fixed some bugs, added tests

Fixed an issue where a runtime update via the API would cause the
bot's discord status to be updated twice

Added `context.Context` to all `DBI` interface functions

Added a new `ShutdownError` type that's used with `context.CancelCause`
to signal to slash commands that `ctx.Err()` shouldn't cause the
command to be marked as failed, for cases where the bot is interrupted.

Fixed a broken tes

I updated the `ChatCommand` resume query, which caused a test to
fail. I updated the "resume" on init to set `expired` on any incomplete
commands with an expired interaction token, except for those which
would get picked up by the 'update run' process

Fixed a bug with user feedback notifications

Feedback notifications (to a configured channel ID) could exceed
the discord message size limit, and fail to be delivered

Also fixed some error shadowing

Fixed a race condition with notifications as well

Updated `isShutdownErr` to more reliably catch the shutdown signal

Re-added some discord ack context, added more context-specific options

New views, simplified config, and other things

Updated the API and webhook servers so that SSL is optional, for
cases where there might be termination at a load balancer. Also updated
`SSLConfig` to support loading certs from both files and envvars
(so `SSL_CERT` and `SSL_KEY` now accept the cert data, while
`SSL_CERT_FILE` and `SSL_KEY_FILE` take file paths). I've also
removed the `LISTEN_NETWORK` option, since I haven't tested running
the bot with unix sockets anyway.

Added `APIConfig.ExternalURL` to help build admin interface URLs to
database records. Related to that, I've also updated the user feedback
discord notifications to just report the user, feedback type, and
links to the `ChatCommand` and `UserFeedback` UI records, instead of
cramming all of the detail into the discord message.

Also related to that, I've added a `UserFeedback` detail view, and
updated the `UserFeedbackList` to link both to the detail view, and
the `ChatCommand` view, via their IDs in the table.

Reworked the 'initial setup' process, so now it's done via a new
`init` CLI command (ex `disconcierge init`), which creates/migrates
the DB, and prompts for user credentials. Removed the API-side
pending setup hold and UI views.

DB migrations no longer happen every time the bot starts, to avoid
potential weirdness when multiple bots are starting up while connected
to the same DB

Cleanup, cleanup, cleanup

Did a LOT of cleanup, moving tests around to where they make sense,
re-ordering functions, types, adding docstrings, etc.

Also replaced the temporary `nil` contexts with `context.TODO`

Also updated the front-end to remove some deprecated 'setup' stuff

Minor... things.

Set default logging levels to WARN

Fixed a reversed `gin.Mode` setting

Re-added `pprof` which I accidentally removed

Added tests, minor cleanup

Added a test for the `init` CLI command

Removed  the healthcheck endpoint- I'll re-add it when I decide on a
good way to actually detect the bot is 'healthy' (aka not partially
deadlocked or something)

Fixed an issue where multiple HTTP responses were sent after an
initial failed login

Removed some unused variables, fields

* Added static file so the build works without the frontend

* Fixed a broken test

Not sure why it broke, something odd must have happened when
I squashed

* Increased a test's timeout

* Added reset to CLI tests

Added `viper.Reset()` to tests, because the wrong string representation
was sticking around between tests
  • Loading branch information
arcward authored Sep 22, 2024
1 parent 26b72e3 commit f508ba0
Show file tree
Hide file tree
Showing 69 changed files with 5,977 additions and 7,869 deletions.
134 changes: 134 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#
# General/database config
#

# Database connection string
DC_DATABASE=/home/foo/disconcierge.sqlite3

# Specifies the type of database, either 'sqlite' or 'postgres'
DC_DATABASE_TYPE=sqlite

DC_DATABASE_LOG_LEVEL=INFO
DC_DATABASE_SLOW_THRESHOLD=200ms
DC_LOG_LEVEL=INFO

# Sets a limit on the amount of time the bot has to initialize/start running
DC_STARTUP_TIMEOUT=30s

# Time to allow for a graceful shutdown
DC_SHUTDOWN_TIMEOUT=60s

# Development, if true, has the following affects:
#
# For the backend API:
# - The `gin.Recovery` middleware will **not** be used, allowing
# panics to bubble up to the caller.
# - The session cookie's SameSite attribute will be set to None.
# - If `api.cors.allow_origin` isn't set, it will be set to "*".
# - pprof will be enabled at `/debug`
#
# For the webhook server (if enabled):
# - The `gin.Recovery` middleware will **not** be used
DC_DEVELOPMENT=true

#
# In-memory ChatCommand queue config
#

# Maximum queue size. 0=unlimited
DC_QUEUE_SIZE=100

# Maximum age of a request that will be returned from the queue. Requests older than this will be discarded. 0=unlimited
DC_QUEUE_MAX_AGE=3m

# Sleep for this duration when the queue is empty, before checking again
DC_QUEUE_SLEEP_EMPTY=1s

# Sleep for this duration when the bot is paused, before checking again
DC_QUEUE_SLEEP_PAUSED=5s

#
# OpenAI config
#

# OpenAI API token
DC_OPENAI_TOKEN=your-assistant-token

# ID specifying which OpenAI assistant to use
DC_OPENAI_ASSISTANT_ID=asst_byFzFiJ9P4IEzrLEOigAuppS

DC_OPENAI_LOG_LEVEL=INFO

#
# Discord bot config
#

DC_DISCORD_TOKEN=your-discord-bot-token
DC_DISCORD_APPLICATION_ID=your-discord-bot-app-id

# GuildID specifies the guild ID used when registering slash commands. Leave empty for commands to be registered as global.
DC_DISCORD_GUILD_ID=

DC_DISCORD_LOG_LEVEL=WARN
DC_DISCORD_DISCORDGO_LOG_LEVEL=WARN

# Message sent to the notification channel when the bot connects to the discord gateway.
# Only applies when a notification channel ID is set in the admin interface.
DC_DISCORD_STARTUP_MESSAGE="I'm here!"

# Discord gateway intents (see https://discord.com/developers/docs/topics/gateway#gateway-intents)
DC_DISCORD_GATEWAY_INTENTS=3243773

#
# Discord webhook server
#

# Determines if the webhook server should be active
DC_DISCORD_WEBHOOK_SERVER_ENABLED=false

# The public key used for verifying Discord interaction requests
DC_DISCORD_WEBHOOK_SERVER_PUBLIC_KEY=your_discord_bot_public_key

DC_DISCORD_WEBHOOK_SERVER_LISTEN=127.0.0.1:5001
DC_DISCORD_WEBHOOK_SERVER_LISTEN_NETWORK=tcp
DC_DISCORD_WEBHOOK_SERVER_SSL_CERT_FILE=/etc/ssl/cert.pem
DC_DISCORD_WEBHOOK_SERVER_SSL_KEY_FILE=/etc/ssl/cert.key

# 772 = TLS13
DC_DISCORD_WEBHOOK_SERVER_SSL_TLS_MIN_VERSION=772

DC_DISCORD_WEBHOOK_SERVER_LOG_LEVEL=INFO
DC_DISCORD_WEBHOOK_SERVER_READ_TIMEOUT=5s
DC_DISCORD_WEBHOOK_SERVER_READ_HEADER_TIMEOUT=5s
DC_DISCORD_WEBHOOK_SERVER_WRITE_TIMEOUT=10s
DC_DISCORD_WEBHOOK_SERVER_IDLE_TIMEOUT=30s

# API server

DC_API_EXTERNAL_URL=https://127.0.0.1:5000
DC_API_LISTEN=127.0.0.1:5000
DC_API_LISTEN_NETWORK=tcp
DC_API_SSL_CERT_FILE=/etc/ssl/cert.pem
DC_API_SSL_KEY_FILE=/etc/ssl/key.pem
DC_API_SSL_TLS_MIN_VERSION=771

# Secret used for signing cookies
DC_API_SECRET=your-api-secret

DC_API_LOG_LEVEL=INFO

# Allow origins/methods/headers and expose headers are space-delimited lists

DC_API_CORS_ALLOW_ORIGINS=https://127.0.0.1:5000 https://localhost:5000
DC_API_CORS_ALLOW_METHODS=GET POST PUT PATCH DELETE OPTIONS HEAD
DC_API_CORS_ALLOW_HEADERS=Origin Content-Length Content-Type Accept Authorization X-Requested-With Cache-Control X-CSRF-Token X-Request-ID
DC_API_CORS_EXPOSE_HEADERS=Content-Type Content-Length Accept-Encoding X-Request-ID Location ETag Authorization Last-Modified
DC_API_CORS_ALLOW_CREDENTIALS=true
DC_API_CORS_MAX_AGE=12h
DC_API_READ_TIMEOUT=5s
DC_API_READ_HEADER_TIMEOUT=5s
DC_API_WRITE_TIMEOUT=10s
DC_API_IDLE_TIMEOUT=30s

# Session cookie max age, for the admin interface
DC_API_SESSION_MAX_AGE=6h
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,5 @@ go.work
*.sqlite3
files/
data/
disconcierge.yaml
disconcierge.yaml
.env
44 changes: 31 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,41 +55,59 @@ ENV REACT_APP_API_PORT=5000
ENV DC_DATABASE_TYPE=sqlite
ENV DC_DATABASE=/data/disconcierge.sqlite3
ENV DC_DATABASE_SLOW_THRESHOLD="200ms"
ENV DC_DEVELOPMENT="false"
ENV DC_STARTUP_TIMEOUT="60s"
ENV DC_SHUTDOWN_TIMEOUT="60s"
ENV DC_RECOVER_PANIC="true"

ENV DC_DISCORD_TOKEN=""
ENV DC_DISCORD_APPLICATION_ID=""
ENV DC_OPENAI_TOKEN=""
ENV DC_OPENAI_ASSISTANT_ID=""


ENV DC_API_LISTEN=":5000"
ENV DC_API_SECRET=""
ENV DC_API_DEVELOPMENT="true"
ENV DC_API_CORS_ALLOW_ORIGINS=""
ENV DC_API_CORS_ALLOW_METHODS="GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD"
ENV DC_API_CORS_ALLOW_HEADERS="Origin,Content-Length-Content-Type,Accept,Authorization,X-Requested-With,Cache-Control,X-CSRF-Tokens,X-Request-Id"
ENV DC_API_CORS_EXPOSE_HEADERS="Content-Type,Content-Length,Accept-Encoding,X-CSRF-Token,Authorization,X-User-Agent,X-Grpc-Web,X-Request-Id,ETag,Last-Modified"
ENV DC_API_CORS_ALLOW_METHODS="GET POST PUT PATCH DELETE OPTIONS HEAD"
ENV DC_API_CORS_ALLOW_HEADERS="Origin Content-Length-Content-Type Accept Authorization X-Requested-With Cache-Control X-CSRF-Tokens X-Request-Id"
ENV DC_API_CORS_EXPOSE_HEADERS="Content-Type Content-Length Accept-Encoding X-CSRF-Token Authorization X-User-Agent X-Grpc-Web X-Request-Id ETag Last-Modified"
ENV DC_API_CORS_ALLOW_CREDENTIALS="true"
ENV DC_API_CORS_MAX_AGE="24h"
ENV DC_API_SSL_KEY="/data/cert.key"
ENV DC_API_SSL_CERT="/data/cert.pem"
ENV DC_API_SSL_KEY_FILE="/data/cert.key"
ENV DC_API_SSL_CERT_FILE="/data/cert.pem"
ENV DC_API_EXTERNAL_URL=""

ENV DC_DISCORD_TOKEN=""
ENV DC_DISCORD_APPLICATION_ID=""
ENV DC_DISCORD_GUILD_ID=""
ENV DC_DISCORD_NOTIFICATION_CHANNEL_ID=""
ENV DC_STARTUP_TIMEOUT="60s"
ENV DC_SHUTDOWN_TIMEOUT="60s"
ENV DC_RECOVER_PANIC="true"

ENV DC_DISCORD_WEBHOOK_SERVER_ENABLED="false"
ENV DC_DISCORD_WEBHOOK_SERVER_PUBLIC_KEY=""
ENV DC_DISCORD_WEBHOOK_SERVER_LISTEN=":5001"
ENV DC_DISCORD_WEBHOOK_SERVER_LISTEN_NETWORK="tcp"
ENV DC_DISCORD_WEBHOOK_SERVER_SSL_CERT_FILE="/data/cert.key"
ENV DC_DISCORD_WEBHOOK_SERVER_SSL_KEY_FILE="/data/cert.pem"

ENV DC_DISCORD_WEBHOOK_SERVER_SSL_TLS_MIN_VERSION=771

ENV DC_DISCORD_WEBHOOK_SERVER_LOG_LEVEL=INFO
ENV DC_DISCORD_WEBHOOK_SERVER_READ_TIMEOUT=5s
ENV DC_DISCORD_WEBHOOK_SERVER_READ_HEADER_TIMEOUT=5s
ENV DC_DISCORD_WEBHOOK_SERVER_WRITE_TIMEOUT=10s
ENV DC_DISCORD_WEBHOOK_SERVER_IDLE_TIMEOUT=30s

ENV DC_QUEUE_SIZE="100"
ENV DC_QUEUE_MAX_AGE="3m"
ENV DC_QUEUE_SLEEP_EMPTY="1s"
ENV DC_QUEUE_SLEEP_PAUSED="5s"


ENV DC_LOG_LEVEL="INFO"
ENV DC_OPENAI_LOG_LEVEL="INFO"
ENV DC_DISCORD_LOG_LEVEL="INFO"
ENV DC_DISCORD_LOG_LEVEL="WARN"
ENV DC_DISCORD_DISCORDGO_LOG_LEVEL="WARN"
ENV DC_API_LOG_LEVEL="INFO"
ENV DC_DATABASE_LOG_LEVEL="INFO"
ENV DC_DATABASE_LOG_LEVEL="WARN"


EXPOSE 5000
Expand Down
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ LDFLAGS := -X main.Version=$(VERSION) -X main.CommitSHA=$(COMMIT_SHA) -X main.Bu


.PHONY: all
all: build

.PHONY: install-frontend
install-frontend:
Expand Down
Loading

0 comments on commit f508ba0

Please sign in to comment.