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
package/AGENTS.md
CHANGED
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
|
|
10
10
|
## Extensions
|
|
11
11
|
|
|
12
|
-
Pi extensions live in `./
|
|
12
|
+
Pi extensions live in `./extensions`. When working in this repo, add or update extensions there. You can consult the `pi-mono` for reference, but do not modify code in `pi-mono`.
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ All notable changes to agent-stuff are documented here.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 1.6.0
|
|
8
|
+
|
|
9
|
+
* Added a redesigned `btw` extension with side chat markdown rendering, tool visibility, deferred session creation, and main-context improvements.
|
|
10
|
+
* Added a `/split-fork` Ghostty fork command for opening split sessions.
|
|
11
|
+
* Added email-based multi-account authentication to the `google-workspace` skill.
|
|
12
|
+
* Added left/right arrow key paging in the todo detail overlay. (#15)
|
|
13
|
+
* Added a shared custom instructions toggle to review workflows.
|
|
14
|
+
* Updated extensions for the new command and API-key APIs, including namespaced keybindings and `sourceInfo` support.
|
|
15
|
+
* Improved the `multi-edit` extension with sequential same-file ordering, redundant-edit skipping, and clearer patch-mode diff output.
|
|
16
|
+
* Fixed the `web-browser` skill and session-control refresh behavior after forks. (#16)
|
|
17
|
+
* Fixed `intercepted-commands/python` and `intercepted-commands/python3` to avoid recursive `uv` spawn loops by resolving a uv-managed non-shim interpreter for `uv run --python`.
|
|
18
|
+
|
|
19
|
+
## 1.5.0
|
|
20
|
+
|
|
21
|
+
* Added a `multi-edit` extension that replaces `edit` with support for batched `multi` edits and Codex-style `patch` payloads.
|
|
22
|
+
* Added preflight validation before mutating files for both `multi` edits and `patch` operations in `multi-edit`.
|
|
23
|
+
* Added `/session-breakdown` views for cwd, day-of-week, and time-of-day breakdowns.
|
|
24
|
+
* Added `pi-share` support for `pi.dev` URLs and `#session_id` inputs.
|
|
25
|
+
* Improved day rendering in `/session-breakdown`.
|
|
26
|
+
* Fixed PDF handling in the `summarize` skill.
|
|
27
|
+
* Hardened `uv` command handling by blocking pip/poetry bypasses.
|
|
28
|
+
* Fixed `web-browser` startup behavior to avoid killing user Chrome instances.
|
|
29
|
+
* Updated README extension docs to include `pi-extensions/multi-edit.ts`.
|
|
30
|
+
|
|
7
31
|
## 1.4.0
|
|
8
32
|
|
|
9
33
|
* Added a prompt editor extension for managing prompt modes (create, rename, delete, and edit), with persistence and detection fixes.
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ All skills live in the [`skills`](skills) folder:
|
|
|
20
20
|
* [`/native-web-search`](skills/native-web-search) - Trigger native web search with concise summaries and source URLs.
|
|
21
21
|
* [`/oebb-scotty`](skills/oebb-scotty) - Plan Austrian rail journeys via ÖBB Scotty API.
|
|
22
22
|
* [`/openscad`](skills/openscad) - Create/render OpenSCAD models and export STL files.
|
|
23
|
-
* [`/pi-share`](skills/pi-share) - Load and parse session transcripts from shittycodingagent.ai/buildwithpi URLs.
|
|
23
|
+
* [`/pi-share`](skills/pi-share) - Load and parse session transcripts from shittycodingagent.ai/buildwithpi/pi.dev URLs.
|
|
24
24
|
* [`/sentry`](skills/sentry) - Fetch and analyze Sentry issues, events, transactions, and logs.
|
|
25
25
|
* [`/summarize`](skills/summarize) - Convert files/URLs to Markdown via `uvx markitdown` and summarize.
|
|
26
26
|
* [`/tmux`](skills/tmux) - Drive tmux sessions via keystrokes and pane output scraping.
|
|
@@ -30,27 +30,37 @@ All skills live in the [`skills`](skills) folder:
|
|
|
30
30
|
|
|
31
31
|
## Pi Coding Agent Extensions
|
|
32
32
|
|
|
33
|
-
Custom extensions for Pi Coding Agent are in [`
|
|
34
|
-
|
|
35
|
-
* [`answer.ts`](
|
|
36
|
-
* [`
|
|
37
|
-
* [`
|
|
38
|
-
* [`
|
|
39
|
-
* [`
|
|
40
|
-
* [`
|
|
41
|
-
* [`
|
|
42
|
-
* [`
|
|
43
|
-
* [`
|
|
44
|
-
* [`
|
|
45
|
-
* [`
|
|
46
|
-
* [`
|
|
47
|
-
* [`
|
|
33
|
+
Custom extensions for Pi Coding Agent are in [`extensions`](extensions):
|
|
34
|
+
|
|
35
|
+
* [`answer.ts`](extensions/answer.ts) - Interactive TUI for answering questions one by one.
|
|
36
|
+
* [`btw.ts`](extensions/btw.ts) - Simple `/btw` side-chat popover with optional summary injection back into the main chat on close.
|
|
37
|
+
* [`context.ts`](extensions/context.ts) - Context breakdown (extensions, skills, AGENTS.md/CLAUDE.md) + token usage, including loaded-skill highlighting.
|
|
38
|
+
* [`control.ts`](extensions/control.ts) - Session control helpers (list controllable sessions, etc.).
|
|
39
|
+
* [`files.ts`](extensions/files.ts) - Unified file browser with git status + session references and reveal/open/edit/diff actions.
|
|
40
|
+
* [`split-fork.ts`](extensions/split-fork.ts) - `/split-fork` command to branch the current session into a new pi process in a right-hand Ghostty split.
|
|
41
|
+
* [`go-to-bed.ts`](extensions/go-to-bed.ts) - Late-night safety guard with explicit confirmation after midnight.
|
|
42
|
+
* [`loop.ts`](extensions/loop.ts) - Prompt loop for rapid iterative coding with optional auto-continue.
|
|
43
|
+
* [`multi-edit.ts`](extensions/multi-edit.ts) - Replaces the built-in `edit` tool with batch `multi` edits and Codex-style `patch` support, including preflight validation.
|
|
44
|
+
* [`notify.ts`](extensions/notify.ts) - Native desktop notifications when the agent finishes.
|
|
45
|
+
* [`prompt-editor.ts`](extensions/prompt-editor.ts) - In-editor prompt mode selector with persistence, history, config, and shortcuts.
|
|
46
|
+
* [`review.ts`](extensions/review.ts) - Code review command (working tree, PR-style diff, commits, custom instructions, optional fix loop).
|
|
47
|
+
* [`session-breakdown.ts`](extensions/session-breakdown.ts) - TUI for 7/30/90-day session and cost analysis with usage graph.
|
|
48
|
+
* [`todos.ts`](extensions/todos.ts) - Todo manager extension with file-backed storage and TUI.
|
|
49
|
+
* [`uv.ts`](extensions/uv.ts) - Helpers for uv-based Python workflows.
|
|
50
|
+
* [`whimsical.ts`](extensions/whimsical.ts) - Replaces the default thinking message with random whimsical phrases.
|
|
48
51
|
|
|
49
52
|
## Pi Coding Agent Themes
|
|
50
53
|
|
|
51
|
-
Custom themes are in [`
|
|
54
|
+
Custom themes are in [`themes`](themes):
|
|
52
55
|
|
|
53
|
-
* [`nightowl.json`](
|
|
56
|
+
* [`nightowl.json`](themes/nightowl.json) - Night Owl-inspired theme.
|
|
57
|
+
|
|
58
|
+
## Distributions
|
|
59
|
+
|
|
60
|
+
This repo also contains distribution packages in [`distributions`](distributions):
|
|
61
|
+
|
|
62
|
+
* [`mitsupi-common`](distributions/mitsupi-common) - Minimal/default set (all resources except `anachb`, `apple-mail`, `oebb-scotty`, `openscad`, and `go-to-bed`).
|
|
63
|
+
* [`mitsupi-loaded`](distributions/mitsupi-loaded) - Add-on package that provides `anachb`, `apple-mail`, `oebb-scotty`, `openscad`, and `go-to-bed`.
|
|
54
64
|
|
|
55
65
|
## Plumbing Commands
|
|
56
66
|
|
package/analyze-edits.py
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.12"
|
|
3
|
+
# dependencies = []
|
|
4
|
+
# ///
|
|
5
|
+
"""Analyze edit tool invocations in pi session JSONL files.
|
|
6
|
+
|
|
7
|
+
Usage: uv run analyze-edits.py <session.jsonl> [session2.jsonl ...]
|
|
8
|
+
|
|
9
|
+
Reports how many times the Edit tool was invoked via each mode:
|
|
10
|
+
- single: classic path/oldText/newText
|
|
11
|
+
- multi(N): multi array with N edits
|
|
12
|
+
- single+multi(N): top-level edit + multi array (N total)
|
|
13
|
+
- patch: Codex-style patch
|
|
14
|
+
|
|
15
|
+
Also breaks down by file extension.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import os
|
|
20
|
+
import sys
|
|
21
|
+
from collections import Counter
|
|
22
|
+
from dataclasses import dataclass
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def base_mode(mode: str) -> str:
|
|
27
|
+
if mode.startswith("multi(") or mode.startswith("single+multi("):
|
|
28
|
+
return "multi"
|
|
29
|
+
return mode
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def classify_edit(args: dict) -> tuple[str, list[str]]:
|
|
33
|
+
"""Returns (mode_label, list_of_file_extensions)."""
|
|
34
|
+
has_patch = "patch" in args
|
|
35
|
+
has_multi = "multi" in args
|
|
36
|
+
has_single = "path" in args and "oldText" in args
|
|
37
|
+
|
|
38
|
+
paths: list[str] = []
|
|
39
|
+
|
|
40
|
+
if has_patch:
|
|
41
|
+
# Parse paths from patch text
|
|
42
|
+
patch_text = args["patch"]
|
|
43
|
+
for line in patch_text.split("\n"):
|
|
44
|
+
line = line.strip()
|
|
45
|
+
for prefix in ("*** Add File: ", "*** Delete File: ", "*** Update File: "):
|
|
46
|
+
if line.startswith(prefix):
|
|
47
|
+
paths.append(line[len(prefix):])
|
|
48
|
+
return "patch", paths
|
|
49
|
+
|
|
50
|
+
multi_items = args.get("multi", [])
|
|
51
|
+
|
|
52
|
+
if has_single and has_multi:
|
|
53
|
+
paths.append(args["path"])
|
|
54
|
+
paths.extend(item.get("path", "") for item in multi_items)
|
|
55
|
+
return f"single+multi({1 + len(multi_items)})", paths
|
|
56
|
+
|
|
57
|
+
if has_multi:
|
|
58
|
+
paths.extend(item.get("path", "") for item in multi_items)
|
|
59
|
+
return f"multi({len(multi_items)})", paths
|
|
60
|
+
|
|
61
|
+
if has_single:
|
|
62
|
+
paths.append(args["path"])
|
|
63
|
+
return "single", paths
|
|
64
|
+
|
|
65
|
+
return "unknown", paths
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_ext(path: str) -> str:
|
|
69
|
+
ext = Path(path).suffix
|
|
70
|
+
return ext if ext else "(no ext)"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass
|
|
74
|
+
class EditCall:
|
|
75
|
+
mode: str
|
|
76
|
+
extensions: list[str]
|
|
77
|
+
failed: bool
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def analyze_session(filepath: str) -> list[EditCall]:
|
|
81
|
+
"""Returns list of EditCall for each edit tool invocation."""
|
|
82
|
+
# First pass: collect edit tool calls and their IDs
|
|
83
|
+
calls: list[tuple[str, str, list[str]]] = [] # (toolCallId, mode, exts)
|
|
84
|
+
tool_call_ids: dict[str, int] = {} # toolCallId -> index in calls
|
|
85
|
+
|
|
86
|
+
# Also collect tool results to check for errors
|
|
87
|
+
tool_results: dict[str, bool] = {} # toolCallId -> isError
|
|
88
|
+
|
|
89
|
+
entries = []
|
|
90
|
+
with open(filepath) as f:
|
|
91
|
+
for line in f:
|
|
92
|
+
entries.append(json.loads(line))
|
|
93
|
+
|
|
94
|
+
for d in entries:
|
|
95
|
+
if d.get("type") != "message":
|
|
96
|
+
continue
|
|
97
|
+
msg = d.get("message", {})
|
|
98
|
+
role = msg.get("role")
|
|
99
|
+
if role == "assistant":
|
|
100
|
+
for c in msg.get("content", []):
|
|
101
|
+
if c.get("type") == "toolCall" and c.get("name") in ("edit", "Edit"):
|
|
102
|
+
mode, paths = classify_edit(c.get("arguments", {}))
|
|
103
|
+
exts = [get_ext(p) for p in paths]
|
|
104
|
+
tc_id = c.get("id", "")
|
|
105
|
+
idx = len(calls)
|
|
106
|
+
calls.append((tc_id, mode, exts))
|
|
107
|
+
tool_call_ids[tc_id] = idx
|
|
108
|
+
elif role == "toolResult":
|
|
109
|
+
tc_id = msg.get("toolCallId", "")
|
|
110
|
+
is_error = msg.get("isError", False)
|
|
111
|
+
tool_results[tc_id] = is_error
|
|
112
|
+
|
|
113
|
+
results = []
|
|
114
|
+
for tc_id, mode, exts in calls:
|
|
115
|
+
failed = tool_results.get(tc_id, False)
|
|
116
|
+
results.append(EditCall(mode=mode, extensions=exts, failed=failed))
|
|
117
|
+
return results
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def main():
|
|
121
|
+
if len(sys.argv) < 2:
|
|
122
|
+
print(__doc__.strip())
|
|
123
|
+
sys.exit(1)
|
|
124
|
+
|
|
125
|
+
all_results: list[EditCall] = []
|
|
126
|
+
session_files = []
|
|
127
|
+
|
|
128
|
+
for arg in sys.argv[1:]:
|
|
129
|
+
p = Path(arg)
|
|
130
|
+
if p.is_dir():
|
|
131
|
+
session_files.extend(sorted(p.glob("**/*.jsonl")))
|
|
132
|
+
else:
|
|
133
|
+
session_files.append(p)
|
|
134
|
+
|
|
135
|
+
for sf in session_files:
|
|
136
|
+
all_results.extend(analyze_session(str(sf)))
|
|
137
|
+
|
|
138
|
+
if not all_results:
|
|
139
|
+
print("No edit tool calls found.")
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
total = len(all_results)
|
|
143
|
+
total_failed = sum(1 for r in all_results if r.failed)
|
|
144
|
+
|
|
145
|
+
# Count tool calls (not individual edits) by base mode
|
|
146
|
+
mode_calls: Counter[str] = Counter()
|
|
147
|
+
mode_fails: Counter[str] = Counter()
|
|
148
|
+
# Count tool calls by (base_mode, primary_ext)
|
|
149
|
+
# For a tool call, we pick the dominant extension
|
|
150
|
+
mode_ext_calls: Counter[tuple[str, str]] = Counter()
|
|
151
|
+
mode_ext_fails: Counter[tuple[str, str]] = Counter()
|
|
152
|
+
ext_calls: Counter[str] = Counter()
|
|
153
|
+
ext_fails: Counter[str] = Counter()
|
|
154
|
+
|
|
155
|
+
for r in all_results:
|
|
156
|
+
bm = base_mode(r.mode)
|
|
157
|
+
mode_calls[bm] += 1
|
|
158
|
+
if r.failed:
|
|
159
|
+
mode_fails[bm] += 1
|
|
160
|
+
|
|
161
|
+
# For extension: count one call per unique extension touched
|
|
162
|
+
exts = set(r.extensions) if r.extensions else {"(no ext)"}
|
|
163
|
+
for ext in exts:
|
|
164
|
+
mode_ext_calls[(bm, ext)] += 1
|
|
165
|
+
ext_calls[ext] += 1
|
|
166
|
+
if r.failed:
|
|
167
|
+
mode_ext_fails[(bm, ext)] += 1
|
|
168
|
+
ext_fails[ext] += 1
|
|
169
|
+
|
|
170
|
+
print(f"{'='*60}")
|
|
171
|
+
print(f"Edit Tool Analysis ({len(session_files)} session(s))")
|
|
172
|
+
print(f"{'='*60}")
|
|
173
|
+
print(f"\nTotal edit tool calls: {total}")
|
|
174
|
+
print(f"Total failures: {total_failed} ({total_failed/total*100:.1f}%)")
|
|
175
|
+
|
|
176
|
+
print(f"\n--- By Mode (tool calls) ---")
|
|
177
|
+
for mode, count in sorted(mode_calls.items(), key=lambda x: -x[1]):
|
|
178
|
+
pct = count / total * 100
|
|
179
|
+
fails = mode_fails[mode]
|
|
180
|
+
fail_pct = fails / count * 100 if count else 0
|
|
181
|
+
print(f" {mode:<12s} {count:>4d} ({pct:5.1f}%) fail: {fails:>3d} ({fail_pct:5.1f}%)")
|
|
182
|
+
|
|
183
|
+
print(f"\n--- By Extension (tool calls) ---")
|
|
184
|
+
for ext, count in sorted(ext_calls.items(), key=lambda x: -x[1]):
|
|
185
|
+
fails = ext_fails[ext]
|
|
186
|
+
fail_pct = fails / count * 100 if count else 0
|
|
187
|
+
print(f" {ext:<12s} {count:>4d} fail: {fails:>3d} ({fail_pct:5.1f}%)")
|
|
188
|
+
|
|
189
|
+
# Pivot table
|
|
190
|
+
all_modes = sorted(mode_calls.keys(), key=lambda m: -mode_calls[m])
|
|
191
|
+
all_exts = sorted(ext_calls.keys(), key=lambda e: -ext_calls[e])
|
|
192
|
+
|
|
193
|
+
col_w = 12
|
|
194
|
+
ext_w = max(12, *(len(e) for e in all_exts))
|
|
195
|
+
|
|
196
|
+
print(f"\n--- Extension × Mode (tool calls / failures) ---")
|
|
197
|
+
header = f" {'extension':<{ext_w}s}" + "".join(f" {m:>{col_w}s}" for m in all_modes) + f" {'total':>{col_w}s}"
|
|
198
|
+
print(header)
|
|
199
|
+
print(f" {'-'*(len(header)-2)}")
|
|
200
|
+
for ext in all_exts:
|
|
201
|
+
row = f" {ext:<{ext_w}s}"
|
|
202
|
+
row_total = 0
|
|
203
|
+
row_total_f = 0
|
|
204
|
+
for m in all_modes:
|
|
205
|
+
v = mode_ext_calls.get((m, ext), 0)
|
|
206
|
+
vf = mode_ext_fails.get((m, ext), 0)
|
|
207
|
+
row_total += v
|
|
208
|
+
row_total_f += vf
|
|
209
|
+
cell = f"{v}" if vf == 0 else f"{v} ({vf}✗)"
|
|
210
|
+
row += f" {cell:>{col_w}s}"
|
|
211
|
+
cell = f"{row_total}" if row_total_f == 0 else f"{row_total} ({row_total_f}✗)"
|
|
212
|
+
row += f" {cell:>{col_w}s}"
|
|
213
|
+
print(row)
|
|
214
|
+
# totals row
|
|
215
|
+
print(f" {'-'*(len(header)-2)}")
|
|
216
|
+
row = f" {'TOTAL':<{ext_w}s}"
|
|
217
|
+
grand = 0
|
|
218
|
+
grand_f = 0
|
|
219
|
+
for m in all_modes:
|
|
220
|
+
v = sum(mode_ext_calls.get((m, ext), 0) for ext in all_exts)
|
|
221
|
+
vf = sum(mode_ext_fails.get((m, ext), 0) for ext in all_exts)
|
|
222
|
+
grand += v
|
|
223
|
+
grand_f += vf
|
|
224
|
+
cell = f"{v}" if vf == 0 else f"{v} ({vf}✗)"
|
|
225
|
+
row += f" {cell:>{col_w}s}"
|
|
226
|
+
cell = f"{grand}" if grand_f == 0 else f"{grand} ({grand_f}✗)"
|
|
227
|
+
row += f" {cell:>{col_w}s}"
|
|
228
|
+
print(row)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
if __name__ == "__main__":
|
|
232
|
+
main()
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Distributions
|
|
2
|
+
|
|
3
|
+
This folder contains publishable Pi package variants based on `mitsupi`:
|
|
4
|
+
|
|
5
|
+
- `mitsupi-common`: default/minimal profile
|
|
6
|
+
- `mitsupi-loaded`: add-on profile with travel/CAD extras
|
|
7
|
+
|
|
8
|
+
`mitsupi-loaded` is intended to be installed together with `mitsupi-common`.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mitsupi-common",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Common/default Mitsupi package without heavy travel and CAD extras",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/mitsuhiko/agent-stuff.git",
|
|
8
|
+
"directory": "distributions/mitsupi-common"
|
|
9
|
+
},
|
|
10
|
+
"readme": "README.md",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"pi-package",
|
|
13
|
+
"pi-extension",
|
|
14
|
+
"pi-skill",
|
|
15
|
+
"pi-theme"
|
|
16
|
+
],
|
|
17
|
+
"pi": {
|
|
18
|
+
"extensions": [
|
|
19
|
+
"../../extensions/answer.ts",
|
|
20
|
+
"../../extensions/btw.ts",
|
|
21
|
+
"../../extensions/context.ts",
|
|
22
|
+
"../../extensions/control.ts",
|
|
23
|
+
"../../extensions/files.ts",
|
|
24
|
+
"../../extensions/loop.ts",
|
|
25
|
+
"../../extensions/multi-edit.ts",
|
|
26
|
+
"../../extensions/notify.ts",
|
|
27
|
+
"../../extensions/prompt-editor.ts",
|
|
28
|
+
"../../extensions/session-breakdown.ts",
|
|
29
|
+
"../../extensions/split-fork.ts",
|
|
30
|
+
"../../extensions/todos.ts",
|
|
31
|
+
"../../extensions/uv.ts",
|
|
32
|
+
"../../extensions/whimsical.ts",
|
|
33
|
+
"node_modules/mitsupi/extensions/answer.ts",
|
|
34
|
+
"node_modules/mitsupi/extensions/btw.ts",
|
|
35
|
+
"node_modules/mitsupi/extensions/context.ts",
|
|
36
|
+
"node_modules/mitsupi/extensions/control.ts",
|
|
37
|
+
"node_modules/mitsupi/extensions/files.ts",
|
|
38
|
+
"node_modules/mitsupi/extensions/loop.ts",
|
|
39
|
+
"node_modules/mitsupi/extensions/multi-edit.ts",
|
|
40
|
+
"node_modules/mitsupi/extensions/notify.ts",
|
|
41
|
+
"node_modules/mitsupi/extensions/prompt-editor.ts",
|
|
42
|
+
"node_modules/mitsupi/extensions/session-breakdown.ts",
|
|
43
|
+
"node_modules/mitsupi/extensions/split-fork.ts",
|
|
44
|
+
"node_modules/mitsupi/extensions/todos.ts",
|
|
45
|
+
"node_modules/mitsupi/extensions/uv.ts",
|
|
46
|
+
"node_modules/mitsupi/extensions/whimsical.ts"
|
|
47
|
+
],
|
|
48
|
+
"skills": [
|
|
49
|
+
"../../skills/commit",
|
|
50
|
+
"../../skills/frontend-design",
|
|
51
|
+
"../../skills/ghidra",
|
|
52
|
+
"../../skills/github",
|
|
53
|
+
"../../skills/google-workspace",
|
|
54
|
+
"../../skills/librarian",
|
|
55
|
+
"../../skills/mermaid",
|
|
56
|
+
"../../skills/native-web-search",
|
|
57
|
+
"../../skills/pi-share",
|
|
58
|
+
"../../skills/sentry",
|
|
59
|
+
"../../skills/summarize",
|
|
60
|
+
"../../skills/tmux",
|
|
61
|
+
"../../skills/update-changelog",
|
|
62
|
+
"../../skills/uv",
|
|
63
|
+
"../../skills/web-browser",
|
|
64
|
+
"node_modules/mitsupi/skills/commit",
|
|
65
|
+
"node_modules/mitsupi/skills/frontend-design",
|
|
66
|
+
"node_modules/mitsupi/skills/ghidra",
|
|
67
|
+
"node_modules/mitsupi/skills/github",
|
|
68
|
+
"node_modules/mitsupi/skills/google-workspace",
|
|
69
|
+
"node_modules/mitsupi/skills/librarian",
|
|
70
|
+
"node_modules/mitsupi/skills/mermaid",
|
|
71
|
+
"node_modules/mitsupi/skills/native-web-search",
|
|
72
|
+
"node_modules/mitsupi/skills/pi-share",
|
|
73
|
+
"node_modules/mitsupi/skills/sentry",
|
|
74
|
+
"node_modules/mitsupi/skills/summarize",
|
|
75
|
+
"node_modules/mitsupi/skills/tmux",
|
|
76
|
+
"node_modules/mitsupi/skills/update-changelog",
|
|
77
|
+
"node_modules/mitsupi/skills/uv",
|
|
78
|
+
"node_modules/mitsupi/skills/web-browser"
|
|
79
|
+
],
|
|
80
|
+
"themes": [
|
|
81
|
+
"../../themes",
|
|
82
|
+
"node_modules/mitsupi/themes"
|
|
83
|
+
],
|
|
84
|
+
"prompts": [
|
|
85
|
+
"../../commands",
|
|
86
|
+
"node_modules/mitsupi/commands"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
"dependencies": {
|
|
90
|
+
"mitsupi": "^1.5.0"
|
|
91
|
+
},
|
|
92
|
+
"bundledDependencies": [
|
|
93
|
+
"mitsupi"
|
|
94
|
+
]
|
|
95
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# mitsupi-loaded
|
|
2
|
+
|
|
3
|
+
Add-on Mitsupi distribution.
|
|
4
|
+
|
|
5
|
+
Includes only:
|
|
6
|
+
|
|
7
|
+
- `extensions/go-to-bed.ts`
|
|
8
|
+
- `skills/anachb`
|
|
9
|
+
- `skills/apple-mail`
|
|
10
|
+
- `skills/oebb-scotty`
|
|
11
|
+
- `skills/openscad`
|
|
12
|
+
|
|
13
|
+
Install together with `mitsupi-common` to get the full setup.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mitsupi-loaded",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Add-on Mitsupi package with travel and CAD extras",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/mitsuhiko/agent-stuff.git",
|
|
8
|
+
"directory": "distributions/mitsupi-loaded"
|
|
9
|
+
},
|
|
10
|
+
"readme": "README.md",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"pi-package",
|
|
13
|
+
"pi-extension",
|
|
14
|
+
"pi-skill"
|
|
15
|
+
],
|
|
16
|
+
"pi": {
|
|
17
|
+
"extensions": [
|
|
18
|
+
"../../extensions/go-to-bed.ts",
|
|
19
|
+
"node_modules/mitsupi/extensions/go-to-bed.ts"
|
|
20
|
+
],
|
|
21
|
+
"skills": [
|
|
22
|
+
"../../skills/anachb",
|
|
23
|
+
"../../skills/apple-mail",
|
|
24
|
+
"../../skills/oebb-scotty",
|
|
25
|
+
"../../skills/openscad",
|
|
26
|
+
"node_modules/mitsupi/skills/anachb",
|
|
27
|
+
"node_modules/mitsupi/skills/apple-mail",
|
|
28
|
+
"node_modules/mitsupi/skills/oebb-scotty",
|
|
29
|
+
"node_modules/mitsupi/skills/openscad"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"mitsupi": "^1.5.0"
|
|
34
|
+
},
|
|
35
|
+
"bundledDependencies": [
|
|
36
|
+
"mitsupi"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { complete, type Model, type Api, type UserMessage } from "@mariozechner/pi-ai";
|
|
14
|
-
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
14
|
+
import type { ExtensionAPI, ExtensionContext, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
|
15
15
|
import { BorderedLoader } from "@mariozechner/pi-coding-agent";
|
|
16
16
|
import {
|
|
17
17
|
type Component,
|
|
@@ -75,15 +75,12 @@ const HAIKU_MODEL_ID = "claude-haiku-4-5";
|
|
|
75
75
|
*/
|
|
76
76
|
async function selectExtractionModel(
|
|
77
77
|
currentModel: Model<Api>,
|
|
78
|
-
modelRegistry:
|
|
79
|
-
find: (provider: string, modelId: string) => Model<Api> | undefined;
|
|
80
|
-
getApiKey: (model: Model<Api>) => Promise<string | undefined>;
|
|
81
|
-
},
|
|
78
|
+
modelRegistry: ModelRegistry,
|
|
82
79
|
): Promise<Model<Api>> {
|
|
83
80
|
const codexModel = modelRegistry.find("openai-codex", CODEX_MODEL_ID);
|
|
84
81
|
if (codexModel) {
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
82
|
+
const auth = await modelRegistry.getApiKeyAndHeaders(codexModel);
|
|
83
|
+
if (auth.ok) {
|
|
87
84
|
return codexModel;
|
|
88
85
|
}
|
|
89
86
|
}
|
|
@@ -93,8 +90,8 @@ async function selectExtractionModel(
|
|
|
93
90
|
return currentModel;
|
|
94
91
|
}
|
|
95
92
|
|
|
96
|
-
const
|
|
97
|
-
if (!
|
|
93
|
+
const auth = await modelRegistry.getApiKeyAndHeaders(haikuModel);
|
|
94
|
+
if (!auth.ok) {
|
|
98
95
|
return currentModel;
|
|
99
96
|
}
|
|
100
97
|
|
|
@@ -457,7 +454,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
457
454
|
loader.onAbort = () => done(null);
|
|
458
455
|
|
|
459
456
|
const doExtract = async () => {
|
|
460
|
-
const
|
|
457
|
+
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(extractionModel);
|
|
458
|
+
if (!auth.ok) {
|
|
459
|
+
throw new Error(auth.error);
|
|
460
|
+
}
|
|
461
461
|
const userMessage: UserMessage = {
|
|
462
462
|
role: "user",
|
|
463
463
|
content: [{ type: "text", text: lastAssistantText! }],
|
|
@@ -467,7 +467,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
467
467
|
const response = await complete(
|
|
468
468
|
extractionModel,
|
|
469
469
|
{ systemPrompt: SYSTEM_PROMPT, messages: [userMessage] },
|
|
470
|
-
{ apiKey, signal: loader.signal },
|
|
470
|
+
{ apiKey: auth.apiKey, headers: auth.headers, signal: loader.signal },
|
|
471
471
|
);
|
|
472
472
|
|
|
473
473
|
if (response.stopReason === "aborted") {
|