@aliou/pi-dev-kit 0.6.0 → 0.6.1
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliou/pi-dev-kit",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
"@sinclair/typebox": "^0.34.41"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@mariozechner/pi-coding-agent": "0.
|
|
43
|
-
"@mariozechner/pi-tui": "0.
|
|
42
|
+
"@mariozechner/pi-coding-agent": "0.65.2",
|
|
43
|
+
"@mariozechner/pi-tui": "0.65.2"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@biomejs/biome": "^2.3.13",
|
|
47
47
|
"@changesets/cli": "^2.27.11",
|
|
48
|
-
"@mariozechner/pi-coding-agent": "0.
|
|
49
|
-
"@mariozechner/pi-tui": "0.
|
|
48
|
+
"@mariozechner/pi-coding-agent": "0.65.2",
|
|
49
|
+
"@mariozechner/pi-tui": "0.65.2",
|
|
50
50
|
"@types/node": "^25.0.10",
|
|
51
51
|
"husky": "^9.1.7",
|
|
52
52
|
"typescript": "^5.9.3"
|
|
@@ -11,10 +11,10 @@ Guide for creating and maintaining Pi extensions. Read the relevant reference fi
|
|
|
11
11
|
|
|
12
12
|
Pi injects these packages via jiti at runtime. Extensions do not need to install them — they are available as peer dependencies:
|
|
13
13
|
|
|
14
|
-
- `@mariozechner/pi-coding-agent` — core types, utilities,
|
|
14
|
+
- `@mariozechner/pi-coding-agent` — core types, utilities, and extension APIs
|
|
15
15
|
- `@mariozechner/pi-tui` — TUI components
|
|
16
16
|
- `@mariozechner/pi-ai` — AI utilities (`StringEnum`, etc.)
|
|
17
|
-
- `@sinclair/typebox` — schema definitions
|
|
17
|
+
- `@sinclair/typebox` — schema definitions for tool parameters and related types
|
|
18
18
|
|
|
19
19
|
```typescript
|
|
20
20
|
// Tool UI components (from @aliou/pi-utils-ui)
|
|
@@ -109,7 +109,7 @@ When implementing, look at these existing extensions for patterns:
|
|
|
109
109
|
13. **Output truncation**: For tools returning large text, use `truncateHead()` from `@mariozechner/pi-coding-agent`. Write full content to temp file. Append footer with line/byte counts and temp file path.
|
|
110
110
|
14. **Core/lib pattern**: Extract domain logic into modules (`client.ts`, `manager.ts`) that don't import from Pi. Tools are thin wrappers. Core modules are unit-testable with vitest.
|
|
111
111
|
15. **Humanize messages**: Show display names first, IDs in dim/parens. `"Started \"backend\" (proc_42)"` not `"Started proc_42"`.
|
|
112
|
-
16. **peerDependencies**: Pi injects `@mariozechner/pi-coding-agent`, `@mariozechner/pi-tui`, `@mariozechner/pi-ai`, and `@sinclair/typebox` via jiti at runtime. Any of these that your extension imports must be listed in `peerDependencies` with `optional: true` in `peerDependenciesMeta`. Without `optional: true`, npm 7+ auto-installs peers, adding hundreds of packages on every install even though Pi already provides them. Keep them in `devDependencies` too for local type checking — `pnpm install` installs peers, so development is unaffected. Use `>=CURRENT_VERSION` range, not `*`.
|
|
112
|
+
16. **peerDependencies**: Pi injects `@mariozechner/pi-coding-agent`, `@mariozechner/pi-tui`, `@mariozechner/pi-ai`, and `@sinclair/typebox` via jiti at runtime. Any of these that your extension imports must be listed in `peerDependencies` with `optional: true` in `peerDependenciesMeta`. Without `optional: true`, npm 7+ auto-installs peers, adding hundreds of packages on every install even though Pi already provides them. Keep them in `devDependencies` too for local type checking — `pnpm install` installs peers, so development is unaffected. Use `>=CURRENT_VERSION` range, not `*`.
|
|
113
113
|
17. **Check existing components**: Before creating a new TUI component, check if `pi-tui` or `pi-coding-agent` already exports one that fits.
|
|
114
114
|
18. **Forward abort signals**: Always pass `signal` through to `fetch()`, `pi.exec()`, and API client methods. A tool that ignores its signal prevents cancellation from reaching the underlying operation. Never prefix with `_signal` unless the tool truly has no async work to cancel.
|
|
115
115
|
19. **Never use Node child_process APIs**: Do not use `child_process.exec`, `execSync`, `spawn`, `spawnSync`, `execFile`, or `execFileSync` to run binaries or shell scripts. Always use `pi.exec()`. `pi.exec` handles CWD, signal propagation, and output capture consistently. The only exception is if you need a long-lived streaming process with stdin/stdout piping that `pi.exec` cannot support — document the reason in code comments.
|
|
@@ -8,13 +8,11 @@ Hooks let extensions react to lifecycle events. They are registered with `pi.on(
|
|
|
8
8
|
|
|
9
9
|
| Event | When | Can Cancel | Payload |
|
|
10
10
|
|---|---|---|---|
|
|
11
|
-
| `session_start` |
|
|
12
|
-
| `
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
15
|
-
| `
|
|
16
|
-
| `session_shutdown` | Pi is shutting down | No | `{}` |
|
|
17
|
-
| `session_before_compact` | Before compaction | Yes (return custom summary string) | `{ summary: string }` |
|
|
11
|
+
| `session_start` | Session starts, reloads, or is replaced | No | `{ reason: "startup" \| "reload" \| "new" \| "resume" \| "fork", previousSessionFile? }` |
|
|
12
|
+
| `session_before_switch` | Before `/new` or `/resume` replaces the current session | Yes (`{ cancel: true }`) | `{ reason: "new" \| "resume", targetSessionFile? }` |
|
|
13
|
+
| `session_before_fork` | Before forking a session | Yes (`{ cancel: true }`) | `{ entryId }` |
|
|
14
|
+
| `session_shutdown` | Current session runtime is shutting down or being replaced | No | `{}` |
|
|
15
|
+
| `session_before_compact` | Before compaction | Yes (cancel or provide custom compaction) | event-specific compaction data |
|
|
18
16
|
|
|
19
17
|
### Agent Events
|
|
20
18
|
|
|
@@ -98,8 +96,13 @@ pi.on("session_before_switch", async (event, ctx) => {
|
|
|
98
96
|
|
|
99
97
|
```typescript
|
|
100
98
|
pi.on("session_before_compact", async (event, ctx) => {
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
return {
|
|
100
|
+
compaction: {
|
|
101
|
+
summary: "Custom summary",
|
|
102
|
+
firstKeptEntryId: event.preparation.firstKeptEntryId,
|
|
103
|
+
tokensBefore: event.preparation.tokensBefore,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
103
106
|
});
|
|
104
107
|
```
|
|
105
108
|
|
|
@@ -1,42 +1,53 @@
|
|
|
1
1
|
# State Management
|
|
2
2
|
|
|
3
|
-
Extensions can persist state in the session history
|
|
3
|
+
Extensions can persist state in the session history. In modern Pi extensions, the usual pattern is to store reconstructible state in tool result `details` and rebuild it from the current branch on `session_start`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Recommended Pattern: Store State in Tool Result Details
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
When a tool changes extension state, return the latest state in `details`. That keeps the state aligned with normal tool history, branching, and reconstruction.
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
|
-
pi
|
|
11
|
-
|
|
12
|
-
toolCallId: `todo-${Date.now()}`,
|
|
13
|
-
input: { action: "add", text: "Buy groceries" },
|
|
14
|
-
output: "Added: Buy groceries",
|
|
15
|
-
display: true,
|
|
16
|
-
details: { items: ["Buy groceries"] },
|
|
17
|
-
});
|
|
18
|
-
```
|
|
10
|
+
export default function (pi: ExtensionAPI) {
|
|
11
|
+
let items: string[] = [];
|
|
19
12
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
14
|
+
items = [];
|
|
15
|
+
for (const entry of ctx.sessionManager.getBranch()) {
|
|
16
|
+
if (entry.type === "message" && entry.message.role === "toolResult") {
|
|
17
|
+
if (entry.message.toolName === "todo") {
|
|
18
|
+
items = entry.message.details?.items ?? [];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
pi.registerTool({
|
|
25
|
+
name: "todo",
|
|
26
|
+
// ...
|
|
27
|
+
async execute() {
|
|
28
|
+
items.push("Buy groceries");
|
|
29
|
+
return {
|
|
30
|
+
content: [{ type: "text", text: "Added todo item" }],
|
|
31
|
+
details: { items: [...items] },
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
```
|
|
28
37
|
|
|
29
38
|
## Reconstructing State from Session
|
|
30
39
|
|
|
31
|
-
When a session loads,
|
|
40
|
+
When a session loads, reconstruct state in `session_start` by iterating over the current branch or full session through `ctx.sessionManager`:
|
|
32
41
|
|
|
33
42
|
```typescript
|
|
34
43
|
pi.on("session_start", async (_event, ctx) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
for (const entry of
|
|
38
|
-
if (entry.
|
|
39
|
-
|
|
44
|
+
todoItems = [];
|
|
45
|
+
|
|
46
|
+
for (const entry of ctx.sessionManager.getBranch()) {
|
|
47
|
+
if (entry.type === "message" && entry.message.role === "toolResult") {
|
|
48
|
+
if (entry.message.toolName === "todo") {
|
|
49
|
+
todoItems = entry.message.details?.items ?? [];
|
|
50
|
+
}
|
|
40
51
|
}
|
|
41
52
|
}
|
|
42
53
|
});
|
|
@@ -53,4 +64,4 @@ This pattern makes state survive session reloads, forks, and compactions (as lon
|
|
|
53
64
|
| Use for | State changes, action logs | Information display, command results |
|
|
54
65
|
| LLM sees | The `output` field | The `content` field |
|
|
55
66
|
|
|
56
|
-
Use `
|
|
67
|
+
Use tool result `details` when the state naturally belongs to a tool call and should follow normal conversation branching. Use `appendEntry` for extension-specific state/history that does not fit a normal tool result. Use `sendMessage` when you are displaying a one-time result.
|
|
@@ -135,10 +135,10 @@ Only include `pi` sub-fields that are actually used. `skills`, `themes`, `prompt
|
|
|
135
135
|
|
|
136
136
|
**`peerDependencies`**: Declares the minimum pi version required. Pi ships these packages and injects them via jiti at runtime, so extensions never need to install them:
|
|
137
137
|
|
|
138
|
-
- `@mariozechner/pi-coding-agent` — core types, utilities,
|
|
138
|
+
- `@mariozechner/pi-coding-agent` — core types, utilities, and extension APIs
|
|
139
139
|
- `@mariozechner/pi-tui` — TUI components
|
|
140
140
|
- `@mariozechner/pi-ai` — AI utilities (`StringEnum`, etc.)
|
|
141
|
-
- `@sinclair/typebox` — schema definitions
|
|
141
|
+
- `@sinclair/typebox` — schema definitions for tool parameters and related types
|
|
142
142
|
|
|
143
143
|
List any of these you import at runtime in `peerDependencies` as optional peers. This prevents npm from installing duplicate copies when a user installs your extension. Use `>=` with the current version when creating.
|
|
144
144
|
|