@songsid/agend 2.0.11-beta.28 β 2.0.11-beta.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ui/settings.html +39 -9
- package/package.json +1 -1
package/dist/ui/settings.html
CHANGED
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
<div class="banner" id="banner"></div>
|
|
78
78
|
<main>
|
|
79
79
|
<section>
|
|
80
|
-
<div class="sec-head"><h2>π€ My Agents</h2><div class="grow"></div><button class="sm" id="newAgentBtn">+ New</button></div>
|
|
80
|
+
<div class="sec-head"><h2>π€ My Agents</h2><div class="grow"></div><input type="text" id="agentSearch" placeholder="π Searchβ¦" style="width:180px;margin-right:8px"><button class="sm" id="newAgentBtn">+ New</button></div>
|
|
81
81
|
<div id="newAgent"></div>
|
|
82
82
|
<div class="card" id="agents"></div>
|
|
83
83
|
</section>
|
|
@@ -170,21 +170,36 @@
|
|
|
170
170
|
const ch = channels()[idx];
|
|
171
171
|
return ch ? `${ch.type} (${chLabel(idx)})` : inst.channel_id;
|
|
172
172
|
}
|
|
173
|
+
// Display name: profile display_name β else strip the -t<topicId> suffix.
|
|
174
|
+
const shortName = (name, inst) => (inst && inst.display_name) || name.replace(/-t\d+$/, "");
|
|
175
|
+
const STATUS_TEXT = { running: "π’ Running", crashed: "π΄ Crashed", stopped: "βͺ Stopped" };
|
|
176
|
+
const STATUS_ORDER = { running: 0, crashed: 1, stopped: 2 };
|
|
173
177
|
function renderAgents() {
|
|
174
178
|
const host = $("agents"); host.innerHTML = "";
|
|
175
179
|
const insts = state.fleet.instances || {};
|
|
176
|
-
const
|
|
177
|
-
|
|
180
|
+
const filter = ($("agentSearch")?.value || "").trim().toLowerCase();
|
|
181
|
+
let names = Object.keys(insts);
|
|
182
|
+
if (filter) names = names.filter(n => n.toLowerCase().includes(filter) || shortName(n, insts[n]).toLowerCase().includes(filter));
|
|
183
|
+
// Group by status: Running first, then Crashed, then Stopped; name within.
|
|
184
|
+
names.sort((a, b) => {
|
|
185
|
+
const sa = STATUS_ORDER[state.live[a]?.status || "stopped"], sb = STATUS_ORDER[state.live[b]?.status || "stopped"];
|
|
186
|
+
return sa !== sb ? sa - sb : a.localeCompare(b);
|
|
187
|
+
});
|
|
188
|
+
if (!Object.keys(insts).length) { host.className = "card empty"; host.textContent = "No agents yet β click + New."; return; }
|
|
189
|
+
if (!names.length) { host.className = "card empty"; host.textContent = "No agents match \"" + filter + "\"."; return; }
|
|
178
190
|
host.className = "card";
|
|
179
191
|
for (const name of names) {
|
|
180
192
|
const inst = insts[name];
|
|
181
193
|
const st = state.live[name]?.status || "stopped";
|
|
182
194
|
const running = st === "running";
|
|
195
|
+
const short = shortName(name, inst);
|
|
183
196
|
const item = el("div", { class: "item" });
|
|
184
197
|
const chTag = agentChannelLabel(inst);
|
|
185
198
|
item.append(el("div", { class: "item-row" },
|
|
186
199
|
el("span", { class: "dot " + st }),
|
|
187
|
-
el("span", { class: "name" },
|
|
200
|
+
el("span", { class: "name", title: name }, short),
|
|
201
|
+
short !== name ? el("span", { class: "sub", style: "margin:0;font-size:11px" }, name) : null,
|
|
202
|
+
el("span", { style: "font-size:12px;color:var(--muted)" }, STATUS_TEXT[st] || st),
|
|
188
203
|
chTag ? el("span", { class: "tag" + (chTag.includes("persona") ? " persona" : chTag.includes("telegram") ? " tg" : "") }, chTag) : null,
|
|
189
204
|
el("span", { class: "sub", style: "margin:0" }, inst.backend || state.fleet.defaults?.backend || "claude-code"),
|
|
190
205
|
el("span", { class: "spacer" }),
|
|
@@ -204,16 +219,30 @@
|
|
|
204
219
|
const fWd = el("input", { type: "text", value: inst.working_directory || "" });
|
|
205
220
|
const fChan = select(inst.channel_id || "", ["", ...channelIds()]);
|
|
206
221
|
const fDesc = el("input", { type: "text", value: inst.description || "" });
|
|
222
|
+
const fSys = el("input", { type: "text", value: inst.systemPrompt || "", placeholder: "e.g. file:prompts/dev.md" });
|
|
223
|
+
const tags = [...(inst.tags || [])];
|
|
224
|
+
const fGeneral = el("input", { type: "checkbox" }); fGeneral.checked = !!inst.general_topic;
|
|
207
225
|
const msg = el("span", { class: "msg" });
|
|
208
226
|
box.append(
|
|
209
227
|
el("div", { class: "grid2" }, el("div", {}, el("label", {}, "Backend"), fBackend), el("div", {}, el("label", {}, "Model"), fModel)),
|
|
210
228
|
el("label", {}, "Working directory"), fWd,
|
|
211
229
|
el("div", { class: "grid2" }, el("div", {}, el("label", {}, "Channel binding"), fChan), el("div", {}, el("label", {}, "Description"), fDesc)),
|
|
212
|
-
el("
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
230
|
+
el("label", {}, "System prompt"), fSys,
|
|
231
|
+
el("label", {}, "Tags"), chipList(tags, null, "tag"),
|
|
232
|
+
el("label", { style: "display:flex;align-items:center;gap:8px;cursor:pointer" }, fGeneral, el("span", {}, "General topic (fleet dispatcher)")),
|
|
233
|
+
el("div", { class: "actions" },
|
|
234
|
+
el("button", { class: "primary sm", onclick: async () => {
|
|
235
|
+
const patch = {
|
|
236
|
+
backend: fBackend.value, model: fModel.value || undefined,
|
|
237
|
+
working_directory: fWd.value, channel_id: fChan.value || undefined,
|
|
238
|
+
description: fDesc.value || undefined, systemPrompt: fSys.value || undefined,
|
|
239
|
+
tags: tags.length ? tags : undefined, general_topic: fGeneral.checked,
|
|
240
|
+
};
|
|
241
|
+
const res = await api(`/api/settings/fleet/instances/${encodeURIComponent(name)}`, { method: "PATCH", body: JSON.stringify(patch) });
|
|
242
|
+
resultMsg(msg, res); if (res.ok) await reload();
|
|
243
|
+
} }, "Save"),
|
|
244
|
+
el("button", { class: "sm ghost", onclick: () => { editing = null; renderAgents(); } }, "Cancel"),
|
|
245
|
+
msg),
|
|
217
246
|
);
|
|
218
247
|
return box;
|
|
219
248
|
}
|
|
@@ -398,6 +427,7 @@
|
|
|
398
427
|
renderAll();
|
|
399
428
|
}
|
|
400
429
|
|
|
430
|
+
$("agentSearch").oninput = () => renderAgents();
|
|
401
431
|
$("newAgentBtn").onclick = () => { const open = $("newAgentBtn").textContent === "+ New"; $("newAgentBtn").textContent = open ? "Cancel" : "+ New"; renderNewAgent(open); };
|
|
402
432
|
$("newBotBtn").onclick = () => { const open = $("newBotBtn").textContent === "+ Add"; $("newBotBtn").textContent = open ? "Cancel" : "+ Add"; renderNewBot(open); };
|
|
403
433
|
$("advToggle").onclick = () => { const b = $("advBody"); const open = !b.classList.contains("open"); b.classList.toggle("open", open); $("advToggle").textContent = open ? "βΌ Collapse" : "βΆ Expand"; };
|