pi-ptc-meter 1.0.35 → 1.0.36

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.
Files changed (3) hide show
  1. package/README.md +2 -2
  2. package/index.ts +11 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -33,7 +33,7 @@ pi install npm:pi-ptc-meter
33
33
 
34
34
  | 键 | 默认 | 说明 |
35
35
  | --- | --- | --- |
36
- | `threshold` | `39` | 每轮调用数阈值 **39 次/轮**(> 0) |
36
+ | `threshold` | 自适应 | 每轮调用数阈值:未显式配置时 = max(3, 2.5× 最近 40 轮中位);显式配置则用配置值 |
37
37
  | `inject` | `true` | 是否注入回灌消息 |
38
38
  | `notify` | `false` | 改用弹窗提示 |
39
39
 
@@ -148,7 +148,7 @@ Config file `~/.pi/ptc-meter.json` (optional; invalid JSON falls back):
148
148
 
149
149
  | Key | Default | Description |
150
150
  | --- | --- | --- |
151
- | `threshold` | `39` | Per-turn call threshold (> 0) |
151
+ | `threshold` | adaptive | Per-turn call threshold: when unset = max(3, 2.5x median of the last 40 turns; an explicit value wins |
152
152
  | `inject` | `true` | Enable the feedback message |
153
153
  | `notify` | `false` | Use UI notifications instead |
154
154
 
package/index.ts CHANGED
@@ -58,9 +58,17 @@ function loadConf(): Conf {
58
58
  }
59
59
 
60
60
  /** 生效阈值(配置无值或非法时回退默认)。 */
61
+ /** 生效阈值:显式配置优先;否则自适应 2.5× 最近窗口中位。 */
62
+ // 固定阈值在短任务会话里永不触发(2026-10-18 实测:本会话中位 6、阈值 50 → 0/60 轮)。
63
+ // 4398 轮回测:固定 50 触发 16.7%(短会话 0),2.5×中位 触发 13.1%(长短会话都能触发)。
61
64
  function threshold(): number {
62
65
  const c = loadConf();
63
- return typeof c.threshold === "number" && c.threshold > 0 ? c.threshold : DEFAULT_THRESHOLD;
66
+ if (typeof c.threshold === "number" && c.threshold > 0) return c.threshold;
67
+ try {
68
+ const cs = recentRows(TAIL, "").map((r) => r.calls).filter((x) => typeof x === "number" && x >= 0);
69
+ if (cs.length >= 10) return Math.max(3, Math.round(2.5 * median(cs)));
70
+ } catch { /* 回退默认 */ }
71
+ return DEFAULT_THRESHOLD;
64
72
  }
65
73
 
66
74
  // 轮内计数(反馈回路:随注入回到上下文,见 before_agent_start)
@@ -134,7 +142,7 @@ function recentRows(n: number, sid: string): Row[] {
134
142
  try {
135
143
  const j = JSON.parse(r) as { calls?: number; ms?: number; est?: number | null; estCalls?: number | null; sid?: string };
136
144
  const jsid = (j.sid ?? "").toLowerCase().replace(/\.jsonl$/, "");
137
- if (jsid !== sid) return null; // 会话不符或无 sid 旧记录:不进统计(sid 已规范化,跨重启/带后缀的历史行可合并)
145
+ if (sid && jsid !== sid) return null; // 空 sid = 跨会话(阈值自适应用) // 会话不符或无 sid 旧记录:不进统计(sid 已规范化,跨重启/带后缀的历史行可合并)
138
146
  return { calls: j.calls ?? 0, ms: typeof j.ms === "number" ? j.ms : 0, est: typeof j.est === "number" ? j.est : null, estCalls: typeof j.estCalls === "number" ? j.estCalls : null };
139
147
  } catch { return null; }
140
148
  })
@@ -166,7 +174,7 @@ const EST_RE = /(?:预计|预估|eta)[^0-9\n]{0,8}(\d+(?:\.\d+)?)\s*(秒|s(?!\w)
166
174
  /** 从我的回复文本里解析预计耗时(秒);无声明或非法值返回 null。 */
167
175
  function parseEstimate(text: string): number | null {
168
176
  try {
169
- // 扫**尾部窗口**:声明写在回复末尾;前 6000 字符从未覆盖到它(实测 est 填充率 9.7%,2026-10-18 全量 4373 轮)
177
+ // 扫**尾部窗口**:声明写在回复末尾;前 6000 字符从未覆盖到它(实测 est 填充率仅 1.5%)
170
178
  // 取最后一个匹配 = 末尾的声明(同时谈格式时,正文中部的不算,因窗口在尾部)
171
179
  const m = [...text.slice(-15000).matchAll(new RegExp(EST_RE.source, "gi"))].pop();
172
180
  if (!m) return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ptc-meter",
3
- "version": "1.0.35",
3
+ "version": "1.0.36",
4
4
  "description": "Measures tool-call batching per turn and feeds the numbers back to the model.",
5
5
  "type": "module",
6
6
  "license": "MIT",