pi-ptc-meter 1.0.34 → 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 +10 -6
  2. package/index.ts +10 -2
  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
 
@@ -52,7 +52,7 @@ pi install npm:pi-ptc-meter
52
52
 
53
53
  | 命令 | 作用 |
54
54
  | --- | --- |
55
- | `/ptc [n]` | 最近 n 轮:次数、时长、中位、超标 |
55
+ | `/ptc [n]` | 状态(阈值 / inject / notify)+ 最近 8 轮明细(次数 · 时长)+ 统计(中位 / 超标轮次) |
56
56
 
57
57
  ## 模拟测试
58
58
 
@@ -74,15 +74,17 @@ pi-ptc-meter 的改动在**隔离副本**上做回放验证后才发版;当前
74
74
  - `turn_end`:记录本轮次数与耗时(不落盘);超阈值时每 run 提示一次(goal 自动续轮共享同一 run 时 `agent_end` 可能整段不触发,避免回路失效)。
75
75
  - `agent_end`:每 run 落盘一行日志。
76
76
  - `before_agent_start`:结算上一轮并以 `nextTurn` 尾部消息回灌——计数、耗时、**缓存命中率**(仅当该轮有 usage 数据时出现;< 90% 标「低」)、会话中位、阈值判定(`display: false`)。
77
- - **1.0.32 起不再回灌「预计 / 实际 / 偏差」**:声明率虽升到 65%,中位误差仍为 94%(调用数)与 199%(耗时),且 412 个声明点上 6 种预测器(常量 12/16、1.1× 上轮、2.0× 上轮、全局中位、区间 3~40)全部落在 71–94% 误差。
77
+ - **1.0.32 起不回灌「预计 / 实际 / 偏差」**:412 个声明点上 6 种预测器全部 71–94% 误差(耗时 199%),预估不可用。
78
78
 
79
79
  **注入样例(示意,字段可能随版本增删)**
80
80
 
81
81
  ```text
82
82
  PTC 计量:上一轮 9 次工具调用 · 实际 34s · 命中 92% · 会话中位 25 · 阈值 50 · 判据 = 本轮计数不超阈值且无同类调用可并
83
83
  ```
84
+ - 耗时预估仍写入日志并在 `/ptc` 中显示(历史值),但不再回灌给模型。
84
85
  - `session_start`:模块级计量归零。
85
86
  - system 内 section `ptc_meter` 只含逐字不变的骨架。
87
+ - 只写自己的 section,**永不返回 `systemPrompt`**(返回即覆盖式替换,会静默丢弃其它扩展的 section 修改)。
86
88
  ## 原理(专业)
87
89
 
88
90
  ```text
@@ -146,7 +148,7 @@ Config file `~/.pi/ptc-meter.json` (optional; invalid JSON falls back):
146
148
 
147
149
  | Key | Default | Description |
148
150
  | --- | --- | --- |
149
- | `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 |
150
152
  | `inject` | `true` | Enable the feedback message |
151
153
  | `notify` | `false` | Use UI notifications instead |
152
154
 
@@ -165,7 +167,7 @@ Also: log `~/.pi/ptc-meter.jsonl` (1 MiB truncation, tail-preserving); no enviro
165
167
 
166
168
  | Command | Purpose |
167
169
  | --- | --- |
168
- | `/ptc [n]` | Last n turns: counts, duration, median, over-threshold |
170
+ | `/ptc [n]` | State (threshold / inject / notify) + last 8 turns (calls · duration) + stats (median / over-threshold) |
169
171
 
170
172
  ## Verification
171
173
 
@@ -186,15 +188,17 @@ Change: both estimates removed. Why: estimates are unpredictable at declaration
186
188
  - `turn_end`: records calls and duration (no disk write); when goal auto-continuation shares one run and `agent_end` never fires, it warns once above threshold (once per run).
187
189
  - `agent_end`: writes one log line per run.
188
190
  - `before_agent_start`: settles the previous turn and feeds back counts, duration, the **cache hit rate** (only when that turn reported usage; flagged low below 90%), the session median and the threshold verdict as a `nextTurn` trailing message (`display: false`).
189
- - **1.0.32 no longer feeds back estimate / actual / deviation**: declaration rate rose to 65% but the median error stayed at 94% (call count) and 199% (duration); on 412 declaration points all six predictors (constant 12/16, 1.1x previous, 2.0x previous, global median, interval 3-40) landed between 71% and 94% error.
191
+ - **1.0.32 drops estimate feedback**: on 412 declaration points all six predictors landed at 71-94% error (duration 199%) - estimating is not viable.
190
192
 
191
193
  **Sample injection (illustrative; fields may change between versions)**
192
194
 
193
195
  ```text
194
196
  PTC metering: last turn 9 tool calls · 34s actual · 92% cache hit · session median 25 · threshold 50 · verdict: under threshold, no obvious merge candidates
195
197
  ```
198
+ - The duration estimate is still logged and shown by `/ptc` as a historical value, but is no longer fed back to the model.
196
199
  - `session_start`: resets module-level counters.
197
200
  - The `ptc_meter` system section holds only a byte-stable skeleton.
201
+ - Writes only its own section and **never returns `systemPrompt`** (a returned prompt replaces everything and silently drops other extensions' sections).
198
202
  ## How it works (technical)
199
203
 
200
204
  ```text
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
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ptc-meter",
3
- "version": "1.0.34",
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",