enhancement
major
minor
defect
critical
major
minor
major
#30166
TL Chat: runPageCommand gives the model the refusal of a page command in English instead of the user's language
Problem
ChatCommandTool.reasons (#30149) resolves the refusal of a page command with Resources.getInstance(Locale.ENGLISH). The refusal is the application's text about the user, the same one the button shows, and it names places of the UI. A German user is then told by the agent "You are a member of no tenant. The git connections of all tenants are managed under "Tenants"", although the ResKey has a German text and the UI says "Mandanten" (tl-factory, Gitea TopLogic/tl-factory #42).
The article ai/development already separates a tool's own text (English) from "text that is about the user and is meant to reach them through the model" (translated). Other places resolve application messages in the user's language (TransactionScope.describeVeto, TLScriptExecutor, AttributeValues); ObjectEditTool.english does not.
Change
ChatCommandTool.reasons and ObjectEditTool resolve application messages they relay in the language of the run's user (the run thread carries the user's sub-session); the tool's own framing stays English. ai/development states this for refusals and validation messages a tool relays.
Test
ChatCommandTool with a command whose executability refuses with a ResKey having @en and @de, run in a German sub-session: the result holds the German text inside the English framing.
Lösung
- An application refusal a tool relays to the model is a structured result in which only the application's messages are prose, in the language of the run's user (Resources.getInstance()), and nothing else wraps them: no English sentence around a translated message.
- Shape (msgbuf, com.top_logic.tl.ai.core.tools.refusal.messages): ApplicationRefusal with refused, what was refused as identifiers (command, object, type), reasons (Reason: optional object, place, attribute, and text - the application's message) and mandatory (MandatoryAttributes: type, attributes). ApplicationRefusals builds it, resolves a ResKey in the user's language and writes the JSON; its DESCRIPTION explains the format in the English tool descriptions. Example: {"refused":true,"command":"connectGit","reasons":[{"text":"Sie sind Mitglied keines Mandanten. ..."}]}.
- Used for the reasons a page command is not executable (ChatCommandTool), the application's veto against a deletion and the constraint violations of an edited or created object (ObjectEditTool, ObjectConstraints, also reported by ChangeDataTool / ChangeReport), and a refused commit: TransactionScope delivers the reasons of a failed commit as a list (CommitFailedException.reasons()), and the notice of the agent loop to the model is English prose followed by the refusal JSON.
- The article ai/development describes the rule: application messages a tool relays go into dedicated fields of a structured result in the user's language; the tool's own prose stays English and never wraps them.
- Tests take their texts from test resource bundles (testTlAiCoreMessages, testTlChatMessages) and assert on the parsed result in a German context: a refused page command, a deletion veto, a constraint violation, a refused commit.