pi-openai-codex-compat 0.0.21 → 0.0.22

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/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.0.22 - 2026-10-08
6
+
7
+ ### Fixed
8
+
9
+ - Create command-output temporary files with owner-only permissions and refuse
10
+ to overwrite existing files or follow symlinks. Failed creation leaves
11
+ existing files intact.
12
+ - Preserve explicit `originator` and `User-Agent` overrides without changing
13
+ the default Pi identity.
14
+ - Honor Pi's horizontal output padding setting in Codex tool calls and results.
15
+ - Do not restart output-limit recovery after the user cancels the Pi run.
16
+
17
+ ### Changed
18
+
19
+ - Require Pi `>=1.1.0 <1.2.0`. Restart Pi after upgrading its runtime.
20
+
5
21
  ## 0.0.21 - 2026-10-02
6
22
 
7
23
  ### Fixed
package/README.md CHANGED
@@ -22,19 +22,19 @@ Pi provides the Codex OAuth flow and model catalog. At session start, this packa
22
22
  ## Requirements
23
23
 
24
24
  - Node.js 22.19 or newer
25
- - Pi `>=1.0.0 <1.1.0`
25
+ - Pi `>=1.1.0 <1.2.0`
26
26
  - An OpenAI Codex login in Pi
27
27
 
28
28
  Restart Pi after upgrading its runtime. `/reload` reloads extensions but cannot
29
29
  upgrade the running Pi process. At load time, the extension requires the host's
30
30
  transcript APIs, the Pi 0.99 APIs `SessionManager.getEntryCount()` and
31
- `ExtensionAPI.getSettings()`, and a reported Pi version of at least 1.0.0. It
31
+ `ExtensionAPI.getSettings()`, and a reported Pi version of at least 1.1.0. It
32
32
  refuses to load otherwise. The load check does not reject newer releases: the
33
- `<1.1.0` bound is the package's peer range, which Pi does not enforce when it
33
+ `<1.2.0` bound is the package's peer range, which Pi does not enforce when it
34
34
  installs packages. `PI_PACKAGE_DIR` can point an older executable at
35
35
  newer package metadata, so the reported version alone does not establish
36
36
  compatibility. The API checks detect missing capabilities from before Pi 0.99.
37
- They do not distinguish a Pi 0.99 executable from Pi 1.0.0 when its metadata
37
+ They do not distinguish a Pi 0.99 executable from Pi 1.1.0 when its metadata
38
38
  points at the newer installation.
39
39
 
40
40
  Authenticate through Pi if needed:
@@ -662,19 +662,18 @@ Both namespace tools are accepted only from the fixed extension-owned allowlist.
662
662
  ```bash
663
663
  mise trust
664
664
  mise install
665
- npm install
665
+ mise run init
666
666
  mise run check
667
667
  npm run pack:dry
668
668
  ```
669
669
 
670
670
  `mise run check` runs the linters, formatters, type checks, and the offline
671
- test suite; `mise run test` runs only the offline suite. Both tasks bind
672
- `PI_PACKAGE_DIR` to `node_modules/@earendil-works/pi-coding-agent`, so tests
673
- that load Pi in-process read this repository's Pi 1.0.0 resources even when a
674
- global `PI_PACKAGE_DIR` points at another installation. Ordinary `pi` launches
675
- outside these tasks are unaffected. Offline tests also exercise
671
+ test suite; `npm test` runs only the offline suite. `npm test` and
672
+ `npm run test:live:codex` remove an inherited `PI_PACKAGE_DIR` from their test
673
+ processes, so tests that load Pi in-process read this repository's Pi
674
+ resources. Ordinary `pi` launches are unaffected. Offline tests also exercise
676
675
  `scripts/release.ts` with every child process mocked: they never run Git, npm,
677
- Mise, or provider calls.
676
+ or provider calls.
678
677
 
679
678
  Run the credentialed Pi/Codex integration tests separately. They load the real
680
679
  extension into headless Pi sessions, use the real WebSocket service, and ask
@@ -682,13 +681,14 @@ the model to report all prior history markers after each text and tool
682
681
  continuation:
683
682
 
684
683
  ```bash
685
- mise run test:live:codex
684
+ npm run test:live:codex
686
685
  ```
687
686
 
688
- The task obtains the local Codex bearer token and runs the tests with
689
- `gpt-5.6-luna`, `gpt-6-sol`, `gpt-6-luna`, and `gpt-6.1-sol` at medium reasoning
690
- effort. It also packs the extension and loads that archive through the shipped Pi
691
- 1.0.0 CLI. Ordinary Responses and Responses Lite tests exercise tool calls,
687
+ `scripts/test-live.ts` first runs the offline packaged terminal tests. It then
688
+ obtains the local Codex bearer token through the repository Pi and runs the
689
+ tests with `gpt-5.6-luna`, `gpt-6-sol`, `gpt-6-luna`, and `gpt-6.1-sol` at
690
+ medium reasoning effort. It also packs the extension and loads that archive through the shipped Pi
691
+ CLI. Ordinary Responses and Responses Lite tests exercise tool calls,
692
692
  prompt reload, native compaction, and persisted-session resume against Codex.
693
693
  SDK tests verify Responses Lite
694
694
  WebSocket history, prewarming, continuation, and the built-in read tool.
@@ -710,12 +710,12 @@ The packaged-CLI test selects its archive and executable as follows:
710
710
  existing regular file that `tar` can list, and an empty, missing, directory,
711
711
  or invalid value fails the test instead of falling back to a fresh pack.
712
712
  - `PI_CODEX_CLI_PATH` selects another Pi `cli.js`; the default is this
713
- repository's Pi 1.0.0 dependency. The test asserts that the selected
714
- executable reports version 1.0.0, the only Pi version the packaged CLI test
715
- is run against. The supported range is `>=1.0.0 <1.1.0`.
716
- - Each Pi child process receives `PI_PACKAGE_DIR` bound to the selected
717
- executable's package directory, so the runtime under test reads its own
718
- metadata.
713
+ repository's Pi development dependency. The live test asserts that the
714
+ selected executable has the development dependency's version, the only Pi
715
+ version releases are validated against. The supported range is
716
+ `>=1.1.0 <1.2.0`.
717
+ - Each Pi child process resolves its own package directory, so the runtime
718
+ under test reads its own metadata.
719
719
 
720
720
  The public package entrypoint is `extensions/index.ts`; implementation modules remain under
721
721
  `extensions/openai-codex-compat/`. The focused Pi AI serializer copy lives under
@@ -748,7 +748,7 @@ The release command runs these steps in order:
748
748
  only those two files.
749
749
  3. Check out the staged index into a temporary directory, run
750
750
  `npm ci --ignore-scripts` and `npm pack` there, validate the package
751
- identity, file list, and manifest, then run `mise run test:live:codex` in
751
+ identity, file list, and manifest, then run `npm run test:live:codex` in
752
752
  the repository with `PI_CODEX_PACKAGE_ARCHIVE` set to that archive. This is
753
753
  the exact archive release gate: the live CLI tests load that archive and
754
754
  nothing else. A live process that cannot start, a nonzero exit, or a failed
@@ -17,6 +17,7 @@ type ApplyPatchArgs = {
17
17
  };
18
18
 
19
19
  type ApplyPatchRenderContext = {
20
+ outputPad: number;
20
21
  cwd: string;
21
22
  isPartial: boolean;
22
23
  expanded: boolean;
@@ -132,6 +133,7 @@ export function renderApplyPatchCall(
132
133
 
133
134
  return new CodexToolSurfaceComponent(container, theme, {
134
135
  background: resolveBackground,
136
+ outputPad: context.outputPad,
135
137
  status: context.isPartial ? "pending" : context.isError ? "error" : "success",
136
138
  top: true,
137
139
  bottom: context.isPartial,
@@ -163,6 +165,7 @@ export function renderApplyPatchResult(
163
165
  theme,
164
166
  {
165
167
  background: resolveBackground,
168
+ outputPad: context.outputPad,
166
169
  status: context.isError ? "error" : "success",
167
170
  top: true,
168
171
  bottom: true,
@@ -176,6 +179,7 @@ export function renderApplyPatchResult(
176
179
  theme,
177
180
  {
178
181
  background: resolveBackground,
182
+ outputPad: context.outputPad,
179
183
  status: "error",
180
184
  top: true,
181
185
  bottom: true,
@@ -155,6 +155,7 @@ export class CodexToolSurfaceComponent implements Component {
155
155
  private readonly status: CodexToolSurfaceStatus;
156
156
  private readonly topPadding: boolean;
157
157
  private readonly bottomPadding: boolean;
158
+ private readonly outputPad: number;
158
159
  private renderCache:
159
160
  | {
160
161
  width: number;
@@ -172,6 +173,7 @@ export class CodexToolSurfaceComponent implements Component {
172
173
  status: CodexToolSurfaceStatus;
173
174
  top: boolean;
174
175
  bottom: boolean;
176
+ outputPad: number;
175
177
  },
176
178
  ) {
177
179
  this.component = component;
@@ -180,12 +182,13 @@ export class CodexToolSurfaceComponent implements Component {
180
182
  this.status = options.status;
181
183
  this.topPadding = options.top;
182
184
  this.bottomPadding = options.bottom;
185
+ this.outputPad = options.outputPad;
183
186
  }
184
187
 
185
188
  render(width: number): string[] {
186
189
  const effectiveWidth = Math.max(1, width);
187
190
  const background = surfaceBackground(this.theme, this.resolveBackground(), this.status);
188
- const horizontalPadding = effectiveWidth > 2 ? 1 : 0;
191
+ const horizontalPadding = Math.min(this.outputPad, Math.floor((effectiveWidth - 1) / 2));
189
192
  const contentWidth = Math.max(1, effectiveWidth - horizontalPadding * 2);
190
193
  const componentLines = this.component.render(contentWidth);
191
194
  const cached = this.renderCache;
@@ -164,19 +164,20 @@ export function baseHeaders(
164
164
  accountId: string,
165
165
  token: string,
166
166
  ): Headers {
167
- const headers = new Headers(modelHeaders);
167
+ const os = nodeOs();
168
+ const headers = new Headers({
169
+ originator: "pi",
170
+ "User-Agent": os ? `pi (${os.platform()} ${os.release()}; ${os.arch()})` : "pi (browser)",
171
+ });
172
+ for (const [name, value] of Object.entries(modelHeaders ?? {})) {
173
+ headers.set(name, value);
174
+ }
168
175
  for (const [name, value] of Object.entries(additionalHeaders ?? {})) {
169
176
  if (value === null) headers.delete(name);
170
177
  else headers.set(name, value);
171
178
  }
172
179
  headers.set("Authorization", `Bearer ${token}`);
173
180
  headers.set("chatgpt-account-id", accountId);
174
- headers.set("originator", "pi");
175
- const os = nodeOs();
176
- headers.set(
177
- "User-Agent",
178
- os ? `pi (${os.platform()} ${os.release()}; ${os.arch()})` : "pi (browser)",
179
- );
180
181
  return headers;
181
182
  }
182
183
 
@@ -134,6 +134,7 @@ export class CommandOutputAccumulator {
134
134
  private hasOpenLine = false;
135
135
  private finished = false;
136
136
  private tempFilePath: string | undefined;
137
+ private tempFileCreated = false;
137
138
  private tempFileStream: WriteStream | undefined;
138
139
  private tempFileError: Error | undefined;
139
140
  private readonly retainCompleteOutput: boolean;
@@ -230,6 +231,8 @@ export class CommandOutputAccumulator {
230
231
 
231
232
  const stream = this.tempFileStream;
232
233
  this.tempFileStream = undefined;
234
+ const previousError = this.tempFileError;
235
+ if (previousError) throw previousError;
233
236
  await new Promise<void>((resolve, reject) => {
234
237
  const onError = (error: Error): void => {
235
238
  stream.off("finish", onFinish);
@@ -256,8 +259,9 @@ export class CommandOutputAccumulator {
256
259
  ? error
257
260
  : new Error("Could not close discarded command output.", { cause: error });
258
261
  }
259
- if (this.tempFilePath !== undefined) {
262
+ if (this.tempFileCreated && this.tempFilePath !== undefined) {
260
263
  await rm(this.tempFilePath, { force: true });
264
+ this.tempFileCreated = false;
261
265
  }
262
266
  if (closeError) throw closeError;
263
267
  }
@@ -325,7 +329,10 @@ export class CommandOutputAccumulator {
325
329
  private ensureTempFile(): void {
326
330
  if (this.tempFilePath) return;
327
331
  this.tempFilePath = tempFilePath(this.tempFilePrefix);
328
- const stream = createWriteStream(this.tempFilePath);
332
+ const stream = createWriteStream(this.tempFilePath, { mode: 0o600, flags: "wx" });
333
+ stream.once("open", () => {
334
+ this.tempFileCreated = true;
335
+ });
329
336
  stream.on("error", (error) => {
330
337
  this.tempFileError = error;
331
338
  });
@@ -344,6 +351,7 @@ export class CommandOutputSpool {
344
351
  private readonly tempFilePrefix: string;
345
352
  private totalBytes = 0;
346
353
  private tempFilePath: string | undefined;
354
+ private tempFileCreated = false;
347
355
  private tempFileStream: WriteStream | undefined;
348
356
  private tempFileError: Error | undefined;
349
357
  private finishing: Promise<void> | undefined;
@@ -390,8 +398,9 @@ export class CommandOutputSpool {
390
398
  ? error
391
399
  : new Error("Could not finish disposable command output.", { cause: error });
392
400
  }
393
- if (this.tempFilePath !== undefined) {
401
+ if (this.tempFileCreated && this.tempFilePath !== undefined) {
394
402
  await rm(this.tempFilePath, { force: true });
403
+ this.tempFileCreated = false;
395
404
  }
396
405
  if (finishError) throw finishError;
397
406
  }
@@ -400,6 +409,10 @@ export class CommandOutputSpool {
400
409
  if (this.finishing) return this.finishing;
401
410
  const stream = this.tempFileStream;
402
411
  this.tempFileStream = undefined;
412
+ if (this.tempFileError) {
413
+ this.finishing = Promise.reject(this.tempFileError);
414
+ return this.finishing;
415
+ }
403
416
  if (!stream) {
404
417
  this.finishing = Promise.resolve();
405
418
  return this.finishing;
@@ -423,7 +436,10 @@ export class CommandOutputSpool {
423
436
  private ensureTempFile(): void {
424
437
  if (this.tempFilePath) return;
425
438
  this.tempFilePath = tempFilePath(this.tempFilePrefix);
426
- const stream = createWriteStream(this.tempFilePath);
439
+ const stream = createWriteStream(this.tempFilePath, { mode: 0o600, flags: "wx" });
440
+ stream.once("open", () => {
441
+ this.tempFileCreated = true;
442
+ });
427
443
  stream.on("error", (error) => {
428
444
  this.tempFileError = error;
429
445
  });
@@ -9,6 +9,7 @@ import { DEFAULT_CONFIG } from "./config.ts";
9
9
  export type CommandRenderContext = {
10
10
  isError: boolean;
11
11
  isPartial: boolean;
12
+ outputPad: number;
12
13
  };
13
14
 
14
15
  export type CommandCallRenderContext = CommandRenderContext & {
@@ -223,6 +224,7 @@ export function renderCommandCall(
223
224
  theme,
224
225
  {
225
226
  background: resolveBackground,
227
+ outputPad: context.outputPad,
226
228
  status: context.isPartial ? "pending" : context.isError ? "error" : "success",
227
229
  top: true,
228
230
  bottom: context.isPartial && !context.executionStarted,
@@ -243,6 +245,7 @@ export function renderCommandResult(
243
245
  theme,
244
246
  {
245
247
  background: resolveBackground,
248
+ outputPad: context.outputPad,
246
249
  status: context.isPartial ? "pending" : context.isError ? "error" : "success",
247
250
  top: output.length > 0,
248
251
  bottom: true,
@@ -25,6 +25,7 @@ export const IMAGE_GENERATION_DETAILS_SCHEMA = {
25
25
  export type ImageGenerationDetails = Static<typeof IMAGE_GENERATION_DETAILS_SCHEMA>;
26
26
 
27
27
  type ImageGenerationRenderContext = {
28
+ outputPad: number;
28
29
  args: ImageGenerationParameters;
29
30
  isPartial: boolean;
30
31
  expanded: boolean;
@@ -150,6 +151,7 @@ export function renderImageGenerationCall(
150
151
  const summary = theme.fg("muted", describeImageCall(args));
151
152
  return new CodexToolSurfaceComponent(new Text(`${title} ${summary}`, 0, 0), theme, {
152
153
  background: resolveBackground,
154
+ outputPad: context.outputPad,
153
155
  status: context.isPartial ? "pending" : context.isError ? "error" : "success",
154
156
  top: true,
155
157
  bottom: context.isPartial,
@@ -171,6 +173,7 @@ export function renderImageGenerationResult(
171
173
  theme,
172
174
  {
173
175
  background: resolveBackground,
176
+ outputPad: context.outputPad,
174
177
  status: context.isError ? "error" : "success",
175
178
  top: false,
176
179
  bottom: true,
@@ -36,9 +36,14 @@ export type OutputLimitContinuationLifecycleHandler = (
36
36
  ctx: OutputLimitContinuationContext,
37
37
  ) => Promise<void> | void;
38
38
 
39
+ export type OutputLimitContinuationSettledHandler = (
40
+ event: { aborted: boolean },
41
+ ctx: OutputLimitContinuationContext,
42
+ ) => Promise<void> | void;
43
+
39
44
  export type OutputLimitContinuationApi = {
40
45
  onAgentEnd: (handler: OutputLimitContinuationAgentEndHandler) => void;
41
- onAgentSettled: (handler: OutputLimitContinuationLifecycleHandler) => void;
46
+ onAgentSettled: (handler: OutputLimitContinuationSettledHandler) => void;
42
47
  onSessionBeforeCompact: (handler: OutputLimitContinuationCompactionHandler) => void;
43
48
  onSessionCompact: (handler: OutputLimitContinuationLifecycleHandler) => void;
44
49
  onSessionShutdown: (handler: OutputLimitContinuationLifecycleHandler) => void;
@@ -66,7 +71,8 @@ export function outputLimitContinuationApi(pi: ExtensionAPI): OutputLimitContinu
66
71
  return {
67
72
  onAgentEnd: (handler) =>
68
73
  pi.on("agent_end", (event, ctx) => handler({ messages: event.messages }, context(ctx))),
69
- onAgentSettled: (handler) => pi.on("agent_settled", (_event, ctx) => handler(context(ctx))),
74
+ onAgentSettled: (handler) =>
75
+ pi.on("agent_settled", (event, ctx) => handler({ aborted: event.aborted }, context(ctx))),
70
76
  onSessionBeforeCompact: (handler) =>
71
77
  pi.on("session_before_compact", (event, ctx) =>
72
78
  handler({ signal: event.signal }, context(ctx)),
@@ -181,7 +187,7 @@ export default function registerOutputLimitContinuation(pi: OutputLimitContinuat
181
187
  if (recovery?.compaction === "started") recovery.compaction = "completed";
182
188
  });
183
189
 
184
- pi.onAgentSettled((ctx) => {
190
+ pi.onAgentSettled((event, ctx) => {
185
191
  const sessionId = ctx.sessionManager.getSessionId();
186
192
  const recovery = pendingRecoveries.get(sessionId);
187
193
  if (!recovery) return;
@@ -189,6 +195,7 @@ export default function registerOutputLimitContinuation(pi: OutputLimitContinuat
189
195
 
190
196
  const compactionFailed = recovery.compaction === "started";
191
197
  if (
198
+ event.aborted ||
192
199
  recovery.cancelled ||
193
200
  compactionFailed ||
194
201
  !ctx.isIdle() ||
@@ -31,7 +31,7 @@ export const SESSION_APIS = ["buildSessionProjection"] as const;
31
31
  */
32
32
  export const PI_099_APIS = ["SessionManager.getEntryCount", "ExtensionAPI.getSettings"] as const;
33
33
 
34
- export const MINIMUM_PI_VERSION = "1.0.0";
34
+ export const MINIMUM_PI_VERSION = "1.1.0";
35
35
  export const REQUIRED_PI = `Pi ${MINIMUM_PI_VERSION} or later`;
36
36
 
37
37
  function isFunction(value: unknown): boolean {
@@ -62,9 +62,9 @@ export function atLeastVersion(version: unknown, minimum: string): boolean {
62
62
  }
63
63
 
64
64
  /**
65
- * Require the Pi 0.99 host surface and a reported version of at least 1.0.0. The version comes
65
+ * Require the Pi 0.99 host surface and a reported version of at least 1.1.0. The version comes
66
66
  * from package metadata. The API checks detect missing capabilities, but cannot distinguish
67
- * a Pi 0.99 executable pointed at Pi 1.0.0 metadata through `PI_PACKAGE_DIR`.
67
+ * a Pi 0.99 executable pointed at Pi 1.1.0 metadata through `PI_PACKAGE_DIR`.
68
68
  */
69
69
  export function requirePiRuntime(
70
70
  transcriptApi: Record<string, unknown>,
@@ -36,6 +36,7 @@ type NullishOptionalProperties<Value> = Value extends readonly (infer Item)[]
36
36
  export type WebRunRenderCommands = NullishOptionalProperties<WebRunCommands>;
37
37
 
38
38
  type WebRunRenderContext = {
39
+ outputPad: number;
39
40
  args: WebRunRenderCommands;
40
41
  isPartial: boolean;
41
42
  expanded: boolean;
@@ -683,6 +684,7 @@ export function renderWebRunCall(
683
684
  const summary = theme.fg("muted", describeWebRunCall(args));
684
685
  return new CodexToolSurfaceComponent(new Text(`${title} ${summary}`, 0, 0), theme, {
685
686
  background: resolveBackground,
687
+ outputPad: context.outputPad,
686
688
  status: context.isPartial ? "pending" : context.isError ? "error" : "success",
687
689
  top: true,
688
690
  bottom: context.isPartial,
@@ -702,6 +704,7 @@ export function renderWebRunResult(
702
704
  theme,
703
705
  {
704
706
  background: resolveBackground,
707
+ outputPad: context.outputPad,
705
708
  status: context.isError ? "error" : "success",
706
709
  top: false,
707
710
  bottom: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-openai-codex-compat",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "OpenAI Codex compatibility for Pi with native compaction, fast mode, and Codex-optimized capabilities",
5
5
  "keywords": [
6
6
  "pi-package"
@@ -34,9 +34,8 @@
34
34
  ],
35
35
  "type": "module",
36
36
  "scripts": {
37
- "check": "hk check --all --check",
38
- "test": "node --test --test-concurrency=4 test/*.test.ts",
39
- "test:live:codex": "PI_CODEX_LIVE_TEST=1 node --test --test-concurrency=1 test/codex-host.live.test.ts test/codex-cli.live.test.ts test/command-render-cli.test.ts",
37
+ "test": "env -u PI_PACKAGE_DIR node --test --test-concurrency=4 test/*.test.ts",
38
+ "test:live:codex": "node scripts/test-live.ts",
40
39
  "pack:dry": "npm pack --dry-run --allow-directory=all",
41
40
  "release": "node scripts/release.ts",
42
41
  "fmt": "oxfmt",
@@ -49,22 +48,22 @@
49
48
  "tree-sitter-bash": "0.25.1"
50
49
  },
51
50
  "devDependencies": {
52
- "@2h2d/oxlint-config": "0.1.1",
51
+ "@2h2d/oxlint-config": "0.1.2",
53
52
  "@2h2d/ts-config": "0.0.1",
54
- "@earendil-works/pi-ai": "1.0.0",
55
- "@earendil-works/pi-coding-agent": "1.0.0",
56
- "@earendil-works/pi-tui": "1.0.0",
57
- "@types/node": "22.20.1",
58
- "oxfmt": "0.64.0",
59
- "oxlint": "1.79.0",
60
- "oxlint-tsgolint": "7.0.2001",
61
- "typebox": "1.3.16",
53
+ "@earendil-works/pi-ai": "1.1.0",
54
+ "@earendil-works/pi-coding-agent": "1.1.0",
55
+ "@earendil-works/pi-tui": "1.1.0",
56
+ "@types/node": "22.20.4",
57
+ "oxfmt": "0.70.0",
58
+ "oxlint": "1.85.0",
59
+ "oxlint-tsgolint": "7.0.2003",
60
+ "typebox": "1.3.34",
62
61
  "typescript": "7.0.2"
63
62
  },
64
63
  "peerDependencies": {
65
- "@earendil-works/pi-ai": ">=1.0.0 <1.1.0",
66
- "@earendil-works/pi-coding-agent": ">=1.0.0 <1.1.0",
67
- "@earendil-works/pi-tui": ">=1.0.0 <1.1.0",
64
+ "@earendil-works/pi-ai": ">=1.1.0 <1.2.0",
65
+ "@earendil-works/pi-coding-agent": ">=1.1.0 <1.2.0",
66
+ "@earendil-works/pi-tui": ">=1.1.0 <1.2.0",
68
67
  "typebox": "*"
69
68
  },
70
69
  "engines": {