@taylorsatula/pi-timestamp 0.1.0
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/README.md +62 -0
- package/extensions/timestamp.ts +65 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# @taylorsatula/pi-timestamp
|
|
2
|
+
|
|
3
|
+
Timestamp injection extension for [Pi](https://pi.dev) — the model always knows what time it is.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Hooks `before_provider_request` and appends a synthetic tool-call pair to the outgoing message list, carrying the current local wall-clock time:
|
|
8
|
+
|
|
9
|
+
```jsonc
|
|
10
|
+
[
|
|
11
|
+
{
|
|
12
|
+
"role": "assistant",
|
|
13
|
+
"tool_calls": [
|
|
14
|
+
{
|
|
15
|
+
"id": "ts_1756220400000",
|
|
16
|
+
"type": "function",
|
|
17
|
+
"function": { "name": "__timestamp", "arguments": "{\"timestamp\":\"[3:00pm - 8/26/25]\"}" }
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{ "role": "tool", "tool_call_id": "ts_1756220400000", "content": "ok" }
|
|
22
|
+
]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Injection happens only at **turn boundaries**, not on every provider call:
|
|
26
|
+
|
|
27
|
+
- Last message is a **user message** → inject.
|
|
28
|
+
- Last message is an **assistant message with text content** (a vocalization between tool steps) → inject.
|
|
29
|
+
- Last message is an assistant message with only `tool_calls`, or a tool result (mid-turn churn) → skip.
|
|
30
|
+
|
|
31
|
+
This keeps the timestamp fresh each time control returns to the user-facing side of the loop, without spamming intermediate tool-loop requests.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pi install npm:@taylorsatula/pi-timestamp
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or add to `~/.pi/agent/settings.json` under `packages`:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"packages": ["npm:@taylorsatula/pi-timestamp"]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Notes
|
|
48
|
+
|
|
49
|
+
- Timestamps use the machine's **local time**, formatted `h:mmam/pm - M/D/YY` (e.g. `[3:07pm - 8/26/25]`).
|
|
50
|
+
- No tools, commands, shortcuts, or settings are registered — the extension is invisible except for the injected messages.
|
|
51
|
+
- The injected pair is added to the outgoing payload only; it is not persisted to the session transcript.
|
|
52
|
+
|
|
53
|
+
## Development
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install
|
|
57
|
+
npm run check # tsc --noEmit
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
MIT
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
function formatTimestamp(): string {
|
|
4
|
+
const now = new Date();
|
|
5
|
+
let hours = now.getHours();
|
|
6
|
+
const minutes = now.getMinutes();
|
|
7
|
+
const ampm = hours >= 12 ? "pm" : "am";
|
|
8
|
+
hours = hours % 12;
|
|
9
|
+
if (hours === 0) hours = 12;
|
|
10
|
+
const month = now.getMonth() + 1;
|
|
11
|
+
const day = now.getDate();
|
|
12
|
+
const year = String(now.getFullYear()).slice(-2);
|
|
13
|
+
return `[${hours}:${String(minutes).padStart(2, "0")}${ampm} - ${month}/${day}/${year}]`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function shouldInject(msgs: Array<Record<string, unknown>>): boolean {
|
|
17
|
+
const last = msgs[msgs.length - 1];
|
|
18
|
+
if (!last) return false;
|
|
19
|
+
|
|
20
|
+
// User message → inject
|
|
21
|
+
if (last.role === "user") return true;
|
|
22
|
+
|
|
23
|
+
// Assistant with text content (vocalization) → inject
|
|
24
|
+
// Assistant with only tool_calls (intermediate) → skip
|
|
25
|
+
if (last.role === "assistant") {
|
|
26
|
+
const hasToolCalls = Array.isArray(last.tool_calls) && last.tool_calls.length > 0;
|
|
27
|
+
const hasContent = last.content != null && last.content !== "";
|
|
28
|
+
return !hasToolCalls && hasContent;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Tool results → skip (intermediate)
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default function (pi: ExtensionAPI) {
|
|
36
|
+
pi.on("before_provider_request", (event) => {
|
|
37
|
+
const payload = event.payload as Record<string, unknown>;
|
|
38
|
+
const msgs = payload.messages as Array<Record<string, unknown>>;
|
|
39
|
+
|
|
40
|
+
if (!shouldInject(msgs)) return;
|
|
41
|
+
|
|
42
|
+
const timestamp = formatTimestamp();
|
|
43
|
+
const callId = `ts_${Date.now()}`;
|
|
44
|
+
|
|
45
|
+
msgs.push(
|
|
46
|
+
{
|
|
47
|
+
role: "assistant",
|
|
48
|
+
tool_calls: [
|
|
49
|
+
{
|
|
50
|
+
id: callId,
|
|
51
|
+
type: "function",
|
|
52
|
+
function: { name: "__timestamp", arguments: JSON.stringify({ timestamp }) },
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
role: "tool",
|
|
58
|
+
tool_call_id: callId,
|
|
59
|
+
content: "ok",
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return event.payload;
|
|
64
|
+
});
|
|
65
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@taylorsatula/pi-timestamp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Timestamp injection extension for Pi — appends the current wall-clock time as a synthetic tool-call pair to every provider request at turn boundaries, so the model always knows what time it is.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"pi-package"
|
|
7
|
+
],
|
|
8
|
+
"type": "module",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/taylorsatula/pi-timestamp"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"extensions",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@earendil-works/pi-agent-core": "*",
|
|
20
|
+
"@earendil-works/pi-ai": "*",
|
|
21
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^24.13.3",
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"check": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"pi": {
|
|
31
|
+
"extensions": [
|
|
32
|
+
"./extensions/timestamp.ts"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|