@hk_net/pi-timestamp 0.1.9 → 0.1.10

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/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## 0.1.10 - 2026-08-23
4
+
5
+ ### Changed
6
+
7
+ - Mark Pi's host-provided SDK packages as optional wildcard peers so npm does not install a redundant Pi SDK dependency tree.
8
+ - Verify development and tests against Pi SDK 0.84.2 while retaining runtime compatibility with Pi 0.84.1 and newer.
9
+ - Measure completion through `agent_settled` so automatic retries, compaction recovery, and queued continuations produce one complete task duration.
10
+ - Document that the individual package and GitHub bundle must not be installed together.
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # pi-timestamp
2
2
 
3
- Shows timestamps for user input and agent completion timing. Requires pi `>=0.84.1`.
3
+ Shows timestamps for user input and agent completion timing. Requires Pi 0.84.1 or newer (tested with the current Pi 0.84.2 release).
4
4
 
5
5
  ## What it does
6
6
 
@@ -16,6 +16,8 @@ Timestamps appear inline in the **chat display**, similar to Pi's built-in tool
16
16
 
17
17
  ## Installation
18
18
 
19
+ > **Avoid duplicate installation.** Install this npm package or the GitHub bundle, not both. Loading both copies can duplicate timestamps and runtime summaries.
20
+
19
21
  ```bash
20
22
  pi install npm:@hk_net/pi-timestamp
21
23
  ```
@@ -29,7 +31,7 @@ cp packages/pi-timestamp/timestamp.ts ~/.pi/agent/extensions/timestamp.ts
29
31
 
30
32
  ## Duration measurement
31
33
 
32
- Captured from `agent_start` (when the model starts processing) to `agent_end` (when all tool calls and model processing are done).
34
+ Captured from the first `agent_start` to `agent_settled`, so automatic retries, compaction recovery, tool calls, and queued continuations are included in one complete task duration.
33
35
 
34
36
  ## Issues and feedback
35
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hk_net/pi-timestamp",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Pi extension that shows timestamps for user input and agent completion timing",
5
5
  "type": "module",
6
6
  "private": false,
@@ -23,11 +23,23 @@
23
23
  "homepage": "https://github.com/hknet/pi-extensions/tree/main/packages/pi-timestamp#readme",
24
24
  "files": [
25
25
  "timestamp.ts",
26
- "README.md"
26
+ "README.md",
27
+ "CHANGELOG.md"
27
28
  ],
29
+ "engines": {
30
+ "node": ">=22.19.0"
31
+ },
28
32
  "peerDependencies": {
29
- "@earendil-works/pi-coding-agent": ">=0.84.1",
30
- "@earendil-works/pi-tui": ">=0.84.1"
33
+ "@earendil-works/pi-coding-agent": "*",
34
+ "@earendil-works/pi-tui": "*"
35
+ },
36
+ "peerDependenciesMeta": {
37
+ "@earendil-works/pi-coding-agent": {
38
+ "optional": true
39
+ },
40
+ "@earendil-works/pi-tui": {
41
+ "optional": true
42
+ }
31
43
  },
32
44
  "pi": {
33
45
  "extensions": [
package/timestamp.ts CHANGED
@@ -128,23 +128,17 @@ export function formatRuntimeDuration(ms: number): string {
128
128
  return parts.filter((part): part is string => part !== undefined).join(" ");
129
129
  }
130
130
 
131
- function isTimeoutErrorMessage(message: string | undefined): boolean {
132
- return /timed? out|timeout/i.test(message ?? "");
133
- }
134
-
135
131
  export default function (pi: ExtensionAPI) {
136
132
  let taskStartTime: number | undefined;
137
- let waitingForRetryAfterTimeout = false;
138
133
 
139
134
  function notifyAccent(ctx: ExtensionContext, message: string): void {
140
135
  ctx.ui.notify(ctx.ui.theme.fg("accent", message), "info");
141
136
  }
142
137
 
143
- // Track when the agent starts processing. If Pi is auto-retrying after a timeout,
144
- // keep the original start time so the eventual completion covers the full task.
138
+ // Track the complete run. Automatic retries and compaction recovery can emit
139
+ // additional agent_start events before agent_settled, so retain the first start.
145
140
  pi.on("agent_start", async () => {
146
- if (waitingForRetryAfterTimeout) return;
147
- taskStartTime = Date.now();
141
+ taskStartTime ??= Date.now();
148
142
  });
149
143
 
150
144
  // Show "Sent HH:MM:SS" after each user message.
@@ -153,33 +147,17 @@ export default function (pi: ExtensionAPI) {
153
147
  pi.on("message_end", async (event, ctx) => {
154
148
  if (event.message.role !== "user") return;
155
149
 
156
- if (waitingForRetryAfterTimeout) {
157
- taskStartTime = undefined;
158
- waitingForRetryAfterTimeout = false;
159
- }
160
-
161
150
  const ts = event.message.timestamp;
162
151
  if (!ts) return;
163
152
 
164
153
  ctx.ui.notify(`Sent ${formatTime(ts)}`, "info");
165
154
  });
166
155
 
167
- // Show completion timing after the whole task finishes. If Pi ended this agent loop
168
- // with a timeout error and will likely auto-retry, wait for the later completion.
169
- pi.on("agent_end", async (event, ctx) => {
170
- const lastAssistantMessage = [...event.messages].reverse().find((message) => message.role === "assistant");
171
- if (
172
- lastAssistantMessage?.role === "assistant" &&
173
- lastAssistantMessage.stopReason === "error" &&
174
- isTimeoutErrorMessage(lastAssistantMessage.errorMessage)
175
- ) {
176
- waitingForRetryAfterTimeout = true;
177
- return;
178
- }
179
-
156
+ // Show completion timing only after retries, compaction recovery, and queued
157
+ // continuations have fully settled.
158
+ pi.on("agent_settled", async (_event, ctx) => {
180
159
  const startTime = taskStartTime;
181
160
  taskStartTime = undefined;
182
- waitingForRetryAfterTimeout = false;
183
161
 
184
162
  if (startTime === undefined) return;
185
163