@songsid/agend 2.2.0-beta.13 → 2.2.0-beta.14

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.
@@ -19,7 +19,7 @@ export declare function avatarFor(input: {
19
19
  displayName?: string | null;
20
20
  /** The profile picture's version, when one is uploaded (step 0). */
21
21
  profileVersion?: string | null;
22
- /** The bot's avatar: its connection id and cached version, when the instance has its own bot and the avatar is on disk. */
22
+ /** The bot's avatar (step 1 or 2): its connection id and cached version, when the avatar is on disk. */
23
23
  bot?: {
24
24
  connection: string;
25
25
  version: string;
@@ -2,11 +2,14 @@
2
2
  * #1630 (design: the comment on #1630): what stands for an instance in the web app — decided here, on the server,
3
3
  * once; the page only draws it. In order:
4
4
  * 0. the picture uploaded for it in View (its profile avatar);
5
- * 1. its own bot's avatar — only when it has a bot of its own: an instance on the shared bot skips this, the same
6
- * face for everyone tells nobody apart; so does a bot with no avatar set (a default avatar says nothing);
7
- * 2. its persona emoji (`status_emojis.delivered`, what set_persona_emoji sets): unicode as text, a Discord server
5
+ * 1. its own bot's avatar, when it has a bot of its own (a persona bot);
6
+ * 2. (#1867) else the avatar of the bot it speaks through on Telegram/Discord — the General (primary) bot, or a bot it
7
+ * shares — so the web shows the face the chat shows; with no connection of its own (web-only), the primary's.
8
+ * A bot with no avatar set falls through at 1 and 2 (a default avatar says nothing);
9
+ * 3. its persona emoji (`status_emojis.delivered`, what set_persona_emoji sets): unicode as text, a Discord server
8
10
  * emoji through the emoji route (a Telegram custom emoji has no picture here and falls through);
9
- * 3. the first character of its display name, or of its name.
11
+ * 4. the first character of its display name, or of its name.
12
+ * The accent ring (a Discord role colour) goes with an own bot's face only: a shared bot's would ring everyone alike.
10
13
  * Images are same-origin `/ui/img/…` URLs only; the version makes a changed picture a new URL.
11
14
  */
12
15
  import { normalizeEmoji } from "./status-emojis.js";
@@ -1 +1 @@
1
- {"version":3,"file":"instance-avatar.js","sourceRoot":"","sources":["../src/instance-avatar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAQpD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;AAC7E,wGAAwG;AACxG,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAAE,OAAO,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAC7F,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KASzB;IACC,IAAI,KAAK,CAAC,cAAc;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,kBAAkB,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;IAC1J,IAAI,KAAK,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;IACnJ,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACjD,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAC3E,IAAI,KAAK,EAAE,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC;IACjH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA2B,EAAE,WAAuF;IACpJ,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC1C,KAAK,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,WAAW,EAAE,CAAC;QACjD,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACnC,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;;YAAM,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAU,gCAAgC;IAChF,KAAK,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,KAAK;QAAE,IAAI,UAAU,KAAK,OAAO,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAE,EAAE,UAAU,CAAC,CAAC;IACtI,OAAO,GAAG,CAAC;AACb,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9H,CAAC"}
1
+ {"version":3,"file":"instance-avatar.js","sourceRoot":"","sources":["../src/instance-avatar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAQpD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;AAC7E,wGAAwG;AACxG,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAAE,OAAO,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAC7F,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KASzB;IACC,IAAI,KAAK,CAAC,cAAc;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,kBAAkB,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;IAC1J,IAAI,KAAK,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;IACnJ,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACjD,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAC3E,IAAI,KAAK,EAAE,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC;IACjH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA2B,EAAE,WAAuF;IACpJ,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC1C,KAAK,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,WAAW,EAAE,CAAC;QACjD,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACnC,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;;YAAM,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAU,gCAAgC;IAChF,KAAK,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,KAAK;QAAE,IAAI,UAAU,KAAK,OAAO,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAE,EAAE,UAAU,CAAC,CAAC;IACtI,OAAO,GAAG,CAAC;AACb,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9H,CAAC"}
@@ -13,6 +13,8 @@ import { UsageBody, UsageDialog } from "./usage-dialog.js";
13
13
 
14
14
  export const TEXT_SIZE_KEY = "agend_text_size";
15
15
  export const VIEW_FIT_KEY = "agend_view_fit";
16
+ /** #1869: set once this device's View Fit was put back (a size chosen on another page used to turn it off). */
17
+ export const VIEW_FIT_RESTORED_KEY = "agend_view_fit_1869";
16
18
  const LEGACY_DENSITY_KEY = "agend_view_density";
17
19
  export const TEXT_SIZES = ["s", "m", "l"];
18
20
  /** View's terminal: its fitted size times this (S / M / L are View's old compact / – / comfortable). */
@@ -24,6 +26,7 @@ const write = (k, v) => { try { localStorage.setItem(k, v); } catch { /* this pa
24
26
  /**
25
27
  * This device's choice: `agend_text_size` (+ View's Fit), else — once — from View's `agend_view_density`:
26
28
  * comfortable → L, compact → S (Fit off); fit, or nothing → M with View on Fit (View's default, as before).
29
+ * #1869: until then any page's S / M / L also turned View's Fit off, so a Fit off from before is put back once.
27
30
  */
28
31
  export function loadTextSize() {
29
32
  let size = read(TEXT_SIZE_KEY), fit = read(VIEW_FIT_KEY);
@@ -31,7 +34,11 @@ export function loadTextSize() {
31
34
  const legacy = read(LEGACY_DENSITY_KEY);
32
35
  size = legacy === "comfortable" ? "l" : legacy === "compact" ? "s" : "m";
33
36
  fit = legacy === "comfortable" || legacy === "compact" ? "0" : "1";
34
- write(TEXT_SIZE_KEY, size); write(VIEW_FIT_KEY, fit);
37
+ write(TEXT_SIZE_KEY, size); write(VIEW_FIT_KEY, fit); write(VIEW_FIT_RESTORED_KEY, "1");
38
+ }
39
+ if (read(VIEW_FIT_RESTORED_KEY) !== "1") {
40
+ if (fit === "0") { fit = "1"; write(VIEW_FIT_KEY, fit); }
41
+ write(VIEW_FIT_RESTORED_KEY, "1");
35
42
  }
36
43
  return { size, viewFit: fit !== "0" };
37
44
  }
@@ -50,11 +57,15 @@ export function initTextSize() {
50
57
  window.addEventListener("storage", (e) => { if (!e || e.key === TEXT_SIZE_KEY || e.key === VIEW_FIT_KEY || e.key === null) textSizeStore.set(loadTextSize()); });
51
58
  }
52
59
  }
53
- /** A size chosen anywhere is the size everywhere (View's Fit included: the last choice wins). */
54
- export function setTextSize(size) {
60
+ /**
61
+ * A size chosen anywhere is the size everywhere. View's Fit is left only from View's own Aa (`view`): a size chosen on
62
+ * another page keeps View on Fit (#1869).
63
+ */
64
+ export function setTextSize(size, { view = false } = {}) {
55
65
  if (!TEXT_SIZES.includes(size)) return;
56
- write(TEXT_SIZE_KEY, size); write(VIEW_FIT_KEY, "0");
57
- textSizeStore.set({ size, viewFit: false });
66
+ write(TEXT_SIZE_KEY, size);
67
+ if (view) write(VIEW_FIT_KEY, "0");
68
+ textSizeStore.set((s) => ({ size, viewFit: view ? false : s.viewFit }));
58
69
  }
59
70
  export function setViewFit() { write(VIEW_FIT_KEY, "1"); textSizeStore.set((s) => ({ ...s, viewFit: true })); }
60
71
 
@@ -69,7 +80,7 @@ export function TextSizeButton({ view = false }) {
69
80
  const next = order[(order.indexOf(cur) + 1) % order.length];
70
81
  const name = t(`app.textSize_${cur}`);
71
82
  const label = t("app.textSize", name);
72
- return html`<button type="button" class="btn btn-ghost btn-sm hd-text" onClick=${() => (next === "fit" ? setViewFit() : setTextSize(next))}
83
+ return html`<button type="button" class="btn btn-ghost btn-sm hd-text" onClick=${() => (next === "fit" ? setViewFit() : setTextSize(next, { view }))}
73
84
  title=${label} aria-label=${label}><${Icon} name="type" size=${16} /><span class="hide-narrow" aria-hidden="true"><span class="hd-text-names">${
74
85
  ["fit", ...TEXT_SIZES].map(k => html`<span key=${k} class=${k === cur ? "on" : undefined}>${t(`app.textSize_${k}`)}</span>`)}</span></span></button>`;
75
86
  }
@@ -114,7 +114,9 @@ export { viewStore };
114
114
  // ── The panel ──
115
115
 
116
116
  // readStream: one stream of reads under a lease (read-stream.js; View's pane and roster use it).
117
- const MIN_PX = 12, MAX_PX = 22;
117
+ // S / M / L: the fitted size kept within 12–22 px, then scaled. Fit (#1869): never larger than what fits — only a 6 px
118
+ // floor for legibility (a grid too wide for the box even at 6 px, e.g. 200 columns on a phone, still scrolls).
119
+ const MIN_PX = 12, MAX_PX = 22, FIT_FLOOR_PX = 6;
118
120
 
119
121
  export function ViewPanel({ route, navKey }) {
120
122
  const lease = useLease(navKey);
@@ -219,10 +221,11 @@ function Terminal({ name, lease, density }) {
219
221
  const lh = parseFloat(pcs.lineHeight) / parseFloat(pcs.fontSize);
220
222
  const lineH = Number.isFinite(lh) && lh > 0 ? lh : 1.2;
221
223
  let size = Math.min(innerW / (g.cols * glyphRatio(p)), innerH / (g.rows * lineH)) * 0.995;
222
- size = Math.max(MIN_PX, Math.min(size, MAX_PX)) * (density === "fit" ? 1 : VIEW_SCALE[density] || 1);
223
- size = Math.max(8, Math.min(size, 32));
224
+ if (density === "fit") size = Math.max(FIT_FLOOR_PX, Math.min(size, MAX_PX));
225
+ else size = Math.max(8, Math.min(Math.max(MIN_PX, Math.min(size, MAX_PX)) * (VIEW_SCALE[density] || 1), 32));
224
226
  g.key = key;
225
- if (Math.abs(size - g.applied) < 0.75) return;
227
+ // A small change is skipped only when growing (the size applied still fits); a smaller box always shrinks it.
228
+ if (size >= g.applied && size - g.applied < 0.75) return;
226
229
  g.applied = size;
227
230
  p.style.fontSize = `${size.toFixed(2)}px`; // CSSOM, never a style attribute (#1300)
228
231
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@songsid/agend",
3
- "version": "2.2.0-beta.13",
3
+ "version": "2.2.0-beta.14",
4
4
  "description": "Multi-agent fleet daemon — run any coding CLI (Claude, Gemini, Codex, OpenCode) from Telegram",
5
5
  "type": "module",
6
6
  "bin": {