@groeponline/pi-wishcraft 0.17.3

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.
Files changed (106) hide show
  1. package/AGENTS.md +68 -0
  2. package/CHANGELOG.md +724 -0
  3. package/CONTRIBUTING.md +37 -0
  4. package/README.md +648 -0
  5. package/RELEASE.md +117 -0
  6. package/ROADMAP.md +52 -0
  7. package/bash-mode/completion-providers.ts +269 -0
  8. package/bash-mode/completion.ts +416 -0
  9. package/bash-mode/editor-ghost.ts +40 -0
  10. package/bash-mode/editor-input.ts +80 -0
  11. package/bash-mode/editor.ts +437 -0
  12. package/bash-mode/history.ts +263 -0
  13. package/bash-mode/shell-session.ts +286 -0
  14. package/bash-mode/transcript.ts +108 -0
  15. package/bash-mode/types.ts +80 -0
  16. package/index.ts +6 -0
  17. package/package.json +55 -0
  18. package/queue/store.ts +443 -0
  19. package/queue/types.ts +54 -0
  20. package/src/config/custom-items.ts +182 -0
  21. package/src/config/extension-statuses.ts +51 -0
  22. package/src/config/layout.ts +60 -0
  23. package/src/config/parse.ts +127 -0
  24. package/src/config/powerline-config.ts +18 -0
  25. package/src/config/presets.ts +245 -0
  26. package/src/config/primitives.ts +117 -0
  27. package/src/config/segment-ids.ts +114 -0
  28. package/src/config/segment-options.ts +128 -0
  29. package/src/config/settings-patch.ts +26 -0
  30. package/src/config/types.ts +277 -0
  31. package/src/core/frontmatter.ts +40 -0
  32. package/src/editor/autocomplete-chain.ts +41 -0
  33. package/src/extension/activate.ts +28 -0
  34. package/src/extension/bash-mode-actions.ts +104 -0
  35. package/src/extension/commands.ts +268 -0
  36. package/src/extension/constants.ts +46 -0
  37. package/src/extension/custom-editor.ts +406 -0
  38. package/src/extension/git-invalidation.ts +40 -0
  39. package/src/extension/layout.ts +160 -0
  40. package/src/extension/menu-views.ts +393 -0
  41. package/src/extension/powerline-widgets.ts +95 -0
  42. package/src/extension/prompt-history.ts +219 -0
  43. package/src/extension/queue-commands.ts +245 -0
  44. package/src/extension/queue-context.ts +12 -0
  45. package/src/extension/queue-integration.ts +434 -0
  46. package/src/extension/segment-context.ts +212 -0
  47. package/src/extension/session-lifecycle.ts +373 -0
  48. package/src/extension/settings-io.ts +202 -0
  49. package/src/extension/shortcuts-config.ts +357 -0
  50. package/src/extension/shortcuts-router.ts +383 -0
  51. package/src/extension/skills/inline-invocation.ts +174 -0
  52. package/src/extension/skills/ook.md +6 -0
  53. package/src/extension/skills/test.md +6 -0
  54. package/src/extension/stale-context.ts +10 -0
  55. package/src/extension/stash-history.ts +103 -0
  56. package/src/extension/state.ts +159 -0
  57. package/src/extension/status-line-renderers.ts +222 -0
  58. package/src/extension/types.ts +97 -0
  59. package/src/extension/vibe-command.ts +160 -0
  60. package/src/extension/welcome-control.ts +27 -0
  61. package/src/extension/welcome-integration.ts +153 -0
  62. package/src/git/status.ts +332 -0
  63. package/src/paths/agent-dirs.ts +67 -0
  64. package/src/render/timer.ts +46 -0
  65. package/src/segments/core.ts +256 -0
  66. package/src/segments/custom.ts +114 -0
  67. package/src/segments/index.ts +3 -0
  68. package/src/segments/registry.ts +87 -0
  69. package/src/segments/shared.ts +36 -0
  70. package/src/segments/system.ts +235 -0
  71. package/src/segments/usage.ts +178 -0
  72. package/src/shell/cd-command.ts +190 -0
  73. package/src/shortcuts/matching.ts +61 -0
  74. package/src/theme/colors.ts +60 -0
  75. package/src/theme/icons.ts +175 -0
  76. package/src/theme/separators.ts +41 -0
  77. package/src/theme/theme.ts +211 -0
  78. package/src/tools/graph.ts +75 -0
  79. package/src/tools/patch.ts +179 -0
  80. package/src/tools/ripgrep.ts +104 -0
  81. package/src/usage/context.ts +97 -0
  82. package/src/usage/ledger.ts +293 -0
  83. package/src/usage/rates.ts +155 -0
  84. package/src/welcome/auto-dismiss.ts +43 -0
  85. package/src/welcome/banner.ts +68 -0
  86. package/src/welcome/discover.ts +234 -0
  87. package/src/welcome/format.ts +18 -0
  88. package/src/welcome/index.ts +5 -0
  89. package/src/welcome/layout.ts +36 -0
  90. package/src/welcome/overlay.ts +80 -0
  91. package/src/welcome/renderer.ts +157 -0
  92. package/src/welcome/sessions.ts +107 -0
  93. package/src/welcome/types.ts +41 -0
  94. package/src/welcome/widgets/graph-widget.ts +25 -0
  95. package/src/welcome/widgets/index.ts +20 -0
  96. package/src/welcome/widgets/queue-widget.ts +26 -0
  97. package/src/welcome/widgets/sessions-widget.ts +23 -0
  98. package/src/welcome/widgets/shortcuts-widget.ts +17 -0
  99. package/src/welcome/widgets/system-widget.ts +29 -0
  100. package/src/working-vibes/generate.ts +144 -0
  101. package/src/working-vibes/index.ts +24 -0
  102. package/src/working-vibes/manager.ts +198 -0
  103. package/src/working-vibes/provider.ts +163 -0
  104. package/src/working-vibes/storage.ts +357 -0
  105. package/theme.example.json +24 -0
  106. package/tsconfig.json +13 -0
@@ -0,0 +1,286 @@
1
+ import { mkdtempSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { basename, join } from "node:path";
4
+ import { spawn, type ChildProcessWithoutNullStreams } from "node:child_process";
5
+ import type { BashTranscriptStore } from "./transcript.ts";
6
+ import type { ShellSessionState } from "./types.ts";
7
+
8
+ const READY_SENTINEL = "__PI_READY__";
9
+ const COMMAND_START_SENTINEL = "__PI_CMD_START__";
10
+ const COMMAND_DONE_SENTINEL = "__PI_CMD_DONE__";
11
+
12
+ function stripAnsi(value: string): string {
13
+ return value
14
+ .replace(/\x1B\[[0-9;?]*[ -/]*[@-~]/g, "")
15
+ .replace(/\x1B\][^\u0007]*(?:\u0007|\x1b\\)/g, "")
16
+ .replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, "");
17
+ }
18
+
19
+ function quoteShellArg(value: string): string {
20
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
21
+ }
22
+
23
+ function getCloseExitCode(code: number | null, signal: NodeJS.Signals | null): number {
24
+ if (typeof code === "number") {
25
+ return code;
26
+ }
27
+
28
+ if (signal === "SIGINT") {
29
+ return 130;
30
+ }
31
+
32
+ if (signal === "SIGTERM") {
33
+ return 143;
34
+ }
35
+
36
+ if (signal === "SIGKILL") {
37
+ return 137;
38
+ }
39
+
40
+ return 1;
41
+ }
42
+
43
+ function getShellInitScript(shellName: string): string {
44
+ if (shellName.includes("fish")) {
45
+ return `
46
+ function __pi_eval
47
+ set -l __pi_id $argv[1]
48
+ set -l __pi_file $argv[2]
49
+ echo "${COMMAND_START_SENTINEL}:$__pi_id:$PWD"
50
+ source $__pi_file
51
+ set -l __pi_status $status
52
+ rm -f $__pi_file
53
+ echo "${COMMAND_DONE_SENTINEL}:$__pi_id:$__pi_status:$PWD"
54
+ end
55
+ echo "${READY_SENTINEL}:$PWD"
56
+ `;
57
+ }
58
+
59
+ if (shellName.includes("bash")) {
60
+ return `
61
+ __pi_eval() {
62
+ local __pi_id="$1"
63
+ local __pi_file="$2"
64
+ printf '%s:%s:%s\n' '${COMMAND_START_SENTINEL}' "$__pi_id" "$PWD"
65
+ source "$__pi_file"
66
+ local __pi_status=$?
67
+ rm -f "$__pi_file"
68
+ printf '%s:%s:%s:%s\n' '${COMMAND_DONE_SENTINEL}' "$__pi_id" "$__pi_status" "$PWD"
69
+ }
70
+ printf '%s:%s\n' '${READY_SENTINEL}' "$PWD"
71
+ `;
72
+ }
73
+
74
+ return `
75
+ function __pi_eval() {
76
+ local __pi_id="$1"
77
+ local __pi_file="$2"
78
+ print -r -- "${COMMAND_START_SENTINEL}:$__pi_id:$PWD"
79
+ builtin source "$__pi_file"
80
+ local __pi_status=$?
81
+ rm -f "$__pi_file"
82
+ print -r -- "${COMMAND_DONE_SENTINEL}:$__pi_id:$__pi_status:$PWD"
83
+ }
84
+ print -r -- "${READY_SENTINEL}:$PWD"
85
+ `;
86
+ }
87
+
88
+ export class ManagedShellSession {
89
+ private readonly shellPath: string;
90
+ private readonly transcript: BashTranscriptStore;
91
+ private readonly onStateChange: () => void;
92
+ private readonly onCommandSuccess: (command: string, cwd: string) => void;
93
+ private process: ChildProcessWithoutNullStreams | null = null;
94
+ private readonly tempDir = mkdtempSync(join(tmpdir(), "powerline-bash-mode-"));
95
+ private buffer = "";
96
+ private commandCounter = 0;
97
+ private currentCommandId: string | null = null;
98
+ private readyPromise: Promise<void> | null = null;
99
+ private readyResolve: (() => void) | null = null;
100
+ private readyReject: ((error: Error) => void) | null = null;
101
+ private disposed = false;
102
+ readonly state: ShellSessionState;
103
+
104
+ constructor(
105
+ shellPath: string,
106
+ cwd: string,
107
+ transcript: BashTranscriptStore,
108
+ onStateChange: () => void,
109
+ onCommandSuccess: (command: string, cwd: string) => void,
110
+ ) {
111
+ this.shellPath = shellPath;
112
+ this.transcript = transcript;
113
+ this.onStateChange = onStateChange;
114
+ this.onCommandSuccess = onCommandSuccess;
115
+ const shellName = basename(shellPath).toLowerCase();
116
+ this.state = {
117
+ ready: false,
118
+ running: false,
119
+ shellPath,
120
+ shellName,
121
+ cwd,
122
+ lastExitCode: null,
123
+ };
124
+ }
125
+
126
+ async ensureReady(): Promise<void> {
127
+ if (this.state.ready) return;
128
+ if (this.readyPromise) return this.readyPromise;
129
+
130
+ this.readyPromise = new Promise<void>((resolve, reject) => {
131
+ this.readyResolve = resolve;
132
+ this.readyReject = reject;
133
+ });
134
+
135
+ this.process = spawn(this.shellPath, [], {
136
+ cwd: this.state.cwd,
137
+ env: {
138
+ ...process.env,
139
+ DISABLE_AUTO_UPDATE: "true",
140
+ DISABLE_UPDATE_PROMPT: "true",
141
+ },
142
+ stdio: ["pipe", "pipe", "pipe"],
143
+ detached: true,
144
+ });
145
+
146
+ this.process.stdout.setEncoding("utf8");
147
+ this.process.stderr.setEncoding("utf8");
148
+ this.process.stdout.on("data", (chunk) => this.handleChunk(String(chunk)));
149
+ this.process.stderr.on("data", (chunk) => this.handleChunk(String(chunk)));
150
+ this.process.on("error", (error) => {
151
+ if (!this.state.ready) {
152
+ this.readyReject?.(error instanceof Error ? error : new Error(String(error)));
153
+ }
154
+ });
155
+ this.process.on("close", (code, signal) => {
156
+ const exitCode = getCloseExitCode(code, signal);
157
+ if (!this.disposed && !this.state.ready) {
158
+ this.readyReject?.(new Error(`Shell failed to start (exit ${exitCode})`));
159
+ }
160
+
161
+ if (this.currentCommandId) {
162
+ this.transcript.finishCommand(this.currentCommandId, exitCode);
163
+ this.state.lastExitCode = exitCode;
164
+ this.currentCommandId = null;
165
+ }
166
+
167
+ this.process = null;
168
+ this.buffer = "";
169
+ this.readyPromise = null;
170
+ this.readyResolve = null;
171
+ this.readyReject = null;
172
+ this.state.ready = false;
173
+ this.state.running = false;
174
+ this.onStateChange();
175
+ });
176
+
177
+ this.sendRaw(getShellInitScript(this.state.shellName) + "\n");
178
+ return this.readyPromise;
179
+ }
180
+
181
+ async runCommand(command: string): Promise<void> {
182
+ await this.ensureReady();
183
+ if (!this.process) {
184
+ throw new Error("Shell process not available");
185
+ }
186
+ if (this.state.running) {
187
+ throw new Error("Shell command already running");
188
+ }
189
+
190
+ const id = `cmd-${++this.commandCounter}`;
191
+ const extension = this.state.shellName.includes("fish") ? "fish" : "sh";
192
+ const filePath = join(this.tempDir, `${id}.${extension}`);
193
+ writeFileSync(filePath, command.endsWith("\n") ? command : `${command}\n`, "utf8");
194
+
195
+ this.currentCommandId = id;
196
+ this.state.running = true;
197
+ this.transcript.startCommand(id, command, this.state.cwd);
198
+ this.onStateChange();
199
+ this.sendRaw(`__pi_eval ${quoteShellArg(id)} ${quoteShellArg(filePath)}\n`);
200
+ }
201
+
202
+ interrupt(): void {
203
+ if (!this.process || !this.state.running) return;
204
+ try {
205
+ process.kill(-this.process.pid!, "SIGINT");
206
+ } catch {
207
+ // The shell may not own a process group anymore.
208
+ this.process.kill("SIGINT");
209
+ }
210
+ }
211
+
212
+ dispose(): void {
213
+ this.disposed = true;
214
+ this.readyPromise = null;
215
+ this.readyResolve = null;
216
+ this.readyReject = null;
217
+ if (!this.process) return;
218
+ try {
219
+ process.kill(-this.process.pid!, "SIGKILL");
220
+ } catch {
221
+ // The shell may not own a process group anymore.
222
+ this.process.kill("SIGKILL");
223
+ }
224
+ this.process = null;
225
+ }
226
+
227
+ private sendRaw(text: string): void {
228
+ if (!this.process) return;
229
+ this.process.stdin.write(text);
230
+ }
231
+
232
+ private handleChunk(chunk: string): void {
233
+ const sanitized = stripAnsi(chunk).replace(/\r/g, "");
234
+ if (!sanitized) return;
235
+
236
+ this.buffer += sanitized;
237
+ const parts = this.buffer.split("\n");
238
+ this.buffer = parts.pop() ?? "";
239
+
240
+ for (const rawLine of parts) {
241
+ const line = rawLine.trimEnd();
242
+ if (!this.state.ready) {
243
+ if (line.startsWith(`${READY_SENTINEL}:`)) {
244
+ this.state.ready = true;
245
+ this.state.cwd = line.slice(READY_SENTINEL.length + 1) || this.state.cwd;
246
+ this.readyResolve?.();
247
+ this.readyResolve = null;
248
+ this.readyReject = null;
249
+ this.onStateChange();
250
+ }
251
+ continue;
252
+ }
253
+
254
+ if (line.startsWith(`${COMMAND_START_SENTINEL}:`)) {
255
+ const [, id, cwd] = line.split(":");
256
+ if (cwd) this.state.cwd = cwd;
257
+ this.currentCommandId = id ?? this.currentCommandId;
258
+ this.onStateChange();
259
+ continue;
260
+ }
261
+
262
+ if (line.startsWith(`${COMMAND_DONE_SENTINEL}:`)) {
263
+ const [, id, exitCodeText, cwd] = line.split(":");
264
+ const exitCode = Number.parseInt(exitCodeText ?? "1", 10);
265
+ this.state.running = false;
266
+ this.state.lastExitCode = Number.isFinite(exitCode) ? exitCode : 1;
267
+ if (cwd) this.state.cwd = cwd;
268
+ if (id) {
269
+ this.transcript.finishCommand(id, this.state.lastExitCode);
270
+ const snapshot = this.transcript.getSnapshot();
271
+ const command = snapshot.commands.find((entry) => entry.id === id);
272
+ if (command && this.state.lastExitCode === 0) {
273
+ this.onCommandSuccess(command.command, this.state.cwd);
274
+ }
275
+ }
276
+ this.currentCommandId = null;
277
+ this.onStateChange();
278
+ continue;
279
+ }
280
+
281
+ if (!this.currentCommandId) continue;
282
+ this.transcript.appendOutput(this.currentCommandId, line);
283
+ this.onStateChange();
284
+ }
285
+ }
286
+ }
@@ -0,0 +1,108 @@
1
+ import type { BashCommandRecord, BashModeSettings, BashTranscriptSnapshot } from "./types.ts";
2
+
3
+ function byteLength(value: string): number {
4
+ return Buffer.byteLength(value, "utf8");
5
+ }
6
+
7
+ function compactLines(lines: string[]): string[] {
8
+ const normalized: string[] = [];
9
+ for (const line of lines) {
10
+ const sanitized = line.replace(/\r/g, "");
11
+ if (sanitized.length === 0) {
12
+ normalized.push("");
13
+ continue;
14
+ }
15
+ normalized.push(...sanitized.split("\n"));
16
+ }
17
+ return normalized;
18
+ }
19
+
20
+ export class BashTranscriptStore {
21
+ private readonly settings: Pick<BashModeSettings, "transcriptMaxLines" | "transcriptMaxBytes">;
22
+ private commands: BashCommandRecord[] = [];
23
+ private commandIndex = new Map<string, BashCommandRecord>();
24
+ private totalLines = 0;
25
+ private totalBytes = 0;
26
+ private truncatedCommands = 0;
27
+
28
+ constructor(settings: Pick<BashModeSettings, "transcriptMaxLines" | "transcriptMaxBytes">) {
29
+ this.settings = settings;
30
+ }
31
+
32
+ startCommand(id: string, command: string, cwdAtStart: string): BashCommandRecord {
33
+ const entry: BashCommandRecord = {
34
+ id,
35
+ command,
36
+ cwdAtStart,
37
+ startedAt: Date.now(),
38
+ output: [],
39
+ outputBytes: 0,
40
+ exitCode: null,
41
+ finishedAt: null,
42
+ truncated: false,
43
+ };
44
+
45
+ this.commands.push(entry);
46
+ this.commandIndex.set(id, entry);
47
+ this.enforceLimits();
48
+ return entry;
49
+ }
50
+
51
+ appendOutput(id: string, chunk: string): void {
52
+ const entry = this.commandIndex.get(id);
53
+ if (!entry || !chunk) return;
54
+
55
+ const lines = compactLines([chunk]);
56
+ if (lines.length === 0) return;
57
+
58
+ entry.output.push(...lines);
59
+ const addedBytes = lines.reduce((sum, line) => sum + byteLength(line) + 1, 0);
60
+ entry.outputBytes += addedBytes;
61
+ this.totalLines += lines.length;
62
+ this.totalBytes += addedBytes;
63
+ this.enforceLimits();
64
+ }
65
+
66
+ finishCommand(id: string, exitCode: number): void {
67
+ const entry = this.commandIndex.get(id);
68
+ if (!entry) return;
69
+
70
+ entry.exitCode = exitCode;
71
+ entry.finishedAt = Date.now();
72
+ }
73
+
74
+ clear(): void {
75
+ this.commands = [];
76
+ this.commandIndex.clear();
77
+ this.totalLines = 0;
78
+ this.totalBytes = 0;
79
+ this.truncatedCommands = 0;
80
+ }
81
+
82
+ getSnapshot(): BashTranscriptSnapshot {
83
+ return {
84
+ commands: this.commands.map((command) => ({
85
+ ...command,
86
+ output: [...command.output],
87
+ })),
88
+ totalLines: this.totalLines,
89
+ totalBytes: this.totalBytes,
90
+ truncatedCommands: this.truncatedCommands,
91
+ };
92
+ }
93
+
94
+ private enforceLimits(): void {
95
+ while (
96
+ this.commands.length > 1
97
+ && (this.totalLines > this.settings.transcriptMaxLines || this.totalBytes > this.settings.transcriptMaxBytes)
98
+ ) {
99
+ const removed = this.commands.shift();
100
+ if (!removed) break;
101
+ this.commandIndex.delete(removed.id);
102
+ this.totalLines = Math.max(0, this.totalLines - removed.output.length);
103
+ this.totalBytes = Math.max(0, this.totalBytes - removed.outputBytes);
104
+ this.truncatedCommands += 1;
105
+ removed.truncated = true;
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,80 @@
1
+ import type { KeybindingsManager } from "@earendil-works/pi-coding-agent";
2
+
3
+ import type { EditorBoundaryShortcuts } from "./editor-input.ts";
4
+
5
+ export interface BashModeSettings {
6
+ toggleShortcut: string | null;
7
+ transcriptMaxLines: number;
8
+ transcriptMaxBytes: number;
9
+ }
10
+
11
+ export interface BashCommandRecord {
12
+ id: string;
13
+ command: string;
14
+ startedAt: number;
15
+ cwdAtStart: string;
16
+ output: string[];
17
+ outputBytes: number;
18
+ exitCode: number | null;
19
+ finishedAt: number | null;
20
+ truncated: boolean;
21
+ }
22
+
23
+ export interface BashTranscriptSnapshot {
24
+ commands: BashCommandRecord[];
25
+ totalLines: number;
26
+ totalBytes: number;
27
+ truncatedCommands: number;
28
+ }
29
+
30
+ export interface GhostSuggestion {
31
+ value: string;
32
+ source:
33
+ | "project-history"
34
+ | "global-history"
35
+ | "git"
36
+ | "path"
37
+ | "executable";
38
+ }
39
+
40
+ export interface ExtendedCompletionItem {
41
+ value: string;
42
+ label: string;
43
+ description?: string;
44
+ replacement: string;
45
+ startCol: number;
46
+ endCol: number;
47
+ source:
48
+ | "project-history"
49
+ | "global-history"
50
+ | "git"
51
+ | "path"
52
+ | "executable";
53
+ score: number;
54
+ }
55
+
56
+ export interface ShellSessionState {
57
+ ready: boolean;
58
+ running: boolean;
59
+ shellPath: string;
60
+ shellName: string;
61
+ cwd: string;
62
+ lastExitCode: number | null;
63
+ }
64
+
65
+ export interface BashModeEditorOptions {
66
+ keybindings: KeybindingsManager;
67
+ isBashModeActive: () => boolean;
68
+ isShellRunning: () => boolean;
69
+ onExitBashMode: () => void;
70
+ onSubmitCommand: (command: string) => void;
71
+ onEditorSubmit?: () => void;
72
+ editorBoundaryShortcuts?: EditorBoundaryShortcuts;
73
+ onInterrupt: () => void;
74
+ onNotify: (message: string, level?: "info" | "warning" | "error") => void;
75
+ getHistoryEntries: (prefix: string) => string[];
76
+ resolveGhostSuggestion: (
77
+ text: string,
78
+ signal: AbortSignal,
79
+ ) => Promise<GhostSuggestion | null>;
80
+ }
package/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { default } from "./src/extension/activate.ts";
2
+ export {
3
+ parseBashModeSettings,
4
+ resolveShortcutConfig,
5
+ } from "./src/extension/shortcuts-config.ts";
6
+ export type { PowerlineShortcuts } from "./src/extension/types.ts";
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@groeponline/pi-wishcraft",
3
+ "version": "0.17.3",
4
+ "description": "Wishcraft status bar & interaction layer for the pi coding agent — powerline segments, vibes, queue, bash mode, and full customization.",
5
+ "type": "module",
6
+ "files": [
7
+ "*.ts",
8
+ "*.md",
9
+ "*.json",
10
+ "src/**/*.ts",
11
+ "src/**/*.md",
12
+ "src/**/*.txt",
13
+ "bash-mode/**/*.ts",
14
+ "queue/**/*.ts"
15
+ ],
16
+ "keywords": [
17
+ "pi-package",
18
+ "pi",
19
+ "coding-agent",
20
+ "powerline",
21
+ "status-bar",
22
+ "extension"
23
+ ],
24
+ "author": "Nico Bailon",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/GroepOnline/pi-wishcraft.git"
29
+ },
30
+ "scripts": {
31
+ "typecheck": "tsc --noEmit",
32
+ "test": "node --experimental-strip-types --test tests/**/*.test.ts",
33
+ "release": "node scripts/release.mjs",
34
+ "prepublishOnly": "tsc --noEmit",
35
+ "circular": "madge --circular src index.ts bash-mode queue"
36
+ },
37
+ "peerDependencies": {
38
+ "@earendil-works/pi-ai": ">=0.81.0 <0.85.0",
39
+ "@earendil-works/pi-coding-agent": ">=0.81.0 <0.85.0",
40
+ "@earendil-works/pi-tui": ">=0.81.0 <0.85.0"
41
+ },
42
+ "devDependencies": {
43
+ "@earendil-works/pi-ai": "^0.84.0",
44
+ "@earendil-works/pi-coding-agent": "^0.84.0",
45
+ "@earendil-works/pi-tui": "^0.84.0",
46
+ "@types/node": "24.13.3",
47
+ "madge": "^8.0.0",
48
+ "typescript": "5.9.3"
49
+ },
50
+ "pi": {
51
+ "extensions": [
52
+ "./index.ts"
53
+ ]
54
+ }
55
+ }