tokenwait 0.1.2 → 0.1.3

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/bin/tokenwait.js CHANGED
@@ -81,7 +81,8 @@ What it changes:
81
81
  • stores ads, counters and an install key in ~/.tokenwait
82
82
  What it never does:
83
83
  • read your code, prompts, responses or transcripts
84
- • send anything except ad ids, impression counts, waiting time and the install key
84
+ • send anything except ad ids, impression counts, waiting time, the install key,
85
+ the package version and which agents and IDE add-ons are connected
85
86
  Undo at any time: npx tokenwait uninstall
86
87
  `;
87
88
 
package/lib/api.js CHANGED
@@ -24,8 +24,34 @@ function credentials() {
24
24
  return c && c.server === server() && c.client_id && c.client_secret ? c : null;
25
25
  }
26
26
 
27
- async function request(method, path, body, auth = true, timeoutMs = 5000) {
28
- const headers = { accept: 'application/json', 'user-agent': 'tokenwait/' + require('../package.json').version };
27
+ /**
28
+ * Что стоит на этой установке — для статистики оператора (без данных о человеке):
29
+ * подключённые агенты и дополнения IDE, которые выходили на связь за последние 7 дней (~/.tokenwait/ide.json).
30
+ */
31
+ function installInfo() {
32
+ const out = {};
33
+ try {
34
+ const agents = require('./agents');
35
+ out['x-tokenwait-agents'] = Object.keys(agents.AGENTS).filter((id) => agents.isInstalled(id)).join(',');
36
+ } catch (_) {}
37
+ const ide = readJson(p('ide.json'), {});
38
+ const fresh = Object.entries(ide && typeof ide === 'object' ? ide : {})
39
+ .filter(([k, v]) => /^(jetbrains|vscode)$/.test(k) && v && Date.now() - Number(v.t) < 7 * 86400_000 && /^\d+\.\d+\.\d+$/.test(String(v.v)))
40
+ .map(([k, v]) => k + '/' + v.v);
41
+ out['x-tokenwait-ide'] = fresh.join(',');
42
+ return out;
43
+ }
44
+
45
+ /** Отметка дополнения IDE: вызывают JetBrains и VS Code при запуске и раз в час. */
46
+ function markIde(kind, version) {
47
+ if (!/^(jetbrains|vscode)$/.test(kind)) return;
48
+ const ide = readJson(p('ide.json'), {});
49
+ ide[kind] = { v: String(version), t: Date.now() };
50
+ writeJson(p('ide.json'), ide);
51
+ }
52
+
53
+ async function request(method, path, body, auth = true, timeoutMs = 5000, extraHeaders = {}) {
54
+ const headers = { accept: 'application/json', 'user-agent': 'tokenwait/' + require('../package.json').version, ...extraHeaders };
29
55
  if (body !== undefined) headers['content-type'] = 'application/json';
30
56
  if (auth) {
31
57
  const c = credentials() || (await register());
@@ -55,7 +81,7 @@ async function register() {
55
81
  }
56
82
 
57
83
  async function fetchAds() {
58
- const r = await request('GET', '/v1/ads');
84
+ const r = await request('GET', '/v1/ads', undefined, true, 5000, installInfo());
59
85
  const data = {
60
86
  fetched_at: Date.now(),
61
87
  ttl_seconds: Math.min(Math.max(Number(r.ttl_seconds) || 600, 60), 3600),
@@ -76,6 +102,8 @@ async function me() {
76
102
  }
77
103
 
78
104
  module.exports = {
105
+ installInfo,
106
+ markIde,
79
107
  HttpError,
80
108
  server,
81
109
  config,
package/lib/worker.js CHANGED
@@ -54,8 +54,11 @@ async function report() {
54
54
  if (Date.now() - (pend.last_report || 0) < (ads.report_seconds || 60) * 1000) return null;
55
55
  const { counts, rest } = toImpressions(pend.ads, impSec);
56
56
  if (!Object.keys(counts).length) return null;
57
- const waitMs = pend.wait_ms || 0;
58
- writeJson(p('pending.json'), { ads: rest, wait_ms: 0, last_report: Date.now() });
57
+ // Остаток неполных показов переносим вместе с его временем ожидания: иначе в следующем отчёте
58
+ // показ, собранный из остатка, сервер отклонит (показов не больше, чем время ожидания).
59
+ const restMs = Object.values(rest).reduce((x, y) => x + y, 0);
60
+ const waitMs = Math.max(0, (pend.wait_ms || 0) - restMs);
61
+ writeJson(p('pending.json'), { ads: rest, wait_ms: Math.min(restMs, pend.wait_ms || 0), last_report: Date.now() });
59
62
  return { counts, waitMs };
60
63
  });
61
64
  if (!taken) return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokenwait",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Get paid while your AI coding agent thinks. A clearly labelled sponsored line for Claude Code, Codex CLI and Gemini CLI.",
5
5
  "bin": {
6
6
  "tokenwait": "bin/tokenwait.js"