@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.
@@ -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 names = Object.keys(insts);
177
- if (!names.length) { host.className = "card empty"; host.textContent = "No agents yet β€” click + New."; return; }
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" }, 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("div", { class: "actions" }, el("button", { class: "primary sm", onclick: async () => {
213
- const patch = { backend: fBackend.value, model: fModel.value || undefined, working_directory: fWd.value, channel_id: fChan.value || undefined, description: fDesc.value || undefined };
214
- const res = await api(`/api/settings/fleet/instances/${encodeURIComponent(name)}`, { method: "PATCH", body: JSON.stringify(patch) });
215
- resultMsg(msg, res); if (res.ok) await reload();
216
- } }, "Save"), msg),
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"; };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@songsid/agend",
3
- "version": "2.0.11-beta.28",
3
+ "version": "2.0.11-beta.29",
4
4
  "description": "Multi-agent fleet daemon β€” run any coding CLI (Claude, Gemini, Codex, OpenCode) from Telegram",
5
5
  "type": "module",
6
6
  "bin": {