shadok-ai 0.2.64 → 0.2.66
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/package.json +1 -1
- package/public/index.html +36 -33
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -1092,10 +1092,10 @@
|
|
|
1092
1092
|
#chanBar .gauge .label { display: none; } /* valeurs seules, plus compact */
|
|
1093
1093
|
#chanBar { gap: 6px; padding: 6px 10px; }
|
|
1094
1094
|
header { flex-wrap: wrap; row-gap: 6px; gap: 8px; padding: 8px 12px; }
|
|
1095
|
-
/* One header row: brand + dials +
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
its base `display: contents
|
|
1095
|
+
/* One header row: brand + dials + ⋯. reflowHeaderTools (JS) moves ALL tool
|
|
1096
|
+
icons into the ⋯ menu on a phone, so nothing wraps to a second line. The
|
|
1097
|
+
spacer that right-aligns them on desktop is dropped so what remains packs
|
|
1098
|
+
left. .hdr-tools keeps its base `display: contents`. */
|
|
1099
1099
|
header .spacer { display: none; }
|
|
1100
1100
|
header button.icon { padding: 5px 7px; }
|
|
1101
1101
|
/* The star pill is the widest tool and would push an icon off the row; on a
|
|
@@ -2895,7 +2895,7 @@
|
|
|
2895
2895
|
}
|
|
2896
2896
|
}
|
|
2897
2897
|
|
|
2898
|
-
// ── Window title: tokens consumed
|
|
2898
|
+
// ── Window title: instance name, then tokens consumed ───────────────────
|
|
2899
2899
|
const BASE_TITLE = document.title;
|
|
2900
2900
|
|
|
2901
2901
|
// ── Notifications: favicon badge + title badge + sound ──────────────
|
|
@@ -2904,6 +2904,20 @@
|
|
|
2904
2904
|
// channel you're not already looking at. All driven off setTabMood.
|
|
2905
2905
|
const favicon = $("favicon");
|
|
2906
2906
|
let titleBase = BASE_TITLE; // current title without the notification badge
|
|
2907
|
+
let titleTokens = 0; // summed tokens across open channels (0 = none yet)
|
|
2908
|
+
|
|
2909
|
+
// The tab title is: INSTANCE NAME first, then the tokens consumed —
|
|
2910
|
+
// "Prod — 12.3k tok". Name alone when there are no tokens yet; the default
|
|
2911
|
+
// "shadok-ai — cockpit" only when neither a custom name nor tokens exist.
|
|
2912
|
+
// Both the name change and the token tick funnel through here, so one no
|
|
2913
|
+
// longer clobbers the other (they used to fight over titleBase).
|
|
2914
|
+
function recomposeTitle() {
|
|
2915
|
+
const name = cockpitTitle || "shadok-ai";
|
|
2916
|
+
titleBase = titleTokens
|
|
2917
|
+
? name + " — " + fmtTokens(titleTokens) + " tok"
|
|
2918
|
+
: (cockpitTitle || BASE_TITLE);
|
|
2919
|
+
paint(); // re-stamp document.title (with any notification badge)
|
|
2920
|
+
}
|
|
2907
2921
|
|
|
2908
2922
|
// ── Cockpit name: editable header brand, persisted server-side ──────────
|
|
2909
2923
|
// Several cockpits (one per launch directory) are easy to confuse; a custom
|
|
@@ -2914,8 +2928,7 @@
|
|
|
2914
2928
|
cockpitTitle = title && title.trim() ? title.trim() : null;
|
|
2915
2929
|
const brandName = $("brandName");
|
|
2916
2930
|
if (brandName && !brandName.isContentEditable) brandName.textContent = cockpitTitle || "shadok-ai";
|
|
2917
|
-
|
|
2918
|
-
paint(); // re-stamp document.title (with any notification badge)
|
|
2931
|
+
recomposeTitle(); // name goes first in the tab title, tokens after
|
|
2919
2932
|
if (typeof scheduleReflow === "function") scheduleReflow(); // name width changed
|
|
2920
2933
|
}
|
|
2921
2934
|
|
|
@@ -3125,17 +3138,18 @@
|
|
|
3125
3138
|
}
|
|
3126
3139
|
|
|
3127
3140
|
/**
|
|
3128
|
-
*
|
|
3129
|
-
* Counts fresh input + cache writes + output; cache READS are
|
|
3130
|
-
* they re-bill the whole context on every turn and would drown the
|
|
3141
|
+
* The tokens consumed by the open channels, shown AFTER the instance name in
|
|
3142
|
+
* the tab title. Counts fresh input + cache writes + output; cache READS are
|
|
3143
|
+
* excluded — they re-bill the whole context on every turn and would drown the
|
|
3144
|
+
* number. The name/tokens composition lives in recomposeTitle.
|
|
3131
3145
|
*/
|
|
3132
3146
|
function refreshTitle() {
|
|
3133
3147
|
let sum = 0;
|
|
3134
3148
|
for (const t of tabs) {
|
|
3135
3149
|
if (t.tokens) sum += t.tokens.input + t.tokens.cacheCreation + t.tokens.output;
|
|
3136
3150
|
}
|
|
3137
|
-
|
|
3138
|
-
|
|
3151
|
+
titleTokens = sum;
|
|
3152
|
+
recomposeTitle();
|
|
3139
3153
|
}
|
|
3140
3154
|
|
|
3141
3155
|
/**
|
|
@@ -4835,34 +4849,23 @@
|
|
|
4835
4849
|
window.open("https://github.com/shadok-ai/shadok-ai", "_blank", "noopener");
|
|
4836
4850
|
});
|
|
4837
4851
|
|
|
4838
|
-
// ── Header
|
|
4839
|
-
//
|
|
4840
|
-
//
|
|
4841
|
-
// the real button
|
|
4842
|
-
//
|
|
4852
|
+
// ── Header tools placement ───────────────────────────────────────────
|
|
4853
|
+
// Desktop keeps every tool icon in the header. A phone keeps the header to a
|
|
4854
|
+
// SINGLE row (brand + dials + ⋯) by moving EVERY tool icon into the ⋯ menu —
|
|
4855
|
+
// the real button elements, so their click handlers travel with them.
|
|
4856
|
+
// Recomputed on load, on resize, and when the instance name changes.
|
|
4843
4857
|
const OVERFLOW_TOOLS = ["secretsBtn", "profilesBtn", "telegramBtn", "muteNotif"];
|
|
4844
4858
|
function reflowHeaderTools() {
|
|
4845
4859
|
const hdrTools = document.querySelector(".hdr-tools");
|
|
4846
4860
|
const moreWrap = document.querySelector(".more-wrap");
|
|
4847
|
-
const moreBtn = $("moreBtn");
|
|
4848
4861
|
const overflow = $("overflowTools");
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
// 1. Reset: every tool back in the header, in the declared order.
|
|
4862
|
+
if (!hdrTools || !moreWrap || !overflow) return;
|
|
4863
|
+
const mobile = matchMedia("(max-width: 640px)").matches;
|
|
4852
4864
|
for (const id of OVERFLOW_TOOLS) {
|
|
4853
4865
|
const el = $(id);
|
|
4854
|
-
if (el)
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
if (!matchMedia("(max-width: 640px)").matches) return;
|
|
4858
|
-
// 3. Move icons from the end into the menu until ⋯ is back on the first row.
|
|
4859
|
-
// Two rows → ⋯ sits a line-height below the brand; the 8px threshold
|
|
4860
|
-
// ignores sub-pixel jitter.
|
|
4861
|
-
const rowTop = () => brand.getBoundingClientRect().top;
|
|
4862
|
-
for (let i = OVERFLOW_TOOLS.length - 1; i >= 0; i--) {
|
|
4863
|
-
if (moreBtn.getBoundingClientRect().top - rowTop() < 8) break; // it fits now
|
|
4864
|
-
const el = $(OVERFLOW_TOOLS[i]);
|
|
4865
|
-
if (el) overflow.insertBefore(el, overflow.firstChild); // keep original order
|
|
4866
|
+
if (!el) continue;
|
|
4867
|
+
if (mobile) overflow.appendChild(el); // all into the ⋯ menu
|
|
4868
|
+
else hdrTools.insertBefore(el, moreWrap); // back in the header, in order
|
|
4866
4869
|
}
|
|
4867
4870
|
}
|
|
4868
4871
|
let reflowPending = false;
|