mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-06 04:23:15 -05:00
A person can now choose four save levels on the Memory tab: Save it and tell me, Ask me first (the default), Always confirm and Never. Always confirm is like ask, and nothing can loosen it: no agent or messaging setting overrides it, and the model cannot undo or forget a note by itself (revert_change is refused, and the person uses the Undo). One function, effectiveSaveLevel, combines the rules. The strictest wins, in the order auto, ask, always, never. The inputs are the level of the person, the rule of the saved agent, the messaging row and the chat. A table test covers every combination. A saved agent has an optional memory_save field: always or never. It can only be stricter than the person, so auto is not offered and the API refuses it. A write without the field keeps the stored rule, and use_mine clears it. It is stored by both stores and is part of an agent export and import. The agent form shows three cards under When it wants to save a note. The new row In messaging apps (messaging_save on GET and PUT /api/chats/memory) takes ask (the default), paired_private or never. With paired_private a note is saved at once only when the sender is paired and the chat is one-to-one, and it goes to the notes of that conversation, with an Undo. The limits stay: five notes a reply, the size limit, and a note that looks like a secret still waits. The row cannot loosen the level of the person when that is always or never. A setting that cannot be read reads as ask. The connector turn now carries whether the chat is one-to-one and whether the sender is paired, in the turn grant and in the worker JSON. Both read as false when unknown. The Telegram, Slack and Discord transports already set Direct; new specs pin it for private, group and supergroup chats, direct messages, channels, group conversations and threads. A note from a messaging chat goes to the conversation first. It reaches the notes of the agent or of the person only from a paired sender, only when the memory choice of the agent allows that scope, and only after that sender confirms it. Under Always confirm only the paired sender who asked can confirm. An agent whose memory is None still saves nothing. The script of the confirm-in-chat specs now proposes a note for the conversation, because a sender who is only listed cannot write to the notes of the person. Assisted-by: Claude:claude-sonnet-5-5
47 lines
2.1 KiB
Go
47 lines
2.1 KiB
Go
package workerctl
|
|
|
|
// ChatStartRequest is the payload of a chat start: a frontend asks a chat
|
|
// worker to run the next turn of an unattended chat (a trigger run, a job or a
|
|
// connector message). The worker reads the chat, its owner and its model from
|
|
// the shared database, so the request names only the chat and the message.
|
|
type ChatStartRequest struct {
|
|
// Principal is the owner of the chat as the chats service names it.
|
|
Principal string `json:"principal"`
|
|
ChatID string `json:"chat_id"`
|
|
Text string `json:"text"`
|
|
// Grant is set for a connector message: what the sender of the turn may
|
|
// do. The worker keeps it for the turn, so a tool it builds is offered
|
|
// only for the capabilities in it. A start without a grant for a connector
|
|
// chat gets none of the gated tools.
|
|
Grant *ChatGrant `json:"grant,omitempty"`
|
|
}
|
|
|
|
// ChatGrant is the outcome of the permission check for the senders of one
|
|
// connector turn (see studio.Authorize). It holds IDs, never message text.
|
|
type ChatGrant struct {
|
|
Binding string `json:"binding"`
|
|
Kind string `json:"kind,omitempty"`
|
|
Senders []string `json:"senders,omitempty"`
|
|
Roles []string `json:"roles,omitempty"`
|
|
// Caps are the capabilities every sender of the turn holds.
|
|
Caps []string `json:"caps,omitempty"`
|
|
// Denied says why a capability in the ceiling is not held, by name.
|
|
Denied map[string]string `json:"denied,omitempty"`
|
|
// Direct says the chat is one-to-one and Paired that the sender is paired
|
|
// with the bot. A grant from an older frontend has neither, which reads as
|
|
// a group chat and an unpaired sender.
|
|
Direct bool `json:"direct,omitempty"`
|
|
Paired bool `json:"paired,omitempty"`
|
|
}
|
|
|
|
// ChatStartReply is the worker's answer to a ChatStartRequest. With Error
|
|
// empty, Started says whether the message began a turn on the worker;
|
|
// otherwise a turn was running, and the message waits under PendingID. A
|
|
// non-empty Error is the worker's refusal: the worker is present, and nothing
|
|
// started.
|
|
type ChatStartReply struct {
|
|
Started bool `json:"started,omitempty"`
|
|
PendingID string `json:"pending_id,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|