mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-06 12:33:16 -05:00
2316e1463243ee69ead3e0c2ba363579cca58abb
59
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7df9b263ed |
feat(addons): carry translated text in the manifest and the library
The manifest said its text in English only. An add-on can now translate what the host shows to people, and the library list shows it before the add-on is installed. The title and the description use the language maps of ui.title and ui.description, which every host already reads. A new optional field, i18n, translates the connector kinds by language tag. It stays under api 2 and its set of fields is closed: the title and the description of a declared kind, and only where the English kind has them. Tool descriptions, schemas and skills are for the model and stay English. Tags follow the language map rule (at most 16, no English), each string has the limit of its English field, all translated text has at most 12 000 characters, and markup, control characters and direction overrides are refused. A host that does not know the field refuses the manifest, as it refuses any unknown field. The field is part of the manifest, so the package digest and the signature cover it. The catalog generator copies the translated title and description of the manifest into each library entry (ui.titles, ui.descriptions), the host validates them like the manifest values, and a library search matches the English and the translated text. The apps list and the connector kinds return the text of every language and, when the request names a language (lang, else Accept-Language), the resolved text beside the English fields: language, localizedTitle and localizedDescription. No existing field changes. Every add-on on master now has its title and description in Italian, German, Spanish, French, Brazilian Portuguese, Simplified Chinese, Korean and Indonesian, and the chat connectors carry their kind text in the same languages. The packaging tests require that, and that a translation has the fields of the English text it translates. The names of the add-ons that provide a role are matched in their English title only: a translation is often an ordinary word of its language. Assisted-by: Claude:claude-sonnet-5-5 go |
||
|
|
82b9984e06 |
feat(memory): serve the notes of memory from the host
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 |
||
|
|
bab8a605cc |
feat(addons): add the PiKVM add-on
Chats and agents can check a PiKVM (kvmd) device and, when a person confirms each call, press the power buttons of the machine it controls and use its keyboard. Read tools: get-info (model, versions, no serial or host name), get-power-state (ATX LEDs) and get-keyboard-state. Write tools: power-action (on, off, reset; off_hard, reset_hard and long_press only with a per-device switch), type-text (bounded, no control characters, refuses key, token and password-list shapes) and send-key (a short allowlist, no Windows or Meta chords). All three declare approval always. The preview reads the power state; apply reads it again and rejects a stale operation. The add-on journals before it sends, never retries and reports unknown when the connection drops. One connection is one device: the address is the single resource of the connection and the one sealed credential holds user:password, split at the first colon. A one-time code is not supported. The add-on speaks only to that address, refuses redirects, uses no proxy and accepts a self-signed certificate only through a #sha256= pin in the address. Typing, the text length and hard power actions are per-device switches that an administrator sets on the add-on page; all start off. Snapshots, mass storage, GPIO and the mouse are left out. The add-on ships a skill, a connection page with a Test button and approval cards, the package files, the library entry and the docs, and joins the package workflow and the case inventory. PiKVM API reference: https://docs.pikvm.org/api/ Assisted-by: Claude:claude-sonnet-5-5 go node |
||
|
|
6be3a96083 |
feat(addons): add the Home Assistant add-on
Chats and agents can read a Home Assistant instance and, if the person allows it, switch things in it. Read tools: server summary, areas, entity search, state, history, logbook and the catalogue of callable services. Results are bounded, marked as untrusted data, and stripped of pictures, access tokens, secrets and locations. Write tools: call-service for quiet services (lights, switches, input booleans, media transport) follows the write mode of the connection; call-physical-service always needs a confirmation. A deny-by-default allowlist decides which services a model may call. A hard exclusion list that no setting can lift covers locks, alarms, sirens, valves, cameras, garage-type covers, restarts, reloads and shell, system and add-on management. Calls name entities one by one, up to a cap. Entities can be excluded by domain, area, pattern or label. One connection is one instance: the token is the credential and the address is its one allowed resource, so the host refuses any other address before the add-on runs. The add-on speaks only to that address, refuses redirects, verifies TLS, and accepts a self-signed certificate only through a pinned SHA-256 fingerprint. The policy lives in the add-on data folder and is edited on the add-on page by an administrator. For that, the host no longer asks a credential for a uiOnly tool of a credentialed add-on, since the page has no chat to name a connection. Assisted-by: Claude:claude-sonnet-5-5 go node |
||
|
|
7abbef8236 |
feat(addons): wire the Discord add-on into packaging, catalog and docs
List the add-on in the package workflow matrix, the package checks, the host operation policy, the catalog template and index, the case inventories of the contract and packaging suites, and the architecture guard (two links to the project community server are not the add-on). Document the connector in the chats guide. Assisted-by: Claude:claude-sonnet-5-5 go |
||
|
|
68438344d3 |
feat(addons): add the Jellyfin add-on
Let chats and agents query a Jellyfin media server and, when the person allows it, remote control its players. Read tools: search, libraries, browse, item details, latest, continue watching, next up, playlists, sessions, user names and server info. Write tools: control-playback (play, pause, resume, stop, seek, volume), mark-played, set-favorite and add-to-playlist. There is no tool that deletes, scans or edits the library or manages users. One connection holds one API key (credential kind token) and one server. The server address is the single entry of the connection's resource list, so the host checks it before every call and several servers work through the connection selector. The add-on talks only to that address: http and https only, no user information or query, redirects refused, paths built from fixed segments, and the key sent in the Authorization header only. A self-signed certificate is accepted only when the address carries #sha256=<fingerprint>; the connection then accepts that one certificate and TLS checks are otherwise on. Results are bounded (50 items a page, cut overviews), marked as untrusted data, and hold no file path, stream or image address. The write mode off, propose or auto is the host's per-connection setting. A write is previewed from the server's own records and rejected as stale when the player or playlist changed before the person confirmed. The add-on ships a skill, a connection page with a Test button and approval cards, the package files, the library entry and the docs, and joins the package workflow and the case inventory. Assisted-by: Claude:claude-sonnet-5-5 go node |
||
|
|
f4f36ab746 |
feat(studio): confirm change proposals in the chat of a messaging app
A note, a profile, a skill, a page or a dashboard change that the agent proposed in a messaging chat could not be confirmed there: a plain "yes" went to the model, and the tool result sent the person to Studio, which the connector prompt says they do not read. The host now writes the question in the chat, with the kind, the scope and the lines that will be saved, and answers the reply before any model turn. yes/ok/confirm saves, no/cancel drops, a four-character code picks one when several wait, and "undo" takes back a save for 30 minutes. Only a sender with proposals.confirm may answer; the kinds that change what the agent may do need a paired sender, and in a shared chat only the sender who asked. The tool result tells the model what the host did, and the Studio wording stays for Studio chats. The permission text of "Confirm changes from the chat" now says what it covers. The proposal source keeps the asking sender. Assisted-by: Claude:claude-sonnet-5-5 |
||
|
|
cbec432ed6 |
feat(addons): upload a zip to the owner and install it from the Add-ons API
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 |
||
|
|
d537695895 |
feat(addons): write one add-on package as a zip
Add the zip format of a package (a digest manifest plus the files of the OCI package for one platform) and an addonpkg zip subcommand that writes it from a verified layout, with a sha256 file. The zip comes from the same layout the registry package comes from, so there is one build path. Version comparison moves to contract.CompareVersions so the installer can use it for upgrades and downgrades. Assisted-by: Claude:claude-sonnet-5-5 go gofmt |
||
|
|
23beb6dc80 |
feat(chats): let a person choose how memory notes are saved
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 |
||
|
|
7ce4507da1 |
feat(addons): keep per-person settings that an add-on declares
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
|
||
|
|
c56c1ac343 |
feat(addons): choose the connection of a credentialed add-on explicitly
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 |
||
|
|
c5400edd3f |
feat(addons): add the /api/addons/host-grants routes
Seven routes: read the host access state, preview an install, install or upgrade with an approval, edit or revoke the grants of an add-on, change the blanket approval and change the deny rules (with a dry run). Reads take an administrator session or API key. Every write takes only the administrator's own browser session: same-origin fetch and the confirm header equal to the operation ID. An API key, bearer token, MCP session or tool call gets 403 not_human_surface. The dry run of a deny change is a read. The first path segment host-grants is reserved as an add-on ID, and the routes are listed in the feature registry. Assisted-by: Claude:claude-sonnet-5-5 go gofmt ginkgo |
||
|
|
43f4a2845b |
feat(addons): declare the connector file operations in Slack and Telegram
The two connectors move files through connector.file.get and connector.file.put but their manifests asked for nothing, so the install dialog and blanket approval could not cover them. Declare both as optional: a connector works without files. Delivery is pull, so neither calls connector.inbound and it is not declared. The audit of official packages now reads the operation constants of the shared connector code. A deployment whose policy file already grants the connector prefix sees no change. Assisted-by: Claude:claude-sonnet-5-5 go |
||
|
|
8cf6153ea6 |
feat(connectors): let a credentials-only kind have bindings without an agent
A connector kind can declare agentOptional. A binding of such a kind may have no agent: it holds the token, the resource list and the write mode for the tools of a chat, and never receives or answers a message. The GitHub kind declares it, so a person no longer makes a throwaway agent only to store a token. Without an agent the host refuses every setting that needs one: listening, accepting senders, an allowlist, a notification chat, talk-back channels, permissions, pairing and trigger approval. The places that read the agent of a binding handle the empty value: inbound routing, the polling loop, notifications, pairing, the capability check (deny by default) and the grant switch. A kind that does not declare the key still needs an agent on every binding. The binding page makes the agent field optional for such a kind with help text, and the list shows "Credentials only". Assisted-by: Claude:claude-sonnet-5-5 go gofmt ginkgo node protoc swag |
||
|
|
3607c08c17 |
feat(connectors): grant the usual permissions once to old bindings
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 |
||
|
|
afb06fd42f |
docs(addons): describe manifest api 2 only and update the test inventory
The add-on guide names one manifest api, one way to move a file and no migration path, and drops the section on arguments of older tool versions. The Swagger files are generated again, which also brings in fields that the last generation missed, and the test of the apps view now emits every field it documents. The inventory of the add-on suites lists the specs by their new names. Assisted-by: Claude:claude-sonnet-5-5 go swag |
||
|
|
c5f636d1b9 |
refactor(addons): move connector file bytes by handle only
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 |
||
|
|
2a491cb2cf |
refactor(addons): remove the shims for older add-on data
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 |
||
|
|
1834d4fd72 |
refactor(addons): make manifest api 2 the only version
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
|
||
|
|
ab0848293e |
feat(slack,telegram): stream files by handle
Both add-ons implement the streaming side of the connector route: they
read a file from the platform and put it to the host chunk by chunk, and
they pull the file to send from the host and stream it into the
platform upload. Neither holds more than one chunk in memory.
Slack uploads with the external upload flow and tells Slack the length
first. Telegram sends a multipart body of known length, and a picture
over 10 MB goes as a document, because sendPhoto refuses more. The
client of a streamed file has no total timeout; the context carries the
bound.
The manifests declare the limits that the platforms state, and
files.transfer. Telegram moves to manifest API 2 for it. The limits are:
Slack: 1 GB per file, as in the help center article
https://slack.com/help/articles/201330736-Add-files-to-Slack
The upload API names no per-file cap
https://docs.slack.dev/reference/methods/files.getUploadURLExternal
Telegram, public Bot API: bots download up to 20 MB with getFile and
send up to 50 MB (10 MB for photos)
https://core.telegram.org/bots/faq
A local Bot API server lifts both (no download limit, 2000 MB upload)
https://core.telegram.org/bots/api#using-a-local-bot-api-server
The add-on has no setting for another server, so it declares the
limits of the public one.
Slack gets the host operation prefix connector. in the official host
policy, as Telegram has, so it can call the two file operations.
Assisted-by: Claude:claude-sonnet-5-5 go test
|
||
|
|
4ba1b7b2bd |
feat(addons): move connector file bytes by handle
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 |
||
|
|
2b588a7350 |
fix(connectors): hold add-on write tools to tools.write in connector chats
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 |
||
|
|
15e2321d50 |
feat(connectors): edit the permissions of a binding on the shared connector page
Bindings saved before permissions were enforced have no capabilities, so they deny files from senders, triggers, memory writes and talk-back, and the owner could only fix that through the REST API. The shared connector page now has a section for it, so every connector add-on gets it: a switch and a description for each capability with the sensitive ones marked, the role matrix (never a sensitive capability, never above the ceiling), pairing with a code shown once, the approved channels for talk-back, and a read-only view of the access check with the latest decisions. A binding with no capability shows a notice that says why the features are off, with an "Allow the usual" button that turns on the non-sensitive everyday set. The kinds endpoint returns the closed list of capabilities with a title, a description and the sensitive and usual flags. The field is additive. Assisted-by: Claude:claude-sonnet-5-5 go node playwright swag |
||
|
|
24c837e453 |
feat(studio): grant built-in capabilities to a saved agent
A saved agent now has a Builtins list: the capabilities its owner gave it (memory.write, profile.write, skills.write, pages.write, dashboard.write, triggers.propose, triggers.run, talkback.channels, talkback.new_channel, files.upload, act.files, act.addons, act.send, act.spend and the opt-in group saved_agents). The list is empty by default, and nothing turns a grant on for a template, an import or a write that omits the field. A chat of the agent holds the grants the user may use at the turn (agent scope). A tool exists when the grant is held, the chat did not switch its group off and the run can hold rights: a sub-agent or a run that started by itself never does. propose_change and revert_change now exist only for a chat that holds the grant of at least one kind, and the schema lists only those kinds. propose_change gains the kinds skill, page and dashboard. A skill is a SKILL.md for the personal or the agent layer, and a skill with locked: true is refused, also as a shadow of a locked personal skill. A page is a set of files checked against the Pages rules and written as one change set. The dashboard is a home.json checked against its schema. All three are re-checked when the owner confirms or edits. GET /api/chats/agents/builtin-grants lists each grant with its title, description and sensitive flag. The agent record, the write body and the export file carry builtins; an old file imports as before and an unknown name is dropped in an import and refused in a write. Assisted-by: Claude:claude-sonnet-5-5 go gofmt swag |
||
|
|
e790271c63 |
feat(addons): let the GitHub add-on write, under a per-connection write mode
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 |
||
|
|
337a034601 |
feat(addons): declare document slots and legacy arguments in the manifest
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 |
||
|
|
b15905e90f |
fix: restore the files that the previous commit removed by mistake
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 |
||
|
|
9e6d6520bd |
feat(connectors): enforce add-on permissions on each connector turn
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
|
||
|
|
3bbb40b6ff |
feat(addons): GitHub settings page, registration and docs
Add the GitHub connection page (fine-grained token, repository list, read-only note, Test that checks each listed repository), let the shared connector page hide messaging settings for a kind that carries no messages, register the add-on in the package matrix and the catalog, and document the credential slot and the GitHub add-on. Assisted-by: Claude:claude-sonnet-5-5 [go node] |
||
|
|
e0da582988 |
feat(addons): credential slot, resource allowlist and rate-limit error
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] |
||
|
|
df14cf43e2 |
feat(addons): add the Short memory add-on
The add-on declares the three index files of the person's notes (capabilities.contextFiles, manifest API 2), so the host loads them into the prompt and serves their topics with context_read. It ships two skills: memory, whose description asks the model to read the matching topic before it answers almost anything and to save a note only as a proposal the person confirms, and memory-check-own-files, which says what the model can and cannot read. Its executable serves no tool, and its page explains the notes and opens the Memory tab of the account. The add-on joins the packaging matrix, the release workflow, the library index and the case inventory. The declared capabilities the host hands to an add-on now include the context files. Assisted-by: Claude:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
ad7e9b3261 |
feat(addons): let a manifest declare the context files the host loads
An add-on that keeps small notes for the person can now name the index files that the host puts in the prompt of a chat. The declaration is capabilities.contextFiles: at most one file for each scope (user, agent, channel), each a path under Memory/ that ends in .md, with an optional byte cap that can only lower the host's 2 KiB cap. The field is new, so a manifest that uses it must accept manifest API 2. The add-on only names paths. The host reads them as the person, so the declaration gives the add-on no access to files. Assisted-by: Claude:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
1f481b0747 |
feat(connectors): add-on roles and permissions, and sender pairing
A connector kind can now declare the roles it gives to a sender and the capabilities it can grant to a role. The owner of a binding enables a ceiling of capabilities and maps roles to them. The host stores these values and returns them with the binding and the kind list, so an add-on settings page can show them. Capability names are a closed list owned by the host. Sensitive names may be listed by a kind but are never granted to a role; only a paired sender can use them. Pairing proves that the owner controls a platform account. The owner asks for a one-use code (valid ten minutes) and sends it as a direct message to the bot from an allowlisted account. The host checks the code before any model turn and never logs it. A binding holds three paired senders, a pairing ends after 90 days, and five wrong codes in an hour lock the sender out for an hour. Contract: connector kinds gain optional roles and permissions, and a message gains optional roles. They need manifest api 2, which the host already accepts; protocol is unchanged and manifests that declare nothing new behave as before. The host drops roles a kind does not declare. Enforcement of the capabilities by feature is not part of this change. Assisted-by: Claude:claude-sonnet-5-5 go swag |
||
|
|
6cda05c526 |
test(addons): name the files API spec apart from the network one
Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
6d3aec30b3 |
feat(studio): build connector file limits and sentences from one resolver
The limit of a file is the smallest of the host ceiling, the ability the connector kind declares, the owner's setting for the binding and the cap of the inline path. One function decides it and names the layer that won. The sentences to the sender and to the model are built from that number and layer, in KiB or MiB, instead of a fixed 1 MB. A guard spec fails when these files carry a size or a byte count of their own. The owner can lower the limit of a binding; a value above the limit of the kind is refused. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
198d03125b |
feat(addons): let a connector kind declare its file abilities
A connector kind can declare files.receive and files.send, each with a maximum size and optional media types. The field is additive and needs manifest api 2. A kind that declares nothing keeps the inline path. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
0e50c3f9ca |
feat(addons): let a connector kind declare per-binding options
A kind can declare options with a few values and a default (manifest api 2). The host checks the owner's choice against the declaration, stores it on the binding, shows it in the REST API and sends the value in effect with every poll. The add-on decides what the option means. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
ca5c8e79e3 |
feat(addons): add the history op to the connector contract
A connector kind can declare history.thread in its manifest (api 2) and then serves the op history: the earlier messages of one thread, oldest first, bounded by a limit. A kind that declares nothing is never asked. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
3273f1772b |
test(addons): inventory the network capability specs
Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
bcd81fbc2e |
docs(addons): document the network capability
Describe capabilities.network for add-on authors: its fields, how the host control attaches to it, that the chats_egress_* settings keep their names and values, and how a manifest without the field keeps working. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
cf3de8886f |
feat(sandbox): declare the network capability in the manifest
The manifest keeps asking for the network-policy control and the egress.check operation, and now also declares capabilities.network with the title the host uses in text. A test keeps the control working for a manifest of the same shape that declares no network. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
f7a4c68fad |
feat(addons): add a network capability to the manifest
The network-policy host control was tied to a tool that shadows bash, so it could only belong to an add-on that replaces that one tool. An add-on now declares capabilities.network (kind egress-check, an optional title and optional preset titles) and the host attaches the control to the declaration. A manifest that declares nothing keeps the old attachment. The field is additive and needs manifest api 2 and the egress.check host operation. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
c1dd87e0d5 |
feat(addons): declare a resource listing in the manifest
An add-on that keeps resources can now ask the host for a read tool that lists the ones the caller may use, by declaring capabilities.resources.list. The declaration names the tool and, optionally, the key of the result array. It needs manifest API 2 and must not reuse the name of a tool the add-on declares. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
0cd265e86e |
merge: bring master into the proposal UI branch
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> |
||
|
|
0c08e17a30 |
feat(addons): add an execution descriptor to the tool contract
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> |
||
|
|
f7c8dd15d6 |
feat(contract): add the change proposal record
A model can ask to change the person's own state (a memory note, a profile, a skill). Add the versioned wire record, its kinds, scopes, statuses, source and limits, so every surface that runs a model, and any add-on, shares one type without platform code. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
9fafea8fdf |
fix(chats): show the network switcher and say why execution status is unknown
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> |
||
|
|
7904b3d0ab |
feat(addons): declare typed host capabilities (#13034)
* feat(addons): model execution status observations Keep observation lifetimes explicit before runtime integration. The pure reducer rejects retries and stale replies using exact binding identity. Cover all eleven trace families, the complete transition matrix and bounded histories with safety and liveness checks. Assisted-by: nib:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): visualize execution status traces Generate a self-contained viewer from the real reducer and shared traces. Check independent expectations, coverage and bounded invariants before exporting data. Detect stale artifacts and nondeterministic generation without maintaining a second reducer in JavaScript. Assisted-by: nib:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): honor the viewer artifact root Keep default viewer output under SDD_LOCAL_ROOT when configured.\nLet go generate use the same default without forcing a source artifact.\nRetain the portable fallback and explicit output and check semantics. Assisted-by: nib:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): add typed extension contracts Validate optional home commands, execution bindings and requested host operations without changing manifest versions or granting authority. Decode bounded execution status payloads conservatively and document strict staging compatibility for older hosts. Assisted-by: nib:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): reject noncanonical extension keys Reject case aliases before typed decoding can override canonical fields or bypass presence checks. Keep locale maps outside exact-key checks. Add regression coverage for status, declaration objects, and nested entries. All status errors return unknown readiness and isolation. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): reject root enums for status tools Status tools must accept the empty object. The supported schema enums contain only strings, so a root enum excludes every object. Reject root enums only for execution status bindings. Cover incompatible root constraints and optional properties without changing shared validation. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): project typed home commands Resolve declared home destinations and display metadata in the installed Apps view. Pin packaged command icons to immutable asset URLs. Cover strict declaration transport, immutable receipts, exact health echo, and process restart. Keep legacy packages and disabled installed intent. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): preserve typed lifecycle declarations Copy execution and host-operation declarations from installed receipts. The existing capability completeness test exposes the missing fields. Exercise real staged Manager upgrades, activation rollback and recovery. Check installed Apps metadata through pinned mTLS frontends for each actor. Verify mutation isolation and name receipt replay coverage accurately. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): stabilize fixture archive digests Map iteration changes tar entry order between identical publishes. Sort fixture filenames so unchanged packages retain their digest. Check repeated publish bytes, digests and lexical archive entry order with and without a manifest transform. Register the regression case. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): resolve explicit host policy grants Load strict administrator policy files once before application startup. Honor explicit empty overrides without reading ignored policy files. Copy programmatic and manager grants to isolate startup authority. Keep the legacy CLI fallback until the official deployment policy ships. The generic resolver already defaults to empty grants. Verify config, CLI, hostops and execution-status checks with GOMAXPROCS=2, -p=2 and -ldflags="-s -w" to fit the available build disk. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): select explicit deployment grants Move official host grants out of the generic executable into reviewed host deployment policy. Stock Docker explicitly selects the shipped file; unconfigured binaries and nil or empty programmatic grants grant nothing. Document the standalone upgrade break and deliberate operator selection. Do not infer consent from installed addons or merge explicit overrides. Guard policy packaging and generic configuration boundaries with tests. Verify executionstatus, viewer -check, config, CLI, packaging and root architecture tests with auth, GOMAXPROCS=2 and bounded build parallelism. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): gate activation on required host ops Refuse unmet required requests before package publication or runtime withdrawal. Keep installed intent unavailable when startup grants change. Optional requests permit degraded operation and never create authority. Carry bounded admin diagnostics through Apps and the owner carrier. Keep startup policy immutable and broker authorization authoritative. Verify executionstatus, viewer -check, lifecycle, packages, updates, hostops, Apps and gateway offline with auth and bounded parallelism. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * test(addons): guard host operation registry parity Compare startup admission names against real builtin registrations so registry drift cannot silently change request satisfaction. Cover dynamic progress and stop operations and connector inbound. Reject missing, extra, duplicate and case-changed names with negative controls. Record both regression cases in the suite inventory. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): fence status observation effects Keep observation ownership in admitted runtime operations. Deny all correlated callbacks before dispatch, including inbound-class callbacks. Reject status outputs before callers can open or adopt artifact handles. Retain bounded denial correlations until the runtime endpoint closes so late callbacks cannot recover ordinary authority. Preserve independent ordinary operations and document the dedicated read API for T9. Verify the status model, viewer, and race-enabled gateway, hostops and runtime suites with the pinned offline environment. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): drain callbacks before retirement Server.Close does not wait for active callback requests. Clearing retired observation correlations first can restore inbound authority. Stop endpoint admission before closing connections. Drain admitted requests before releasing correlations, and refuse dispatch after Stop. Keep locks out of handlers and cleanup waits so cancellation cannot deadlock teardown. Cover pending inbound callbacks, decoded authorization paused across Stop, and handlers that ignore cancellation. Preserve ordinary authorized work on other endpoints. Document delayed reclamation under the existing bound. Verify the status model and viewer, then race-test gateway, hostops, runtime, the model and root architecture checks with auth enabled. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): bind owner status to exact clients Add authenticated, versioned status reads over the owner carrier. Revalidate actor permissions and provider selection before dispatch and before returning an observation. Keep status separate from authority. Admit the captured client against its immutable identity under the withdrawal lock. Never dispatch an old binding through a replacement. Generate runtime operation IDs on the owner and retain the T8 effect fence. Cover forged identities, strict DTOs, stale replies, restart ordering, wire discriminators, and unchanged model exclusion of uiOnly tools. Document the T10 callback and request-shell integration requirements. Verify the model and viewer, then race-test gateway, runtime, tools, and the model with auth enabled. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * test(addons): compose owner status with runtime Exercise installed addon processes through the authenticated mTLS carrier. Keep runtime clients real while channel barriers control lookup ordering. Reject captured clients after same-generation replacement before dispatch. Reject completed status reads when replacement precedes owner consumption. Prove fresh bindings succeed and record named tools and host operation IDs. Verify the model and viewer, then race-test gateway, runtime, tools, the model, and the protocol fixture package with auth enabled. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(studio): scope execution status observations Run the execution status reducer within one explicit request lifetime. Coalesce consumers without retries and withdraw stale or canceled reads. Keep owner admission and production lifecycle integration separate for review before wiring the shell into requests and turns. Assisted-by: OpenAI:ChatGPT Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(studio): isolate consumer cancellation Consumer cancellation during validation must not withdraw a valid observation from other consumers. Return unknown locally before shared invalidation, while preserving parent closure and freshness failures. Cover cancellation and deterministic deadline expiry with one-read reducer traces and live-consumer checks. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): track selection mutation epochs Detect selection ABA at config and owner mutation boundaries. Clone provider pins for Studio readers and share synchronized selection state across config value copies. Track lifecycle publication, candidate rollback and recovery transitions. Keep reads and unchanged publications stable. These lifetime epochs do not replace current-incarnation checks or grant execution authority. Verify race tests for config and the add-on Manager, plus application compilation with auth tags. Request binding remains separate work. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): expose owner binding transport Add a host-only binding API with an optional owner resolver. Forward conversation claims over authenticated mTLS with strict versioned DTOs. Compare full bindings during validation and deny missing resolvers. Keep ordinary tool execution unchanged through an optional backend. Test trusted resolver fixtures, stale bindings, denial and compatibility. Application authority and store revisions remain a separate milestone. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(studio): fence selection snapshots with epochs Read actor-scoped records and opaque mutation tokens under store locks. Invalidate tokens after successful eligibility changes, including ABA. Keep reads, rejected writes and turn history from invalidating tokens. Clone mutable records so callers cannot bypass mutation tracking. Support authoritative revisions only for memory-only JSON stores. File stores lack exclusive ownership; GORM lacks persisted revisions. Fail closed for both rather than trust frontend-local state. Ordinary chats remain unchanged; application integration stays separate. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(studio): enforce persistent JSON ownership Acquire lifetime sidecar locks before loading or repairing JSON data. Enable selection revisions only under cooperating exclusive ownership. Close drains operations before releasing ownership and rejects later use. Clean up unpublished stores when application initialization fails. Retain published locks through Shutdown because HTTP users may remain live. Document coordinated upgrades and the advisory local-filesystem boundary. Keep GORM revisions unsupported pending a separate approved design. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Codex:gpt-5 * test(application): isolate warning log capture Run warning assertions in isolated test subprocesses. The suite leaves background log producers running, which race with global logger changes. Keep the parent logger unchanged and check child exits and completion markers. Preserve pin persistence and ownership warning assertions. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(studio): resolve local owner execution bindings Resolve execution providers from owner-held chat and agent snapshots. Fence bindings with selection epochs, mutation tokens and live runtime identity. Recompute every component during status authorization. Keep named-user and SQL observations unavailable until authoritative access and shared selection revisions can detect ABA changes. Drain restart test producers before releasing JSON store ownership. Register six product resolver cases in the gateway suite inventory. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(studio): bound product scopes to chat turns Keep request-local product state alive through tool calls, checkpoints and persistence. Give chat priming its own scope instead of seeding the next turn with a closed observation. Exercise one reducer read per scope across prompt and tool consumers. Check closure of pending reads on normal completion and interruption. Provider wiring and safety projection remain separate work. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(studio): consume typed execution providers Replace the Sandbox-specific status heuristic with owner-bound typed reads. Share one reducer observation across turn consumers and close it at the outer scope boundary. Keep priming and standalone requests independent. Sandbox exposes a separate callback-free typed read while preserving its private Settings payload. Unknown backends never imply isolation. Provider isolation does not prove host network-policy enforcement. Local-owner JSON bindings are supported. Named-user and SQL bindings remain explicitly unavailable and fail closed. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * test(application): isolate auth startup lifetime Shutdown does not join every background producer. Auth startup tests can therefore delete their temporary directory while a writer remains. Run each case in a bounded child process. The parent waits for child exit before deleting the fixture, preserving every startup assertion. Production shutdown and JSON ownership retention remain unchanged. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(ui): resolve installed Home app commands Project Home navigation from installed addon declarations, not product IDs. Reserve native and skill names and suppress every colliding addon alias. Re-read the authenticated registry before navigation and reject stale actors, generations, immutable entries and destinations. Keep mounted consumers polling through disabled and failed states. Abort pending reads on actor changes and ignore replies from obsolete request epochs. Studio declares its own alias. Preserve legacy redirects and pin migration. Add unit coverage, localized Home copy and command lifecycle documentation. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): accept resolved Home command metadata Apps resolves inherited titles beyond the explicit manifest label cap. Bound resolved labels to 147 Unicode characters, including secondary pages. Keep the backend's 60-character limit for explicit manifest labels. Match packaged icon paths to the contract's ASCII alphabet and image types. Accept dotted names while rejecting traversal, encodings and foreign assets. Verify 68 focused cases, 657 total cases, lint, i18n checks and the UI build. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): bind safety notices to actual providers Warn for addon host execution and unknown isolation without changing tool permissions or built-in host consent. Reset dismissal when the admitted binding, observation, actor or chat context changes. Expose presentation-only status identity from the admitted request. Keep configured network policy visible when enforcement is unverified. Render bounded provider explanations as escaped React text. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): isolate command status across sessions Invalidate command observations when actors or authentication sessions change, before effects can expose a previous actor’s reply. Keep actual host execution warnings generic instead of recommending Sandbox installation or repair. Cover both regressions with source-hook lifecycle tests and provider notice assertions. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): declare audited host requests Declare actual official hostclient operations without inferring requests from deployment grants. Keep optional settings and egress checks separate from required workspace and job operations. Verify all twelve manifests through strict package fixtures and assert that requests never self-grant. Guard generic provider and Home dispatch without banning historical routes, native Studio, or deployment policy. Document the audited operations and unresolved named-user and SQL gaps. Refresh Sandbox catalog metadata for its existing typed status tool. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * test(addons): wire exact extension inventories and real provider selection Run contract, official packaging and root architecture gates through actual report inventories. Exercise two installed execution providers through the real owner resolver and distinguish callback pass-through coverage. Share strict report validation with focused-scope handling and missing/skipped artifact self-tests; document direct evidence and remaining harness limits. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): expire registry reads on auth refresh Bind registry authority to the actual authentication session epoch. Same-user refresh now rejects old polls and pending Home navigation before effect cleanup, even when permissions and metadata stay unchanged. Exercise both races through the production registry provider harness. Verify 59 focused tests, 669 total tests, lint, i18n, and the UI build. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(studio): resolve current execution selection Use existing principal-scoped chat and agent reads for advisory status. Revalidate current named credentials instead of requiring historical SQL revisions. Local-owner mode also works with the existing GORM store. Remove resolver nonces and historical revision prerequisites. Keep exact runtime binding and existing status admission hooks. Document current-read consistency without promising revoke-and-restore detection. Verify the SQLite regression fails before the fix. Two separate full race runs pass: application 262 specs (3 skips), auth 257, gateway 115, tools 91. Cover named chat, API key and session credentials and current-state denial. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactor(addons): drop selection revision tracking Use current selection comparisons for advisory status instead of mutation history. Keep actor, credential and conversation identity explicit in the model. Hash current inputs at the gateway without exposing raw store data. Remove unused epochs, revision interfaces and JSON ownership lifetimes. Preserve current authorization, runtime identity, mutexes and atomic writes. Document current-read semantics without historical ABA guarantees. Verify all affected packages with the race detector and auth tag. Check the trace viewer, prerequisite self-tests and 18 chat-command unit tests. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): scope Apps reads and provider status Bind Apps replies and registry ingestion to their originating auth session. Reject late replies before effect cleanup on refresh or account switch. Use selected-provider command DTOs in the composer instead of private Sandbox discovery. Keep unknown isolation unknown and remove specific add-on installation recommendations from the affected native surfaces. Test production Apps, registry, switches and composer paths with controlled cleanup and two arbitrary providers. Update the matching feature docs. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): guard composer and session publication Remove the deleted Sandbox variable from the full composer render. Report unknown command isolation explicitly in the about card. Bind Apps records and admin action results to their originating actor and actual authentication epoch before cleanup can run. Reject stale request admission and verification without changing server authorization. Add full-component render and pending session-transition regressions. Enable no-undef for the production composer in normal UI lint. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): expire cancelled upgrade reconciliation Bind cancellation reconciliation to the initiating session authority. Discard status replies after expiry without publishing old outcomes. Match the exact operation identity before clearing a held action. Cover pending cancellation reads, expiry before reads, and preservation of a newer attempt with the same action key. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): bind background upgrades to auth lifetime Keep background upgrade authority in AuthProvider, independent of views. Expire pending observations before auth consumers render or logout waits. Preserve same-session navigation and exact-operation cleanup. Cover cancellation, completion, and verification after the origin unmounts with actual provider transitions and the real upgrade store. Thread captured authority through Activity retries and document expiry. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactor(addons): remove implicit sidebar pins Start every account without implicit Studio or Talk pins. Preserve saved user selections and durable explicit pins across reopen and frontends. Remove startup seeding, seed metadata APIs, and first-install exceptions. Apply equal retention to all absent IDs without dropping database tables. Keep store initialization, cached errors, and the leader sweep unchanged. Verify genuine RED regressions before removal. Race checks pass for all 42 pin specs, 10 focused application specs, and 10 pin endpoint specs. Update pin documentation; renamed specs have no exact inventory entries. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(addons): declare typed model destinations Let installed addons own model launch destinations without teaching core about addon identities or private routes. Keep native chat and completion outside the declaration vocabulary. Validate strict keys, unique capabilities, declared pages and SDK route bounds. Carry cloned typed metadata through Apps using the shared contract type, and add owning Studio, Talk, Face and Voice declarations. Verify strict contract RED before implementation, then 1276 passing specs across contract, Apps, packages, runtime, protocol, config and manager. Verify 178 packaging and architecture specs and exact carrier inventories. Frontend dispatch and route cleanup remain a separate milestone. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactor(ui): resolve declared model launch actions Resolve installed model actions through the shared addon registry. Keep native chat and completion launches, and never promote absent providers. Refresh actor-filtered Apps before navigation and reject stale authority, provider metadata, generation, immutable entry and destination claims. Use named menu choices for collisions without loading addon modules. Remove unreleased addon-specific redirects and migrate browser fixtures to canonical declared pages. Preserve native chat handoff and addon-local navigation adapters. Update user documentation and historical plans. Verify three production UI consumers fail against their previous code, then pass all 13 mocked-HTTP browser regressions. Verify 696 host unit cases, full quiet lint, targeted no-undef, locales, inline styles and build. Full backend/browser integration remains outside these mocked-HTTP checks. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): validate Ginkgo hooks before focus Ginkgo emits null container hierarchies for suite hooks. Require hooks\nto pass before applying focus only to It cases. Normalize null\nhierarchies without weakening exact required-case comparisons.\n\nRun reporter regressions in prerequisites. Register the declared uiOnly\ntool case and remove an update fixture case excluded by the existing\nmanager focus. Both inventories match the complete CI case output.\n\nVerify 12 reporter regressions, 39 prerequisite cases, three existing\nreports, and fresh runtime, tools and focused update manager suites. Assisted-by: Codex:gpt-5 [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): restore Go CI contract checks Align route fixtures with explicit pins and declared network controls. Keep network enforcement unknown instead of inferring it from isolation. Propagate viewer output errors and select output paths with CLI arguments. Check test writes and use Ginkgo assertions without copying atomic state. Register the three migrated binding cases in the exact suite inventory. Document two narrow security false positives for administrator file access and symbolic credentials in reducer traces. Focused race tests pass. The available golangci-lint reports zero issues in affected packages. Assisted-by: OpenAI ChatGPT [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(ui): align browser coverage with addon contracts The generic provider refactor removes implicit install advice and private Sandbox discovery. Update browser fixtures to use the installed command metadata and typed execution observations without restoring those paths. Keep command warnings, consent, disabled switches and privacy assertions. Home now holds a live command consumer. Exercise polling shutdown on a route without that consumer, after its lazy transition finishes. Preserve the bounded cadence, error backoff and disable-stop assertions. Restore the remembered-voices link through the addon's compatibility router. Cover native migrations and NotFound for removed generator aliases. Validation: 293 affected browser cases and three native service cases pass. The gallery command passes all 74 inventoried cases. Full UI units, quiet lint, locale parity, production build and diff checks pass. Assisted-by: OpenAI ChatGPT [functions] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(addons): bind status to owner provider policy Resolve typed status with the same current owner pins as execution. Fail closed on owner policy outages and fingerprint authoritative pins. Exercise CAS updates, conflicts, stale bindings, and policy outages. Retain host settings when the named-account fixture replaces its gateway. Refresh exact gateway and Apps inventories from passing reports. Validation: the new regression fails before the fix. All 16 focused binding and policy cases pass. Gateway passes 361 exact cases and Apps passes 265 exact cases across their configured package reports. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactor(addons): share qualified tool identities Use one formatter and contract-component parser for add-on identities. Keep callable names bounded to 64 characters while recognizing long unavailable stand-ins without granting dispatch authority. Validate selected execution names and their provider ID at the owner binding boundary. The real adapter already emits canonical identities. Update exact importer and case inventories from passing reports. Migrate the binding backend test to Ginkgo and check shutdown errors reported by lint in the affected packages. Validation: behavioral RED proves malformed stand-in acceptance and plain selected-name acceptance. Affected full race suites pass: tools 94 and Studio 638, with zero skips. Application passes 275 of 278; three existing PostgreSQL cases skip without their configured URL. All 12 owner-binding cases pass and match the exact inventory. Scoped golangci-lint reports no issues. Assisted-by: Codex:gpt-5 golangci-lint Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactor(addons): share execution declarations Share pure declaration predicates across manifest validation, gateway observations, and owner bindings. Keep authorization and exact-runtime admission checks local. Reuse the strict manifest schema validator so raw status definitions fail closed without changing manifest acceptance. Share the workspace-operation prefix scan without changing grant sources. Add declaration parity and workspace-prefix tables and update exact inventories from passing reports. Validation: two new gateway cases fail before the fix; all 14 pass after. Race tests pass: contract 245, gateway 136, tools 94, and focused application binding/workspace cases 22. Scoped golangci-lint: 0 issues. Assisted-by: Codex:gpt-5 golangci-lint Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * test(addons): retain document skill cases Match the contract inventory to the passing report after rebasing.\nKeep the new document-provider case and updated reserved-name cases. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: OpenAI:gpt-6.1-sol * test(addons): follow owner-managed upgrades Accepted upgrades belong to the owner and cannot be cancelled by UI. Exercise observer expiry during reads, completion and verification. Supply the real upgrade store to source-executed auth harnesses so logout reaches its synchronous authority invalidation. Match whole-package inventories to fresh Manager and gateway reports. Assisted-by: Codex:gpt-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io> |
||
|
|
74e293ef38 |
feat(sandbox): own document authoring skills (#13038)
* feat(skills): reserve document provider slots Separate document provider slots from protected core skill names. Keep existing same-name shadows declarations compatible. Normalize legacy document OFF markers in JSON and database stores. Persist normalization under the existing lock or transaction so an explicit re-enable cannot be overwritten by a stale read. Cover persistence, rollback, ownership and concurrent replacement. Refresh the contracts inventory from the passing Ginkgo report. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: nib:gpt-6.1-sol * feat(skills): gate Sandbox document procedures Resolve document providers against the selected isolated command backend. Keep Office guidance available without command execution and preserve explicit provider pins when their backend is unavailable. Reuse authorized chat access during tool construction to avoid reentering the session lock. Recheck access and capabilities when loading guidance. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: nib:gpt-6.1-sol * fix(skills): resolve saved-agent child command grants Describe saved-agent child commands from their current agent scope rather than the inherited tool map reserved for ad-hoc children. Cover index, picker and loader behavior for permitted, absent and revoked Sandbox grants without changing saved skill selections. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: nib:gpt-6.1-sol * feat(sandbox): install and exercise guest-owned PDF helpers Preserve PDF helper sources and MIT attribution in the guest image. Exercise valid, empty-text and defective PDFs during the image build and through the packaged isolated command route. Register the packaging regression in the exact suite inventory. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: nib:gpt-5 * feat(sandbox): own document skills and consolidated references Move the four document authoring trees out of core and package their text-only procedures with Sandbox. Preserve source coverage with offline fingerprints, guest PDF helper paths, and package-local license notices. Exercise actual skill receipt materialization across install, upgrade and uninstall; keep stale built-in cleanup and report-derived suite inventories current. Assisted-by: nib:gpt-6.1-sol Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(ui): explain document skill providers and unavailable selections Show provider-owned document procedures without removed built-in fallbacks, retain remaining built-in replacement notices, and translate install guidance in every locale. Cover picker labels, saved names and real API OFF normalization, and document grants, isolated execution and unchanged extraction. Acknowledge the intentionally injected GORM callback error in preference regression tests for lint. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: nib:gpt-6.1-sol * docs(agents): fix document guidance formatting Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: nib:gpt-6.1-sol * fix(ui): correct rebased skill label import Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: nib:gpt-6.1-sol --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io> |