pi-curiosity 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 ADDED
@@ -0,0 +1,31 @@
1
+ # pi-curiosity
2
+
3
+ A small Pi extension that periodically nudges coding agents to investigate evidence, reuse existing code, and keep new code easy for humans to find and understand.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pi install npm:pi-curiosity
9
+ ```
10
+
11
+ To try it without installing:
12
+
13
+ ```sh
14
+ pi -e npm:pi-curiosity
15
+ ```
16
+
17
+ ## Configure
18
+
19
+ The default is one cue every 10 tool calls. Configure the interval globally in `~/.pi/agent/settings.json`:
20
+
21
+ ```json
22
+ {
23
+ "pi-curiosity": {
24
+ "toolInterval": 10
25
+ }
26
+ }
27
+ ```
28
+
29
+ A project `.pi/settings.json` value overrides the global value. `toolInterval` must be a positive integer; invalid values use the default.
30
+
31
+ The cue is injected into the next model context after the configured number of tool calls and is hidden from the visible transcript.
@@ -0,0 +1,73 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import {
4
+ getAgentDir,
5
+ type ExtensionAPI,
6
+ } from "@earendil-works/pi-coding-agent";
7
+
8
+ const CURIOSITY_CUE =
9
+ "I'm curious—like a baby discovering the world: investigate the latest result, verify the next detail, reuse existing code, and keep new code easy for humans to find and understand as the project grows.";
10
+ const DEFAULT_TOOL_INTERVAL = 10;
11
+ const SETTINGS_KEY = "pi-curiosity";
12
+
13
+ function readToolInterval(cwd: string): number {
14
+ let interval = DEFAULT_TOOL_INTERVAL;
15
+ for (const path of [
16
+ join(getAgentDir(), "settings.json"),
17
+ join(cwd, ".pi", "settings.json"),
18
+ ]) {
19
+ if (!existsSync(path)) continue;
20
+ try {
21
+ const settings = JSON.parse(readFileSync(path, "utf8")) as Record<
22
+ string,
23
+ unknown
24
+ >;
25
+ const configured = (
26
+ settings[SETTINGS_KEY] as Record<string, unknown> | undefined
27
+ )?.toolInterval;
28
+ if (Number.isInteger(configured) && configured > 0) interval = configured;
29
+ } catch {
30
+ // Ignore malformed or unreadable settings and keep the last valid value.
31
+ }
32
+ }
33
+ return interval;
34
+ }
35
+
36
+ export default function (pi: ExtensionAPI) {
37
+ let toolUsesSinceCue = 0;
38
+ let injectOnNextContext = false;
39
+ let toolInterval = DEFAULT_TOOL_INTERVAL;
40
+
41
+ pi.on("session_start", (_event, ctx) => {
42
+ toolInterval = readToolInterval(ctx.cwd);
43
+ });
44
+
45
+ pi.on("turn_end", (event) => {
46
+ toolUsesSinceCue += event.toolResults.length;
47
+ injectOnNextContext = toolUsesSinceCue >= toolInterval;
48
+ });
49
+
50
+ pi.on("context", (event) => {
51
+ if (!injectOnNextContext) return;
52
+ injectOnNextContext = false;
53
+ toolUsesSinceCue = 0;
54
+
55
+ return {
56
+ messages: [
57
+ ...event.messages,
58
+ {
59
+ role: "custom",
60
+ customType: "curiosity-steering",
61
+ content: CURIOSITY_CUE,
62
+ display: false,
63
+ timestamp: Date.now(),
64
+ },
65
+ ],
66
+ };
67
+ });
68
+
69
+ pi.on("agent_end", () => {
70
+ injectOnNextContext = false;
71
+ toolUsesSinceCue = 0;
72
+ });
73
+ }
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "pi-curiosity",
3
+ "version": "0.1.0",
4
+ "description": "Periodic curiosity and code-navigation steering for Pi",
5
+ "keywords": ["pi-package", "pi", "extension", "curiosity"],
6
+ "license": "MIT",
7
+ "files": ["extensions/curiosity-steering.ts", "README.md", "package.json"],
8
+ "pi": {
9
+ "extensions": ["./extensions/curiosity-steering.ts"]
10
+ },
11
+ "peerDependencies": {
12
+ "@earendil-works/pi-coding-agent": "*"
13
+ }
14
+ }