Per-provider state used to live as flat keys in [ai] with naming
conventions to avoid collisions: <name>_url, <name>_models,
<name>_default_model, and the bare <name> for the API token. Custom
settings (/ai set custom) never made it to disk at all — they only
lived in the runtime AIProvider.settings hash table and were lost on
restart.
Move every per-provider field into a [ai/<name>] subsection of the
keyfile with stable key names:
[ai/openai]
url=https://api.openai.com/
key=sk-...
default_model=gpt-4
models=gpt-4;gpt-3.5-turbo
setting.tools=enabled
[ai] now keeps only the global "defaults_initialized" sentinel.
Migration runs once in _prefs_load: collect provider names from the
old <name>_url keys, then move url/models/default_model/token of each
provider into its subsection and drop the flat keys. Idempotent on
subsequent loads.
prefs_ai_* API surface kept compatible; storage backend changes only.
Adds:
prefs_ai_remove_section() — wipe whole subsection in one call
prefs_ai_{set,get,remove,list}_setting() — persist custom settings
ai_client wiring:
- ai_set_provider_setting now writes to prefs as well as the runtime
hash table; ai_client_init loads them back on startup.
- ai_remove_provider replaces four prefs_ai_remove_* calls with a
single prefs_ai_remove_section.
- Persist per-provider default model in [ai] prefs (set/get/remove
helpers, load on init, clear with provider removal). Previously
/ai set default-model only updated runtime state.
- Stop re-seeding openai/perplexity into [ai] every time the configured
provider list is empty. The defaults are now seeded once, guarded by
a "defaults_initialized" sentinel, so removing every provider does
not silently restore them.
- /ai providers (no arg) now lists the configured providers with key
status, instead of the hardcoded openai/perplexity blurb.
- /ai models <provider> (fresh fetch) prints the model names it cached,
not just a count. Previously the user had to follow up with --cached
to actually see them.
- /ai remove provider now also clears the persisted default model,
token, and cached model list, leaving no orphan keys in [ai].
- Drop dead ai_models_find declaration from ai_client.h (no
implementation in this tree).
Fix /ai set provider <name> <url> not persisting across restarts.
- Add prefs_ai_set_provider(), prefs_ai_remove_provider(),
prefs_ai_get_provider_url(), prefs_ai_list_providers(),
prefs_free_ai_providers(), and prefs_ai_get_default_provider_url()
to preferences.h/c for provider persistence.
- Move default provider URL definitions (openai, perplexity) from
ai_client.c to preferences.c, following the established pattern
where defaults are returned as fallbacks when no config value exists.
- Modify ai_add_provider() to persist new/updated providers to config.
- Modify ai_remove_provider() to remove provider from config.
- Add internal _ai_add_provider_nopersist() helper for adding default
providers and loading from config without double-persisting.
- Update ai_client_init() to load custom providers from config on
startup, allowing users to override defaults or add new ones.
Users now have full control: default providers remain as fallbacks,
user-added providers persist to config, and users can override or
remove defaults freely.
- Introduce model caching with persistence to preferences
- Add provider default model and custom settings management
- Implement `/ai switch`, `/ai models`, and improve `/ai start`
- Add model name autocomplete for chat commands
- Update command definitions and help text
- Add unit tests for new functionality
Add an AI client module that integrates with OpenAI-compatible API
providers (OpenAI, Perplexity, and custom providers) to provide
AI-assisted responses within the profanity client.
The implementation includes:
- src/ai/ai_client.c/h: Core AI client with provider management,
session handling, and async HTTP request handling via libcurl.
Supports per-provider API keys stored in preferences, reference-
counted sessions, and conversation history tracking.
- src/ui/window.c/window_list.c: New AI window type (ProfAiWin) for
displaying AI conversations, with response streaming and error
display capabilities.
- Command integration: New `/ai` command (cmd_defs.c, cmd_funcs.c)
for creating sessions, sending prompts, and managing providers.
Provider autocomplete support in cmd_ac.c.
- Preferences integration: API keys for providers are persisted in
the preferences system (config/preferences.c).
- Unit tests: 472 lines of comprehensive tests covering provider
management, session lifecycle, JSON escaping, and autocomplete
(tests/unittests/test_ai_client.c).
Architecture decisions:
- Asynchronous design: HTTP requests run on a separate thread to
avoid blocking the main UI loop. Callbacks are invoked on the main
thread via direct function call (profanity uses ncurses, not GLib
main loop).
- Reference counting: Both AIProvider and AISession use ref counting
for safe shared ownership.
- Response size limit: 10MB cap on HTTP responses to prevent OOM.
Implement /force-encryption command to configure forced encryption
settings with on|off and policy resend-to-confirm|block options.
The changes enhance user experience by clarifying encryption requirements
and providing actionable commands. Users can now press Enter again to
confirm unencrypted messages in resend-to-confirm mode.
Commit to allow unicode support in omemo/pgp/otr chars misses
adding support to set correction character.
1f8b1eb740
Further fixing commit also misses adding support to set the unicode character,
it only adds ability to display unicode correction character in the settings.
5cf6ee15cf6ee1bc6d0b99b01891bc455a657bf022a72b0
Add ability to completely turn logs off,
Needed since `/logging` and `/history` didn't stop history logging
in the DB, only in files.
Command might break something on usage,
hence it was primarily introduced for privacy geeks.
Privacy command discussion #1836
Refactor `p_gpg_list_keys`
Add `/pgp autoimport` command,
it's not described in XEP-0027, but used in some clients,
such as PSI, Pidgin. It will autoimport keys received with
`/pgp sendpub`, in plain text as a message, or using features,
provided in other clients. It doesn't autoassign them, but shows
command to assign, letting user to decide.
Improve documentation for some preexisting functions
Add contact argument to `/pgp sendpub`
The existing way how active tabs are displayed didn't allow showing more
than 10 tabs. This patch adds a mode where the statusbar shows a
comma-separated list of tabs which were active since the last time viewed.
This view is inspired by how `irssi` shows the active tabs, therefore
it is also called `actlist`.
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
Only nicknames, photos, birthdays, addresses, telephone numbers, emails,
JIDs, titles, roles, notes, and URLs are supported
Due to the synopsis array not having enough space, `/vcard photo
open-self` and `/vcard photo save-self` are not documented properly in
the synopsis section of the `/vcard` command, but they are documented in
the arguments section
Fixed memory leak in vcard autocomplete (thanks to debXwoody)
This and the following commits should make a couple of more configs
allow utf8 chars so people can use their weird icons :-)
We did the same for the otr/omemo/pgp indicators at:
1f8b1eb7405cf6ee1bc6
I feel like this mostly is confusing people.
Also don't see much value for it.
To me it looks like a regular workflow is like:
```
/plugin install ~/src/profanity-plugins/my.py
```
The whole thing with sourcepath, install (which also loads without
having that described anywhere), load etc is confusing.
Also each plugin file that is present in
`.local/share/profanity/plugins` will then be auto loaded. Which means
after installation.
Old: `/intype on|of`
Typing information is printed in console and titlebar.
New: `/intype titlebar|console on|off`
Typing information can be configured in more detail.
Regards https://github.com/profanity-im/profanity/issues/1516