@hk_net/pi-timestamp 0.1.9 → 0.1.11

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,17 @@
1
+ # Changelog
2
+
3
+ ## 0.1.11 - 2026-08-23
4
+
5
+ ### Changed
6
+
7
+ - Add the copyright holder and EUPL licensing notice to the package license and canonical TypeScript source.
8
+ - Identify KAPPER NETWORK-COMMUNICATIONS GmbH and kapper.net in the npm author metadata.
9
+
10
+ ## 0.1.10 - 2026-08-23
11
+
12
+ ### Changed
13
+
14
+ - Mark Pi's host-provided SDK packages as optional wildcard peers so npm does not install a redundant Pi SDK dependency tree.
15
+ - Verify development and tests against Pi SDK 0.84.2 while retaining runtime compatibility with Pi 0.84.1 and newer.
16
+ - Measure completion through `agent_settled` so automatic retries, compaction recovery, and queued continuations produce one complete task duration.
17
+ - Document that the individual package and GitHub bundle must not be installed together.
package/LICENSE CHANGED
@@ -1,3 +1,6 @@
1
+ Copyright © 2026 kapper.net - KAPPER NETWORK-COMMUNICATIONS GmbH
2
+ Licensed under the EUPL
3
+
1
4
  EUROPEAN UNION PUBLIC LICENCE v. 1.2
2
5
  EUPL © the European Union 2007, 2016
3
6
 
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.11",
4
4
  "description": "Pi extension that shows timestamps for user input and agent completion timing",
5
5
  "type": "module",
6
6
  "private": false,
@@ -11,7 +11,10 @@
11
11
  "timestamp"
12
12
  ],
13
13
  "license": "EUPL-1.2",
14
- "author": "hknet",
14
+ "author": {
15
+ "name": "KAPPER NETWORK-COMMUNICATIONS GmbH",
16
+ "url": "https://kapper.net"
17
+ },
15
18
  "repository": {
16
19
  "type": "git",
17
20
  "url": "git+https://github.com/hknet/pi-extensions.git",
@@ -23,11 +26,23 @@
23
26
  "homepage": "https://github.com/hknet/pi-extensions/tree/main/packages/pi-timestamp#readme",
24
27
  "files": [
25
28
  "timestamp.ts",
26
- "README.md"
29
+ "README.md",
30
+ "CHANGELOG.md"
27
31
  ],
32
+ "engines": {
33
+ "node": ">=22.19.0"
34
+ },
28
35
  "peerDependencies": {
29
- "@earendil-works/pi-coding-agent": ">=0.84.1",
30
- "@earendil-works/pi-tui": ">=0.84.1"
36
+ "@earendil-works/pi-coding-agent": "*",
37
+ "@earendil-works/pi-tui": "*"
38
+ },
39
+ "peerDependenciesMeta": {
40
+ "@earendil-works/pi-coding-agent": {
41
+ "optional": true
42
+ },
43
+ "@earendil-works/pi-tui": {
44
+ "optional": true
45
+ }
31
46
  },
32
47
  "pi": {
33
48
  "extensions": [
package/timestamp.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // Copyright © 2026 kapper.net - KAPPER NETWORK-COMMUNICATIONS GmbH
2
+ // SPDX-License-Identifier: EUPL-1.2
3
+
1
4
  /**
2
5
  * Timestamp Extension
3
6
  *
@@ -128,23 +131,17 @@ export function formatRuntimeDuration(ms: number): string {
128
131
  return parts.filter((part): part is string => part !== undefined).join(" ");
129
132
  }
130
133
 
131
- function isTimeoutErrorMessage(message: string | undefined): boolean {
132
- return /timed? out|timeout/i.test(message ?? "");
133
- }
134
-
135
134
  export default function (pi: ExtensionAPI) {
136
135
  let taskStartTime: number | undefined;
137
- let waitingForRetryAfterTimeout = false;
138
136
 
139
137
  function notifyAccent(ctx: ExtensionContext, message: string): void {
140
138
  ctx.ui.notify(ctx.ui.theme.fg("accent", message), "info");
141
139
  }
142
140
 
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.
141
+ // Track the complete run. Automatic retries and compaction recovery can emit
142
+ // additional agent_start events before agent_settled, so retain the first start.
145
143
  pi.on("agent_start", async () => {
146
- if (waitingForRetryAfterTimeout) return;
147
- taskStartTime = Date.now();
144
+ taskStartTime ??= Date.now();
148
145
  });
149
146
 
150
147
  // Show "Sent HH:MM:SS" after each user message.
@@ -153,33 +150,17 @@ export default function (pi: ExtensionAPI) {
153
150
  pi.on("message_end", async (event, ctx) => {
154
151
  if (event.message.role !== "user") return;
155
152
 
156
- if (waitingForRetryAfterTimeout) {
157
- taskStartTime = undefined;
158
- waitingForRetryAfterTimeout = false;
159
- }
160
-
161
153
  const ts = event.message.timestamp;
162
154
  if (!ts) return;
163
155
 
164
156
  ctx.ui.notify(`Sent ${formatTime(ts)}`, "info");
165
157
  });
166
158
 
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
-
159
+ // Show completion timing only after retries, compaction recovery, and queued
160
+ // continuations have fully settled.
161
+ pi.on("agent_settled", async (_event, ctx) => {
180
162
  const startTime = taskStartTime;
181
163
  taskStartTime = undefined;
182
- waitingForRetryAfterTimeout = false;
183
164
 
184
165
  if (startTime === undefined) return;
185
166