Skip to content

Configuration ​

Every setting lives in Settings, a published property you can fill at design time, in code, or from a JSON file. The file is what lets an installed application be changed without a new build: the API key, the model, even moving the engine to a server.

helpchatai.json ​

With ConfigFileName empty (the default) the component merges, in this order, on activation:

#FileMeant for
1%APPDATA%\HelpChatAI\helpchatai.jsonSettings shared by every HelpChatAI application of this user — typically the API key
2helpchatai.json next to the executableWhat the application ships or what IT deploys
3%APPDATA%\<YourApp>\helpchatai.jsonThis application, this user: wins over the others

Only the keys present in a file are applied, so each file can carry just what it needs to change.

One file instead of three ​

Name a file in ConfigFileName and that file is the configuration: the three above are not read at all. A relative path is resolved against the executable.

pascal
HelpChatAI.ConfigFileName := 'config\helpchatai.json';

A file named here and not found raises EHelpChatConfigError when the component activates. That is deliberate: an application that asked for a configuration and quietly runs without it is an application shipped with the wrong settings, and nobody finds out until a customer does.

json
{
  "Provider": "claude",
  "Language": "it",
  "DocIndexFile": "help-index.json",
  "DocBaseUrl": "https://help.mycompany.com/myapp/",
  "Claude": {
    "ApiKey": "sk-ant-...",
    "Model": "claude-haiku-4-5",
    "GroundingMaxPages": 3
  }
}

One section per model provider — Claude, OpenAI, Gemini — all with the same keys, plus the few that belong to one of them (Claude.ApiVersion, the OpenAI.Azure* trio). Only the section of the configured Provider is read, and an empty Model or BaseUrl means the default of that provider, so a file that never mentions them keeps following the library.

Never ship a file with a key in it

helpchatai.json is in the repository's ignore list for a reason, and the installer excludes it from what it packages. A key in an installer is a key on every customer's disk.

The settings that matter most ​

SettingDefaultWhat it does
ProviderstubWhich provider answers
LanguagehclAutoInterface and reply language: auto (OS locale), en, it
Greeting(localized)The first bubble of an empty conversation
DocIndexFilehelp-index.json next to the exeThe documentation index
DocBaseUrl(empty)Prefix of the documentation links
PersistConversationTrueSave and restore the conversation between runs
ConversationMaxAgeDays30Older saved conversations are discarded
MaxStoredMessages200Kept in the store (older ones are pruned)
HistoryMaxMessages50Sent to the provider as context
MessageMaxLength4000A user message longer than this is cut
PoolSize2Worker threads answering in parallel

The complete list, with the JSON key of every one of them, is in the Settings reference.

Checking a configuration ​

HelpChatAI.Diagnostics answers "would this work?" without sending a question: it reports the provider (registered? configured?), the documentation index, the folder of the pages, or the server when Settings.Remote names one.

pascal
uses HelpChatAI.Diagnostics;

LIssues := HelpChatCheckSettings(HelpChat1.Settings);
if HelpChatHasErrors(LIssues) then
  ShowMessage(HelpChatIssuesToText(LIssues));

What a provider needs is the provider's own business: the check asks it through ConfigurationIssue instead of knowing about it, so a provider of yours is checked like the built-in ones. The same code runs behind Check configuration... in the component editor.

Where files are written ​

FileWhereWhat
helpchatai-conversation.json%APPDATA%\<YourApp>\The saved conversation
helpchatai-ui.json%APPDATA%\<YourApp>\Position and size of the chat window
WebView2\%APPDATA%\<YourApp>\The WebView2 user data folder

Nothing is written to the installation folder, so the application runs under a limited account.

Changing settings at runtime ​

Settings are snapshotted per request: a provider works on a private copy, so changing Provider or Model while a reply is streaming does not corrupt it — the change applies to the next message. That is how the demo can switch provider from a combo box while the chat is open.

pascal
HelpChatAI.Settings.Provider := ProviderCombo.Text;   // next question uses it

Reading and writing the file from code ​

pascal
HelpChatAI.Settings.LoadFromFile('C:\Deploy\helpchatai.json');
HelpChatAI.Settings.SaveToFile(THelpChatSettings.UserConfigFile);   // %APPDATA%\<YourApp>\

THelpChatSettings.SharedUserConfigFile, AppConfigFile and UserConfigFile give you the three standard locations, so an "advanced settings" dialog of yours can write the right one.

Moving the engine to a server ​

The same file decides where the engine runs:

json
{
  "Remote": {
    "BaseUrl": "https://help.acme.com",
    "AppKey": "the-key-of-this-application",
    "UserId": ""
  }
}

With a BaseUrl the component talks to a HelpChatAI server instead of running the engine in process — no recompilation, no code change.

Released under the Apache License 2.0