The connector spec "keeps asking when the setting is ..." read the tool
results as soon as the bot had an answer. The harness records a result
after it emitted the turn events, so under load the answer could come
first and the list was empty. The spec now waits for the result.
Shutdown left two background writers running: the file text indexer loop
ran on the application context, and the chat search backfill had no stop.
A test that removed its temp directory right after Shutdown could meet a
write into the "textindex" folder ("directory not empty"). The indexer
loop now has its own context and Shutdown waits for it, and the chat
store gets a Close that stops the backfill and waits.
Assisted-by: Claude:claude-sonnet-5-5
The Memory add-on only declared three index files, two skills and a save
setting; the host did the rest. Without the add-on a memory proposal
worked but nothing was read back, and removing the add-on silently reset
the save level.
The host now loads the three indexes (user, agent, conversation) with
the same caps and data wrapping, serves context_read, ships the two
skills as built-in skills with the same text, and keeps the save level
as its own per-person setting (ask, auto, never; default ask). The code
sits behind a small MemoryProvider interface.
The add-on stays installed and harmless: its index files and skills are
ignored while the host serves memory, so nothing loads twice. A person
who chose a level on its page keeps it until they choose in the host
setting; auto still needs the add-on to run. A person who disabled the
add-on and never chose keeps memory off. Saved agents still read notes
only when their add-ons list names memory, and messaging chats still
ask before saving.
A person with no note and no add-on gets no extra block in the prompt.
Assisted-by: Claude:claude-sonnet-5-5
The access view said only that a capability was refused, in free text.
It now reports, for every capability of every kind of sender, the first
link of the permission chain that fails: a closed code, who holds the
link (server, tools, agent, connection, sender), one plain sentence, one
fix as a kind and a stable target, and the links not yet checked. The
chain order is server setting, Tools switch, agent permission, the
permission of the connection, then sender trust. The code is produced
where Authorize and the capability switches decide, so the English
reason and the decision cannot drift apart. The Tools switch of the
agent and the server triggers setting are now switches in that chain.
POST /api/chats/connectors/{id}/access/preview runs the same chain on a
form that is not saved (id "new" works with a kind), optionally for one
kind of sender. It writes nothing, records nothing and never takes or
returns the token.
The held-back note for the model, the tool errors and the trigger tool
reason take their sentence from the same table of codes, in plain words
with no setting names.
Assisted-by: Claude:claude-sonnet-5-5
AuthorizeConnector had no case for the op history, so the default
branch refused it. A mention in a Slack thread then logged "connectors:
forbidden" and the first turn of the new chat got no thread block.
History now follows the rules of a send: the binding is the whole
authority, the token comes from owner storage and a disabled binding
keeps it. Only the poll stops with the binding.
The studio specs ran over a transport that skipped the scope check, so
none of them saw the refusal. The rig now authorizes every call with the
real manager, and a new spec table pins each op of the contract.
Assisted-by: Claude:claude-sonnet-5-5
POST /api/addons/files streams the zip to the owner in chunks over the
host access call, so a frontend of a split deployment keeps no copy and
the owner enforces the size limit while it receives. GET and DELETE read
and remove a staged file. The install is the existing host access
preview and install with sourceId local-file, so it keeps the human
surface rule, the nonce and the digest binding. The install body gains a
downgrade confirmation.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt
The manager takes a staged file as a release: sourceId local-file and
the file ID as the version. It runs through the one lifecycle path, so
generations, backup, recovery and the host access approval apply as for
a library package. The approval digest is the sha256 of the zip.
The same version is refused, and an older one needs a confirmed
downgrade. Files wait in a private per-user staging area for an hour.
An add-on from a file has no library, so no update check answers for it.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt
The document validator requires a blanket grant to name a revision of the
switch in the document. A deployment-fixed mode is never written there,
so its grants have no revision to name. Record them as the grant of the
install or upgrade that made them; the audit line still carries the
blanket tag.
Assisted-by: Claude:claude-sonnet-5-5 go
With authentication off every caller that reaches the port is the same
local owner, and the checks that tell a person from a script are
headers the caller chooses. Any process or agent that could reach the
port could grant host operations, set deny rules and turn the blanket
approval on.
UI host grants are now locked by default in that mode. The policy file
and flags still grant, and every write route answers 403
locked_by_deployment with a sentence that says why. The overview and the
preview carry the lock and its reason for the page. The new flag
--addon-host-ui-grants-without-auth turns the UI grants on knowingly and
logs a startup warning. With sign-in on nothing changes.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt
Staging the grants of an install now goes through Store.UpdateAudited, so
an install fails and the document stays as it was when the audit line
cannot be written.
A write from an API key, an MCP session or a tool call was refused in the
HTTP layer before it reached the owner, so the refusal left no audit line.
The route now hands the refused write to the owner without the human
mark; the owner refuses it and records the credential kind, never the
credential.
Manager.HostGrantsChangedReport names the add-ons the re-sync started or
stopped, and the owner writes a restart-for-grant line for each. The
event constant was never used before.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt
Stage copied the blanket mode that a flag fixes into host-grants.json
at the first install. After the flag was removed the document still
said "any", so the switch stayed on without anyone typing the
confirmation text.
The deployment mode is now applied at read time only. The document keeps
what a person set, and a grant made under the flag records revision 0,
which the validator accepts for a blanket grant of the deployment.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt
A memory note is still a proposal that the person confirms by default.
An add-on can declare the user setting with the role memory.save-mode,
and the person then picks: ask first, save it and tell me, or never.
With auto, a note from the person's own Studio chat is applied at once
through the whole proposal path (grant, gate, checks, rate limit, audit)
and confirmed as the person, so it is one change set that revert_change
and the Undo on the chat restore. The chat shows "Saved to memory" with
Undo and no confirmation card. The record carries auto: true and the
audit says the write was automatic.
Safety rules live in the host. A connector chat always asks, a trigger or
job has no tool, a saved agent cannot widen the choice, and a failure to
read the setting asks. At most 5 notes are saved unasked in a turn; a note
over 4 KiB or one that looks like it holds a secret becomes a normal
proposal. With never the memory kind is hidden from propose_change and a
stray call is refused. Only memory reads the setting.
Assisted-by: Claude:claude-sonnet-5-5 go node playwright
An add-on can declare userSettings in its manifest: a key, the allowed
values and a default. The host keeps each person's answer in the account
database every frontend shares (one file when accounts are off), checks
every write against the declaration, and never asks the add-on.
GET and PUT /api/addons/{id}/user-settings read and write them. A write
needs the person's own browser session, so no API key, model or tool can
change one. A setting may carry a role that the host reads for its own
rules; the host fixes the values and the default of a role so a manifest
cannot loosen it. Pages reach their settings through sdk.userSettings,
which is bound to the add-on that calls it.
Assisted-by: Claude:claude-sonnet-5-5 go node
A chat now enables a set of connections for an add-on whose tools run with
a credential, and the model names one of them in each call. This applies to
every add-on that declares a credential in its manifest.
- The Tools menu row of the add-on lists the connections with a checkbox
each. The saved agent names a set too (an empty set means each chat
chooses). A chat that a connector binding started keeps that binding
alone. With one connection, it is the set. With none enabled, the tools
are not offered.
- With one connection enabled the tools are unchanged. With two or more,
the host adds a required `connection` argument to every tool of the
add-on in the definitions it gives the model: an enum of the connection
names (the display name folded to lower case, digits and hyphens; the
description keeps the display name). The add-on never sees the argument.
- The name is checked against the set the chat has now, not against all the
connections of the person. A missing or unknown name returns a sentence
that lists the allowed names, and nothing is sent. A write tool never runs
without the name. Text in a tool result cannot widen the set, and the
owner checks the chosen binding against the set again.
- The resource list of the named connection is the only one that applies.
Results, the approval card and the text for a pending change name the
connection; the audit line has the binding ID.
- A connection name must be unique per person and add-on among the
credential-only connections, compared by name fold. Older duplicates get
a numeric suffix in the model's list.
- The stored chat, draft and agent values move from one binding ID per
add-on to a list of IDs. A single string is read as a set of one in the
stores and in every request, so older data and clients keep working.
PUT /api/chats/{id}/connections takes `connections`; the older
`connection` field still works.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt ginkgo node eslint playwright swag
Open the grants document and its audit file under the owner state
directory, and make the Authority read them on every call, with the
deployment floor, the deny rules and the blanket switch from the flags.
An unreadable document refuses every operation. Adapt the store to the
manager's GrantStore and the manager to the host access service of the
routes, and wire that service on the owner only. A frontend keeps the
floor and stores nothing.
Add an end-to-end test of install with approval, revoke, deny, a held
upgrade, restart and the split deployment.
Assisted-by: Claude:claude-sonnet-5-5 go
A chat never uses a connection that the host picked for it. For an add-on
whose tools run with the token of a connection (such as GitHub):
- With one connection, it is selected. With several, the Tools menu row
of the add-on has a Connection selector, and until the person picks one
the tools are not offered and the row says so. With none, the row says
so and links to the Connectors page. The choice is stored with the chat
and its draft, like the other switches, and follows a fork, a
sub-agent and the runs of a trigger the chat proposed.
- A saved agent can name its connection per add-on (agent form field, API
field connections). Its chats use it, show it read only and cannot
change it. An agent with no choice follows the same rule as a chat. A
chat that a connector binding started keeps using that binding.
- CredentialFor takes the selected binding and uses only it, so the
resource list of that binding is the only one that applies. A call with
no selected binding is refused with the code select_connection and a
note the model can relay. The first-match code (connectors.Pick) is
removed.
- Tool results and proposal cards say which connection acted, for example
"as Work, repository acme/widgets". A proposal is applied with the
connection it was previewed with. The credential use is logged with the
binding ID.
Contract: the credential slot takes an optional resourceLabel (the word
for the resource in that line). The agent export file does not carry the
connections, since a binding ID belongs to one server.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt ginkgo node playwright protoc swag
A chat on a model whose config has no context_size got a window of zero,
so the harness fell back to its own default for compaction and for the
context meter, while the backend actually runs with its default window.
The meter and the compaction trigger then disagreed with the model.
Report the window that a request can use, the same value that
/v1/models/capabilities gives (backend.EffectiveRequestContextSize). A
model with no local config, such as a remote one, still gives zero.
Assisted-by: Claude:claude-sonnet-5-5 go-test
An administrator can now grant host operations when an add-on is
installed or upgraded. The manager checks the approval against the
package it actually stages: the digest must match, and only operations
the verified manifest declares and the host registers are granted, never
a denied one. A required operation that is neither held nor approved
refuses the install with approval_required, or blocked_by_policy when a
deny rule forbids it. An upgrade that needs more required operations is
held and the old version keeps running. Optional operations are never
granted without approval, and a manifest that asks for fewer operations
shrinks nothing.
Grants are written to a GrantStore before the journal commits the
operation and removed if it fails, and they count only once the
operation completed. Uninstall deletes them after the journal. A start
reconciles the store with the journal. The automatic upgrade never
approves; only the blanket hook of the store can. HostGrantsChanged
stops an add-on that lost a required operation and retries one that was
refused.
Assisted-by: Claude:claude-sonnet-5-5 go
An application a spec starts on its own, such as the isolated ones of
the router specs, took the shared test transport over and pointed its
file transfers at a table with no blob store. Which specs ran before
decided if the file specs of Telegram and Slack passed, and they failed
in CI with "addon owner unavailable". The transport now keeps the table
of the first application.
Assisted-by: Claude:claude-sonnet-5-5 go ginkgo
The broker copied the allowed prefixes when an add-on started, so a
change of grants needed a restart of the add-on. Take an Authority
instead and ask it on each call: a revoke or a deny applies to the next
call, and a call that already runs finishes. A refused call answers the
same text whatever the reason; the reason goes to the log.
The supervisor opens the host endpoint when the add-on holds an
operation or its manifest declares one, so an add-on with an optional
operation and no grant starts degraded and a later grant works at once.
The broker now exists whenever the add-on manager does. The manager,
the apps list and the tool filters read the same Authority, which is the
startup policy until another one is set. Admission also tells a denied
operation from a missing grant.
Assisted-by: Claude:claude-sonnet-5-5 go
Bindings saved before permission enforcement have an empty capability
list, so file upload, triggers, memory and talk-back stay denied until
the owner sets them. Give those bindings the set that "Allow the usual"
grants, one time.
An empty list is stored the same whether the owner never chose or
cleared every switch, so the store keeps a migration record instead of
a flag on each binding. The record is claimed atomically with a lease,
so several frontends starting together run it once, and a finished
record is never claimed again: later empty lists are the owner's choice.
Each binding is written only while it still has no capabilities, so a
save made at the same moment is not overwritten.
Only bindings whose kind is running and lists permissions are changed;
sensitive capabilities are never granted. One log line per binding and
one summary. LOCALAI_SKIP_BINDING_CAPS_MIGRATION skips it.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt protoc
The connector specs broke when bindings began to need a kind, to hold
no capability until the owner enables it, and to move file bytes by
handle only. The Telegram specs now name the kind. The Slack file spec
enables files.upload and pairs the sender, since a sender without a
role needs a pairing to send files. A test transport that can move
files gets the transfer table of the application, so its add-ons
declare the files ability as installed ones do.
Assisted-by: Claude:claude-sonnet-5-5 go ginkgo
A binding needs a kind now, so the route specs name the platform, and
the spec for an offline binding checks that nothing is kept while no
add-on serves the kind.
Assisted-by: Claude:claude-sonnet-5-5 go test
A connector add-on no longer carries file bytes in the connector
envelope. The ops media and send_file need a transfer handle, and the
gateway refuses a call to them without one, or for a kind that declares
no files.
- The manifest field files.transfer, the inline file of a request and
of an answer (ConnectorFile) and the 1 MiB cap
(MaxConnectorFileBytes) are removed. The 2 MiB limit of a connector
call between hosts drops to 1 MiB, because it holds text and no file.
- A kind that declares no files moves no file: the host answers a sender
who attaches one with a plain sentence and does not offer attach_file.
A direction left out of a declared files block still gets the host
ceiling.
- The inline layer is gone from the file limit, from the API
(inline_bytes) and from the Files section of the connector page.
- The Telegram and Slack add-ons keep only the streaming paths. The
tests moved to the handle path, and the studio test rig gives every
connector add-on a table of handles.
Assisted-by: Claude:claude-sonnet-5-5 go test node
No release carried add-ons, so nothing reads older add-on data or
manifests. Delete the code that did.
- Connectors: the kind and the add-on of the Telegram connectors that
core once carried are gone (LegacyAddon, KindTelegram, the stored
binding normalization, the platform titles). A binding needs a kind,
and its add-on is the one that serves the kind. The conversion of the
old agent pool lists every connector as dropped instead of making a
Telegram binding, and its notes say so.
- The library index reads only the id field of an entry, not addonId.
- A host control that has a capability block (the network policy) is
attached by that block alone, not by a tool that replaces bash.
- The Office create tools no longer answer for the argument names of an
earlier schema, and the identity file note about old addresses is
gone.
- The known debt of the provider-name guard drops the entries of the
conversion and of the resource listing shim, and its ceiling goes
from 13 to 5.
Assisted-by: Claude:claude-sonnet-5-5 go test
No release ever shipped add-ons, so there is no installed base on api 1.
The manifest must now declare api {"min": 2, "max": 2}; a manifest with
api 1, no api or a wider range is refused with a message that names the
range.
Every field that was gated on api 2 is now part of the contract, so the
Min*API constants and their gates are gone, and so are HostAPIMin and
the apiMin host field. Three older-manifest shims go with them: the
resource listing the host implied for one add-on, the legacyArgs hint
for arguments an older version of a tool took, and the tests that
checked the gates. All shipped manifests and the test fixtures declare
api 2.
Assisted-by: Claude:claude-sonnet-5-5 go test
A connector add-on that declares files.transfer no longer carries file
bytes in the connector envelope. The host puts a random handle in the
request of the op media (write) or send_file (read), and the add-on
streams the file with two new host operations, connector.file.put and
connector.file.get, in chunks of at most 256 KiB.
The process that runs the add-on registers the handle when the call
arrives and ends it when the call returns. A handle is bound to the
add-on, so another add-on gets the same answer as for an unknown
handle. An unfinished inbound file is dropped with its partial bytes,
and a handle with no call for two minutes expires. Inbound bytes go
to the blob store of the workspace, outbound bytes come from it, so a
cluster needs the shared object store and no shared disk. The file is
never held in memory. The host overwrites the size and hash of an
inbound file with its own record.
The change is additive: the field files.transfer needs manifest API 2,
a kind without it keeps the inline path and its 1 MiB cap, and the host
never sends it a handle. A call that carries a handle may run up to 15
minutes. The ceiling of a file also stays under the largest file of a
workspace.
Assisted-by: Claude:claude-sonnet-5-5 go test
A write tool of an add-on that holds a credential was protected only by
the write mode of the connection and the confirmation of the proposal.
In a connector chat it now also needs the capability tools.write for the
sender of the turn, through the same Authorize path as the other
capabilities: the tool is not offered without it, a call is checked again
and every decision is audited. The default is no.
The rule is by shape, not by name. The manifest says an add-on holds a
credential, and contract.ToolPermission maps its non-read tools to
tools.write. The chat reads the permission from the tool definition, so
the core names no add-on.
Also close a hole in local-owner mode, where a chat turn and the browser
share one credential: a proposal that waits for a person could be
confirmed from a chat turn. The call of a chat tool now carries a mark,
and the owner refuses to confirm such a proposal under it. A remote owner
does not see the mark; local-owner mode has no remote owner.
Assisted-by: Claude:claude-sonnet-5-5 go test
A connection now has a write mode, chosen on the add-on page: off (the
default), propose (each change waits for the person to confirm) or auto
(a chat of the person makes it at once). The host enforces it for every
write tool of an add-on that holds a credential, before the add-on is
called, and holds the call to the repository list of the connection.
Host:
- Binding.WriteMode, stored in both stores and in the connector API
(write_mode). Absent means off, so existing bindings stay read only.
- A credentialed add-on may declare write tools. They name the resource
with the credential slot argument, never resourceId. A tool can set
approval "always", a ceiling that keeps a proposal even in auto.
- The proposal broker fetches the credential for the preview and again
for the apply, so it is never stored. A mode lowered between the
proposal and the confirmation refuses the apply. A proposal that
awaits a person cannot be confirmed by a chat turn.
- New capability name tools.write for the roles a connector kind
declares.
Add-on, tools (kind write): comment-issue, comment-pr, create-issue,
edit-issue (title, close or reopen), add-labels, review-comment-pr.
They preview plain facts, refuse a stale target, cap and screen the
text for secrets, and keep a receipt journal plus a hidden marker in the
text, so a change whose answer was lost is not sent twice.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt ginkgo node
The four document skill names were code in the contract, the hint for
binary files kept its own list of formats and libraries, and the chat
boundary rewrote the old arguments of one add-on by its ID.
A skill that shadows a name can now declare the slot it serves: kind,
file extensions, name words and a library hint. A tool can declare
legacyArgs, the arguments it refuses now, each with a hint. Both need
manifest api 2. The four default slots move to a data file that the
contract reads, so a manifest that declares nothing keeps working.
The host takes the replaceable names, the files a skill covers and the
hint for a script from the skills the add-ons list. It compares no
format or add-on ID. A guard spec fails when it does again. The Office
manifest declares its slots and legacy arguments and accepts api 2.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt
A connector chat whose sender holds talkback.channels gets the tool
send_message. It writes in the conversation, or as a new top-level
message in a channel that the owner listed on the binding (id, label,
approved; at most 10). The tool names no platform.
An unlisted channel is refused and the error lists the ones that are.
A listed channel that the owner did not approve needs the sensitive
talkback.new_channel for each message, so only a paired sender can use
it. The agent cannot add or approve a channel, so text it read in a page
or a file cannot widen where it writes.
Messages go through the outbox (rate limit and queue), with the size cap
and the mention breaking. Each attempt adds an audit row with channel,
kind, capability, length and a hash, never the text.
A trigger can report to an approved channel with delivery target
channel. The binding, the capability and the listing are checked again
when the run ends; any failure sends the notice to the Inbox.
LOCALAI_DISABLE_CONNECTOR_TALKBACK turns both off.
Assisted-by: Claude:claude-sonnet-5-5 go swag
The previous commit was made on a stale base and so reverted work that
landed on master before it. This commit puts every file back to the
state of its parent's parent. The permission enforcement of the
previous commit stays.
Assisted-by: Claude:claude-sonnet-5-5 go
The capabilities, role grants and pairing that a connector binding
stores now decide what a sender can make the agent do.
Authorize is one pure function: the capability must be in the owner's
ceiling for the binding and the sender must be on the allowlist. A
sensitive capability then needs a paired sender; roles never count for
it. Any other capability needs a pairing or a role that the owner
granted and that the kind lists. The default is no.
Each message gets a grant for its sender. A message that joins a
running turn narrows it to what both senders may do. The tool builder
offers a gated tool only for a held capability, and the tool checks
again when the model calls it, so a call that gets through is refused
with the reason. Today this covers propose_change (memory and profile
kinds), revert_change, the trigger tools, and files sent to the bot. A
chat worker gets the grant with the start request.
The capability gate that the trigger features ask is now answered by
Authorize, and the application sets it. Other features can add a
global switch with AddCapabilitySwitch.
Every use records an allow or deny row (time, binding, sender IDs,
roles, capability, result; no text or codes). GET
/api/chats/connectors/{id}/access returns the effective permissions
per kind of sender and the latest rows, for an add-on settings page.
A binding saved before this change has no capabilities, so its senders
lose these features until the owner enables them.
Assisted-by: Claude:claude-sonnet-5-5 go swag
The Tools menu of a chat listed a ninth built-in group, "changes", by its
raw ID with no text, and only some rows said what a switch did. The
registry now carries a title, a description of what the model can do when
the group is on, and what happens when it is off, for every group. Groups
that nobody described fall back to the label and description of their
first tool, so a new tool group needs no change in the interface.
An add-on row can show the title and description its manifest declares:
the broker may implement the optional AddonLister, and the lists carry
both fields next to the ID.
A saved agent gets builtins_off and builtins_on. builtins_off is a
ceiling: a chat of the agent shows the group off with a reason and cannot
switch it on, and a sub-agent follows it. builtins_on lists the opt-in
groups the agent's chats start with. Both are additive columns, a write
that does not name them keeps the stored ones, and groups the server does
not offer are dropped so an imported file still loads. An agent with
switches exports as version 3, so an older server refuses the file
instead of giving the agent every tool; a single-folder agent without
switches still exports as version 2.
Assisted-by: Claude:claude-sonnet-5-5 go gofmt swag
Add a manifest credentials declaration, host-enforced per-binding
resource lists, Request.Credential and ResourceKey set by the host, and
a typed ErrRateLimited that reaches the model as rate_limited.
Assisted-by: Claude:claude-sonnet-5-5 [go]
A turn now asks the add-on broker which running add-ons declare context
files, and loads their index files with the loader that already reads
registered sources. The same rules as for add-on skills apply: a stopped
add-on, one the chat switched off, one the chat's agent does not grant,
and one that cannot work for the user bring nothing. memory_read serves
the topics of those sources. The Memory page lists the files of any
installed add-on, running or not, because the files belong to the person.
The channel notes folder of a chat is now the one propose_change writes
for the same conversation: the binding and a hash of the chat. A note the
person confirmed is read back by the conversation that proposed it. Before,
the loader built the folder from the binding alone, so the two never met.
The prompt names the save tool only in a chat that has it, so a chat that
switched propose_change off is not told to call it.
Assisted-by: Claude:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
The chat harness took the context window, agent options and input
modalities from the config of the name a chat asked for. An alias has
no model of its own and the loader gives it the generic default
window, so a chat on an alias budgeted against 4096 tokens and failed
on tool schemas even when the target ran with a far larger window.
Resolve the alias to its target first, as the capabilities endpoint
already does.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
The key connector_files_ceiling_bytes sets the largest file a connector
moves. Zero means the default of 100 MB. The key is always written, and
a policy document stored before it reads as the default. The connector
manager reads the ceiling from the owner policy at each resolution.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
The chat's network view, the administrator view and the line the model
reads about the network of its commands now take their name from the
capabilities.network an add-on declares, or from the title of its
commands tool when it declares none. The sentences no longer say
"Sandbox" or "the sandbox". The API gains a network object with the
title and the preset titles next to the existing addon field.
The text of the built-in bash and of the host-exec setting names an
add-on that provides bash instead of one add-on.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
The prompt, the Tools menu reasons, the network error texts, the CLI help,
the API instructions and the assistant tool descriptions said "Sandbox" for
the add-on that runs commands. Core must not know that name.
The reason a chat has no commands now uses the title the provider declares
("the Zeta add-on is off for this chat") or, when none is installed, says
"the add-on that runs commands". Text that has no provider in hand speaks of
the network of commands or of an add-on that isolates them.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Union of both case lists in the add-on suite inventory; the swagger
files are regenerated from the merged code.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Document skills, the Commands block of the prompt and load_skill no
longer compare an add-on ID or provider with "sandbox". The host asks
whether the add-on that ships a skill serves the chat's commands and
whether the typed execution status reports them isolated. Skills that
need that are listed by the broker from the add-on's manifest, and the
text names the provider by the title its manifest declares.
An add-on whose commands tool declares no descriptor behaves as a
provider of commands under its own title and keeps the isolation check
for its document skills.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
A tool that shadows bash can now declare an execution descriptor: its
class, a title and a note for the model, and the skill kinds whose
runtime it supplies. The host reads it to build its text and to decide
which skills need isolated execution, instead of knowing add-on IDs.
The field is optional and needs manifest API 2. The host now speaks
API 2 and still accepts add-ons that declare only API 1, so manifests
that declare nothing new keep working unchanged.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
The Memory page reads the context-file sources that master added.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Open the proposal store beside the chats (auth database, file or memory)
and document the mechanism for add-on authors: the wire record, the
limits, the gate, the audit, the REST routes and how a cluster shares
it. Update the registry and actor-scan specs for the new tools.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Describe the 1.2-second case as success within its configured timeout,
not as exceeding the actual 60-second connector default.
Remove trailing whitespace from the P2P command example.
Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Pass the resource-limit choice through application and node configuration.
Keep only the exact string true enabled, including worker and explorer
entry points. Leave other legacy environment reads unchanged.
Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Assisted-by: Claude Code:claude-sonnet-5-5
Name the MCP tool explicitly so the Ginkgo-only lint rule does not
mistake its Run method for testing.T.Run.
Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
A tool call through an MCP connector was cut after the connector
package default of 60 seconds, while the model's own MCP servers allow
360 seconds. Research and document tools behind a connector take
minutes, so a saved agent lost them mid-turn with "connection closed:
calling tools/call: client is closing" and the model fell back to a
weaker tool.
The connector service now gets the MCP tool timeout the rest of
LocalAI uses (DistributedConfig.MCPToolTimeoutOrDefault, 360 s by
default). The package default and the per-call output cap are
unchanged.
Tests in core/application start the connector service on JSON stores
against a slow MCP server: the timeout defaults to the MCP tool
timeout, a tool slower than the old cap but within the timeout
returns, and a tool past the timeout is still stopped.
Docs: chats-connectors.md, "How chats use them".
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Stefan Walcz <stefan.walcz@walcz.de>
(cherry picked from commit 99f663a777)
The Network row of the Tools menu could never show the Off, Registries and
All switcher: the host stopped setting `applies` because isolation alone does
not prove network-policy enforcement, and nothing else set it.
Let the provider report enforcement in its typed execution status
(`networkPolicyEnforced`). The host sets `applies` only when that report is
true and the status is available and isolated. The Sandbox reports it for the
gVisor and KVM backends, whose guests reach the network only through the proxy
that asks the host. Providers that do not report it keep the "not enforced"
text.
When the host cannot read the status, give the unknown state a reason
(`unknown_reason`) in the API and the Tools menu: owner unreachable, not
reported, stale, invalid, not selected, no answer or reported unknown. Log the
class of each failure, rate limited. After a failure that a restart of the
add-on owner can cause, let a long turn bind and read again, at most once every
five seconds, instead of keeping the first failure for the whole turn.
The Sandbox now reports "unavailable" with a reason when it started without
settings, and explains a backend it does not know.
When the Sandbox document skills are hidden because the Sandbox is not known to
be isolated, say so in the skill list, in the turn note and in the
`load_skill` error, instead of "This chat has no skills now".
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>