takomi 2.1.30 → 2.1.31

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.
@@ -1,262 +1,262 @@
1
- import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@mariozechner/pi-coding-agent";
2
- import { mkdir, readFile, writeFile } from "node:fs/promises";
3
- import { dirname, join } from "node:path";
4
- import { homedir, platform } from "node:os";
5
- import { spawn } from "node:child_process";
6
-
7
- type NotifySoundConfig = {
8
- enabled: boolean;
9
- };
10
-
11
- type NotifyMethod = "auto" | "wav";
12
-
13
- const GLOBAL_NOTIFY_DIR = join(homedir(), ".pi", "agent", "notify-sound");
14
- const CONFIG_PATH = join(GLOBAL_NOTIFY_DIR, "notify-sound.json");
15
- const WAV_PATH = join(GLOBAL_NOTIFY_DIR, "notify-sound.wav");
16
- const PS1_PATH = join(GLOBAL_NOTIFY_DIR, "notify-sound.ps1");
17
- const VBS_PATH = join(GLOBAL_NOTIFY_DIR, "notify-sound.vbs");
18
- const STALE_AGENT_START_MS = 24 * 60 * 60 * 1000;
19
-
20
- let config: NotifySoundConfig = { enabled: true };
21
- let lastAgentStartedAt = 0;
22
-
23
- export default async function notifySoundExtension(pi: ExtensionAPI) {
24
- await loadConfig();
25
- await ensureTuneWav();
26
-
27
- pi.on("session_start", async (_event, ctx) => {
28
- updateStatus(ctx);
29
- });
30
-
31
- pi.on("agent_start", async () => {
32
- lastAgentStartedAt = Date.now();
33
- });
34
-
35
- pi.on("agent_end", async (_event, ctx) => {
36
- updateStatus(ctx);
37
-
38
- if (!config.enabled) return;
39
- if (!lastAgentStartedAt) return;
40
- if (Date.now() - lastAgentStartedAt > STALE_AGENT_START_MS) return;
41
-
42
- playCompletionTune();
43
- });
44
-
45
- const command = {
46
- description: "Toggle or test the agent completion tune notification",
47
- getArgumentCompletions: (argumentPrefix: string) => {
48
- const token = argumentPrefix.trim().toLowerCase();
49
- return [
50
- { value: "status", label: "status", description: "Show whether the completion tune is on" },
51
- { value: "test", label: "test", description: "Play the completion tune" },
52
- { value: "test wav", label: "test wav", description: "Play the generated WAV completion tune" },
53
- { value: "on", label: "on", description: "Enable the completion tune" },
54
- { value: "off", label: "off", description: "Disable the completion tune" },
55
- { value: "toggle", label: "toggle", description: "Toggle the completion tune" },
56
- ].filter((completion) => !token || completion.value.startsWith(token));
57
- },
58
- handler: async (args: string, ctx: ExtensionCommandContext) => {
59
- const action = args.trim().toLowerCase() || "toggle";
60
-
61
- if (action === "test") {
62
- playCompletionTune("wav");
63
- ctx.ui.notify("Played completion tune using WAV mode. This is the default reliable Windows path.", "info");
64
- return;
65
- }
66
-
67
- if (action === "test wav") {
68
- playCompletionTune("wav");
69
- ctx.ui.notify("Played completion tune using WAV mode.", "info");
70
- return;
71
- }
72
-
73
- if (action.startsWith("test ")) {
74
- ctx.ui.notify("Usage: /notify test", "warning");
75
- return;
76
- }
77
-
78
- if (action === "status") {
79
- updateStatus(ctx);
80
- ctx.ui.notify(`Completion tune is ${config.enabled ? "ON" : "OFF"}.`, "info");
81
- return;
82
- }
83
-
84
- if (action === "on") {
85
- await setEnabled(true, ctx);
86
- return;
87
- }
88
-
89
- if (action === "off") {
90
- await setEnabled(false, ctx);
91
- return;
92
- }
93
-
94
- if (action === "toggle") {
95
- await setEnabled(!config.enabled, ctx);
96
- return;
97
- }
98
-
99
- ctx.ui.notify("Usage: /notify [test|status|on|off|toggle]", "warning");
100
- },
101
- };
102
-
103
- pi.registerCommand("notify-sound", command);
104
- pi.registerCommand("notify", {
105
- ...command,
106
- description: "Alias for /notify-sound",
107
- });
108
- }
109
-
110
- async function loadConfig(): Promise<void> {
111
- try {
112
- const raw = await readFile(CONFIG_PATH, "utf8");
113
- const parsed = JSON.parse(raw) as Partial<NotifySoundConfig>;
114
- config = { enabled: parsed.enabled !== false };
115
- } catch {
116
- config = { enabled: true };
117
- await saveConfig();
118
- }
119
- }
120
-
121
- async function saveConfig(): Promise<void> {
122
- await mkdir(dirname(CONFIG_PATH), { recursive: true });
123
- await writeFile(CONFIG_PATH, `${JSON.stringify(config, null, 2)}\n`, "utf8");
124
- }
125
-
126
- async function setEnabled(enabled: boolean, ctx: ExtensionContext): Promise<void> {
127
- config.enabled = enabled;
128
- await saveConfig();
129
- updateStatus(ctx);
130
- ctx.ui.notify(`Completion tune ${enabled ? "enabled" : "disabled"}.`, "info");
131
- }
132
-
133
- async function ensureTuneWav(): Promise<void> {
134
- await mkdir(dirname(WAV_PATH), { recursive: true });
135
- await writeFile(WAV_PATH, createTuneWav(), "binary");
136
- const wav = WAV_PATH.replace(/'/g, "''");
137
- await writeFile(PS1_PATH, [
138
- "$ErrorActionPreference = 'SilentlyContinue'",
139
- `if (Test-Path '${wav}') {`,
140
- ` $p = New-Object System.Media.SoundPlayer '${wav}'`,
141
- " $p.Load()",
142
- " $p.PlaySync()",
143
- "}",
144
- "[System.Media.SystemSounds]::Asterisk.Play()",
145
- "Start-Sleep -Milliseconds 250",
146
- "",
147
- ].join("\n"), "utf8");
148
- const ps1 = PS1_PATH.replace(/"/g, "\"\"");
149
- await writeFile(VBS_PATH, [
150
- "Set shell = CreateObject(\"WScript.Shell\")",
151
- `shell.Run "powershell.exe -NoProfile -ExecutionPolicy Bypass -File ""${ps1}""", 0, False`,
152
- "",
153
- ].join("\r\n"), "utf8");
154
- }
155
-
156
- function createTuneWav(): Buffer {
157
- const sampleRate = 44100;
158
- const notes = [
159
- [659, 0.11],
160
- [784, 0.11],
161
- [988, 0.15],
162
- [1319, 0.21],
163
- [1175, 0.12],
164
- [1319, 0.26],
165
- ];
166
- const gapSeconds = 0.035;
167
- const samples: number[] = [];
168
-
169
- for (const [freq, seconds] of notes) {
170
- const count = Math.floor(sampleRate * seconds);
171
- for (let i = 0; i < count; i++) {
172
- const t = i / sampleRate;
173
- const fadeIn = Math.min(1, i / 120);
174
- const fadeOut = Math.min(1, (count - i) / 300);
175
- const env = Math.min(fadeIn, fadeOut) * 0.28;
176
- samples.push(Math.sin(2 * Math.PI * freq * t) * env);
177
- }
178
- for (let i = 0; i < Math.floor(sampleRate * gapSeconds); i++) samples.push(0);
179
- }
180
-
181
- const dataSize = samples.length * 2;
182
- const buffer = Buffer.alloc(44 + dataSize);
183
- buffer.write("RIFF", 0);
184
- buffer.writeUInt32LE(36 + dataSize, 4);
185
- buffer.write("WAVE", 8);
186
- buffer.write("fmt ", 12);
187
- buffer.writeUInt32LE(16, 16);
188
- buffer.writeUInt16LE(1, 20);
189
- buffer.writeUInt16LE(1, 22);
190
- buffer.writeUInt32LE(sampleRate, 24);
191
- buffer.writeUInt32LE(sampleRate * 2, 28);
192
- buffer.writeUInt16LE(2, 32);
193
- buffer.writeUInt16LE(16, 34);
194
- buffer.write("data", 36);
195
- buffer.writeUInt32LE(dataSize, 40);
196
-
197
- let offset = 44;
198
- for (const sample of samples) {
199
- const value = Math.max(-1, Math.min(1, sample));
200
- buffer.writeInt16LE(Math.round(value * 32767), offset);
201
- offset += 2;
202
- }
203
- return buffer;
204
- }
205
-
206
- function updateStatus(ctx: ExtensionContext): void {
207
- if (!ctx.hasUI) return;
208
- ctx.ui.setStatus("notify-sound", ctx.ui.theme.fg("dim", `tune:${config.enabled ? "on" : "off"}`));
209
- }
210
-
211
- function playCompletionTune(method: NotifyMethod = "auto"): void {
212
- const os = platform();
213
-
214
- if (os === "win32") {
215
- playWindowsTune(method);
216
- return;
217
- }
218
-
219
- if (os === "darwin") {
220
- runDetached("osascript", ["-e", "beep 1", "-e", "delay 0.12", "-e", "beep 1", "-e", "delay 0.12", "-e", "beep 2"]);
221
- return;
222
- }
223
-
224
- playLinuxTune();
225
- }
226
-
227
- function playWindowsTune(method: NotifyMethod): void {
228
- // Windows uses the generated WAV path because Console.Beep, system sounds,
229
- // and terminal bells are silent on many modern Windows machines.
230
- playWindowsWav();
231
- }
232
-
233
- function playWindowsWav(): void {
234
- // WScript launches the PowerShell player hidden without stealing focus. This
235
- // is more reliable than spawning hidden PowerShell directly from Pi's TUI.
236
- runDetached("wscript.exe", [VBS_PATH]);
237
- }
238
-
239
- function playLinuxTune(): void {
240
- // Prefer shell printf bells for broad compatibility; terminal may silence them.
241
- // If paplay/aplay exists, play the freedesktop complete sound as an additional fallback.
242
- runDetached("sh", [
243
- "-c",
244
- "(command -v paplay >/dev/null 2>&1 && paplay /usr/share/sounds/freedesktop/stereo/complete.oga >/dev/null 2>&1) || " +
245
- "(command -v aplay >/dev/null 2>&1 && aplay /usr/share/sounds/alsa/Front_Center.wav >/dev/null 2>&1) || " +
246
- "printf '\\a'; sleep 0.12; printf '\\a'; sleep 0.12; printf '\\a'",
247
- ]);
248
- }
249
-
250
- function runDetached(command: string, args: string[]): void {
251
- try {
252
- const child = spawn(command, args, {
253
- detached: true,
254
- stdio: "ignore",
255
- windowsHide: true,
256
- shell: false,
257
- });
258
- child.unref();
259
- } catch {
260
- // Notification failures should never interrupt pi.
261
- }
262
- }
1
+ import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { homedir, platform } from "node:os";
5
+ import { spawn } from "node:child_process";
6
+
7
+ type NotifySoundConfig = {
8
+ enabled: boolean;
9
+ };
10
+
11
+ type NotifyMethod = "auto" | "wav";
12
+
13
+ const GLOBAL_NOTIFY_DIR = join(homedir(), ".pi", "agent", "notify-sound");
14
+ const CONFIG_PATH = join(GLOBAL_NOTIFY_DIR, "notify-sound.json");
15
+ const WAV_PATH = join(GLOBAL_NOTIFY_DIR, "notify-sound.wav");
16
+ const PS1_PATH = join(GLOBAL_NOTIFY_DIR, "notify-sound.ps1");
17
+ const VBS_PATH = join(GLOBAL_NOTIFY_DIR, "notify-sound.vbs");
18
+ const STALE_AGENT_START_MS = 24 * 60 * 60 * 1000;
19
+
20
+ let config: NotifySoundConfig = { enabled: true };
21
+ let lastAgentStartedAt = 0;
22
+
23
+ export default async function notifySoundExtension(pi: ExtensionAPI) {
24
+ await loadConfig();
25
+ await ensureTuneWav();
26
+
27
+ pi.on("session_start", async (_event, ctx) => {
28
+ updateStatus(ctx);
29
+ });
30
+
31
+ pi.on("agent_start", async () => {
32
+ lastAgentStartedAt = Date.now();
33
+ });
34
+
35
+ pi.on("agent_end", async (_event, ctx) => {
36
+ updateStatus(ctx);
37
+
38
+ if (!config.enabled) return;
39
+ if (!lastAgentStartedAt) return;
40
+ if (Date.now() - lastAgentStartedAt > STALE_AGENT_START_MS) return;
41
+
42
+ playCompletionTune();
43
+ });
44
+
45
+ const command = {
46
+ description: "Toggle or test the agent completion tune notification",
47
+ getArgumentCompletions: (argumentPrefix: string) => {
48
+ const token = argumentPrefix.trim().toLowerCase();
49
+ return [
50
+ { value: "status", label: "status", description: "Show whether the completion tune is on" },
51
+ { value: "test", label: "test", description: "Play the completion tune" },
52
+ { value: "test wav", label: "test wav", description: "Play the generated WAV completion tune" },
53
+ { value: "on", label: "on", description: "Enable the completion tune" },
54
+ { value: "off", label: "off", description: "Disable the completion tune" },
55
+ { value: "toggle", label: "toggle", description: "Toggle the completion tune" },
56
+ ].filter((completion) => !token || completion.value.startsWith(token));
57
+ },
58
+ handler: async (args: string, ctx: ExtensionCommandContext) => {
59
+ const action = args.trim().toLowerCase() || "toggle";
60
+
61
+ if (action === "test") {
62
+ playCompletionTune("wav");
63
+ ctx.ui.notify("Played completion tune using WAV mode. This is the default reliable Windows path.", "info");
64
+ return;
65
+ }
66
+
67
+ if (action === "test wav") {
68
+ playCompletionTune("wav");
69
+ ctx.ui.notify("Played completion tune using WAV mode.", "info");
70
+ return;
71
+ }
72
+
73
+ if (action.startsWith("test ")) {
74
+ ctx.ui.notify("Usage: /notify test", "warning");
75
+ return;
76
+ }
77
+
78
+ if (action === "status") {
79
+ updateStatus(ctx);
80
+ ctx.ui.notify(`Completion tune is ${config.enabled ? "ON" : "OFF"}.`, "info");
81
+ return;
82
+ }
83
+
84
+ if (action === "on") {
85
+ await setEnabled(true, ctx);
86
+ return;
87
+ }
88
+
89
+ if (action === "off") {
90
+ await setEnabled(false, ctx);
91
+ return;
92
+ }
93
+
94
+ if (action === "toggle") {
95
+ await setEnabled(!config.enabled, ctx);
96
+ return;
97
+ }
98
+
99
+ ctx.ui.notify("Usage: /notify [test|status|on|off|toggle]", "warning");
100
+ },
101
+ };
102
+
103
+ pi.registerCommand("notify-sound", command);
104
+ pi.registerCommand("notify", {
105
+ ...command,
106
+ description: "Alias for /notify-sound",
107
+ });
108
+ }
109
+
110
+ async function loadConfig(): Promise<void> {
111
+ try {
112
+ const raw = await readFile(CONFIG_PATH, "utf8");
113
+ const parsed = JSON.parse(raw) as Partial<NotifySoundConfig>;
114
+ config = { enabled: parsed.enabled !== false };
115
+ } catch {
116
+ config = { enabled: true };
117
+ await saveConfig();
118
+ }
119
+ }
120
+
121
+ async function saveConfig(): Promise<void> {
122
+ await mkdir(dirname(CONFIG_PATH), { recursive: true });
123
+ await writeFile(CONFIG_PATH, `${JSON.stringify(config, null, 2)}\n`, "utf8");
124
+ }
125
+
126
+ async function setEnabled(enabled: boolean, ctx: ExtensionContext): Promise<void> {
127
+ config.enabled = enabled;
128
+ await saveConfig();
129
+ updateStatus(ctx);
130
+ ctx.ui.notify(`Completion tune ${enabled ? "enabled" : "disabled"}.`, "info");
131
+ }
132
+
133
+ async function ensureTuneWav(): Promise<void> {
134
+ await mkdir(dirname(WAV_PATH), { recursive: true });
135
+ await writeFile(WAV_PATH, createTuneWav(), "binary");
136
+ const wav = WAV_PATH.replace(/'/g, "''");
137
+ await writeFile(PS1_PATH, [
138
+ "$ErrorActionPreference = 'SilentlyContinue'",
139
+ `if (Test-Path '${wav}') {`,
140
+ ` $p = New-Object System.Media.SoundPlayer '${wav}'`,
141
+ " $p.Load()",
142
+ " $p.PlaySync()",
143
+ "}",
144
+ "[System.Media.SystemSounds]::Asterisk.Play()",
145
+ "Start-Sleep -Milliseconds 250",
146
+ "",
147
+ ].join("\n"), "utf8");
148
+ const ps1 = PS1_PATH.replace(/"/g, "\"\"");
149
+ await writeFile(VBS_PATH, [
150
+ "Set shell = CreateObject(\"WScript.Shell\")",
151
+ `shell.Run "powershell.exe -NoProfile -ExecutionPolicy Bypass -File ""${ps1}""", 0, False`,
152
+ "",
153
+ ].join("\r\n"), "utf8");
154
+ }
155
+
156
+ function createTuneWav(): Buffer {
157
+ const sampleRate = 44100;
158
+ const notes = [
159
+ [659, 0.11],
160
+ [784, 0.11],
161
+ [988, 0.15],
162
+ [1319, 0.21],
163
+ [1175, 0.12],
164
+ [1319, 0.26],
165
+ ];
166
+ const gapSeconds = 0.035;
167
+ const samples: number[] = [];
168
+
169
+ for (const [freq, seconds] of notes) {
170
+ const count = Math.floor(sampleRate * seconds);
171
+ for (let i = 0; i < count; i++) {
172
+ const t = i / sampleRate;
173
+ const fadeIn = Math.min(1, i / 120);
174
+ const fadeOut = Math.min(1, (count - i) / 300);
175
+ const env = Math.min(fadeIn, fadeOut) * 0.28;
176
+ samples.push(Math.sin(2 * Math.PI * freq * t) * env);
177
+ }
178
+ for (let i = 0; i < Math.floor(sampleRate * gapSeconds); i++) samples.push(0);
179
+ }
180
+
181
+ const dataSize = samples.length * 2;
182
+ const buffer = Buffer.alloc(44 + dataSize);
183
+ buffer.write("RIFF", 0);
184
+ buffer.writeUInt32LE(36 + dataSize, 4);
185
+ buffer.write("WAVE", 8);
186
+ buffer.write("fmt ", 12);
187
+ buffer.writeUInt32LE(16, 16);
188
+ buffer.writeUInt16LE(1, 20);
189
+ buffer.writeUInt16LE(1, 22);
190
+ buffer.writeUInt32LE(sampleRate, 24);
191
+ buffer.writeUInt32LE(sampleRate * 2, 28);
192
+ buffer.writeUInt16LE(2, 32);
193
+ buffer.writeUInt16LE(16, 34);
194
+ buffer.write("data", 36);
195
+ buffer.writeUInt32LE(dataSize, 40);
196
+
197
+ let offset = 44;
198
+ for (const sample of samples) {
199
+ const value = Math.max(-1, Math.min(1, sample));
200
+ buffer.writeInt16LE(Math.round(value * 32767), offset);
201
+ offset += 2;
202
+ }
203
+ return buffer;
204
+ }
205
+
206
+ function updateStatus(ctx: ExtensionContext): void {
207
+ if (!ctx.hasUI) return;
208
+ ctx.ui.setStatus("notify-sound", ctx.ui.theme.fg("dim", `tune:${config.enabled ? "on" : "off"}`));
209
+ }
210
+
211
+ function playCompletionTune(method: NotifyMethod = "auto"): void {
212
+ const os = platform();
213
+
214
+ if (os === "win32") {
215
+ playWindowsTune(method);
216
+ return;
217
+ }
218
+
219
+ if (os === "darwin") {
220
+ runDetached("osascript", ["-e", "beep 1", "-e", "delay 0.12", "-e", "beep 1", "-e", "delay 0.12", "-e", "beep 2"]);
221
+ return;
222
+ }
223
+
224
+ playLinuxTune();
225
+ }
226
+
227
+ function playWindowsTune(method: NotifyMethod): void {
228
+ // Windows uses the generated WAV path because Console.Beep, system sounds,
229
+ // and terminal bells are silent on many modern Windows machines.
230
+ playWindowsWav();
231
+ }
232
+
233
+ function playWindowsWav(): void {
234
+ // WScript launches the PowerShell player hidden without stealing focus. This
235
+ // is more reliable than spawning hidden PowerShell directly from Pi's TUI.
236
+ runDetached("wscript.exe", [VBS_PATH]);
237
+ }
238
+
239
+ function playLinuxTune(): void {
240
+ // Prefer shell printf bells for broad compatibility; terminal may silence them.
241
+ // If paplay/aplay exists, play the freedesktop complete sound as an additional fallback.
242
+ runDetached("sh", [
243
+ "-c",
244
+ "(command -v paplay >/dev/null 2>&1 && paplay /usr/share/sounds/freedesktop/stereo/complete.oga >/dev/null 2>&1) || " +
245
+ "(command -v aplay >/dev/null 2>&1 && aplay /usr/share/sounds/alsa/Front_Center.wav >/dev/null 2>&1) || " +
246
+ "printf '\\a'; sleep 0.12; printf '\\a'; sleep 0.12; printf '\\a'",
247
+ ]);
248
+ }
249
+
250
+ function runDetached(command: string, args: string[]): void {
251
+ try {
252
+ const child = spawn(command, args, {
253
+ detached: true,
254
+ stdio: "ignore",
255
+ windowsHide: true,
256
+ shell: false,
257
+ });
258
+ child.unref();
259
+ } catch {
260
+ // Notification failures should never interrupt pi.
261
+ }
262
+ }
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
3
  import type { ContextManagerState } from "./state";
4
4
  import { renderReport } from "./diagnostics";
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { loadConfig, DEFAULT_CONFIG } from "./config";
3
3
  import { createState } from "./state";
4
4
  import { collectSkillsFromOptions, collectSkillsFromXml, mergeSkills } from "./skill-registry";
@@ -1,7 +1,7 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
4
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
5
5
  import type { ContextManagerState } from "./state";
6
6
  import { recordBlocked } from "./state";
7
7
  import { resolveTakomiRoutingPolicy } from "../takomi-runtime/routing-policy";
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
3
  import type { ContextManagerState } from "./state";
4
4
  import { syncReportLedger } from "./state";
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import type { ContextManagerConfig } from "./types";
3
3
  import type { ContextManagerState } from "./state";
4
4
  import { recordBlocked, syncReportLedger } from "./state";
@@ -1,6 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
3
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
4
4
  import { Type } from "typebox";
5
5
  import type { ContextManagerState } from "./state";
6
6
  import { findSkill, normalizeName, sortedSkills } from "./skill-registry";
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import type {
3
3
  TakomiLaunchMode,
4
4
  TakomiRole,