Subagents: one slider with two handles, Min and Max; 1 is the agent alone
ci / check (push) Failing after 3s
ci / start (push) Failing after 3s

The chip's popover is one range from 1 to the server's cap (subagents.cap, /models
subagents_cap, else 32) with two handles: two range inputs overlaid on one track, the span
filled, aria-labels Min and Max with value text, keyboard as any slider, Min never past Max,
the values said above it ("Min 1 · Max 4") and the two ends under it. "Fewest"/"Most" are
gone. The hint says what the numbers count: the chat's own agent -- 1 is the agent alone, Max 4
is the agent and up to 3 subagents. Untouched on a new chat it still leaves the server's
defaults (1-4, shown). i18n: Min, Max and the new hint in all eight languages. CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
HomerandClaude Opus 5.5 committed 2026-11-09 18:06:06 +00:00
1 parent ede91887f7
commit 3510582c8f
6 files changed
+183 -95

No files matched your search

+4 -1
View File
@@ -9,7 +9,10 @@ All notable changes to LLeMbas Desktop. The format follows
### Changed
- **Subagents**, by that name everywhere. The chip under the message box says **Subagents** with the
fewest and the most a chat runs, and opens the two fields under those words; it shows where the
least and the most agents a chat runs ("Subagents 1–4"), and opens one slider with two handles,
**Min** and **Max**, from 1 to the server's cap -- Min never passes Max, and both move with the
arrow keys as well. The numbers count the chat's own agent: **1 is the agent alone**, with no
subagents; Max 4 is the agent and up to 3 subagents. The chip shows where the
server offers subagents for the chat (for a new chat, for its model), and the most is the
server's cap. Where the chat's model serves one request at a time, it says that subagents need
another model, on another server, named in the chat. Subagents work on the chat's own model
+27 -11
View File
@@ -194,8 +194,8 @@ KEYS = (
"off",
"default",
"Think before answering",
"Fewest",
"Most",
"Min",
"Max",
"Continue in a terminal…",
"Continue in a terminal",
"Run this in a terminal: the agent's session goes on there, in this chat's folder, and the chat keeps it.",
@@ -367,7 +367,7 @@ KEYS = (
"Subagent",
"Team member",
"Subagents",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.",
"This model serves one request at a time: subagents need another model, on another server, named in the chat.",
"None",
"Up to %(n)s at once",
@@ -382,7 +382,9 @@ KEYS = (
OWN: dict[str, dict[str, str]] = {
"cs": {
"This model serves one request at a time: subagents need another model, on another server, named in the chat.": "Tento model vyřizuje najednou jeden požadavek: podagenti potřebují jiný model na jiném serveru, pojmenovaný v konverzaci.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Počítá se včetně vlastního agenta konverzace. Podagent běží na modelu konverzace, na jiném jen tehdy, když ho v konverzaci pojmenujete.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Čísla počítají i vlastního agenta konverzace: 1 je agent sám, bez podagentů; Max 4 je agent a až 3 podagenti. Podagent běží na modelu konverzace, na jiném jen tehdy, když ho v konverzaci pojmenujete.",
"Min": "Min",
"Max": "Max",
"Tasks: %(n)s": "Úlohy: %(n)s",
"%(n)s running": "Běží: %(n)s",
"%(tokens)s until auto-compact": "%(tokens)s do automatického shrnutí",
@@ -601,7 +603,9 @@ OWN: dict[str, dict[str, str]] = {
},
"de": {
"This model serves one request at a time: subagents need another model, on another server, named in the chat.": "Dieses Modell bedient eine Anfrage zur Zeit: Subagenten brauchen ein anderes Modell auf einem anderen Server, im Chat genannt.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Der eigene Agent des Chats zählt mit. Ein Subagent läuft auf dem Modell des Chats, auf einem anderen nur, wenn Sie es im Chat nennen.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Die Zahlen zählen den eigenen Agenten des Chats mit: 1 ist der Agent allein, ohne Subagenten; Max 4 ist der Agent und bis zu 3 Subagenten. Ein Subagent läuft auf dem Modell des Chats, auf einem anderen nur, wenn Sie es im Chat nennen.",
"Min": "Min",
"Max": "Max",
"Tasks: %(n)s": "Aufgaben: %(n)s",
"%(n)s running": "%(n)s laufen",
"%(tokens)s until auto-compact": "%(tokens)s bis zur automatischen Zusammenfassung",
@@ -820,7 +824,9 @@ OWN: dict[str, dict[str, str]] = {
},
"es": {
"This model serves one request at a time: subagents need another model, on another server, named in the chat.": "Este modelo atiende una petición a la vez: los subagentes necesitan otro modelo, en otro servidor, nombrado en el chat.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Cuenta también el agente propio del chat. Un subagente usa el modelo del chat, u otro solo si lo nombra en el chat.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Los números cuentan el agente propio del chat: 1 es el agente solo, sin subagentes; Máx. 4 es el agente y hasta 3 subagentes. Un subagente usa el modelo del chat, u otro solo si lo nombra en el chat.",
"Min": "Mín.",
"Max": "Máx.",
"Tasks: %(n)s": "Tareas: %(n)s",
"%(n)s running": "%(n)s en marcha",
"%(tokens)s until auto-compact": "%(tokens)s hasta la compactación automática",
@@ -1039,7 +1045,9 @@ OWN: dict[str, dict[str, str]] = {
},
"fr": {
"This model serves one request at a time: subagents need another model, on another server, named in the chat.": "Ce modèle traite une requête à la fois : les sous-agents ont besoin d’un autre modèle, sur un autre serveur, nommé dans la conversation.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "L’agent de la conversation compte aussi. Un sous-agent utilise le modèle de la conversation, ou un autre seulement si vous le nommez dans la conversation.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Les nombres comptent l’agent de la conversation : 1, c’est l’agent seul, sans sous-agents ; Max 4, c’est l’agent et jusqu’à 3 sous-agents. Un sous-agent utilise le modèle de la conversation, ou un autre seulement si vous le nommez dans la conversation.",
"Min": "Min",
"Max": "Max",
"Tasks: %(n)s": "Tâches : %(n)s",
"%(n)s running": "%(n)s en cours",
"%(tokens)s until auto-compact": "%(tokens)s avant le compactage automatique",
@@ -1258,7 +1266,9 @@ OWN: dict[str, dict[str, str]] = {
},
"hu": {
"This model serves one request at a time: subagents need another model, on another server, named in the chat.": "Ez a modell egyszerre egy kérést szolgál ki: az alügynököknek másik modell kell, másik szerveren, a beszélgetésben megnevezve.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "A beszélgetés saját ügynöke is beleszámít. Az alügynök a beszélgetés modelljén fut, másikon csak akkor, ha megnevezi a beszélgetésben.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "A számokba a beszélgetés saját ügynöke is beleszámít: az 1 maga az ügynök, alügynökök nélkül; a Max. 4 az ügynök és legfeljebb 3 alügynök. Az alügynök a beszélgetés modelljén fut, másikon csak akkor, ha megnevezi a beszélgetésben.",
"Min": "Min.",
"Max": "Max.",
"Tasks: %(n)s": "Feladatok: %(n)s",
"%(n)s running": "%(n)s fut",
"%(tokens)s until auto-compact": "%(tokens)s az automatikus tömörítésig",
@@ -1477,7 +1487,9 @@ OWN: dict[str, dict[str, str]] = {
},
"it": {
"This model serves one request at a time: subagents need another model, on another server, named in the chat.": "Questo modello serve una richiesta alla volta: i sottoagenti hanno bisogno di un altro modello, su un altro server, nominato nella chat.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Conta anche l’agente della chat. Un sottoagente usa il modello della chat, o un altro solo se lo nomini nella chat.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "I numeri contano anche l’agente della chat: 1 è l’agente da solo, senza sottoagenti; Max 4 è l’agente più fino a 3 sottoagenti. Un sottoagente usa il modello della chat, o un altro solo se lo nomini nella chat.",
"Min": "Min",
"Max": "Max",
"Tasks: %(n)s": "Attività: %(n)s",
"%(n)s running": "%(n)s in corso",
"%(tokens)s until auto-compact": "%(tokens)s alla compattazione automatica",
@@ -1696,7 +1708,9 @@ OWN: dict[str, dict[str, str]] = {
},
"pl": {
"This model serves one request at a time: subagents need another model, on another server, named in the chat.": "Ten model obsługuje jedno żądanie naraz: podagenci potrzebują innego modelu, na innym serwerze, wskazanego w czacie.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Liczony razem z własnym agentem czatu. Podagent działa na modelu czatu, na innym tylko wtedy, gdy wskażesz go w czacie.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Liczby obejmują własnego agenta czatu: 1 to sam agent, bez podagentów; Maks 4 to agent i do 3 podagentów. Podagent działa na modelu czatu, na innym tylko wtedy, gdy wskażesz go w czacie.",
"Min": "Min",
"Max": "Maks",
"Tasks: %(n)s": "Zadania: %(n)s",
"%(n)s running": "Działa: %(n)s",
"%(tokens)s until auto-compact": "%(tokens)s do automatycznego streszczenia",
@@ -1915,7 +1929,9 @@ OWN: dict[str, dict[str, str]] = {
},
"sk": {
"This model serves one request at a time: subagents need another model, on another server, named in the chat.": "Tento model vybavuje naraz jednu požiadavku: podagenti potrebujú iný model na inom serveri, pomenovaný v konverzácii.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Počíta sa vrátane vlastného agenta konverzácie. Podagent beží na modeli konverzácie, na inom len vtedy, keď ho v konverzácii pomenujete.",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Čísla počítajú aj vlastného agenta konverzácie: 1 je agent sám, bez podagentov; Max 4 je agent a až 3 podagenti. Podagent beží na modeli konverzácie, na inom len vtedy, keď ho v konverzácii pomenujete.",
"Min": "Min",
"Max": "Max",
"Tasks: %(n)s": "Úlohy: %(n)s",
"%(n)s running": "Beží: %(n)s",
"%(tokens)s until auto-compact": "%(tokens)s do automatického zhrnutia",
+66 -19
View File
@@ -709,28 +709,75 @@ details[open] > summary .step__chev .icon { transform: rotate(90deg); }
}
.toggle input:checked { background: var(--accent); border-color: var(--accent); }
.toggle input:checked::after { background: var(--accent-ink); transform: translateX(var(--check-size)); }
/* The subagents, fewest and most: two number fields of one width with a dash between them, and in the header
its word before them -- fixed tracks, so nothing moves when a number grows a digit. */
.agents, .agents__heads {
display: inline-grid;
grid-template-columns: minmax(0, 1fr) var(--sp-3) minmax(0, 1fr);
gap: var(--sp-2);
align-items: center;
/* The subagents, Min and Max: one range with two handles. Three rows of known height -- the
values said on one line, the track box (one control high), the two ends -- and in the box two
range inputs laid over one track, the span between the handles filled. The inputs let only
their handles take the pointer, so either can be grabbed wherever the other is. */
.range2 { display: grid; grid-template-rows: auto var(--control-h) auto; gap: var(--sp-1); width: 100%; }
.range2__said { font: 600 var(--text-sm) / var(--leading-tight) var(--font-ui); color: var(--ink); font-variant-numeric: tabular-nums; }
.range2__box { position: relative; display: block; height: var(--control-h); --lo: 0%; --hi: 100%; }
.range2__track {
position: absolute;
top: 50%;
left: calc(var(--check-size) / 2);
right: calc(var(--check-size) / 2);
height: var(--sp-1);
transform: translateY(-50%);
background: var(--border);
border-radius: var(--radius-full);
}
.range2__fill {
position: absolute;
top: 0;
bottom: 0;
left: var(--lo);
right: calc(100% - var(--hi));
background: var(--accent);
border-radius: var(--radius-full);
}
.range2__input {
position: absolute;
inset: 0;
width: 100%;
height: var(--control-h);
height: 100%;
margin: 0;
background: none;
pointer-events: none;
-webkit-appearance: none;
appearance: none;
}
.agents__dash { color: var(--ink-muted); text-align: center; }
/* The words over the subagents' two fields, on the fields' own tracks. */
.agents__heads { height: auto; font-size: var(--text-xs); color: var(--ink-muted); }
.agents__input { width: 100%; min-width: 0; height: var(--control-h); padding: 0 var(--control-px-sm); }
.agents--compact {
grid-template-columns: auto calc(var(--w-field-xs) / 2) auto calc(var(--w-field-xs) / 2);
width: auto;
height: var(--control-h-sm);
font: var(--text-sm) var(--font-ui);
.range2__input.is-top { z-index: 1; }
.range2__input::-webkit-slider-runnable-track { height: 100%; background: none; border: 0; }
.range2__input::-moz-range-track { height: 100%; background: none; border: 0; }
.range2__input::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: var(--check-size);
height: var(--check-size);
margin-top: calc((var(--control-h) - var(--check-size)) / 2);
background: var(--surface-raised);
border: var(--border-w-thick) solid var(--accent);
border-radius: var(--radius-full);
box-shadow: var(--shadow-sm);
cursor: grab;
pointer-events: auto;
}
.agents--compact .agents__input { height: var(--control-h-sm); }
.agents__label { color: var(--ink-muted); white-space: nowrap; }
.range2__input::-moz-range-thumb {
width: var(--check-size);
height: var(--check-size);
background: var(--surface-raised);
border: var(--border-w-thick) solid var(--accent);
border-radius: var(--radius-full);
box-shadow: var(--shadow-sm);
cursor: grab;
pointer-events: auto;
}
.range2__input:focus-visible { outline: none; }
.range2__input:focus-visible::-webkit-slider-thumb { box-shadow: var(--ring); }
.range2__input:focus-visible::-moz-range-thumb { box-shadow: var(--ring); }
/* The two ends, each one handle wide, so each number sits centred under its handle at that end. */
.range2__ends { display: flex; justify-content: space-between; font-size: var(--text-xs); color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.range2__ends > span { width: var(--check-size); text-align: center; white-space: nowrap; }
/* Markdown, drawn by markdown.js from model output (never as HTML). */
.md { overflow-wrap: anywhere; min-width: 0; }
.md > * + * { margin-top: var(--sp-3); }
+24 -24
View File
@@ -83,7 +83,6 @@ const LEMBAS_I18N = {
"Copied": "Zkopírováno",
"Copy": "Kopírovat",
"Counted by the model at the last reply; the categories are estimated.": "Spočítal model při poslední odpovědi; kategorie jsou odhadnuté.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Počítá se včetně vlastního agenta konverzace. Podagent běží na modelu konverzace, na jiném jen tehdy, když ho v konverzaci pojmenujete.",
"Cut short here; the whole of it is in the web interface.": "Zde zkráceno; celé je to ve webovém rozhraní.",
"Days": "Dny",
"Delete": "Smazat",
@@ -109,7 +108,6 @@ const LEMBAS_I18N = {
"Every result, even with nothing to report.": "Každý výsledek, i když není co hlásit.",
"Every weekday at 8:00, summarise the news on my reading list": "Každý pracovní den v 8:00 shrň zprávy z mého seznamu ke čtení",
"Failed": "Selhalo",
"Fewest": "Nejméně",
"Files": "Soubory",
"Finished %(n)s": "Dokončeno: %(n)s",
"Folder": "Složka",
@@ -134,11 +132,13 @@ const LEMBAS_I18N = {
"Looking for a LLeMbas server there…": "Hledám tam server LLeMbas…",
"MCP tools": "Nástroje MCP",
"Manual — asks first": "Manual — nejdřív se zeptá",
"Max": "Max",
"Maximise": "Maximalizovat",
"Memory and personal": "Paměť a osobní",
"Menu": "Nabídka",
"Message": "Zpráva",
"Messages": "Zprávy",
"Min": "Min",
"Minimise": "Minimalizovat",
"Missed": "Zmeškáno",
"Mode": "Režim",
@@ -146,7 +146,6 @@ const LEMBAS_I18N = {
"Models": "Modely",
"Models for scheduled tasks": "Modely pro naplánované úlohy",
"More": "Více",
"Most": "Nejvíce",
"Never": "Nikdy",
"New agent chat": "Nová agentní konverzace",
"New chat": "Nová konverzace",
@@ -269,6 +268,7 @@ const LEMBAS_I18N = {
"The model's own": "Podle modelu",
"The most an agent chat may do here": "Nejvíc, co tu agentní konverzace smí",
"The next runs": "Další spuštění",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Čísla počítají i vlastního agenta konverzace: 1 je agent sám, bez podagentů; Max 4 je agent a až 3 podagenti. Podagent běží na modelu konverzace, na jiném jen tehdy, když ho v konverzaci pojmenujete.",
"The reply is ready.": "Odpověď je hotová.",
"The result is no longer there.": "Výsledek už tu není.",
"The server refused this computer's link: %(why)s": "Server odmítl propojení tohoto počítače: %(why)s",
@@ -412,7 +412,6 @@ const LEMBAS_I18N = {
"Copied": "Kopiert",
"Copy": "Kopieren",
"Counted by the model at the last reply; the categories are estimated.": "Vom Modell bei der letzten Antwort gezählt; die Kategorien sind geschätzt.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Der eigene Agent des Chats zählt mit. Ein Subagent läuft auf dem Modell des Chats, auf einem anderen nur, wenn Sie es im Chat nennen.",
"Cut short here; the whole of it is in the web interface.": "Hier gekürzt; vollständig steht es in der Weboberfläche.",
"Days": "Tage",
"Delete": "Löschen",
@@ -438,7 +437,6 @@ const LEMBAS_I18N = {
"Every result, even with nothing to report.": "Jedes Ergebnis, auch ohne Neuigkeiten.",
"Every weekday at 8:00, summarise the news on my reading list": "Jeden Werktag um 8:00 die Nachrichten auf meiner Leseliste zusammenfassen",
"Failed": "Fehlgeschlagen",
"Fewest": "Mindestens",
"Files": "Dateien",
"Finished %(n)s": "Fertig: %(n)s",
"Folder": "Ordner",
@@ -463,11 +461,13 @@ const LEMBAS_I18N = {
"Looking for a LLeMbas server there…": "Suche dort nach einem LLeMbas-Server…",
"MCP tools": "MCP-Werkzeuge",
"Manual — asks first": "Manual — fragt zuerst",
"Max": "Max",
"Maximise": "Maximieren",
"Memory and personal": "Gedächtnis und Persönliches",
"Menu": "Menü",
"Message": "Nachricht",
"Messages": "Nachrichten",
"Min": "Min",
"Minimise": "Minimieren",
"Missed": "Verpasst",
"Mode": "Modus",
@@ -475,7 +475,6 @@ const LEMBAS_I18N = {
"Models": "Modelle",
"Models for scheduled tasks": "Modelle für geplante Aufgaben",
"More": "Mehr",
"Most": "Höchstens",
"Never": "Nie",
"New agent chat": "Neuer Agenten-Chat",
"New chat": "Neuer Chat",
@@ -598,6 +597,7 @@ const LEMBAS_I18N = {
"The model's own": "Die des Modells",
"The most an agent chat may do here": "Das Meiste, was ein Agent-Chat hier darf",
"The next runs": "Die nächsten Läufe",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Die Zahlen zählen den eigenen Agenten des Chats mit: 1 ist der Agent allein, ohne Subagenten; Max 4 ist der Agent und bis zu 3 Subagenten. Ein Subagent läuft auf dem Modell des Chats, auf einem anderen nur, wenn Sie es im Chat nennen.",
"The reply is ready.": "Die Antwort ist fertig.",
"The result is no longer there.": "Das Ergebnis ist nicht mehr da.",
"The server refused this computer's link: %(why)s": "Der Server hat die Verknüpfung dieses Computers abgelehnt: %(why)s",
@@ -741,7 +741,6 @@ const LEMBAS_I18N = {
"Copied": "Copiado",
"Copy": "Copiar",
"Counted by the model at the last reply; the categories are estimated.": "Contado por el modelo en la última respuesta; las categorías son estimaciones.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Cuenta también el agente propio del chat. Un subagente usa el modelo del chat, u otro solo si lo nombra en el chat.",
"Cut short here; the whole of it is in the web interface.": "Recortado aquí; completo está en la interfaz web.",
"Days": "Días",
"Delete": "Eliminar",
@@ -767,7 +766,6 @@ const LEMBAS_I18N = {
"Every result, even with nothing to report.": "Cada resultado, incluso sin nada que informar.",
"Every weekday at 8:00, summarise the news on my reading list": "Cada día laborable a las 8:00, resume las noticias de mi lista de lectura",
"Failed": "Fallidos",
"Fewest": "Mínimo",
"Files": "Archivos",
"Finished %(n)s": "Terminadas: %(n)s",
"Folder": "Carpeta",
@@ -792,11 +790,13 @@ const LEMBAS_I18N = {
"Looking for a LLeMbas server there…": "Buscando un servidor LLeMbas allí…",
"MCP tools": "Herramientas MCP",
"Manual — asks first": "Manual — pregunta primero",
"Max": "Máx.",
"Maximise": "Maximizar",
"Memory and personal": "Memoria y datos personales",
"Menu": "Menú",
"Message": "Mensaje",
"Messages": "Mensajes",
"Min": "Mín.",
"Minimise": "Minimizar",
"Missed": "Perdida",
"Mode": "Modo",
@@ -804,7 +804,6 @@ const LEMBAS_I18N = {
"Models": "Modelos",
"Models for scheduled tasks": "Modelos para tareas programadas",
"More": "Más",
"Most": "Máximo",
"Never": "Nunca",
"New agent chat": "Nuevo chat de agente",
"New chat": "Nuevo chat",
@@ -927,6 +926,7 @@ const LEMBAS_I18N = {
"The model's own": "La del modelo",
"The most an agent chat may do here": "Lo máximo que un chat de agente puede hacer aquí",
"The next runs": "Las próximas ejecuciones",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Los números cuentan el agente propio del chat: 1 es el agente solo, sin subagentes; Máx. 4 es el agente y hasta 3 subagentes. Un subagente usa el modelo del chat, u otro solo si lo nombra en el chat.",
"The reply is ready.": "La respuesta está lista.",
"The result is no longer there.": "El resultado ya no está.",
"The server refused this computer's link: %(why)s": "El servidor rechazó la vinculación de este equipo: %(why)s",
@@ -1070,7 +1070,6 @@ const LEMBAS_I18N = {
"Copied": "Copié",
"Copy": "Copier",
"Counted by the model at the last reply; the categories are estimated.": "Compté par le modèle lors de la dernière réponse ; les catégories sont estimées.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "L’agent de la conversation compte aussi. Un sous-agent utilise le modèle de la conversation, ou un autre seulement si vous le nommez dans la conversation.",
"Cut short here; the whole of it is in the web interface.": "Tronqué ici ; le tout est dans l'interface web.",
"Days": "Jours",
"Delete": "Supprimer",
@@ -1096,7 +1095,6 @@ const LEMBAS_I18N = {
"Every result, even with nothing to report.": "Chaque résultat, même sans rien à signaler.",
"Every weekday at 8:00, summarise the news on my reading list": "Chaque jour ouvré à 8 h, résume les nouvelles de ma liste de lecture",
"Failed": "Échecs",
"Fewest": "Au moins",
"Files": "Fichiers",
"Finished %(n)s": "Terminées : %(n)s",
"Folder": "Dossier",
@@ -1121,11 +1119,13 @@ const LEMBAS_I18N = {
"Looking for a LLeMbas server there…": "Recherche d'un serveur LLeMbas à cette adresse…",
"MCP tools": "Outils MCP",
"Manual — asks first": "Manual — demande d'abord",
"Max": "Max",
"Maximise": "Agrandir",
"Memory and personal": "Mémoire et informations personnelles",
"Menu": "Menu",
"Message": "Message",
"Messages": "Messages",
"Min": "Min",
"Minimise": "Réduire",
"Missed": "Manquée",
"Mode": "Mode",
@@ -1133,7 +1133,6 @@ const LEMBAS_I18N = {
"Models": "Modèles",
"Models for scheduled tasks": "Modèles pour les tâches planifiées",
"More": "Plus",
"Most": "Au plus",
"Never": "Jamais",
"New agent chat": "Nouvelle discussion d'agent",
"New chat": "Nouvelle conversation",
@@ -1256,6 +1255,7 @@ const LEMBAS_I18N = {
"The model's own": "Celle du modèle",
"The most an agent chat may do here": "Le maximum qu'une conversation d'agent peut faire ici",
"The next runs": "Les prochaines exécutions",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Les nombres comptent l’agent de la conversation : 1, c’est l’agent seul, sans sous-agents ; Max 4, c’est l’agent et jusqu’à 3 sous-agents. Un sous-agent utilise le modèle de la conversation, ou un autre seulement si vous le nommez dans la conversation.",
"The reply is ready.": "La réponse est prête.",
"The result is no longer there.": "Le résultat n'est plus là.",
"The server refused this computer's link: %(why)s": "Le serveur a refusé la liaison de cet ordinateur : %(why)s",
@@ -1399,7 +1399,6 @@ const LEMBAS_I18N = {
"Copied": "Másolva",
"Copy": "Másolás",
"Counted by the model at the last reply; the categories are estimated.": "A modell számolta az utolsó válasznál; a kategóriák becslések.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "A beszélgetés saját ügynöke is beleszámít. Az alügynök a beszélgetés modelljén fut, másikon csak akkor, ha megnevezi a beszélgetésben.",
"Cut short here; the whole of it is in the web interface.": "Itt rövidítve; a teljes a webes felületen van.",
"Days": "Napok",
"Delete": "Törlés",
@@ -1425,7 +1424,6 @@ const LEMBAS_I18N = {
"Every result, even with nothing to report.": "Minden eredmény, akkor is, ha nincs mit jelenteni.",
"Every weekday at 8:00, summarise the news on my reading list": "Minden hétköznap 8:00-kor foglald össze az olvasólistám híreit",
"Failed": "Sikertelen",
"Fewest": "Legalább",
"Files": "Fájlok",
"Finished %(n)s": "Kész: %(n)s",
"Folder": "Mappa",
@@ -1450,11 +1448,13 @@ const LEMBAS_I18N = {
"Looking for a LLeMbas server there…": "LLeMbas-kiszolgáló keresése ott…",
"MCP tools": "MCP-eszközök",
"Manual — asks first": "Manual — előbb kérdez",
"Max": "Max.",
"Maximise": "Teljes méret",
"Memory and personal": "Memória és személyes adatok",
"Menu": "Menü",
"Message": "Üzenet",
"Messages": "Üzenetek",
"Min": "Min.",
"Minimise": "Kis méret",
"Missed": "Elmaradt",
"Mode": "Mód",
@@ -1462,7 +1462,6 @@ const LEMBAS_I18N = {
"Models": "Modellek",
"Models for scheduled tasks": "Modellek az ütemezett feladatokhoz",
"More": "Több",
"Most": "Legfeljebb",
"Never": "Soha",
"New agent chat": "Új ügynökcsevegés",
"New chat": "Új csevegés",
@@ -1585,6 +1584,7 @@ const LEMBAS_I18N = {
"The model's own": "A modell sajátja",
"The most an agent chat may do here": "A legtöbb, amit egy ügynök-csevegés itt tehet",
"The next runs": "A következő futások",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "A számokba a beszélgetés saját ügynöke is beleszámít: az 1 maga az ügynök, alügynökök nélkül; a Max. 4 az ügynök és legfeljebb 3 alügynök. Az alügynök a beszélgetés modelljén fut, másikon csak akkor, ha megnevezi a beszélgetésben.",
"The reply is ready.": "A válasz kész.",
"The result is no longer there.": "Az eredmény már nincs meg.",
"The server refused this computer's link: %(why)s": "A szerver elutasította ennek a számítógépnek a kapcsolatát: %(why)s",
@@ -1728,7 +1728,6 @@ const LEMBAS_I18N = {
"Copied": "Copiato",
"Copy": "Copia",
"Counted by the model at the last reply; the categories are estimated.": "Contato dal modello all’ultima risposta; le categorie sono stime.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Conta anche l’agente della chat. Un sottoagente usa il modello della chat, o un altro solo se lo nomini nella chat.",
"Cut short here; the whole of it is in the web interface.": "Troncato qui; il resto è nell'interfaccia web.",
"Days": "Giorni",
"Delete": "Elimina",
@@ -1754,7 +1753,6 @@ const LEMBAS_I18N = {
"Every result, even with nothing to report.": "Ogni risultato, anche senza nulla da segnalare.",
"Every weekday at 8:00, summarise the news on my reading list": "Ogni giorno feriale alle 8:00, riassumi le notizie della mia lista di lettura",
"Failed": "Non riusciti",
"Fewest": "Minimo",
"Files": "File",
"Finished %(n)s": "Terminate: %(n)s",
"Folder": "Cartella",
@@ -1779,11 +1777,13 @@ const LEMBAS_I18N = {
"Looking for a LLeMbas server there…": "Cerco un server LLeMbas lì…",
"MCP tools": "Strumenti MCP",
"Manual — asks first": "Manual — chiede prima",
"Max": "Max",
"Maximise": "Ingrandisci",
"Memory and personal": "Memoria e dati personali",
"Menu": "Menu",
"Message": "Messaggio",
"Messages": "Messaggi",
"Min": "Min",
"Minimise": "Riduci a icona",
"Missed": "Mancata",
"Mode": "Modalità",
@@ -1791,7 +1791,6 @@ const LEMBAS_I18N = {
"Models": "Modelli",
"Models for scheduled tasks": "Modelli per le attività pianificate",
"More": "Altro",
"Most": "Massimo",
"Never": "Mai",
"New agent chat": "Nuova chat con agente",
"New chat": "Nuova chat",
@@ -1914,6 +1913,7 @@ const LEMBAS_I18N = {
"The model's own": "Quello del modello",
"The most an agent chat may do here": "Il massimo che una chat agente può fare qui",
"The next runs": "Le prossime esecuzioni",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "I numeri contano anche l’agente della chat: 1 è l’agente da solo, senza sottoagenti; Max 4 è l’agente più fino a 3 sottoagenti. Un sottoagente usa il modello della chat, o un altro solo se lo nomini nella chat.",
"The reply is ready.": "La risposta è pronta.",
"The result is no longer there.": "Il risultato non c’è più.",
"The server refused this computer's link: %(why)s": "Il server ha rifiutato il collegamento di questo computer: %(why)s",
@@ -2057,7 +2057,6 @@ const LEMBAS_I18N = {
"Copied": "Skopiowano",
"Copy": "Kopiuj",
"Counted by the model at the last reply; the categories are estimated.": "Policzone przez model przy ostatniej odpowiedzi; kategorie są szacunkowe.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Liczony razem z własnym agentem czatu. Podagent działa na modelu czatu, na innym tylko wtedy, gdy wskażesz go w czacie.",
"Cut short here; the whole of it is in the web interface.": "Tu skrócone; całość jest w interfejsie WWW.",
"Days": "Dni",
"Delete": "Usuń",
@@ -2083,7 +2082,6 @@ const LEMBAS_I18N = {
"Every result, even with nothing to report.": "Każdy wynik, nawet bez niczego do zgłoszenia.",
"Every weekday at 8:00, summarise the news on my reading list": "W każdy dzień roboczy o 8:00 streść wiadomości z mojej listy do czytania",
"Failed": "Nieudane",
"Fewest": "Najmniej",
"Files": "Pliki",
"Finished %(n)s": "Zakończone: %(n)s",
"Folder": "Folder",
@@ -2108,11 +2106,13 @@ const LEMBAS_I18N = {
"Looking for a LLeMbas server there…": "Szukam tam serwera LLeMbas…",
"MCP tools": "Narzędzia MCP",
"Manual — asks first": "Manual — najpierw pyta",
"Max": "Maks",
"Maximise": "Maksymalizuj",
"Memory and personal": "Pamięć i dane osobiste",
"Menu": "Menu",
"Message": "Wiadomość",
"Messages": "Wiadomości",
"Min": "Min",
"Minimise": "Minimalizuj",
"Missed": "Przegapiony",
"Mode": "Tryb",
@@ -2120,7 +2120,6 @@ const LEMBAS_I18N = {
"Models": "Modele",
"Models for scheduled tasks": "Modele dla zaplanowanych zadań",
"More": "Więcej",
"Most": "Najwięcej",
"Never": "Nigdy",
"New agent chat": "Nowy czat z agentem",
"New chat": "Nowy czat",
@@ -2243,6 +2242,7 @@ const LEMBAS_I18N = {
"The model's own": "Domyślne modelu",
"The most an agent chat may do here": "Najwięcej, co czat agenta może tu zrobić",
"The next runs": "Następne uruchomienia",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Liczby obejmują własnego agenta czatu: 1 to sam agent, bez podagentów; Maks 4 to agent i do 3 podagentów. Podagent działa na modelu czatu, na innym tylko wtedy, gdy wskażesz go w czacie.",
"The reply is ready.": "Odpowiedź jest gotowa.",
"The result is no longer there.": "Wyniku już nie ma.",
"The server refused this computer's link: %(why)s": "Serwer odrzucił połączenie tego komputera: %(why)s",
@@ -2386,7 +2386,6 @@ const LEMBAS_I18N = {
"Copied": "Skopírované",
"Copy": "Kopírovať",
"Counted by the model at the last reply; the categories are estimated.": "Spočítal model pri poslednej odpovedi; kategórie sú odhadnuté.",
"Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Počíta sa vrátane vlastného agenta konverzácie. Podagent beží na modeli konverzácie, na inom len vtedy, keď ho v konverzácii pomenujete.",
"Cut short here; the whole of it is in the web interface.": "Tu skrátené; celé je to vo webovom rozhraní.",
"Days": "Dni",
"Delete": "Zmazať",
@@ -2412,7 +2411,6 @@ const LEMBAS_I18N = {
"Every result, even with nothing to report.": "Každý výsledok, aj keď nie je čo hlásiť.",
"Every weekday at 8:00, summarise the news on my reading list": "Každý pracovný deň o 8:00 zhrň správy z môjho zoznamu na čítanie",
"Failed": "Zlyhalo",
"Fewest": "Najmenej",
"Files": "Súbory",
"Finished %(n)s": "Dokončené: %(n)s",
"Folder": "Priečinok",
@@ -2437,11 +2435,13 @@ const LEMBAS_I18N = {
"Looking for a LLeMbas server there…": "Hľadám tam server LLeMbas…",
"MCP tools": "Nástroje MCP",
"Manual — asks first": "Manual — najprv sa opýta",
"Max": "Max",
"Maximise": "Maximalizovať",
"Memory and personal": "Pamäť a osobné",
"Menu": "Ponuka",
"Message": "Správa",
"Messages": "Správy",
"Min": "Min",
"Minimise": "Minimalizovať",
"Missed": "Zmeškané",
"Mode": "Režim",
@@ -2449,7 +2449,6 @@ const LEMBAS_I18N = {
"Models": "Modely",
"Models for scheduled tasks": "Modely pre naplánované úlohy",
"More": "Viac",
"Most": "Najviac",
"Never": "Nikdy",
"New agent chat": "Nová agentská konverzácia",
"New chat": "Nová konverzácia",
@@ -2572,6 +2571,7 @@ const LEMBAS_I18N = {
"The model's own": "Podľa modelu",
"The most an agent chat may do here": "Najviac, čo tu agentská konverzácia smie",
"The next runs": "Ďalšie spustenia",
"The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.": "Čísla počítajú aj vlastného agenta konverzácie: 1 je agent sám, bez podagentov; Max 4 je agent a až 3 podagenti. Podagent beží na modeli konverzácie, na inom len vtedy, keď ho v konverzácii pomenujete.",
"The reply is ready.": "Odpoveď je hotová.",
"The result is no longer there.": "Výsledok už tu nie je.",
"The server refused this computer's link: %(why)s": "Server odmietol prepojenie tohto počítača: %(why)s",
+2 -3
View File
@@ -652,7 +652,7 @@ function effortChip(model, value, onChange) {
}
/**
* The subagents a chat may run: a chip saying the fewest and the most, opening the two fields.
* The subagents a chat may run: a chip saying Min–Max, opening one range with two handles.
* `value` { min, max } or empty; `cap` the instance's most, where the server says it.
*/
function agentsChip(value, onChange, { cap, own } = {}) {
@@ -669,8 +669,7 @@ function agentsChip(value, onChange, { cap, own } = {}) {
h(
"div",
{ class: "pop__body" },
h("label", { class: "pop__title", for: "agents-min", text: t("Subagents") }),
h("div", { class: "agents__heads", "aria-hidden": "true" }, h("span", { text: t("Fewest") }), h("span"), h("span", { text: t("Most") })),
h("p", { class: "pop__title", text: t("Subagents") }),
fields,
own ? h("p", { class: "hint is-warn", text: SUBAGENTS_OWN() }) : null,
h("p", { class: "hint", text: SUBAGENTS_HINT() }),
+60 -37
View File
@@ -226,64 +226,87 @@ export function subagentsCap(...sources) {
}
return knownCap || SUBAGENTS_CAP
}
export const SUBAGENTS_HINT = () => t("Counted with the chat's own agent. A subagent runs on the chat's model, or on another only when you name it in the chat.")
// The numbers count the chat's own agent: 1 is the agent alone.
export const SUBAGENTS_HINT = () => t("The numbers count this chat's own agent: 1 is the agent alone, with no subagents; Max 4 is the agent and up to 3 subagents. A subagent runs on the chat's model, or on another only when you name it in the chat.")
// The spec's `subagents.setting.own`: beside the setting where the chat's model cannot serve them.
export const SUBAGENTS_OWN = () => t("This model serves one request at a time: subagents need another model, on another server, named in the chat.")
// A new chat's setting as the harness spec seeds it (`loop.json` agents): 1 to 4.
export const AGENTS_DEFAULT = { min: 1, max: 4 }
/**
* The subagents a chat may run: the fewest and the most, as two number fields on one shared
* track. `value` is { min, max } (empty fields for a new chat: the server's defaults then stand);
* `cap` the instance's most; `onChange({ min, max })` once a field is changed, with the empty one
* left out. The server checks the pair and says the bounds when it refuses one.
* The agents a chat may run, its own agent counted: one range from 1 to `cap` with two handles,
* Min and Max -- two range inputs overlaid on one track, the span between them filled. Each is a
* real slider (arrow keys, Home/End, Page Up/Down), and Min never passes Max. `value` is
* { min, max } (empty for a new chat: the spec's defaults are shown, and left to the server
* unless a handle moves); `el.value` the pair. The server checks it again.
*/
export function agentsControl({ value, onChange, id, compact, cap = SUBAGENTS_CAP }) {
const field = (which, v, label) =>
export function agentsControl({ value, onChange, id, cap = SUBAGENTS_CAP }) {
const top = Math.max(1, Number(cap) || SUBAGENTS_CAP)
const clamp = (n, d) => Math.min(top, Math.max(1, Number.isFinite(Number(n)) && n !== null && n !== "" ? Number(n) : d))
let given = value || {}
let touched = false
const handle = (which, label) =>
h("input", {
type: "number",
class: "agents__input",
type: "range",
class: `range2__input range2__input--${which}`,
id: which === "min" ? id : null,
min: "1",
max: String(cap),
max: String(top),
step: "1",
inputmode: "numeric",
value: v === undefined || v === null ? "" : String(v),
placeholder: compact ? null : t("default"),
"aria-label": label,
title: label,
})
const low = field("min", value?.min, t("Fewest"))
const high = field("max", value?.max, t("Most"))
const bounds = () => {
high.min = low.value || "1"
low.max = high.value || String(cap)
const low = handle("min", t("Min"))
const high = handle("max", t("Max"))
const said = h("output", { class: "range2__said", "aria-live": "polite", for: id || null })
const fill = h("span", { class: "range2__fill", "aria-hidden": "true" })
const box = h("span", { class: "range2__box" }, h("span", { class: "range2__track", "aria-hidden": "true" }, fill), low, high)
const draw = () => {
const lo = Number(low.value)
const hi = Number(high.value)
const at = (n) => (top > 1 ? ((n - 1) / (top - 1)) * 100 : 0)
box.style.setProperty("--lo", `${at(lo)}%`)
box.style.setProperty("--hi", `${at(hi)}%`)
// Where the two meet, the one that can still move is on top: Min at the far end, else Max.
low.classList.toggle("is-top", lo === hi && hi === top)
low.setAttribute("aria-valuetext", `${t("Min")} ${lo}`)
high.setAttribute("aria-valuetext", `${t("Max")} ${hi}`)
said.textContent = `${t("Min")} ${lo} · ${t("Max")} ${hi}`
}
bounds()
const read = () => {
const out = {}
if (low.value) out.min = Number(low.value)
if (high.value) out.max = Number(high.value)
return out
const set = (v) => {
const hi = clamp(v?.max, Math.min(AGENTS_DEFAULT.max, top))
const lo = Math.min(hi, clamp(v?.min, AGENTS_DEFAULT.min))
high.value = String(hi)
low.value = String(lo)
draw()
}
for (const input of [low, high]) {
input.addEventListener("change", () => {
bounds()
onChange?.(read())
low.addEventListener("input", () => {
if (Number(low.value) > Number(high.value)) low.value = high.value
touched = true
draw()
})
}
high.addEventListener("input", () => {
if (Number(high.value) < Number(low.value)) high.value = low.value
touched = true
draw()
})
for (const input of [low, high]) input.addEventListener("change", () => onChange?.(read()))
const read = () => (touched || given.min || given.max ? { min: Number(low.value), max: Number(high.value) } : {})
set(given)
const el = h(
"span",
{ class: `agents${compact ? " agents--compact" : ""}`, role: "group", "aria-label": t("Subagents"), title: SUBAGENTS_HINT() },
compact ? h("span", { class: "agents__label", text: t("Subagents") }) : null,
low,
h("span", { class: "agents__dash", "aria-hidden": "true", text: "–" }),
high,
{ class: "range2", role: "group", "aria-label": t("Subagents") },
said,
box,
h("span", { class: "range2__ends", "aria-hidden": "true" }, h("span", { text: "1" }), h("span", { text: String(top) })),
)
Object.defineProperty(el, "value", {
get: read,
set: (v) => {
low.value = v?.min ?? ""
high.value = v?.max ?? ""
bounds()
given = v || {}
touched = false
set(given)
},
})
return el