jaitus 0.3.25 → 0.3.26
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/src/adSlots.js +16 -3
- package/src/tui-ink.js +15 -1
package/package.json
CHANGED
package/src/adSlots.js
CHANGED
|
@@ -51,12 +51,18 @@ export function createAdSlots({ source, isVisible, onChange, now = () => Date.no
|
|
|
51
51
|
|
|
52
52
|
function tick() {
|
|
53
53
|
const t = now();
|
|
54
|
-
const
|
|
54
|
+
const prev = lastTick;
|
|
55
55
|
lastTick = t;
|
|
56
56
|
if (!current) { stopTimer(); return; }
|
|
57
|
+
// Only time since THIS line went up counts: the timer may have been running for an
|
|
58
|
+
// earlier one, and crediting the whole tick reported views after ~0.8 s on screen.
|
|
59
|
+
const elapsed = Math.max(0, t - Math.max(prev, current.countFrom ?? current.at));
|
|
57
60
|
if (!current.reported) {
|
|
58
61
|
if (isVisible(current)) {
|
|
59
|
-
|
|
62
|
+
// Uncovered somewhere since the last tick, but when exactly is unknowable from a
|
|
63
|
+
// poll: count from this tick on, never from before it (the advertiser's side).
|
|
64
|
+
if (current.countFrom === Infinity) current.countFrom = t;
|
|
65
|
+
else current.visibleMs += elapsed;
|
|
60
66
|
if (current.visibleMs >= VIEWABLE_MS) {
|
|
61
67
|
current.reported = true;
|
|
62
68
|
const shown = Math.round(current.visibleMs);
|
|
@@ -64,6 +70,7 @@ export function createAdSlots({ source, isVisible, onChange, now = () => Date.no
|
|
|
64
70
|
}
|
|
65
71
|
} else {
|
|
66
72
|
current.visibleMs = 0; // continuous, or it does not count
|
|
73
|
+
current.countFrom = Infinity; // and restarts at the first tick that sees it again
|
|
67
74
|
}
|
|
68
75
|
}
|
|
69
76
|
if (current.placement === 'thinking' && wanted === 'thinking' && t - current.at >= ROTATE_THINKING_MS) {
|
|
@@ -102,6 +109,9 @@ export function createAdSlots({ source, isVisible, onChange, now = () => Date.no
|
|
|
102
109
|
if (current?.placement === wanted) return;
|
|
103
110
|
if (wanted === 'idle' && lastIdle && now() - lastIdle.at < IDLE_REUSE_MS) {
|
|
104
111
|
// Back to waiting moments after the last wait: the same line, not a new serve.
|
|
112
|
+
// Its clock starts again from now — it was off screen in between.
|
|
113
|
+
if (!lastIdle.slot.reported) { lastIdle.slot.visibleMs = 0; }
|
|
114
|
+
lastIdle.slot.countFrom = now();
|
|
105
115
|
set(lastIdle.slot);
|
|
106
116
|
ensureTimer();
|
|
107
117
|
return;
|
|
@@ -134,7 +144,10 @@ export function adSourceFor(client, { timeoutMs = 2500 } = {}) {
|
|
|
134
144
|
return r.ok ? (r.body?.data?.ad || null) : null;
|
|
135
145
|
},
|
|
136
146
|
async seen(token, shownMs) {
|
|
137
|
-
|
|
147
|
+
// No content-type here: client.api already sends one, and a second made the header
|
|
148
|
+
// "application/json, application/json", which the server's JSON parser does not
|
|
149
|
+
// recognise — so in 0.3.25 every report arrived with no body and was refused.
|
|
150
|
+
await call('/ads/cli/seen', { method: 'POST', body: JSON.stringify({ token, shownMs }) });
|
|
138
151
|
},
|
|
139
152
|
};
|
|
140
153
|
}
|
package/src/tui-ink.js
CHANGED
|
@@ -1493,6 +1493,7 @@ export function createTui({ slashCommands = [], fileProvider = null, meta = {},
|
|
|
1493
1493
|
},
|
|
1494
1494
|
}) : null;
|
|
1495
1495
|
|
|
1496
|
+
let adBusyTimer = null;
|
|
1496
1497
|
let inkInstance = null;
|
|
1497
1498
|
let update = () => {};
|
|
1498
1499
|
let pending = null;
|
|
@@ -2893,6 +2894,7 @@ export function createTui({ slashCommands = [], fileProvider = null, meta = {},
|
|
|
2893
2894
|
stop() {
|
|
2894
2895
|
state.active = false;
|
|
2895
2896
|
exited = true;
|
|
2897
|
+
clearTimeout(adBusyTimer);
|
|
2896
2898
|
adSlots?.stop();
|
|
2897
2899
|
if (pending) { clearTimeout(pending); pending = null; }
|
|
2898
2900
|
// Before unmount: the terminal keeps reporting after the process is gone
|
|
@@ -3028,7 +3030,19 @@ export function createTui({ slashCommands = [], fileProvider = null, meta = {},
|
|
|
3028
3030
|
state.busy = !!value;
|
|
3029
3031
|
if (value) { state.turnStartedAt = Date.now(); state.turnTokens = 0; state.turnCredits = 0; }
|
|
3030
3032
|
else { state.status = ''; state.turnStartedAt = null; }
|
|
3031
|
-
adSlots
|
|
3033
|
+
if (adSlots) {
|
|
3034
|
+
clearTimeout(adBusyTimer);
|
|
3035
|
+
if (value) {
|
|
3036
|
+
// Only work that lasts gets a "thinking" line: an instant command (/help,
|
|
3037
|
+
// /usage) would otherwise fetch one just to throw it away.
|
|
3038
|
+
adBusyTimer = setTimeout(() => { if (state.busy && !state.panel?.adSlot) adSlots.want('thinking'); }, 800);
|
|
3039
|
+
adBusyTimer.unref?.();
|
|
3040
|
+
} else {
|
|
3041
|
+
// /usage runs as a command: its panel is still open when the command ends, and
|
|
3042
|
+
// it keeps its own slot until it is closed.
|
|
3043
|
+
adSlots.want(state.panel?.adSlot ? 'usage' : 'idle');
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3032
3046
|
notifyNow();
|
|
3033
3047
|
},
|
|
3034
3048
|
setStatus(value) { state.status = plain(value); notify(); },
|