diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..75492b7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,117 @@ +# Changes + +## v0.1.16 — 2026-06-16 + +- Fixed `resolvePersona()` to reject unknown persona IDs (misspellings now return + "Unknown persona" instead of saving) +- Updated Shakespeare persona to William Shakespeare himself with iambic pentameter +- Removed `/ai model` commands (model selection is admin-only via System Console) +- Removed persona description truncation in list output + +## v0.1.15 — 2026-06-16 + +- Updated Shakespeare persona description + +## v0.1.14 — 2026-06-16 + +- Removed model switching commands from help text and handler + +## v0.1.13 — 2026-06-16 + +- Removed `/resetmatty` slash command (redundant with `/ai new`) +- Wrapped persona list output in code block for proper Mattermost formatting + +## v0.1.12 — 2026-06-16 + +- Rewrote help text with grouped sections (Chat, Personas, Other) +- Updated title to "Matty -- forkless' annoying sidekick" + +## v0.1.11 — 2026-06-16 + +- Fixed persona override bug — KV override value is now resolved through + `resolvePersona()` before being used as the system prompt + +## v0.1.10 — 2026-06-16 + +- Added `/ai persona ` command to switch personas (persisted to KV store) +- Added `/ai persona` to show current active persona +- Added `/ai persona list` to list all personas with descriptions +- Added Debug Logging toggle (bool setting in System Console) +- Wrapped all LogInfo calls with DebugLogging check +- Added Ollama API call body logging (model, URL, full JSON payload) +- Context trimming: Brevity now limits how much conversation history is sent +- Token auto-calculation: Brevity auto-calculates `num_predict` for Ollama + +## v0.1.9 — 2026-06-16 + +- Updated Trump persona with vocabulary of a 12 year old + +## v0.1.8 — 2026-06-16 + +- Added context trimming based on Brevity setting (fewer sentences = less history) +- Adjusted token auto-formula to `100 + brevity * 75` + +## v0.1.7 — 2026-06-16 + +- Added Ollama API call logging (model, URL, full request body) +- Fixed OllamaClient to accept log function from plugin API +- Updated infomercial persona to remove conflicting "BUT WAIT THERE'S MORE" +- Added `"Config loaded"` error logging on configuration failures + +## v0.1.6 — 2026-06-16 + +- Stable persona IDs (short IDs like "trump", "carlin" — never change) +- `resolvePersona()` map in server/persona.go +- Full config logging per Chat request (13 fields) +- General instructions added to all personas + +## v0.1.5 — 2026-06-16 + +- Adjusted Brevity auto-token curve +- Added "only respond to latest message" instruction to system prompt + +## v0.1.4 — 2026-06-16 + +- Brevity now more tightly enforced +- Added penalty fields (repeat_penalty, frequency_penalty) as ints divided by 10 + +## v0.1.3 — 2026-06-16 + +- Added EngagementEngine (Sleep/Active states, 5-min timeout) +- Added Persona dropdown with 18 personas + Custom Persona override +- Added Model dropdown with 6 models from the user's Ollama server +- Added Brevity dropdown (1, 2, 3, 5, 10, unlimited) +- Added Repeat Penalty and Frequency Penalty number fields +- Added `/resetmatty` slash command to clear context +- Bot renamed to @matty (was @matterless) +- Bot posts directly to channel (no thread replies) +- Debug logging added (LogInfo for chat requests) +- "Asleep" message when Ollama is unreachable + +## v0.1.2 — 2026-06-16 + +- Fixed Brevity field type (string → int and back to string for dropdown compat) + +## v0.1.1 — 2026-06-16 + +- Fixed config loading by changing RepeatPenalty/FrequencyPenalty from float64 to int +- Added error logging to OnConfigurationChange() +- Config loaded log now shows all settings on save + +## v0.1.0 — 2026-06-16 + +- Project scaffolded: DESIGN.md, PROJECT.md, CHANGES.md, DECISIONS.md, + README.md, .gitignore, Makefile +- Plugin skeleton: main.go, plugin.go, configuration.go, command.go +- Go module initialised with Mattermost SDK dependency +- Ollama client with ChatCompletion and streaming +- Conversation store with KV-backed context +- Rate limiter with configurable requests/minute +- Working @-mention detection via MessageHasBeenPosted +- Slash command handler for /ai +- Bot account auto-creation via API.CreateBot() +- Stop word matching for natural disengagement +- Streaming Ollama responses into channel posts +- dev/docker-compose.yml with Mattermost 11.6.1 + PostgreSQL 16 +- DESIGN.md with @-mention interaction model +- go-standards skill created in skill tree diff --git a/CHANGES.md b/CHANGES.md deleted file mode 100644 index ad3ace7..0000000 --- a/CHANGES.md +++ /dev/null @@ -1,7 +0,0 @@ -# Changes - -## v0.1.0 — 2026-06-16 - -- Project scaffolded: DESIGN.md, PROJECT.md, CHANGES.md, DECISIONS.md, - README.md, .gitignore -- No functional code yet — this is the pre-implementation skeleton diff --git a/PROJECT.md b/PROJECT.md deleted file mode 100644 index 74d83d8..0000000 --- a/PROJECT.md +++ /dev/null @@ -1,70 +0,0 @@ -# Project: Mattermore - -## Purpose - -Mattermore is a Mattermost (Community Edition) plugin that connects chat to -remote LLMs via Ollama. Users invoke it with a `/ai` slash command and -receive streamed AI responses directly in the channel. - -## Structure - -``` -mattermore/ -├── DESIGN.md — Functional design document -├── DECISIONS.md — Design rationale log -├── PROJECT.md — This file -├── CHANGES.md — Per-release changelog -├── README.md — User-facing docs -├── plugin.json — Mattermost plugin manifest -├── Makefile — Build, lint, dist targets -├── .gitignore — Go + plugin ignores -├── server/ -│ ├── main.go — Plugin entry point (OnActivate, ExecuteCommand) -│ ├── plugin.go — Core plugin struct and hooks -│ ├── configuration.go — Config reading and validation -│ ├── command.go — Slash command parsing and dispatch -│ ├── ollama/ -│ │ ├── client.go — Ollama API client (ChatCompletion, ListModels, Ping) -│ │ └── client_test.go — Unit tests (mocked HTTP server) -│ ├── store/ -│ │ ├── conversation.go — KV-backed conversation storage -│ │ └── conversation_test.go -│ └── rate/ -│ └── limiter.go — Token-bucket rate limiter -└── webapp/ (future — optional) - └── .placeholder -``` - -## Key Files - -| Path | Purpose | -|---|---| -| `plugin.json` | Manifest: id, name, version, settings schema | -| `server/main.go` | `OnActivate()`, `OnDeactivate()`, `ExecuteCommand()` | -| `server/ollama/client.go` | HTTP client for Ollama REST API | -| `server/store/conversation.go` | Context persistence via Mattermost KV store | -| `DESIGN.md` | Full functional design with open decisions | -| `DECISIONS.md` | Record of architectural decisions and their rationale | - -## External Dependencies - -- **Go ≥ 1.21** (toolchain) -- **Mattermost Server ≥ v8.x** (plugin API) -- **Ollama** (remote inference server) -- Go modules (see `go.mod`): - - `github.com/mattermost/mattermost-server/v6` — Plugin SDK - - Standard library only for Ollama HTTP client (no external AI SDKs) - -## Release Cadence - -- Tags: `v0.x.y` -- CI builds on tag (see `.gitea/workflows/ci.yml`) -- Plugin bundle published as Gitea release artifact -- Follows `release-workflow` skill: draft → user test → publish - -## Documentation - -- `DESIGN.md` — functional design (living document) -- `DECISIONS.md` — why key decisions were made -- `CHANGES.md` — user-facing changelog -- `README.md` — quick start, config reference, build instructions diff --git a/DECISIONS.md b/docs/DECISIONS.md similarity index 100% rename from DECISIONS.md rename to docs/DECISIONS.md diff --git a/DESIGN.md b/docs/DESIGN.md similarity index 100% rename from DESIGN.md rename to docs/DESIGN.md diff --git a/docs/PROJECT.md b/docs/PROJECT.md new file mode 100644 index 0000000..1886d37 --- /dev/null +++ b/docs/PROJECT.md @@ -0,0 +1,77 @@ +# Project: Matty + +## Purpose + +Matty is a Mattermost (Community Edition) plugin that connects chat to +remote LLMs via Ollama. Users address the bot by **@-mentioning** it in any +channel (e.g. `@matty write a poem`). The bot responds only when addressed +and disengages naturally. Follow-up messages continue the conversation +without re-@mentioning while the session is active. + +## Structure + +``` +mattermore/ +├── plugin.json — Mattermost plugin manifest (v0.1.x) +├── Makefile — Build, lint, dist targets +├── .golangci.yml — Linter configuration +├── CHANGELOG.md — Per-release changelog +├── README.md — User-facing docs +├── DESIGN.md — Functional design document +├── DECISIONS.md — Design rationale log +├── PROJECT.md — This file +├── .gitignore — Go + plugin ignores +├── dev/ +│ ├── docker-compose.yml — Local Mattermost + PostgreSQL test rig +│ └── init.sh — Admin auto-creation script +├── server/ +│ ├── main.go — plugin.ClientMain entry point +│ ├── plugin.go — Plugin struct with all fields +│ ├── hooks.go — OnActivate, MessageHasBeenPosted, streaming +│ ├── command.go — /ai and subcommands, persona override +│ ├── configuration.go — Config struct, validation, OnConfigurationChange +│ ├── ollama.go — OllamaClient (streaming + blocking chat) +│ ├── store.go — ConversationStore (KV-backed context) +│ ├── rate.go — RateLimiter (per-user token bucket) +│ ├── engagement.go — EngagementEngine (sleep/active states) +│ └── persona.go — PersonaLibrary with 19 personas +└── dist/ + └── com.forkless.mattermore-*.tar.gz +``` + +## Key Files + +| Path | Purpose | +|---|---| +| `plugin.json` | Manifest with 12 configurable settings | +| `server/hooks.go` | Core interaction logic (@-mention detection, streaming) | +| `server/command.go` | `/ai` and `/ai persona` commands | +| `server/ollama.go` | HTTP client for Ollama REST API | +| `server/store.go` | Context persistence via Mattermost KV store | +| `server/engagement.go` | Active session tracking (5-min timeout) | +| `server/persona.go` | 19 personas with stable short IDs | +| `server/configuration.go` | 12 settings, validation, debug logging | +| `DESIGN.md` | Full functional design (up to date with v0.1.16) | +| `CHANGELOG.md` | All versions from v0.1.0 to v0.1.16 | +| `dev/docker-compose.yml` | Disposable Mattermost + PostgreSQL test rig | + +## External Dependencies + +- **Go ≥ 1.21** (toolchain) +- **Mattermost Server ≥ v11.6** (plugin API) +- **Ollama** (remote inference server, any version) +- Go modules (see `go.mod`): + - `github.com/mattermost/mattermost/server/public` — Plugin SDK + +## Release Cadence + +- Tags: `v0.x.y` +- Built manually via `make dist`, uploaded via System Console +- No CI/CD pipeline yet + +## Documentation + +- `docs/DESIGN.md` — full functional design with architecture, interaction model +- `docs/DECISIONS.md` — why key decisions were made +- `CHANGELOG.md` — per-version changelog (17 releases) +- `README.md` — quick start, config reference, build instructions diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 0000000..0480217 --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,50 @@ +# Security — Matty AI Chat Agent + +## Ollama Network Exposure + +Matty connects to an Ollama server to run LLM inference. **Ollama does not +natively support authentication, TLS, or access control.** If exposed to the +public internet, anyone who knows your Ollama URL can: + +- Run inference on your models (costly and potentially abusive) +- Access any model you have pulled +- Potentially execute arbitrary code through model exploits + +### Recommendations + +**DO NOT expose your Ollama server directly to the public internet.** + +Instead, access it through one of these methods: + +1. **Private network** — Run Ollama on the same LAN/VLAN as your Mattermost + server. No public exposure needed. + +2. **WireGuard / Tailscale tunnel** — If Mattermost and Ollama are on + different networks, use a WireGuard or Tailscale tunnel between them. + No public ports required. + +3. **Reverse proxy with IP allowlist** — If a tunnel isn't possible, + put Ollama behind a reverse proxy (nginx, Caddy, HAProxy) that: + - Restricts access to the Mattermost server's IP address only + - Terminates TLS (Ollama doesn't support HTTPS natively) + - Logs all access for auditing + +4. **SSH tunnel** — For temporary access: `ssh -L 11434:localhost:11434 user@ollama-host` + +### Plugin Configuration + +The `OllamaURL` setting in the System Console accepts `http://` or `https://` +URLs. The plugin validates the scheme at config load and rejects invalid URLs. +TLS verification is enabled by default. + +## Other Security Considerations + +- **User access**: Restrict bot usage to specific Mattermost user IDs via + the `AllowedUserIDs` setting in the System Console (empty = all users). +- **Rate limiting**: Set `RateLimitPerMinute` to prevent abuse (0 = unlimited). +- **Stop words**: The bot disengages on configurable stop words ("thanks", + "bye", "stop") to prevent unintended continued conversation. +- **Logging**: Enable Debug Logging only during troubleshooting — it logs + full conversation content and Ollama API requests. +- **Plugin updates**: Upload plugin bundles from trusted sources. Verify + integrity via your Gitea release artifacts.