@code-yeongyu/senpi 2026.6.14 → 2026.6.15
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/CHANGELOG.md +38 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +8 -4
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +87 -12
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +6 -17
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/extensions.md +4 -4
- package/examples/extensions/question.ts +39 -18
- package/examples/extensions/questionnaire.ts +49 -28
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +79 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +55 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +14 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
package/docs/extensions.md
CHANGED
|
@@ -1534,21 +1534,21 @@ const result = await pi.exec("git", ["status"], { signal, timeout: 5000 });
|
|
|
1534
1534
|
|
|
1535
1535
|
### pi.getActiveTools() / pi.getAllTools() / pi.setActiveTools(names)
|
|
1536
1536
|
|
|
1537
|
-
Manage active tools. This works for both built-in tools and dynamically registered tools.
|
|
1537
|
+
Manage active tools. This works for both built-in tools and dynamically registered tools. `pi.getActiveTools()` returns the active tool names as `string[]`; `pi.getAllTools()` returns metadata for all configured tools.
|
|
1538
1538
|
|
|
1539
1539
|
```typescript
|
|
1540
|
-
const active = pi.getActiveTools();
|
|
1540
|
+
const active = pi.getActiveTools(); // ["read", "bash", ...]
|
|
1541
1541
|
const all = pi.getAllTools();
|
|
1542
|
-
// [{
|
|
1542
|
+
// all = [{
|
|
1543
1543
|
// name: "read",
|
|
1544
1544
|
// description: "Read file contents...",
|
|
1545
1545
|
// parameters: ...,
|
|
1546
1546
|
// promptGuidelines: ["Use read to examine files instead of cat or sed."],
|
|
1547
1547
|
// sourceInfo: { path: "<builtin:read>", source: "builtin", scope: "temporary", origin: "top-level" }
|
|
1548
1548
|
// }, ...]
|
|
1549
|
-
const names = all.map(t => t.name);
|
|
1550
1549
|
const builtinTools = all.filter((t) => t.sourceInfo.source === "builtin");
|
|
1551
1550
|
const extensionTools = all.filter((t) => t.sourceInfo.source !== "builtin" && t.sourceInfo.source !== "sdk");
|
|
1551
|
+
pi.setActiveTools([...new Set([...active, "my_custom_tool"])]); // Keep current tools and enable my_custom_tool
|
|
1552
1552
|
pi.setActiveTools(["read", "bash"]); // Switch to read-only
|
|
1553
1553
|
```
|
|
1554
1554
|
|
|
@@ -5,7 +5,15 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { ExtensionAPI } from "@code-yeongyu/senpi";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
Editor,
|
|
10
|
+
type EditorTheme,
|
|
11
|
+
Key,
|
|
12
|
+
matchesKey,
|
|
13
|
+
Text,
|
|
14
|
+
visibleWidth,
|
|
15
|
+
wrapTextWithAnsi,
|
|
16
|
+
} from "@earendil-works/pi-tui";
|
|
9
17
|
import { Type } from "typebox";
|
|
10
18
|
|
|
11
19
|
interface OptionWithDesc {
|
|
@@ -139,10 +147,27 @@ export default function question(pi: ExtensionAPI) {
|
|
|
139
147
|
if (cachedLines) return cachedLines;
|
|
140
148
|
|
|
141
149
|
const lines: string[] = [];
|
|
142
|
-
const
|
|
150
|
+
const renderWidth = Math.max(1, width);
|
|
143
151
|
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
function addWrapped(text: string) {
|
|
153
|
+
lines.push(...wrapTextWithAnsi(text, renderWidth));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function addWrappedWithPrefix(prefix: string, text: string) {
|
|
157
|
+
const prefixWidth = visibleWidth(prefix);
|
|
158
|
+
if (prefixWidth >= renderWidth) {
|
|
159
|
+
addWrapped(prefix + text);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const wrapped = wrapTextWithAnsi(text, renderWidth - prefixWidth);
|
|
163
|
+
const continuationPrefix = " ".repeat(prefixWidth);
|
|
164
|
+
for (let i = 0; i < wrapped.length; i++) {
|
|
165
|
+
lines.push(`${i === 0 ? prefix : continuationPrefix}${wrapped[i]}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
lines.push(theme.fg("accent", "─".repeat(renderWidth)));
|
|
170
|
+
addWrappedWithPrefix(" ", theme.fg("text", params.question));
|
|
146
171
|
lines.push("");
|
|
147
172
|
|
|
148
173
|
for (let i = 0; i < allOptions.length; i++) {
|
|
@@ -150,36 +175,32 @@ export default function question(pi: ExtensionAPI) {
|
|
|
150
175
|
const selected = i === optionIndex;
|
|
151
176
|
const isOther = opt.isOther === true;
|
|
152
177
|
const prefix = selected ? theme.fg("accent", "> ") : " ";
|
|
178
|
+
const label = `${i + 1}. ${opt.label}${isOther && editMode ? " ✎" : ""}`;
|
|
179
|
+
const color = selected || (isOther && editMode) ? "accent" : "text";
|
|
153
180
|
|
|
154
|
-
|
|
155
|
-
add(prefix + theme.fg("accent", `${i + 1}. ${opt.label} ✎`));
|
|
156
|
-
} else if (selected) {
|
|
157
|
-
add(prefix + theme.fg("accent", `${i + 1}. ${opt.label}`));
|
|
158
|
-
} else {
|
|
159
|
-
add(` ${theme.fg("text", `${i + 1}. ${opt.label}`)}`);
|
|
160
|
-
}
|
|
181
|
+
addWrappedWithPrefix(prefix, theme.fg(color, label));
|
|
161
182
|
|
|
162
183
|
// Show description if present
|
|
163
184
|
if (opt.description) {
|
|
164
|
-
|
|
185
|
+
addWrappedWithPrefix(" ", theme.fg("muted", opt.description));
|
|
165
186
|
}
|
|
166
187
|
}
|
|
167
188
|
|
|
168
189
|
if (editMode) {
|
|
169
190
|
lines.push("");
|
|
170
|
-
|
|
171
|
-
for (const line of editor.render(
|
|
172
|
-
|
|
191
|
+
addWrappedWithPrefix(" ", theme.fg("muted", "Your answer:"));
|
|
192
|
+
for (const line of editor.render(Math.max(1, renderWidth - 2))) {
|
|
193
|
+
lines.push(` ${line}`);
|
|
173
194
|
}
|
|
174
195
|
}
|
|
175
196
|
|
|
176
197
|
lines.push("");
|
|
177
198
|
if (editMode) {
|
|
178
|
-
|
|
199
|
+
addWrappedWithPrefix(" ", theme.fg("dim", "Enter to submit • Esc to go back"));
|
|
179
200
|
} else {
|
|
180
|
-
|
|
201
|
+
addWrappedWithPrefix(" ", theme.fg("dim", "↑↓ navigate • Enter to select • Esc to cancel"));
|
|
181
202
|
}
|
|
182
|
-
|
|
203
|
+
lines.push(theme.fg("accent", "─".repeat(renderWidth)));
|
|
183
204
|
|
|
184
205
|
cachedLines = lines;
|
|
185
206
|
return lines;
|
|
@@ -6,7 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { ExtensionAPI } from "@code-yeongyu/senpi";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Editor,
|
|
11
|
+
type EditorTheme,
|
|
12
|
+
Key,
|
|
13
|
+
matchesKey,
|
|
14
|
+
Text,
|
|
15
|
+
visibleWidth,
|
|
16
|
+
wrapTextWithAnsi,
|
|
17
|
+
} from "@earendil-works/pi-tui";
|
|
10
18
|
import { Type } from "typebox";
|
|
11
19
|
|
|
12
20
|
// Types
|
|
@@ -259,13 +267,28 @@ export default function questionnaire(pi: ExtensionAPI) {
|
|
|
259
267
|
if (cachedLines) return cachedLines;
|
|
260
268
|
|
|
261
269
|
const lines: string[] = [];
|
|
270
|
+
const renderWidth = Math.max(1, width);
|
|
262
271
|
const q = currentQuestion();
|
|
263
272
|
const opts = currentOptions();
|
|
264
273
|
|
|
265
|
-
|
|
266
|
-
|
|
274
|
+
function addWrapped(text: string) {
|
|
275
|
+
lines.push(...wrapTextWithAnsi(text, renderWidth));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function addWrappedWithPrefix(prefix: string, text: string) {
|
|
279
|
+
const prefixWidth = visibleWidth(prefix);
|
|
280
|
+
if (prefixWidth >= renderWidth) {
|
|
281
|
+
addWrapped(prefix + text);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const wrapped = wrapTextWithAnsi(text, renderWidth - prefixWidth);
|
|
285
|
+
const continuationPrefix = " ".repeat(prefixWidth);
|
|
286
|
+
for (let i = 0; i < wrapped.length; i++) {
|
|
287
|
+
lines.push(`${i === 0 ? prefix : continuationPrefix}${wrapped[i]}`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
267
290
|
|
|
268
|
-
|
|
291
|
+
lines.push(theme.fg("accent", "─".repeat(renderWidth)));
|
|
269
292
|
|
|
270
293
|
// Tab bar (multi-question only)
|
|
271
294
|
if (isMulti) {
|
|
@@ -287,7 +310,7 @@ export default function questionnaire(pi: ExtensionAPI) {
|
|
|
287
310
|
? theme.bg("selectedBg", theme.fg("text", submitText))
|
|
288
311
|
: theme.fg(canSubmit ? "success" : "dim", submitText);
|
|
289
312
|
tabs.push(`${submitStyled} →`);
|
|
290
|
-
|
|
313
|
+
addWrappedWithPrefix(" ", tabs.join(""));
|
|
291
314
|
lines.push("");
|
|
292
315
|
}
|
|
293
316
|
|
|
@@ -298,54 +321,52 @@ export default function questionnaire(pi: ExtensionAPI) {
|
|
|
298
321
|
const selected = i === optionIndex;
|
|
299
322
|
const isOther = opt.isOther === true;
|
|
300
323
|
const prefix = selected ? theme.fg("accent", "> ") : " ";
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
} else {
|
|
306
|
-
add(prefix + theme.fg(color, `${i + 1}. ${opt.label}`));
|
|
307
|
-
}
|
|
324
|
+
const label = `${i + 1}. ${opt.label}${isOther && inputMode ? " ✎" : ""}`;
|
|
325
|
+
const color = selected || (isOther && inputMode) ? "accent" : "text";
|
|
326
|
+
|
|
327
|
+
addWrappedWithPrefix(prefix, theme.fg(color, label));
|
|
308
328
|
if (opt.description) {
|
|
309
|
-
|
|
329
|
+
addWrappedWithPrefix(" ", theme.fg("muted", opt.description));
|
|
310
330
|
}
|
|
311
331
|
}
|
|
312
332
|
}
|
|
313
333
|
|
|
314
334
|
// Content
|
|
315
335
|
if (inputMode && q) {
|
|
316
|
-
|
|
336
|
+
addWrappedWithPrefix(" ", theme.fg("text", q.prompt));
|
|
317
337
|
lines.push("");
|
|
318
338
|
// Show options for reference
|
|
319
339
|
renderOptions();
|
|
320
340
|
lines.push("");
|
|
321
|
-
|
|
322
|
-
for (const line of editor.render(
|
|
323
|
-
|
|
341
|
+
addWrappedWithPrefix(" ", theme.fg("muted", "Your answer:"));
|
|
342
|
+
for (const line of editor.render(Math.max(1, renderWidth - 2))) {
|
|
343
|
+
lines.push(` ${line}`);
|
|
324
344
|
}
|
|
325
345
|
lines.push("");
|
|
326
|
-
|
|
346
|
+
addWrappedWithPrefix(" ", theme.fg("dim", "Enter to submit • Esc to cancel"));
|
|
327
347
|
} else if (currentTab === questions.length) {
|
|
328
|
-
|
|
348
|
+
addWrappedWithPrefix(" ", theme.fg("accent", theme.bold("Ready to submit")));
|
|
329
349
|
lines.push("");
|
|
330
350
|
for (const question of questions) {
|
|
331
351
|
const answer = answers.get(question.id);
|
|
332
352
|
if (answer) {
|
|
333
353
|
const prefix = answer.wasCustom ? "(wrote) " : "";
|
|
334
|
-
|
|
354
|
+
const summary = `${theme.fg("muted", `${question.label}: `)}${theme.fg("text", prefix + answer.label)}`;
|
|
355
|
+
addWrappedWithPrefix(" ", summary);
|
|
335
356
|
}
|
|
336
357
|
}
|
|
337
358
|
lines.push("");
|
|
338
359
|
if (allAnswered()) {
|
|
339
|
-
|
|
360
|
+
addWrappedWithPrefix(" ", theme.fg("success", "Press Enter to submit"));
|
|
340
361
|
} else {
|
|
341
362
|
const missing = questions
|
|
342
363
|
.filter((q) => !answers.has(q.id))
|
|
343
364
|
.map((q) => q.label)
|
|
344
365
|
.join(", ");
|
|
345
|
-
|
|
366
|
+
addWrappedWithPrefix(" ", theme.fg("warning", `Unanswered: ${missing}`));
|
|
346
367
|
}
|
|
347
368
|
} else if (q) {
|
|
348
|
-
|
|
369
|
+
addWrappedWithPrefix(" ", theme.fg("text", q.prompt));
|
|
349
370
|
lines.push("");
|
|
350
371
|
renderOptions();
|
|
351
372
|
}
|
|
@@ -353,11 +374,11 @@ export default function questionnaire(pi: ExtensionAPI) {
|
|
|
353
374
|
lines.push("");
|
|
354
375
|
if (!inputMode) {
|
|
355
376
|
const help = isMulti
|
|
356
|
-
? "
|
|
357
|
-
: "
|
|
358
|
-
|
|
377
|
+
? "Tab/←→ navigate • ↑↓ select • Enter confirm • Esc cancel"
|
|
378
|
+
: "↑↓ navigate • Enter select • Esc cancel";
|
|
379
|
+
addWrappedWithPrefix(" ", theme.fg("dim", help));
|
|
359
380
|
}
|
|
360
|
-
|
|
381
|
+
lines.push(theme.fg("accent", "─".repeat(renderWidth)));
|
|
361
382
|
|
|
362
383
|
cachedLines = lines;
|
|
363
384
|
return lines;
|
|
@@ -400,7 +421,7 @@ export default function questionnaire(pi: ExtensionAPI) {
|
|
|
400
421
|
let text = theme.fg("toolTitle", theme.bold("questionnaire "));
|
|
401
422
|
text += theme.fg("muted", `${count} question${count !== 1 ? "s" : ""}`);
|
|
402
423
|
if (labels) {
|
|
403
|
-
text += theme.fg("dim", ` (${
|
|
424
|
+
text += theme.fg("dim", ` (${labels})`);
|
|
404
425
|
}
|
|
405
426
|
return new Text(text, 0, 0);
|
|
406
427
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-agent-core",
|
|
3
3
|
"private": true,
|
|
4
|
-
"version": "2026.6.
|
|
4
|
+
"version": "2026.6.15",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"prepublishOnly": "npm run clean && npm run build"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@earendil-works/pi-ai": "^2026.6.
|
|
33
|
+
"@earendil-works/pi-ai": "^2026.6.15",
|
|
34
34
|
"ignore": "7.0.5",
|
|
35
35
|
"typebox": "1.1.38",
|
|
36
36
|
"yaml": "2.9.0"
|
|
@@ -5455,6 +5455,54 @@ export declare const MODELS: {
|
|
|
5455
5455
|
contextWindow: number;
|
|
5456
5456
|
maxTokens: number;
|
|
5457
5457
|
};
|
|
5458
|
+
readonly "gemma-4-E2B-it": {
|
|
5459
|
+
id: string;
|
|
5460
|
+
name: string;
|
|
5461
|
+
api: "google-generative-ai";
|
|
5462
|
+
provider: string;
|
|
5463
|
+
baseUrl: string;
|
|
5464
|
+
reasoning: true;
|
|
5465
|
+
thinkingLevelMap: {
|
|
5466
|
+
off: null;
|
|
5467
|
+
minimal: string;
|
|
5468
|
+
low: null;
|
|
5469
|
+
medium: null;
|
|
5470
|
+
high: string;
|
|
5471
|
+
};
|
|
5472
|
+
input: ("image" | "text")[];
|
|
5473
|
+
cost: {
|
|
5474
|
+
input: number;
|
|
5475
|
+
output: number;
|
|
5476
|
+
cacheRead: number;
|
|
5477
|
+
cacheWrite: number;
|
|
5478
|
+
};
|
|
5479
|
+
contextWindow: number;
|
|
5480
|
+
maxTokens: number;
|
|
5481
|
+
};
|
|
5482
|
+
readonly "gemma-4-E4B-it": {
|
|
5483
|
+
id: string;
|
|
5484
|
+
name: string;
|
|
5485
|
+
api: "google-generative-ai";
|
|
5486
|
+
provider: string;
|
|
5487
|
+
baseUrl: string;
|
|
5488
|
+
reasoning: true;
|
|
5489
|
+
thinkingLevelMap: {
|
|
5490
|
+
off: null;
|
|
5491
|
+
minimal: string;
|
|
5492
|
+
low: null;
|
|
5493
|
+
medium: null;
|
|
5494
|
+
high: string;
|
|
5495
|
+
};
|
|
5496
|
+
input: ("image" | "text")[];
|
|
5497
|
+
cost: {
|
|
5498
|
+
input: number;
|
|
5499
|
+
output: number;
|
|
5500
|
+
cacheRead: number;
|
|
5501
|
+
cacheWrite: number;
|
|
5502
|
+
};
|
|
5503
|
+
contextWindow: number;
|
|
5504
|
+
maxTokens: number;
|
|
5505
|
+
};
|
|
5458
5506
|
};
|
|
5459
5507
|
readonly "google-vertex": {
|
|
5460
5508
|
readonly "gemini-1.5-flash": {
|
|
@@ -14726,6 +14774,37 @@ export declare const MODELS: {
|
|
|
14726
14774
|
contextWindow: number;
|
|
14727
14775
|
maxTokens: number;
|
|
14728
14776
|
};
|
|
14777
|
+
readonly "moonshotai/Kimi-K2.7-Code": {
|
|
14778
|
+
id: string;
|
|
14779
|
+
name: string;
|
|
14780
|
+
api: "openai-completions";
|
|
14781
|
+
provider: string;
|
|
14782
|
+
baseUrl: string;
|
|
14783
|
+
compat: {
|
|
14784
|
+
supportsStore: false;
|
|
14785
|
+
supportsDeveloperRole: false;
|
|
14786
|
+
supportsReasoningEffort: false;
|
|
14787
|
+
maxTokensField: "max_tokens";
|
|
14788
|
+
supportsStrictMode: false;
|
|
14789
|
+
supportsLongCacheRetention: false;
|
|
14790
|
+
thinkingFormat: "together";
|
|
14791
|
+
};
|
|
14792
|
+
reasoning: true;
|
|
14793
|
+
thinkingLevelMap: {
|
|
14794
|
+
minimal: null;
|
|
14795
|
+
low: null;
|
|
14796
|
+
medium: null;
|
|
14797
|
+
};
|
|
14798
|
+
input: "text"[];
|
|
14799
|
+
cost: {
|
|
14800
|
+
input: number;
|
|
14801
|
+
output: number;
|
|
14802
|
+
cacheRead: number;
|
|
14803
|
+
cacheWrite: number;
|
|
14804
|
+
};
|
|
14805
|
+
contextWindow: number;
|
|
14806
|
+
maxTokens: number;
|
|
14807
|
+
};
|
|
14729
14808
|
readonly "nvidia/nemotron-3-ultra-550b-a55b": {
|
|
14730
14809
|
id: string;
|
|
14731
14810
|
name: string;
|