shariq-pi-extensions 0.3.1 → 0.3.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.
package/README.md
CHANGED
|
@@ -73,9 +73,9 @@ Runtime files use Pi's active agent directory rather than a fixed home or checko
|
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
75
|
mise install --locked
|
|
76
|
-
mise exec --locked --
|
|
77
|
-
mise exec --locked --
|
|
78
|
-
mise exec --locked --
|
|
76
|
+
mise exec --locked -- bun install
|
|
77
|
+
mise exec --locked -- bun run validate
|
|
78
|
+
mise exec --locked -- bun run pack:inspect
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
See [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) for repository workflow and release checks, and [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for package boundaries.
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -8,11 +8,11 @@ Last verified: 2026-09-04
|
|
|
8
8
|
- Pi matching the pinned development dependency version
|
|
9
9
|
- platform build support required by `@lydell/node-pty`
|
|
10
10
|
|
|
11
|
-
Install the exact
|
|
11
|
+
Install the exact toolchain and dependencies:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
mise install --locked
|
|
15
|
-
mise exec --locked --
|
|
15
|
+
mise exec --locked -- bun install
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## Validation
|
|
@@ -20,8 +20,8 @@ mise exec --locked -- npm ci
|
|
|
20
20
|
Validate the complete suite and inspect the package payload:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
mise exec --locked --
|
|
24
|
-
mise exec --locked --
|
|
23
|
+
mise exec --locked -- bun run validate
|
|
24
|
+
mise exec --locked -- bun run pack:inspect
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
The root validation checks TypeScript, runtime tests, declared extension and skill entrypoints, and forbidden runtime files. Inspect the package file list before committing. It must not contain credentials, `.env`, first-party caches, databases, sessions, logs, or `node_modules`.
|
|
@@ -74,8 +74,8 @@ gh repo view shariqriazz/shariq-pi-extensions --json visibility,url
|
|
|
74
74
|
Before publishing a new npm version:
|
|
75
75
|
|
|
76
76
|
1. Update `package.json#version` using semantic versioning.
|
|
77
|
-
2. Run `mise exec --locked --
|
|
78
|
-
3. Inspect `mise exec --locked --
|
|
77
|
+
2. Run `mise exec --locked -- bun install` and `mise exec --locked -- bun run validate`.
|
|
78
|
+
3. Inspect `mise exec --locked -- bun run pack:inspect` for secrets, runtime state, and accidental files.
|
|
79
79
|
4. Run the `Publish npm package` workflow. npm trusted publishing authenticates it through GitHub OIDC and records provenance without a long-lived token.
|
|
80
80
|
5. Verify the registry version and install it with `pi install npm:shariq-pi-extensions`.
|
|
81
81
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as os from "node:os";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { spawnUniversalPty, type UniversalPty } from "./pty.ts";
|
|
5
5
|
import { OutputBuffer } from "./output-buffer.ts";
|
|
6
6
|
import type {
|
|
7
7
|
StartTerminalOptions,
|
|
@@ -37,11 +37,11 @@ interface MutableSnapshot {
|
|
|
37
37
|
|
|
38
38
|
interface Entry {
|
|
39
39
|
readonly snapshot: MutableSnapshot;
|
|
40
|
-
readonly pty:
|
|
40
|
+
readonly pty: UniversalPty;
|
|
41
41
|
readonly output: OutputBuffer;
|
|
42
42
|
readonly spill: fs.WriteStream;
|
|
43
|
-
readonly dataSubscription:
|
|
44
|
-
readonly exitSubscription:
|
|
43
|
+
readonly dataSubscription: { dispose(): void };
|
|
44
|
+
readonly exitSubscription: { dispose(): void };
|
|
45
45
|
readonly settled: Promise<TerminalSnapshot>;
|
|
46
46
|
resolveSettled(snapshot: TerminalSnapshot): void;
|
|
47
47
|
killRequested: boolean;
|
|
@@ -202,7 +202,7 @@ export class TerminalManager {
|
|
|
202
202
|
let spillBytes = 0;
|
|
203
203
|
let spillTruncated = false;
|
|
204
204
|
let pausedForSpill = false;
|
|
205
|
-
let pty:
|
|
205
|
+
let pty: UniversalPty | undefined;
|
|
206
206
|
let snapshot: MutableSnapshot | undefined;
|
|
207
207
|
const markSpillTruncated = () => {
|
|
208
208
|
if (spillTruncated) return;
|
|
@@ -223,7 +223,7 @@ export class TerminalManager {
|
|
|
223
223
|
if (payload.length < bytes.length || spillBytes >= this.maxFullLogBytes) markSpillTruncated();
|
|
224
224
|
if (!accepted && pty && !pausedForSpill) {
|
|
225
225
|
pausedForSpill = true;
|
|
226
|
-
pty.pause();
|
|
226
|
+
pty.pause?.();
|
|
227
227
|
}
|
|
228
228
|
});
|
|
229
229
|
output.spillPath = spillPath;
|
|
@@ -231,7 +231,7 @@ export class TerminalManager {
|
|
|
231
231
|
if (!pausedForSpill) return;
|
|
232
232
|
pausedForSpill = false;
|
|
233
233
|
try {
|
|
234
|
-
pty?.resume();
|
|
234
|
+
pty?.resume?.();
|
|
235
235
|
} catch {
|
|
236
236
|
// Exit may have won the drain race.
|
|
237
237
|
}
|
|
@@ -242,7 +242,7 @@ export class TerminalManager {
|
|
|
242
242
|
if (pausedForSpill) {
|
|
243
243
|
pausedForSpill = false;
|
|
244
244
|
try {
|
|
245
|
-
pty?.resume();
|
|
245
|
+
pty?.resume?.();
|
|
246
246
|
} catch {
|
|
247
247
|
// Exit may have won the error race.
|
|
248
248
|
}
|
|
@@ -253,8 +253,9 @@ export class TerminalManager {
|
|
|
253
253
|
|
|
254
254
|
const shell = shellInvocation(options.command);
|
|
255
255
|
try {
|
|
256
|
-
pty =
|
|
257
|
-
|
|
256
|
+
pty = spawnUniversalPty({
|
|
257
|
+
file: shell.file,
|
|
258
|
+
args: shell.args,
|
|
258
259
|
cols,
|
|
259
260
|
rows,
|
|
260
261
|
cwd: options.cwd,
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { spawn as spawnNodePty, type IDisposable, type IPty } from "@lydell/node-pty";
|
|
4
|
+
|
|
5
|
+
export interface UniversalPty {
|
|
6
|
+
readonly pid: number;
|
|
7
|
+
onData(listener: (chunk: string) => void): { dispose(): void };
|
|
8
|
+
onExit(listener: (event: { exitCode: number; signal?: number }) => void): { dispose(): void };
|
|
9
|
+
write(data: string): void;
|
|
10
|
+
resize(cols: number, rows: number): void;
|
|
11
|
+
pause?(): void;
|
|
12
|
+
resume?(): void;
|
|
13
|
+
kill(signal?: string): void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SpawnUniversalPtyOptions {
|
|
17
|
+
file: string;
|
|
18
|
+
args: string[];
|
|
19
|
+
cols: number;
|
|
20
|
+
rows: number;
|
|
21
|
+
cwd: string;
|
|
22
|
+
env: Record<string, string | undefined>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare const Bun: any;
|
|
26
|
+
|
|
27
|
+
class BunPtyAdapter implements UniversalPty {
|
|
28
|
+
readonly pid: number;
|
|
29
|
+
private readonly proc: any;
|
|
30
|
+
private readonly dataListeners = new Set<(chunk: string) => void>();
|
|
31
|
+
private readonly exitListeners = new Set<(event: { exitCode: number; signal?: number }) => void>();
|
|
32
|
+
private exited = false;
|
|
33
|
+
|
|
34
|
+
constructor(options: SpawnUniversalPtyOptions) {
|
|
35
|
+
const cmd = [options.file, ...options.args];
|
|
36
|
+
this.proc = Bun.spawn(cmd, {
|
|
37
|
+
cwd: options.cwd,
|
|
38
|
+
env: options.env,
|
|
39
|
+
terminal: {
|
|
40
|
+
cols: options.cols,
|
|
41
|
+
rows: options.rows,
|
|
42
|
+
data: (_term: unknown, chunk: Uint8Array | string) => {
|
|
43
|
+
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
44
|
+
for (const listener of this.dataListeners) {
|
|
45
|
+
try {
|
|
46
|
+
listener(text);
|
|
47
|
+
} catch {
|
|
48
|
+
// Ignore listener errors
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
this.pid = this.proc.pid;
|
|
56
|
+
|
|
57
|
+
void this.proc.exited.then((exitCode: number) => {
|
|
58
|
+
if (this.exited) return;
|
|
59
|
+
this.exited = true;
|
|
60
|
+
const signal = this.proc.signalCode
|
|
61
|
+
? typeof this.proc.signalCode === "number"
|
|
62
|
+
? this.proc.signalCode
|
|
63
|
+
: undefined
|
|
64
|
+
: undefined;
|
|
65
|
+
for (const listener of this.exitListeners) {
|
|
66
|
+
try {
|
|
67
|
+
listener({ exitCode: typeof exitCode === "number" ? exitCode : 0, signal });
|
|
68
|
+
} catch {
|
|
69
|
+
// Ignore listener errors
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
onData(listener: (chunk: string) => void) {
|
|
76
|
+
this.dataListeners.add(listener);
|
|
77
|
+
return {
|
|
78
|
+
dispose: () => {
|
|
79
|
+
this.dataListeners.delete(listener);
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
onExit(listener: (event: { exitCode: number; signal?: number }) => void) {
|
|
85
|
+
this.exitListeners.add(listener);
|
|
86
|
+
return {
|
|
87
|
+
dispose: () => {
|
|
88
|
+
this.exitListeners.delete(listener);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
write(data: string): void {
|
|
94
|
+
try {
|
|
95
|
+
this.proc.terminal.write(data);
|
|
96
|
+
} catch {
|
|
97
|
+
// Best-effort write
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
resize(cols: number, rows: number): void {
|
|
102
|
+
try {
|
|
103
|
+
this.proc.terminal.resize(cols, rows);
|
|
104
|
+
} catch {
|
|
105
|
+
// Best-effort resize
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
kill(signal?: string): void {
|
|
110
|
+
try {
|
|
111
|
+
this.proc.kill(signal ?? "SIGTERM");
|
|
112
|
+
} catch {
|
|
113
|
+
// Best-effort kill
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
class NodePtyAdapter implements UniversalPty {
|
|
119
|
+
readonly pid: number;
|
|
120
|
+
private readonly pty: IPty;
|
|
121
|
+
|
|
122
|
+
constructor(pty: IPty) {
|
|
123
|
+
this.pty = pty;
|
|
124
|
+
this.pid = pty.pid;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
onData(listener: (chunk: string) => void) {
|
|
128
|
+
return this.pty.onData(listener);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
onExit(listener: (event: { exitCode: number; signal?: number }) => void) {
|
|
132
|
+
return this.pty.onExit(listener);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
write(data: string): void {
|
|
136
|
+
this.pty.write(data);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
resize(cols: number, rows: number): void {
|
|
140
|
+
this.pty.resize(cols, rows);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
kill(signal?: string): void {
|
|
144
|
+
this.pty.kill(signal);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function isBunRuntime(): boolean {
|
|
149
|
+
return typeof Bun !== "undefined" && typeof Bun.spawn === "function";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function spawnUniversalPty(options: SpawnUniversalPtyOptions): UniversalPty {
|
|
153
|
+
if (isBunRuntime()) {
|
|
154
|
+
return new BunPtyAdapter(options);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const pty = spawnNodePty(options.file, options.args, {
|
|
158
|
+
name: "xterm-256color",
|
|
159
|
+
cols: options.cols,
|
|
160
|
+
rows: options.rows,
|
|
161
|
+
cwd: options.cwd,
|
|
162
|
+
env: options.env as Record<string, string>,
|
|
163
|
+
});
|
|
164
|
+
return new NodePtyAdapter(pty);
|
|
165
|
+
}
|
|
@@ -50,6 +50,7 @@ export interface SmartCompactionDetails {
|
|
|
50
50
|
serializedCharacters: number;
|
|
51
51
|
summaryCharacters: number;
|
|
52
52
|
attemptCount: number;
|
|
53
|
+
retainedIdentifiersAppended?: number;
|
|
53
54
|
durationMs: number;
|
|
54
55
|
timestamp: number;
|
|
55
56
|
}
|
|
@@ -328,7 +329,9 @@ const REQUIRED_SECTION_PATTERNS = [
|
|
|
328
329
|
/## 6\.\s+Resume Anchor/i,
|
|
329
330
|
];
|
|
330
331
|
|
|
331
|
-
export
|
|
332
|
+
export const RETAINED_IDENTIFIERS_HEADING = "### Retained Identifiers";
|
|
333
|
+
|
|
334
|
+
export function extractSummaryText(response: AssistantMessage): string {
|
|
332
335
|
if (response.stopReason !== "stop") {
|
|
333
336
|
const errorDetails = response.errorMessage ? `: ${response.errorMessage}` : "";
|
|
334
337
|
throw new Error(`Compaction model did not complete successfully (stopReason="${response.stopReason}"${errorDetails}).`);
|
|
@@ -350,13 +353,38 @@ export function validateSummaryOutput(response: AssistantMessage, protectedFacts
|
|
|
350
353
|
throw new Error("Compaction model returned an empty summary.");
|
|
351
354
|
}
|
|
352
355
|
|
|
356
|
+
return rawSummaryText;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export function getDroppedProtectedFacts(summaryText: string, protectedFacts: readonly string[] = []): string[] {
|
|
360
|
+
return protectedFacts.filter((fact) => fact && !summaryText.includes(fact));
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export function withRetainedIdentifiers(summaryText: string, droppedFacts: readonly string[]): string {
|
|
364
|
+
// Protected facts are single-line opaque identifiers (hashes, UUIDs, clean
|
|
365
|
+
// URLs, IPs), so reproducing them on their own bullet lines is verbatim-safe.
|
|
366
|
+
const lines = [summaryText.trimEnd(), "", RETAINED_IDENTIFIERS_HEADING];
|
|
367
|
+
for (const fact of droppedFacts) {
|
|
368
|
+
const clean = String(fact).trim();
|
|
369
|
+
if (clean) lines.push(`- ${clean}`);
|
|
370
|
+
}
|
|
371
|
+
return lines.join("\n") + "\n";
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export function validateSummaryText(summaryText: string, protectedFacts: readonly string[] = []): string {
|
|
375
|
+
const rawSummaryText = summaryText.trim();
|
|
376
|
+
|
|
377
|
+
if (!rawSummaryText) {
|
|
378
|
+
throw new Error("Compaction model returned an empty summary.");
|
|
379
|
+
}
|
|
380
|
+
|
|
353
381
|
// Verify all 6 required sections exist
|
|
354
382
|
for (const pattern of REQUIRED_SECTION_PATTERNS) {
|
|
355
383
|
if (!pattern.test(rawSummaryText)) {
|
|
356
384
|
throw new Error(`Compaction summary is incomplete: missing required section matching ${pattern.source}`);
|
|
357
385
|
}
|
|
358
386
|
}
|
|
359
|
-
const missingFacts =
|
|
387
|
+
const missingFacts = getDroppedProtectedFacts(rawSummaryText, protectedFacts);
|
|
360
388
|
if (missingFacts.length > 0) {
|
|
361
389
|
throw new Error(`Compaction summary dropped protected facts: ${missingFacts.slice(0, 3).join(" | ")}`);
|
|
362
390
|
}
|
|
@@ -364,6 +392,29 @@ export function validateSummaryOutput(response: AssistantMessage, protectedFacts
|
|
|
364
392
|
return rawSummaryText;
|
|
365
393
|
}
|
|
366
394
|
|
|
395
|
+
export function validateSummaryOutput(response: AssistantMessage, protectedFacts: readonly string[] = []): string {
|
|
396
|
+
return validateSummaryText(extractSummaryText(response), protectedFacts);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Return the summary text when it is structurally sound (extractable with all
|
|
401
|
+
* required sections) regardless of dropped protected facts. Identifier-only
|
|
402
|
+
* defects can be repaired deterministically with {@link withRetainedIdentifiers};
|
|
403
|
+
* structural defects cannot, so those return undefined.
|
|
404
|
+
*/
|
|
405
|
+
export function extractRepairableSummary(response: AssistantMessage): string | undefined {
|
|
406
|
+
let text: string;
|
|
407
|
+
try {
|
|
408
|
+
text = extractSummaryText(response);
|
|
409
|
+
} catch {
|
|
410
|
+
return undefined;
|
|
411
|
+
}
|
|
412
|
+
for (const pattern of REQUIRED_SECTION_PATTERNS) {
|
|
413
|
+
if (!pattern.test(text)) return undefined;
|
|
414
|
+
}
|
|
415
|
+
return text;
|
|
416
|
+
}
|
|
417
|
+
|
|
367
418
|
export function computeCompactionTokenCeiling(
|
|
368
419
|
model: Model<Api>,
|
|
369
420
|
config: SmartCompactionConfig,
|
|
@@ -529,6 +580,8 @@ export async function runSmartCompaction(
|
|
|
529
580
|
|
|
530
581
|
let lastError: Error | undefined;
|
|
531
582
|
let finalSummaryText = "";
|
|
583
|
+
let repairCandidate: string | undefined;
|
|
584
|
+
let retainedIdentifiersAppended = 0;
|
|
532
585
|
let accumulatedUsage: Usage | undefined;
|
|
533
586
|
let attemptCount = 0;
|
|
534
587
|
let activeModel = primaryModel;
|
|
@@ -572,7 +625,16 @@ export async function runSmartCompaction(
|
|
|
572
625
|
if (response.usage) {
|
|
573
626
|
accumulatedUsage = combineCompactionUsage(accumulatedUsage, response.usage);
|
|
574
627
|
}
|
|
575
|
-
|
|
628
|
+
try {
|
|
629
|
+
finalSummaryText = validateSummaryOutput(response, protectedFacts);
|
|
630
|
+
} catch (validationError) {
|
|
631
|
+
// Structurally sound summaries that only drop protected facts are
|
|
632
|
+
// kept as deterministic-repair candidates; structural defects cannot
|
|
633
|
+
// be repaired, so those leave no candidate behind.
|
|
634
|
+
const repairable = extractRepairableSummary(response);
|
|
635
|
+
if (repairable !== undefined) repairCandidate = repairable;
|
|
636
|
+
throw validationError;
|
|
637
|
+
}
|
|
576
638
|
lastError = undefined;
|
|
577
639
|
break; // Success!
|
|
578
640
|
} catch (err) {
|
|
@@ -586,6 +648,23 @@ export async function runSmartCompaction(
|
|
|
586
648
|
}
|
|
587
649
|
}
|
|
588
650
|
|
|
651
|
+
if ((lastError || !finalSummaryText) && repairCandidate !== undefined) {
|
|
652
|
+
// Every stage produced a structurally sound summary but the model
|
|
653
|
+
// deterministically refused to repeat low-signal identifiers. Restore
|
|
654
|
+
// them verbatim instead of failing the whole compaction.
|
|
655
|
+
const stillMissing = getDroppedProtectedFacts(repairCandidate, protectedFacts);
|
|
656
|
+
try {
|
|
657
|
+
finalSummaryText = validateSummaryText(
|
|
658
|
+
withRetainedIdentifiers(repairCandidate, stillMissing),
|
|
659
|
+
protectedFacts,
|
|
660
|
+
);
|
|
661
|
+
lastError = undefined;
|
|
662
|
+
retainedIdentifiersAppended = stillMissing.length;
|
|
663
|
+
} catch {
|
|
664
|
+
// Repair rejected; fall through to the original failure below.
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
589
668
|
if (lastError || !finalSummaryText) {
|
|
590
669
|
throw lastError ?? new Error("All smart compaction retry stages failed.");
|
|
591
670
|
}
|
|
@@ -643,6 +722,7 @@ export async function runSmartCompaction(
|
|
|
643
722
|
serializedCharacters: conversationText.length,
|
|
644
723
|
summaryCharacters: finalSummary.length,
|
|
645
724
|
attemptCount,
|
|
725
|
+
retainedIdentifiersAppended: retainedIdentifiersAppended > 0 ? retainedIdentifiersAppended : undefined,
|
|
646
726
|
durationMs: Date.now() - startedAt,
|
|
647
727
|
timestamp: Date.now(),
|
|
648
728
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shariq-pi-extensions",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Cross-platform extension suite for the Pi coding agent.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Shariq Riaz",
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
"check": "tsc --noEmit -p tsconfig.json",
|
|
63
63
|
"test": "node scripts/run-tests.mjs",
|
|
64
64
|
"validate:package": "node scripts/validate-package.mjs",
|
|
65
|
-
"validate": "
|
|
65
|
+
"validate": "bun run check && node scripts/run-tests.mjs && bun run validate:package",
|
|
66
66
|
"pack:inspect": "npm pack --dry-run",
|
|
67
|
-
"prepublishOnly": "
|
|
67
|
+
"prepublishOnly": "bun run validate"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@lydell/node-pty": "1.1.0",
|
|
70
|
+
"@lydell/node-pty": "^1.1.0",
|
|
71
71
|
"effect": "4.0.0-beta.98"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
@@ -95,12 +95,12 @@
|
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
97
|
"devDependencies": {
|
|
98
|
-
"@earendil-works/pi-agent-core": "0.
|
|
99
|
-
"@earendil-works/pi-ai": "0.
|
|
100
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
101
|
-
"@earendil-works/pi-tui": "0.
|
|
102
|
-
"@types/node": "^26.1
|
|
103
|
-
"typebox": "1.3.
|
|
98
|
+
"@earendil-works/pi-agent-core": "^0.85.1",
|
|
99
|
+
"@earendil-works/pi-ai": "^0.85.1",
|
|
100
|
+
"@earendil-works/pi-coding-agent": "^0.85.1",
|
|
101
|
+
"@earendil-works/pi-tui": "^0.85.1",
|
|
102
|
+
"@types/node": "^26.4.1",
|
|
103
|
+
"typebox": "^1.3.27",
|
|
104
104
|
"typescript": "^7.0.2"
|
|
105
105
|
},
|
|
106
106
|
"allowScripts": {
|