@howaboua/pi-codex-conversion 1.5.7 → 1.5.8-dev.35.57ee19e

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
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.8
4
+
5
+ - Fixed native Responses compaction replay after compaction display messages so requests replace Pi placeholder compaction context with the native compacted window instead of failing parity checks.
6
+
3
7
  ## 1.5.7
4
8
 
5
9
  - Fixed OpenAI Codex custom-provider requests so synthetic `web.run` and `image_generation` adapter tools are rewritten to native Responses tool payloads before sending.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howaboua/pi-codex-conversion",
3
- "version": "1.5.7",
3
+ "version": "1.5.8-dev.35.57ee19e",
4
4
  "description": "Codex-oriented tool and prompt adapter for pi coding agent",
5
5
  "type": "module",
6
6
  "repository": {
@@ -71,6 +71,19 @@ export type NativeReplayPayloadRewriteResult =
71
71
  | NativeReplayPayloadRewrite
72
72
  | NativeReplayPayloadRewriteFailure;
73
73
 
74
+ type ReplayMessageSet = {
75
+ messages: AgentMessage[];
76
+ input: ResponsesInputItem[];
77
+ };
78
+
79
+ type ReplayMatch = {
80
+ originalPiReplayInput: ResponsesInputItem[];
81
+ preCompactionKept: ReplayMessageSet;
82
+ postCompactionTail: ReplayMessageSet;
83
+ actualPostCompactionTail: ResponsesInputItem[];
84
+ extraPostCompactionTail: ResponsesInputItem[];
85
+ };
86
+
74
87
  function isRecord(value: unknown): value is Record<string, unknown> {
75
88
  return !!value && typeof value === "object" && !Array.isArray(value);
76
89
  }
@@ -269,6 +282,13 @@ function toReplayAgentMessage(entry: SessionEntry): AgentMessage | undefined {
269
282
  return undefined;
270
283
  }
271
284
 
285
+ function toPiReplayAgentMessage(entry: SessionEntry): AgentMessage | undefined {
286
+ if (entry.type === "message") return toSessionMessage(entry);
287
+ if (entry.type === "custom_message") return toCustomMessage(entry);
288
+ if (entry.type === "branch_summary") return toBranchSummaryMessage(entry);
289
+ return undefined;
290
+ }
291
+
272
292
  function isPromptEnvelopeItem(item: unknown): item is ResponsesInputMessageItem {
273
293
  return isResponsesInputMessageItem(item) && isPreambleRole(item.role);
274
294
  }
@@ -322,6 +342,15 @@ export function collectReplayMessages(entries: readonly SessionEntry[]): AgentMe
322
342
  return messages;
323
343
  }
324
344
 
345
+ function collectPiReplayMessages(entries: readonly SessionEntry[]): AgentMessage[] {
346
+ const messages: AgentMessage[] = [];
347
+ for (const entry of entries) {
348
+ const message = toPiReplayAgentMessage(entry);
349
+ if (message) messages.push(message);
350
+ }
351
+ return messages;
352
+ }
353
+
325
354
  function createCompactionSummaryAgentMessage(entry: NativeCompactionEntry): AgentMessage {
326
355
  return {
327
356
  role: "compactionSummary",
@@ -343,6 +372,66 @@ function createReplaySlice(
343
372
  };
344
373
  }
345
374
 
375
+ function createReplayMessageSet<TApi extends Api>(model: Model<TApi>, messages: AgentMessage[]): ReplayMessageSet {
376
+ return {
377
+ messages,
378
+ input: serializeMessagesToResponsesInput(model, messages),
379
+ };
380
+ }
381
+
382
+ function createReplayVariants<TApi extends Api>(args: {
383
+ model: Model<TApi>;
384
+ entries: readonly SessionEntry[];
385
+ }): ReplayMessageSet[] {
386
+ const contextMessages = collectReplayMessages(args.entries);
387
+ const piMessages = collectPiReplayMessages(args.entries);
388
+ const contextSet = createReplayMessageSet(args.model, contextMessages);
389
+ if (areEquivalentValues(contextMessages, piMessages)) return [contextSet];
390
+ return [contextSet, createReplayMessageSet(args.model, piMessages)];
391
+ }
392
+
393
+ function findReplayMatch<TApi extends Api>(args: {
394
+ model: Model<TApi>;
395
+ payloadInput: readonly unknown[];
396
+ freshPreamble: FreshAuthoritativePreamble;
397
+ compactionSummaryMessage: AgentMessage;
398
+ preCompactionEntries: readonly SessionEntry[];
399
+ postCompactionEntries: readonly SessionEntry[];
400
+ }): ReplayMatch | undefined {
401
+ const compactionSummaryInput = serializeMessagesToResponsesInput(args.model, [args.compactionSummaryMessage]);
402
+ const preCompactionVariants = createReplayVariants({ model: args.model, entries: args.preCompactionEntries });
403
+ const postCompactionVariants = createReplayVariants({ model: args.model, entries: args.postCompactionEntries });
404
+
405
+ for (const preCompactionKept of preCompactionVariants) {
406
+ for (const postCompactionTail of postCompactionVariants) {
407
+ const expectedBeforeTrailing: ResponsesInputItem[] = [
408
+ ...args.freshPreamble.leadingInput,
409
+ ...compactionSummaryInput,
410
+ ...preCompactionKept.input,
411
+ ...postCompactionTail.input,
412
+ ];
413
+ const originalPiReplayInput: ResponsesInputItem[] = [...expectedBeforeTrailing, ...args.freshPreamble.trailingInput];
414
+ const tailEndIndex = args.payloadInput.length - args.freshPreamble.trailingInput.length;
415
+ const prefixMatches = areEquivalentValues(args.payloadInput.slice(0, expectedBeforeTrailing.length), expectedBeforeTrailing);
416
+ const trailingMatches = areEquivalentValues(args.payloadInput.slice(tailEndIndex), args.freshPreamble.trailingInput);
417
+
418
+ if (prefixMatches && trailingMatches && tailEndIndex >= expectedBeforeTrailing.length) {
419
+ const actualPostCompactionTail = cloneResponsesInputSlice(
420
+ args.payloadInput.slice(
421
+ args.freshPreamble.leadingInput.length + compactionSummaryInput.length + preCompactionKept.input.length,
422
+ tailEndIndex,
423
+ ),
424
+ );
425
+ const extraPostCompactionTail = cloneResponsesInputSlice(args.payloadInput.slice(expectedBeforeTrailing.length, tailEndIndex));
426
+ if (!actualPostCompactionTail || !extraPostCompactionTail) return undefined;
427
+ return { originalPiReplayInput, preCompactionKept, postCompactionTail, actualPostCompactionTail, extraPostCompactionTail };
428
+ }
429
+ }
430
+ }
431
+
432
+ return undefined;
433
+ }
434
+
346
435
  function findEntryIndexByIdBeforeBoundary(
347
436
  entries: readonly SessionEntry[],
348
437
  entryId: string,
@@ -437,22 +526,27 @@ function buildNativeReplaySegmentsInternal<TApi extends Api>(args: {
437
526
 
438
527
  const preCompactionEntries = args.branchEntries.slice(firstKeptEntryIndex, boundaryIndex);
439
528
  const postCompactionEntries = args.branchEntries.slice(boundaryIndex + 1);
440
- const preCompactionKeptMessages = collectReplayMessages(preCompactionEntries);
441
- const postCompactionTailMessages = collectReplayMessages(postCompactionEntries);
529
+ const contextPostCompactionTailMessages = collectReplayMessages(postCompactionEntries);
442
530
  const compactionSummaryMessage = createCompactionSummaryAgentMessage(args.compactionEntry);
443
- const serializedPiHistoryInput = serializeMessagesToResponsesInput(args.model, [
531
+ const replayMatch = findReplayMatch({
532
+ model: args.model,
533
+ payloadInput: args.payload.input,
534
+ freshPreamble,
444
535
  compactionSummaryMessage,
445
- ...preCompactionKeptMessages,
446
- ...postCompactionTailMessages,
447
- ]);
448
- const originalPiReplayInput: ResponsesInputItem[] = [
449
- ...freshPreamble.leadingInput,
450
- ...serializedPiHistoryInput,
451
- ...freshPreamble.trailingInput,
452
- ];
453
-
454
- if (!areEquivalentValues(args.payload.input, originalPiReplayInput)) {
455
- const parity = compareResponsesInputParity(args.payload.input, originalPiReplayInput);
536
+ preCompactionEntries,
537
+ postCompactionEntries,
538
+ });
539
+
540
+ if (!replayMatch) {
541
+ const compactionSummaryInput = serializeMessagesToResponsesInput(args.model, [compactionSummaryMessage]);
542
+ const expectedInput = [
543
+ ...freshPreamble.leadingInput,
544
+ ...compactionSummaryInput,
545
+ ...serializeMessagesToResponsesInput(args.model, collectReplayMessages(preCompactionEntries)),
546
+ ...serializeMessagesToResponsesInput(args.model, collectReplayMessages(postCompactionEntries)),
547
+ ...freshPreamble.trailingInput,
548
+ ];
549
+ const parity = compareResponsesInputParity(args.payload.input, expectedInput);
456
550
  return {
457
551
  ok: false,
458
552
  reason: "expected-pi-replay-mismatch",
@@ -467,7 +561,7 @@ function buildNativeReplaySegmentsInternal<TApi extends Api>(args: {
467
561
  const freshPreambleCount = freshPreamble.leadingInput.length;
468
562
  const trailingPreambleCount = freshPreamble.trailingInput.length;
469
563
  const compactionSummaryCount = serializeMessagesToResponsesInput(args.model, [compactionSummaryMessage]).length;
470
- const preCompactionKeptCount = serializeMessagesToResponsesInput(args.model, preCompactionKeptMessages).length;
564
+ const preCompactionKeptCount = replayMatch.preCompactionKept.input.length;
471
565
  const tailStartIndex = freshPreambleCount + compactionSummaryCount + preCompactionKeptCount;
472
566
  const tailEndIndex = args.payload.input.length - trailingPreambleCount;
473
567
  const actualCompactionSummary = cloneResponsesInputSlice(
@@ -479,7 +573,11 @@ function buildNativeReplaySegmentsInternal<TApi extends Api>(args: {
479
573
  freshPreambleCount + compactionSummaryCount + preCompactionKeptCount,
480
574
  ),
481
575
  );
482
- const actualPostCompactionTail = cloneResponsesInputSlice(args.payload.input.slice(tailStartIndex, tailEndIndex));
576
+ const actualPostCompactionTail = replayMatch.actualPostCompactionTail;
577
+ const contextPostCompactionTail = [
578
+ ...serializeMessagesToResponsesInput(args.model, contextPostCompactionTailMessages),
579
+ ...replayMatch.extraPostCompactionTail,
580
+ ];
483
581
  if (!actualCompactionSummary || !actualPreCompactionKeptWindow || !actualPostCompactionTail) {
484
582
  return {
485
583
  ok: false,
@@ -489,13 +587,13 @@ function buildNativeReplaySegmentsInternal<TApi extends Api>(args: {
489
587
 
490
588
  const preCompactionKeptWindow = createReplaySlice(
491
589
  preCompactionEntries,
492
- preCompactionKeptMessages,
590
+ replayMatch.preCompactionKept.messages,
493
591
  actualPreCompactionKeptWindow,
494
592
  );
495
593
  const postCompactionTail = createReplaySlice(
496
594
  postCompactionEntries,
497
- postCompactionTailMessages,
498
- actualPostCompactionTail,
595
+ contextPostCompactionTailMessages,
596
+ contextPostCompactionTail,
499
597
  );
500
598
 
501
599
  return {
@@ -510,11 +608,11 @@ function buildNativeReplaySegmentsInternal<TApi extends Api>(args: {
510
608
  preCompactionKeptWindow,
511
609
  compactedWindow,
512
610
  postCompactionTail,
513
- originalPiReplayInput,
611
+ originalPiReplayInput: replayMatch.originalPiReplayInput,
514
612
  replayInput: [
515
613
  ...freshPreamble.leadingInput,
516
614
  ...compactedWindow,
517
- ...actualPostCompactionTail,
615
+ ...contextPostCompactionTail,
518
616
  ...freshPreamble.trailingInput,
519
617
  ],
520
618
  },
@@ -524,7 +622,7 @@ function buildNativeReplaySegmentsInternal<TApi extends Api>(args: {
524
622
  input: [
525
623
  ...freshPreamble.leadingInput,
526
624
  ...compactedWindow,
527
- ...actualPostCompactionTail,
625
+ ...contextPostCompactionTail,
528
626
  ...freshPreamble.trailingInput,
529
627
  ],
530
628
  },