@aliou/pi-dev-kit 0.6.4 → 0.7.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 +2 -2
- package/package.json +15 -10
- package/src/commands/index.ts +5 -1
- package/src/commands/update.ts +139 -91
- package/src/skills/pi-extension/SKILL.md +108 -131
- package/src/skills/pi-extension/references/additional-apis.md +256 -173
- package/src/skills/pi-extension/references/commands.md +113 -33
- package/src/skills/pi-extension/references/components.md +267 -102
- package/src/skills/pi-extension/references/hooks.md +229 -156
- package/src/skills/pi-extension/references/messages.md +97 -92
- package/src/skills/pi-extension/references/modes.md +80 -90
- package/src/skills/pi-extension/references/providers.md +255 -96
- package/src/skills/pi-extension/references/publish.md +76 -62
- package/src/skills/pi-extension/references/state.md +80 -33
- package/src/skills/pi-extension/references/structure.md +156 -245
- package/src/skills/pi-extension/references/testing.md +1 -1
- package/src/skills/pi-extension/references/tools.md +212 -816
- package/src/tools/changelog-tool.ts +237 -230
- package/src/tools/docs-tool.ts +127 -130
- package/src/tools/index.ts +5 -1
- package/src/tools/package-manager-tool.ts +152 -147
- package/src/tools/utils.ts +33 -23
- package/src/tools/version-tool.ts +51 -51
- package/src/index.ts +0 -8
|
@@ -1,306 +1,389 @@
|
|
|
1
1
|
# Additional APIs
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
When you implement something using one of these APIs, update this skill reference with a fuller example based on your actual usage.
|
|
3
|
+
This reference covers less common `ExtensionAPI`, `ExtensionContext`, and `ExtensionCommandContext` APIs.
|
|
6
4
|
|
|
7
5
|
## Shortcuts
|
|
8
6
|
|
|
9
|
-
Register
|
|
7
|
+
Register keyboard shortcuts for interactive mode.
|
|
10
8
|
|
|
11
9
|
```typescript
|
|
12
10
|
pi.registerShortcut("ctrl+shift+p", {
|
|
13
11
|
description: "Toggle plan mode",
|
|
14
12
|
handler: async (ctx) => {
|
|
15
13
|
planModeEnabled = !planModeEnabled;
|
|
16
|
-
ctx.ui.setStatus("plan", planModeEnabled ? "
|
|
14
|
+
ctx.ui.setStatus("plan-mode", planModeEnabled ? ctx.ui.theme.fg("accent", "Plan") : undefined);
|
|
17
15
|
},
|
|
18
16
|
});
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
Shortcuts
|
|
19
|
+
Shortcuts are TUI-only.
|
|
22
20
|
|
|
23
21
|
## Flags
|
|
24
22
|
|
|
25
|
-
Register
|
|
23
|
+
Register CLI flags and read them in any handler.
|
|
26
24
|
|
|
27
25
|
```typescript
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
pi.registerFlag("plan", {
|
|
27
|
+
description: "Start in plan mode",
|
|
28
|
+
type: "boolean",
|
|
31
29
|
default: false,
|
|
32
30
|
});
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
const autoCommit = pi.getFlag("auto-commit");
|
|
32
|
+
const planEnabled = pi.getFlag("plan") === true;
|
|
36
33
|
```
|
|
37
34
|
|
|
38
|
-
|
|
35
|
+
## Commands and Sessions
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
Command handlers receive `ExtensionCommandContext`, which adds session-control methods. These methods are command-only because they can deadlock from event handlers.
|
|
41
38
|
|
|
42
|
-
|
|
39
|
+
### Wait for idle
|
|
43
40
|
|
|
44
41
|
```typescript
|
|
45
|
-
pi.
|
|
42
|
+
pi.registerCommand("safe-command", {
|
|
43
|
+
handler: async (_args, ctx) => {
|
|
44
|
+
await ctx.waitForIdle();
|
|
45
|
+
// Safe to inspect or replace session state.
|
|
46
|
+
},
|
|
47
|
+
});
|
|
46
48
|
```
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
### New, fork, switch
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Set or get a name for the current session (shown in the session selector):
|
|
52
|
+
Use `withSession` for post-replacement work. Captured old `pi`, old command `ctx`, and old `ctx.sessionManager` are stale after replacement.
|
|
53
53
|
|
|
54
54
|
```typescript
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
await ctx.newSession({
|
|
56
|
+
setup: async (sm) => {
|
|
57
|
+
sm.appendMessage({
|
|
58
|
+
role: "user",
|
|
59
|
+
content: [{ type: "text", text: "Seed context" }],
|
|
60
|
+
timestamp: Date.now(),
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
withSession: async (ctx) => {
|
|
64
|
+
await ctx.sendUserMessage("Continue from the new session");
|
|
65
|
+
},
|
|
66
|
+
});
|
|
57
67
|
```
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
```typescript
|
|
70
|
+
await ctx.fork(entryId, {
|
|
71
|
+
position: "at",
|
|
72
|
+
withSession: async (ctx) => ctx.ui.notify("Forked", "info"),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
await ctx.switchSession(sessionPath, {
|
|
76
|
+
withSession: async (ctx) => {
|
|
77
|
+
await ctx.sendUserMessage("Resume this work here");
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
```
|
|
60
81
|
|
|
61
|
-
|
|
82
|
+
### Tree navigation
|
|
62
83
|
|
|
63
84
|
```typescript
|
|
64
|
-
|
|
85
|
+
await ctx.navigateTree(targetId, {
|
|
86
|
+
summarize: true,
|
|
87
|
+
customInstructions: "Focus on implementation decisions",
|
|
88
|
+
replaceInstructions: false,
|
|
89
|
+
label: "review-checkpoint",
|
|
90
|
+
});
|
|
65
91
|
```
|
|
66
92
|
|
|
67
|
-
##
|
|
93
|
+
## Reload
|
|
68
94
|
|
|
69
|
-
|
|
95
|
+
Use `ctx.reload()` in command handlers. Treat it as terminal for predictable behavior.
|
|
70
96
|
|
|
71
97
|
```typescript
|
|
72
|
-
|
|
73
|
-
|
|
98
|
+
pi.registerCommand("reload-runtime", {
|
|
99
|
+
description: "Reload extensions, skills, prompts, and themes",
|
|
100
|
+
handler: async (_args, ctx) => {
|
|
101
|
+
await ctx.reload();
|
|
102
|
+
return;
|
|
103
|
+
},
|
|
104
|
+
});
|
|
74
105
|
```
|
|
75
106
|
|
|
76
|
-
|
|
107
|
+
Code after `await ctx.reload()` still runs in the old call frame. Avoid post-reload work in that handler.
|
|
77
108
|
|
|
78
|
-
|
|
109
|
+
Tools cannot call `ctx.reload()`. If the LLM needs a reload tool, create a tool that queues a reload command as a follow-up user message.
|
|
79
110
|
|
|
80
|
-
|
|
111
|
+
```typescript
|
|
112
|
+
async execute() {
|
|
113
|
+
pi.sendUserMessage("/reload-runtime", { deliverAs: "followUp" });
|
|
114
|
+
return { content: [{ type: "text", text: "Queued /reload-runtime." }] };
|
|
115
|
+
}
|
|
116
|
+
```
|
|
81
117
|
|
|
82
|
-
##
|
|
118
|
+
## Sending Messages
|
|
119
|
+
|
|
120
|
+
### `pi.sendUserMessage(content, options?)`
|
|
83
121
|
|
|
84
|
-
|
|
122
|
+
Sends an actual user message and triggers a turn.
|
|
85
123
|
|
|
86
124
|
```typescript
|
|
87
|
-
|
|
88
|
-
pi.
|
|
125
|
+
pi.sendUserMessage("Summarize the current state.");
|
|
126
|
+
pi.sendUserMessage("Focus on tests next.", { deliverAs: "steer" });
|
|
127
|
+
pi.sendUserMessage("After that, summarize.", { deliverAs: "followUp" });
|
|
89
128
|
```
|
|
90
129
|
|
|
91
|
-
|
|
130
|
+
When the agent is streaming, specify `deliverAs: "steer"` or `"followUp"`.
|
|
92
131
|
|
|
93
|
-
|
|
132
|
+
### `pi.sendMessage(message, options?)`
|
|
133
|
+
|
|
134
|
+
Sends a custom message. Use `registerMessageRenderer` for custom display.
|
|
94
135
|
|
|
95
136
|
```typescript
|
|
96
|
-
|
|
97
|
-
|
|
137
|
+
pi.sendMessage(
|
|
138
|
+
{
|
|
139
|
+
customType: "my-extension-status",
|
|
140
|
+
content: "Status update",
|
|
141
|
+
display: true,
|
|
142
|
+
details: { status: "ok" },
|
|
143
|
+
},
|
|
144
|
+
{ deliverAs: "nextTurn" },
|
|
145
|
+
);
|
|
146
|
+
```
|
|
98
147
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
148
|
+
Delivery modes:
|
|
149
|
+
|
|
150
|
+
- `steer`: queue while streaming and deliver before next LLM call.
|
|
151
|
+
- `followUp`: wait until the agent finishes.
|
|
152
|
+
- `nextTurn`: save for the next user prompt.
|
|
153
|
+
|
|
154
|
+
## State and Session Metadata
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
pi.appendEntry("my-extension-state", { enabled: true });
|
|
158
|
+
pi.setSessionName("Feature: auth refactor");
|
|
159
|
+
const name = pi.getSessionName();
|
|
160
|
+
pi.setLabel(entryId, "checkpoint-before-refactor");
|
|
161
|
+
pi.setLabel(entryId, undefined); // clear
|
|
102
162
|
```
|
|
103
163
|
|
|
104
|
-
|
|
164
|
+
Use labels for `/tree` bookmarks and session names for the session selector.
|
|
105
165
|
|
|
106
|
-
|
|
166
|
+
## Shell Execution
|
|
167
|
+
|
|
168
|
+
Use `pi.exec(command, args, options?)` for shell commands.
|
|
107
169
|
|
|
108
170
|
```typescript
|
|
109
|
-
pi.
|
|
110
|
-
|
|
111
|
-
|
|
171
|
+
const result = await pi.exec("git", ["status", "--porcelain"], {
|
|
172
|
+
cwd: ctx.cwd,
|
|
173
|
+
signal,
|
|
174
|
+
timeout: 5_000,
|
|
112
175
|
});
|
|
176
|
+
|
|
177
|
+
// result.stdout, result.stderr, result.code, result.killed
|
|
113
178
|
```
|
|
114
179
|
|
|
115
|
-
The
|
|
180
|
+
Do not use Node `child_process` APIs for normal command execution. The only exception is a documented long-lived streaming process with direct stdin/stdout needs that `pi.exec()` cannot support.
|
|
116
181
|
|
|
117
|
-
|
|
182
|
+
## Active Tools
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
const active = pi.getActiveTools();
|
|
186
|
+
const all = pi.getAllTools();
|
|
187
|
+
const builtin = all.filter((tool) => tool.sourceInfo.source === "builtin");
|
|
188
|
+
|
|
189
|
+
pi.setActiveTools(["read", "grep", "find"]);
|
|
190
|
+
```
|
|
118
191
|
|
|
119
|
-
|
|
192
|
+
`pi.getAllTools()` includes built-in tools, SDK tools, and extension tools with `sourceInfo` provenance.
|
|
120
193
|
|
|
121
|
-
|
|
122
|
-
- Your extension adds a tool that competes with a natural bash fallback (e.g. a process manager, a CI watcher, a search tool)
|
|
123
|
-
- Correct usage depends on subtle conditions (alert flags, when-not-to-use, alert vs. poll)
|
|
124
|
-
- You have observed agents ignoring the tool or reaching for `bash` instead
|
|
194
|
+
## Model and Thinking Control
|
|
125
195
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
196
|
+
```typescript
|
|
197
|
+
const model = ctx.modelRegistry.find("anthropic", "claude-sonnet-4-5");
|
|
198
|
+
if (model) {
|
|
199
|
+
const success = await pi.setModel(model);
|
|
200
|
+
if (!success) ctx.ui.notify("No API key for this model", "error");
|
|
201
|
+
}
|
|
129
202
|
|
|
130
|
-
|
|
203
|
+
const level = pi.getThinkingLevel();
|
|
204
|
+
pi.setThinkingLevel("high");
|
|
205
|
+
```
|
|
131
206
|
|
|
132
|
-
|
|
207
|
+
Thinking levels are `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, and `"xhigh"`. Pi clamps unsupported levels to model capabilities.
|
|
133
208
|
|
|
134
|
-
|
|
209
|
+
## System Prompt Guidance
|
|
135
210
|
|
|
136
|
-
|
|
211
|
+
Prefer tool-level `promptSnippet` and `promptGuidelines` for simple guidance. Use `before_agent_start` only for dynamic or cross-tool guidance.
|
|
137
212
|
|
|
138
|
-
-
|
|
139
|
-
- **`promptGuidelines`** — Appended verbatim to the global "Guidelines" section. Use for a short list of usage rules that still make sense without extra tool-local context.
|
|
213
|
+
### Per-tool metadata
|
|
140
214
|
|
|
141
215
|
```typescript
|
|
142
|
-
const myTool = {
|
|
216
|
+
const myTool = defineTool({
|
|
143
217
|
name: "my_tool",
|
|
144
218
|
label: "My Tool",
|
|
145
219
|
description: "...",
|
|
146
|
-
promptSnippet: "Manage background
|
|
220
|
+
promptSnippet: "Manage background work without blocking the conversation.",
|
|
147
221
|
promptGuidelines: [
|
|
148
|
-
"Use my_tool for long-running commands instead of
|
|
149
|
-
"After starting my_tool, continue
|
|
222
|
+
"Use my_tool for long-running commands instead of shell backgrounding.",
|
|
223
|
+
"After starting my_tool, continue useful work instead of polling my_tool immediately.",
|
|
150
224
|
],
|
|
151
|
-
parameters
|
|
152
|
-
execute
|
|
153
|
-
|
|
225
|
+
parameters,
|
|
226
|
+
async execute() {
|
|
227
|
+
// ...
|
|
228
|
+
},
|
|
229
|
+
});
|
|
154
230
|
```
|
|
155
231
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
Because these bullets are merged into the shared global `Guidelines` section, avoid vague phrasing like `Use this tool...`. Name the exact tool (`my_tool`, `process`, `linkup_web_search`) so the bullet remains clear after injection.
|
|
159
|
-
|
|
160
|
-
#### Tier 2: System Prompt Hook (For Complex Cross-Tool Orchestration)
|
|
232
|
+
Every `promptGuidelines` bullet must name the exact tool because Pi injects bullets flat into the global Guidelines section.
|
|
161
233
|
|
|
162
|
-
|
|
163
|
-
- Guidance involves **cross-tool workflow instructions** (e.g. "use tool A, then tool B, then tool C")
|
|
164
|
-
- You need **dynamic context from config** (e.g. workspace names, team keys, feature flags)
|
|
165
|
-
- The per-tool metadata fields aren't expressive enough
|
|
166
|
-
|
|
167
|
-
**Structure: three files**
|
|
168
|
-
|
|
169
|
-
`src/guidance.ts` — the guidance text as a named export:
|
|
234
|
+
### System prompt hook
|
|
170
235
|
|
|
171
236
|
```typescript
|
|
172
237
|
export const MY_EXTENSION_GUIDANCE = `
|
|
173
238
|
## My Extension
|
|
174
239
|
|
|
175
|
-
Use
|
|
240
|
+
Use \`my_tool\` when ...
|
|
241
|
+
Do not use bash workaround ...
|
|
242
|
+
`;
|
|
176
243
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
244
|
+
pi.on("before_agent_start", async (event) => {
|
|
245
|
+
if (!configLoader.getConfig().systemPromptGuidance) return;
|
|
246
|
+
return {
|
|
247
|
+
systemPrompt: `${event.systemPrompt}\n\n${MY_EXTENSION_GUIDANCE}`,
|
|
248
|
+
};
|
|
249
|
+
});
|
|
250
|
+
```
|
|
180
251
|
|
|
181
|
-
|
|
182
|
-
- You need the result immediately to proceed (quick commands that finish in seconds)
|
|
252
|
+
Use `event.systemPromptOptions` when you need structured prompt inputs such as selected tools, loaded skills, context files, and accumulated prompt guidelines.
|
|
183
253
|
|
|
184
|
-
|
|
185
|
-
\`\`\`bash
|
|
186
|
-
workaround_command # loses observability
|
|
187
|
-
\`\`\`
|
|
254
|
+
## Compaction and Shutdown
|
|
188
255
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
256
|
+
Use `ctx.compact()` to trigger compaction without awaiting the full operation.
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
ctx.compact({
|
|
260
|
+
customInstructions: "Focus on recent code changes",
|
|
261
|
+
onComplete: (result) => ctx.ui.notify("Compaction complete", "info"),
|
|
262
|
+
onError: (error) => ctx.ui.notify(`Compaction failed: ${error.message}`, "error"),
|
|
263
|
+
});
|
|
194
264
|
```
|
|
195
265
|
|
|
196
|
-
`
|
|
266
|
+
Use `ctx.shutdown()` to request graceful shutdown.
|
|
197
267
|
|
|
198
268
|
```typescript
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
import { MY_EXTENSION_GUIDANCE } from "../guidance";
|
|
269
|
+
ctx.shutdown();
|
|
270
|
+
```
|
|
202
271
|
|
|
203
|
-
|
|
204
|
-
pi.on("before_agent_start", async (event) => {
|
|
205
|
-
const config = configLoader.getConfig();
|
|
206
|
-
if (!config.systemPromptGuidance) return;
|
|
272
|
+
In interactive and RPC modes, shutdown is deferred until Pi becomes idle. In print mode it is a no-op.
|
|
207
273
|
|
|
208
|
-
|
|
209
|
-
systemPrompt: `${event.systemPrompt}\n${MY_EXTENSION_GUIDANCE}`,
|
|
210
|
-
};
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
```
|
|
274
|
+
## Event Bus
|
|
214
275
|
|
|
215
|
-
|
|
276
|
+
Use the shared event bus only when extensions need to coordinate.
|
|
216
277
|
|
|
217
278
|
```typescript
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
279
|
+
pi.events.emit("my-extension:data-ready", { items });
|
|
280
|
+
pi.events.on("my-extension:data-ready", (data) => {
|
|
281
|
+
console.log(data.items.length);
|
|
282
|
+
});
|
|
223
283
|
```
|
|
224
284
|
|
|
225
|
-
|
|
285
|
+
Namespace event names with your extension name.
|
|
226
286
|
|
|
227
|
-
|
|
287
|
+
## UI Customization
|
|
228
288
|
|
|
229
|
-
|
|
289
|
+
### Working indicator and message
|
|
230
290
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
- Keep the guidance section header (`## My Extension`) so it reads as a named capability, not a restriction.
|
|
235
|
-
- Avoid stacking emphasis markers (`NEVER`, `ALWAYS`, `IMPORTANT`). One or two land; more are ignored.
|
|
291
|
+
```typescript
|
|
292
|
+
ctx.ui.setWorkingMessage("Thinking through plan...");
|
|
293
|
+
ctx.ui.setWorkingMessage(); // restore default
|
|
236
294
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
- `pi-linear` — Uses `guidance.ts` + `before_agent_start` hook (cross-tool workflow instructions + dynamic workspace context).
|
|
240
|
-
- `pi-processes` — Uses both: `promptSnippet`/`promptGuidelines` on tools for basic guidance, plus system prompt hook for complex multi-tool orchestration patterns.
|
|
295
|
+
ctx.ui.setWorkingVisible(false);
|
|
296
|
+
ctx.ui.setWorkingVisible(true);
|
|
241
297
|
|
|
242
|
-
|
|
298
|
+
ctx.ui.setWorkingIndicator({ frames: [ctx.ui.theme.fg("accent", "●")] });
|
|
299
|
+
ctx.ui.setWorkingIndicator({ frames: [] }); // hide indicator
|
|
300
|
+
ctx.ui.setWorkingIndicator(); // restore default
|
|
301
|
+
```
|
|
243
302
|
|
|
244
|
-
|
|
303
|
+
### Widgets, title, editor text
|
|
245
304
|
|
|
246
305
|
```typescript
|
|
247
|
-
|
|
306
|
+
ctx.ui.setWidget("my-widget", ["Line 1", "Line 2"]);
|
|
307
|
+
ctx.ui.setWidget("my-widget", ["Below"], { placement: "belowEditor" });
|
|
308
|
+
ctx.ui.setWidget("my-widget", undefined);
|
|
309
|
+
|
|
310
|
+
ctx.ui.setTitle("pi - my project");
|
|
311
|
+
ctx.ui.setEditorText("Prefilled prompt");
|
|
312
|
+
const editorText = ctx.ui.getEditorText();
|
|
313
|
+
ctx.ui.pasteToEditor("Pasted content");
|
|
248
314
|
```
|
|
249
315
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
Shut down pi gracefully:
|
|
316
|
+
### Footer
|
|
253
317
|
|
|
254
318
|
```typescript
|
|
255
|
-
|
|
319
|
+
ctx.ui.setFooter((tui, theme, footerData) => ({
|
|
320
|
+
invalidate() {},
|
|
321
|
+
render(width) {
|
|
322
|
+
return [theme.fg("dim", footerData.getGitBranch() ?? "no git")];
|
|
323
|
+
},
|
|
324
|
+
dispose: footerData.onBranchChange(() => tui.requestRender()),
|
|
325
|
+
}));
|
|
326
|
+
|
|
327
|
+
ctx.ui.setFooter(undefined);
|
|
256
328
|
```
|
|
257
329
|
|
|
258
|
-
|
|
330
|
+
### Autocomplete providers
|
|
259
331
|
|
|
260
|
-
|
|
332
|
+
Stack on top of the current provider and delegate when your syntax does not match.
|
|
261
333
|
|
|
262
334
|
```typescript
|
|
263
|
-
|
|
264
|
-
|
|
335
|
+
ctx.ui.addAutocompleteProvider((current) => ({
|
|
336
|
+
async getSuggestions(lines, cursorLine, cursorCol, options) {
|
|
337
|
+
const beforeCursor = (lines[cursorLine] ?? "").slice(0, cursorCol);
|
|
338
|
+
const match = beforeCursor.match(/(?:^|[ \t])#([^\s#]*)$/);
|
|
339
|
+
if (!match) return current.getSuggestions(lines, cursorLine, cursorCol, options);
|
|
265
340
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
341
|
+
return {
|
|
342
|
+
prefix: `#${match[1] ?? ""}`,
|
|
343
|
+
items: [{ value: "#123", label: "#123", description: "Issue title" }],
|
|
344
|
+
};
|
|
345
|
+
},
|
|
346
|
+
applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
|
|
347
|
+
return current.applyCompletion(lines, cursorLine, cursorCol, item, prefix);
|
|
348
|
+
},
|
|
349
|
+
shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {
|
|
350
|
+
return current.shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? true;
|
|
351
|
+
},
|
|
352
|
+
}));
|
|
270
353
|
```
|
|
271
354
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
## Theme Control
|
|
355
|
+
### Theme control
|
|
275
356
|
|
|
276
357
|
```typescript
|
|
277
|
-
|
|
278
|
-
const
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
// Set theme
|
|
282
|
-
const result = ctx.ui.setTheme("catppuccin-mocha");
|
|
283
|
-
// result: { success: boolean, error?: string }
|
|
358
|
+
const themes = ctx.ui.getAllThemes();
|
|
359
|
+
const light = ctx.ui.getTheme("light");
|
|
360
|
+
const result = ctx.ui.setTheme("light");
|
|
361
|
+
if (!result.success) ctx.ui.notify(result.error, "error");
|
|
284
362
|
```
|
|
285
363
|
|
|
286
|
-
##
|
|
364
|
+
## Pi Paths
|
|
287
365
|
|
|
288
|
-
|
|
289
|
-
// Replace the footer
|
|
290
|
-
ctx.ui.setFooter((maxWidth, theme) => {
|
|
291
|
-
return theme.fg("muted", "Custom footer content");
|
|
292
|
-
});
|
|
366
|
+
Use SDK helpers for Pi paths instead of `homedir()` when helpers exist. They respect `PI_CODING_AGENT_DIR` and test/custom setups.
|
|
293
367
|
|
|
294
|
-
|
|
295
|
-
ctx.ui.setHeader((maxWidth, theme) => {
|
|
296
|
-
return theme.fg("accent", "My Custom Header");
|
|
297
|
-
});
|
|
368
|
+
Common helpers exported from the main package include:
|
|
298
369
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
370
|
+
- `getAgentDir()`
|
|
371
|
+
- `getSettingsPath()`
|
|
372
|
+
- `getSessionsDir()`
|
|
373
|
+
- `getPromptsDir()`
|
|
374
|
+
- `getToolsDir()`
|
|
375
|
+
- `getCustomThemesDir()`
|
|
376
|
+
- `getModelsPath()`
|
|
377
|
+
- `getAuthPath()`
|
|
378
|
+
- `getBinDir()`
|
|
379
|
+
- `getDebugLogPath()`
|
|
303
380
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
381
|
+
## Checklist
|
|
382
|
+
|
|
383
|
+
- [ ] Session replacement code uses `withSession` for post-switch work.
|
|
384
|
+
- [ ] Reload handlers return immediately after `await ctx.reload()`.
|
|
385
|
+
- [ ] `pi.exec()` is used instead of `child_process`.
|
|
386
|
+
- [ ] System prompt changes return `{ systemPrompt }` from `before_agent_start`.
|
|
387
|
+
- [ ] `promptGuidelines` bullets name exact tools.
|
|
388
|
+
- [ ] UI customizations account for RPC/print degradation.
|
|
389
|
+
- [ ] Pi path helpers are used instead of `homedir()`.
|