mitsupi 1.4.0 → 1.6.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/AGENTS.md +1 -1
- package/CHANGELOG.md +24 -0
- package/README.md +28 -18
- package/analyze-edits.py +232 -0
- package/distributions/README.md +8 -0
- package/distributions/mitsupi-common/README.md +11 -0
- package/distributions/mitsupi-common/package.json +95 -0
- package/distributions/mitsupi-loaded/README.md +13 -0
- package/distributions/mitsupi-loaded/package.json +38 -0
- package/{pi-extensions → extensions}/answer.ts +11 -11
- package/extensions/btw.ts +963 -0
- package/{pi-extensions → extensions}/context.ts +2 -2
- package/{pi-extensions → extensions}/control.ts +20 -13
- package/{pi-extensions → extensions}/files.ts +6 -8
- package/{pi-extensions → extensions}/go-to-bed.ts +2 -2
- package/{pi-extensions → extensions}/loop.ts +18 -11
- package/extensions/multi-edit.ts +871 -0
- package/{pi-extensions → extensions}/review.ts +254 -82
- package/{pi-extensions → extensions}/session-breakdown.ts +551 -74
- package/extensions/split-fork.ts +130 -0
- package/{pi-extensions → extensions}/todos.ts +41 -34
- package/extensions/uv.ts +123 -0
- package/intercepted-commands/poetry +8 -1
- package/intercepted-commands/python +42 -2
- package/intercepted-commands/python3 +42 -2
- package/package.json +6 -3
- package/skills/google-workspace/SKILL.md +53 -8
- package/skills/google-workspace/scripts/auth.js +106 -28
- package/skills/google-workspace/scripts/common.js +201 -32
- package/skills/google-workspace/scripts/workspace.js +64 -9
- package/skills/native-web-search/SKILL.md +2 -0
- package/skills/native-web-search/search.mjs +102 -15
- package/skills/pi-share/SKILL.md +5 -2
- package/skills/pi-share/fetch-session.mjs +46 -15
- package/skills/summarize/SKILL.md +4 -3
- package/skills/summarize/to-markdown.mjs +3 -1
- package/skills/web-browser/SKILL.md +6 -0
- package/skills/web-browser/scripts/start.js +75 -27
- package/pi-extensions/uv.ts +0 -33
- /package/{pi-extensions → extensions}/notify.ts +0 -0
- /package/{pi-extensions → extensions}/prompt-editor.ts +0 -0
- /package/{pi-extensions → extensions}/whimsical.ts +0 -0
- /package/{pi-themes → themes}/nightowl.json +0 -0
|
@@ -124,7 +124,7 @@ function buildSkillIndex(pi: ExtensionAPI, cwd: string): SkillIndexEntry[] {
|
|
|
124
124
|
.getCommands()
|
|
125
125
|
.filter((c) => c.source === "skill")
|
|
126
126
|
.map((c) => {
|
|
127
|
-
const p = c.path ? normalizeReadPath(c.path, cwd) : "";
|
|
127
|
+
const p = c.sourceInfo?.path ? normalizeReadPath(c.sourceInfo.path, cwd) : "";
|
|
128
128
|
return {
|
|
129
129
|
name: normalizeSkillName(c.name),
|
|
130
130
|
skillFilePath: p,
|
|
@@ -479,7 +479,7 @@ export default function contextExtension(pi: ExtensionAPI) {
|
|
|
479
479
|
|
|
480
480
|
const extensionsByPath = new Map<string, string[]>();
|
|
481
481
|
for (const c of extensionCmds) {
|
|
482
|
-
const p = c.path ?? "<unknown>";
|
|
482
|
+
const p = c.sourceInfo?.path ?? "<unknown>";
|
|
483
483
|
const arr = extensionsByPath.get(p) ?? [];
|
|
484
484
|
arr.push(c.name);
|
|
485
485
|
extensionsByPath.set(p, arr);
|
|
@@ -42,7 +42,13 @@
|
|
|
42
42
|
* Events are JSON objects with { type: "event", event, data?, subscriptionId? }
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
-
import type {
|
|
45
|
+
import type {
|
|
46
|
+
ExtensionAPI,
|
|
47
|
+
ExtensionContext,
|
|
48
|
+
TurnEndEvent,
|
|
49
|
+
MessageRenderer,
|
|
50
|
+
ModelRegistry,
|
|
51
|
+
} from "@mariozechner/pi-coding-agent";
|
|
46
52
|
import { getMarkdownTheme } from "@mariozechner/pi-coding-agent";
|
|
47
53
|
import { complete, type Model, type Api, type UserMessage, type TextContent } from "@mariozechner/pi-ai";
|
|
48
54
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
@@ -165,21 +171,18 @@ Be concise but comprehensive. Preserve exact file paths, function names, and err
|
|
|
165
171
|
|
|
166
172
|
async function selectSummarizationModel(
|
|
167
173
|
currentModel: Model<Api> | undefined,
|
|
168
|
-
modelRegistry:
|
|
169
|
-
find: (provider: string, modelId: string) => Model<Api> | undefined;
|
|
170
|
-
getApiKey: (model: Model<Api>) => Promise<string | undefined>;
|
|
171
|
-
},
|
|
174
|
+
modelRegistry: ModelRegistry,
|
|
172
175
|
): Promise<Model<Api> | undefined> {
|
|
173
176
|
const codexModel = modelRegistry.find("openai-codex", CODEX_MODEL_ID);
|
|
174
177
|
if (codexModel) {
|
|
175
|
-
const
|
|
176
|
-
if (
|
|
178
|
+
const auth = await modelRegistry.getApiKeyAndHeaders(codexModel);
|
|
179
|
+
if (auth.ok) return codexModel;
|
|
177
180
|
}
|
|
178
181
|
|
|
179
182
|
const haikuModel = modelRegistry.find("anthropic", HAIKU_MODEL_ID);
|
|
180
183
|
if (haikuModel) {
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
184
|
+
const auth = await modelRegistry.getApiKeyAndHeaders(haikuModel);
|
|
185
|
+
if (auth.ok) return haikuModel;
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
return currentModel;
|
|
@@ -657,9 +660,9 @@ async function handleCommand(
|
|
|
657
660
|
return;
|
|
658
661
|
}
|
|
659
662
|
|
|
660
|
-
const
|
|
661
|
-
if (!
|
|
662
|
-
respond(false, "get_summary", undefined,
|
|
663
|
+
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
664
|
+
if (!auth.ok) {
|
|
665
|
+
respond(false, "get_summary", undefined, auth.error);
|
|
663
666
|
return;
|
|
664
667
|
}
|
|
665
668
|
|
|
@@ -677,7 +680,7 @@ async function handleCommand(
|
|
|
677
680
|
const response = await complete(
|
|
678
681
|
model,
|
|
679
682
|
{ systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: [userMessage] },
|
|
680
|
-
{ apiKey },
|
|
683
|
+
{ apiKey: auth.apiKey, headers: auth.headers },
|
|
681
684
|
);
|
|
682
685
|
|
|
683
686
|
if (response.stopReason === "aborted" || response.stopReason === "error") {
|
|
@@ -1060,6 +1063,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
1060
1063
|
await refreshServer(ctx);
|
|
1061
1064
|
});
|
|
1062
1065
|
|
|
1066
|
+
pi.on("session_fork", async (_event, ctx) => {
|
|
1067
|
+
await refreshServer(ctx);
|
|
1068
|
+
});
|
|
1069
|
+
|
|
1063
1070
|
pi.on("session_shutdown", async () => {
|
|
1064
1071
|
if (state.aliasTimer) {
|
|
1065
1072
|
clearInterval(state.aliasTimer);
|
|
@@ -24,7 +24,6 @@ import { DynamicBorder } from "@mariozechner/pi-coding-agent";
|
|
|
24
24
|
import {
|
|
25
25
|
Container,
|
|
26
26
|
fuzzyFilter,
|
|
27
|
-
getEditorKeybindings,
|
|
28
27
|
Input,
|
|
29
28
|
matchesKey,
|
|
30
29
|
type SelectItem,
|
|
@@ -856,7 +855,7 @@ const showFileSelector = async (
|
|
|
856
855
|
});
|
|
857
856
|
|
|
858
857
|
let quickAction: "diff" | null = null;
|
|
859
|
-
const selection = await ctx.ui.custom<string | null>((tui, theme,
|
|
858
|
+
const selection = await ctx.ui.custom<string | null>((tui, theme, keybindings, done) => {
|
|
860
859
|
const container = new Container();
|
|
861
860
|
container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
|
|
862
861
|
container.addChild(new Text(theme.fg("accent", theme.bold(" Select file")), 0, 0));
|
|
@@ -937,16 +936,15 @@ const showFileSelector = async (
|
|
|
937
936
|
}
|
|
938
937
|
}
|
|
939
938
|
|
|
940
|
-
const kb = getEditorKeybindings();
|
|
941
939
|
if (
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
940
|
+
keybindings.matches(data, "tui.select.up") ||
|
|
941
|
+
keybindings.matches(data, "tui.select.down") ||
|
|
942
|
+
keybindings.matches(data, "tui.select.confirm") ||
|
|
943
|
+
keybindings.matches(data, "tui.select.cancel")
|
|
946
944
|
) {
|
|
947
945
|
if (selectList) {
|
|
948
946
|
selectList.handleInput(data);
|
|
949
|
-
} else if (
|
|
947
|
+
} else if (keybindings.matches(data, "tui.select.cancel")) {
|
|
950
948
|
done(null);
|
|
951
949
|
}
|
|
952
950
|
tui.requestRender();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
1
|
+
import type { ExtensionAPI, ToolCallEventResult } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
|
|
3
3
|
// "After midnight" usually means late-night usage. Default window: 00:00-05:59 local time.
|
|
4
4
|
const QUIET_HOURS_START = 0;
|
|
@@ -134,7 +134,7 @@ export default function goToBedExtension(pi: ExtensionAPI) {
|
|
|
134
134
|
}
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
pi.on("tool_call", async (event) => {
|
|
137
|
+
pi.on("tool_call", async (event): Promise<ToolCallEventResult | void> => {
|
|
138
138
|
const now = new Date();
|
|
139
139
|
if (!isQuietHours(now)) {
|
|
140
140
|
confirmedNightKey = null;
|
|
@@ -87,22 +87,22 @@ function getConditionText(mode: LoopMode, condition?: string): string {
|
|
|
87
87
|
|
|
88
88
|
async function selectSummaryModel(
|
|
89
89
|
ctx: ExtensionContext,
|
|
90
|
-
): Promise<{ model: Model<Api>; apiKey
|
|
90
|
+
): Promise<{ model: Model<Api>; apiKey?: string; headers?: Record<string, string> } | null> {
|
|
91
91
|
if (!ctx.model) return null;
|
|
92
92
|
|
|
93
93
|
if (ctx.model.provider === "anthropic") {
|
|
94
94
|
const haikuModel = ctx.modelRegistry.find("anthropic", HAIKU_MODEL_ID);
|
|
95
95
|
if (haikuModel) {
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
98
|
-
return { model: haikuModel, apiKey };
|
|
96
|
+
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(haikuModel);
|
|
97
|
+
if (auth.ok) {
|
|
98
|
+
return { model: haikuModel, apiKey: auth.apiKey, headers: auth.headers };
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
const
|
|
104
|
-
if (!
|
|
105
|
-
return { model: ctx.model, apiKey };
|
|
103
|
+
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(ctx.model);
|
|
104
|
+
if (!auth.ok) return null;
|
|
105
|
+
return { model: ctx.model, apiKey: auth.apiKey, headers: auth.headers };
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
async function summarizeBreakoutCondition(
|
|
@@ -124,7 +124,7 @@ async function summarizeBreakoutCondition(
|
|
|
124
124
|
const response = await complete(
|
|
125
125
|
selection.model,
|
|
126
126
|
{ systemPrompt: SUMMARY_SYSTEM_PROMPT, messages: [userMessage] },
|
|
127
|
-
{ apiKey: selection.apiKey },
|
|
127
|
+
{ apiKey: selection.apiKey, headers: selection.headers },
|
|
128
128
|
);
|
|
129
129
|
|
|
130
130
|
if (response.stopReason === "aborted" || response.stopReason === "error") {
|
|
@@ -400,15 +400,22 @@ export default function loopExtension(pi: ExtensionAPI): void {
|
|
|
400
400
|
|
|
401
401
|
pi.on("session_before_compact", async (event, ctx) => {
|
|
402
402
|
if (!loopState.active || !loopState.mode || !ctx.model) return;
|
|
403
|
-
const
|
|
404
|
-
if (!
|
|
403
|
+
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(ctx.model);
|
|
404
|
+
if (!auth.ok) return;
|
|
405
405
|
|
|
406
406
|
const instructionParts = [event.customInstructions, getCompactionInstructions(loopState.mode, loopState.condition)]
|
|
407
407
|
.filter(Boolean)
|
|
408
408
|
.join("\n\n");
|
|
409
409
|
|
|
410
410
|
try {
|
|
411
|
-
const compaction = await compact(
|
|
411
|
+
const compaction = await compact(
|
|
412
|
+
event.preparation,
|
|
413
|
+
ctx.model,
|
|
414
|
+
auth.apiKey ?? "",
|
|
415
|
+
auth.headers,
|
|
416
|
+
instructionParts,
|
|
417
|
+
event.signal,
|
|
418
|
+
);
|
|
412
419
|
return { compaction };
|
|
413
420
|
} catch (error) {
|
|
414
421
|
if (ctx.hasUI) {
|