@hk_net/pi-timestamp 0.1.4 → 0.1.5
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/package.json +3 -3
- package/timestamp.ts +27 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hk_net/pi-timestamp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Pi extension that shows timestamps for user input and agent completion timing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"README.md"
|
|
27
27
|
],
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@earendil-works/pi-coding-agent": ">=0.80.
|
|
30
|
-
"@earendil-works/pi-tui": ">=0.80.
|
|
29
|
+
"@earendil-works/pi-coding-agent": ">=0.80.2",
|
|
30
|
+
"@earendil-works/pi-tui": ">=0.80.2"
|
|
31
31
|
},
|
|
32
32
|
"pi": {
|
|
33
33
|
"extensions": [
|
package/timestamp.ts
CHANGED
|
@@ -32,11 +32,18 @@ function formatDuration(ms: number): string {
|
|
|
32
32
|
return `${Math.floor(hrs)}h ${Math.floor(totalMins % 60)}m`;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function isTimeoutErrorMessage(message: string | undefined): boolean {
|
|
36
|
+
return /timed? out|timeout/i.test(message ?? "");
|
|
37
|
+
}
|
|
38
|
+
|
|
35
39
|
export default function (pi: ExtensionAPI) {
|
|
36
40
|
let taskStartTime: number | undefined;
|
|
41
|
+
let waitingForRetryAfterTimeout = false;
|
|
37
42
|
|
|
38
|
-
// Track when the agent starts processing
|
|
43
|
+
// Track when the agent starts processing. If Pi is auto-retrying after a timeout,
|
|
44
|
+
// keep the original start time so the eventual completion covers the full task.
|
|
39
45
|
pi.on("agent_start", async () => {
|
|
46
|
+
if (waitingForRetryAfterTimeout) return;
|
|
40
47
|
taskStartTime = Date.now();
|
|
41
48
|
});
|
|
42
49
|
|
|
@@ -46,16 +53,33 @@ export default function (pi: ExtensionAPI) {
|
|
|
46
53
|
pi.on("message_end", async (event, ctx) => {
|
|
47
54
|
if (event.message.role !== "user") return;
|
|
48
55
|
|
|
56
|
+
if (waitingForRetryAfterTimeout) {
|
|
57
|
+
taskStartTime = undefined;
|
|
58
|
+
waitingForRetryAfterTimeout = false;
|
|
59
|
+
}
|
|
60
|
+
|
|
49
61
|
const ts = event.message.timestamp;
|
|
50
62
|
if (!ts) return;
|
|
51
63
|
|
|
52
64
|
ctx.ui.notify(`Sent ${formatTime(ts)}`, "info");
|
|
53
65
|
});
|
|
54
66
|
|
|
55
|
-
// Show completion timing after agent
|
|
56
|
-
|
|
67
|
+
// Show completion timing after the whole task finishes. If Pi ended this agent loop
|
|
68
|
+
// with a timeout error and will likely auto-retry, wait for the later completion.
|
|
69
|
+
pi.on("agent_end", async (event, ctx) => {
|
|
70
|
+
const lastAssistantMessage = [...event.messages].reverse().find((message) => message.role === "assistant");
|
|
71
|
+
if (
|
|
72
|
+
lastAssistantMessage?.role === "assistant" &&
|
|
73
|
+
lastAssistantMessage.stopReason === "error" &&
|
|
74
|
+
isTimeoutErrorMessage(lastAssistantMessage.errorMessage)
|
|
75
|
+
) {
|
|
76
|
+
waitingForRetryAfterTimeout = true;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
57
80
|
const startTime = taskStartTime;
|
|
58
81
|
taskStartTime = undefined;
|
|
82
|
+
waitingForRetryAfterTimeout = false;
|
|
59
83
|
|
|
60
84
|
if (startTime === undefined) return;
|
|
61
85
|
|