@cortexkit/pi-magic-context 0.49.14 → 0.49.16

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 (42) hide show
  1. package/dist/auto-search-worker.js +3 -3
  2. package/dist/chunk-embedding-write-worker.js +8 -6
  3. package/dist/{embedding-backfill-7kj16fh9.js → embedding-backfill-c4bdw8pp.js} +10 -8
  4. package/dist/embedding-worker.js +2 -2
  5. package/dist/historian-calibration-extension.js +15 -103
  6. package/dist/index-1cvyaw9a.js +58 -0
  7. package/dist/{index-65kty5te.js → index-4178cbfw.js} +20 -69
  8. package/dist/{index-75ah9413.js → index-44h64qza.js} +3 -3
  9. package/dist/{index-9jvktm7k.js → index-657xh9w4.js} +1 -1
  10. package/dist/{index-7qc73yk5.js → index-afy3dzf9.js} +3 -3
  11. package/dist/{index-y29y2j2w.js → index-ajfpyk0x.js} +164 -11
  12. package/dist/{index-1k729e4f.js → index-bxmf4dhr.js} +6 -6
  13. package/dist/{index-j0n09wtp.js → index-dne4ja7a.js} +7 -5
  14. package/dist/{index-a4pk5yv9.js → index-fhyy4ave.js} +14 -14
  15. package/dist/index-ja1c33qa.js +62 -0
  16. package/dist/{index-1mrvw9en.js → index-mx59cve4.js} +1 -1
  17. package/dist/{index-nwbhe6qv.js → index-n3r2d2pr.js} +5 -5
  18. package/dist/{index-7wagp5jp.js → index-p3evwech.js} +3 -3
  19. package/dist/{index-he9s4qsj.js → index-qqxqwqhp.js} +22 -2
  20. package/dist/{index-djxc8w8c.js → index-s1xn8qfw.js} +21 -25
  21. package/dist/{index-bet4sd3e.js → index-tympym62.js} +1 -1
  22. package/dist/{index-ccsscaap.js → index-v8d4vgam.js} +37 -16
  23. package/dist/index-wrr9rp9a.js +16 -0
  24. package/dist/{index-1vw4f2pe.js → index-x3k1530z.js} +5 -7
  25. package/dist/{index-0awvkeb5.js → index-xmzhrht0.js} +10 -61
  26. package/dist/{index-6ex901g3.js → index-y5c73caa.js} +2 -2
  27. package/dist/index.js +787 -271
  28. package/dist/message-fts-rowid-map-mbanfkt1.js +22 -0
  29. package/dist/{message-index-bounded-z4d3x9ty.js → message-index-bounded-xzerjxmp.js} +7 -7
  30. package/dist/{message-index-dw4z9efj.js → message-index-easvmz22.js} +8 -8
  31. package/dist/{message-time-backfill-r2ar1qvk.js → message-time-backfill-3q4kemfc.js} +4 -4
  32. package/dist/migration-worker.js +6 -4
  33. package/dist/{project-embedding-registry-52zwmtbn.js → project-embedding-registry-xwnmqmx8.js} +9 -7
  34. package/dist/raw-ordinal-warmup-worker.js +37 -7
  35. package/dist/{read-session-chunk-0fsgg2k1.js → read-session-chunk-1sb5n7zs.js} +5 -5
  36. package/dist/{read-session-raw-azkqjgzg.js → read-session-raw-jz5e9jz0.js} +1 -1
  37. package/dist/search-archive-3ma5n0wr.js +20 -0
  38. package/dist/{search-ddbz6v60.js → search-x3fa0561.js} +16 -15
  39. package/dist/{storage-tags-3kb5tvgg.js → storage-tags-jtessrec.js} +1 -1
  40. package/dist/subagent-entry.js +19 -17
  41. package/dist/tag-snapshot-worker-pi.js +15 -18
  42. package/package.json +3 -1
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  claimConfigParseFailuresOnce,
28
28
  parseJsoncRecovering,
29
29
  detectConfigFile,
30
+ OPENCODE_OUTPUT_CAP,
30
31
  MIN_PLAUSIBLE_CONTEXT_LIMIT,
31
32
  catalogOutputReserve,
32
33
  deriveWindowGeometry,
@@ -247,7 +248,7 @@ import {
247
248
  registerTodoStateLifecycle,
248
249
  syncCtxMemoryToolEnabled,
249
250
  registerMagicContextTools
250
- } from "./index-65kty5te.js";
251
+ } from "./index-4178cbfw.js";
251
252
  import {
252
253
  canonicalModelIdentity,
253
254
  piModelRefToCanonical,
@@ -264,7 +265,7 @@ import {
264
265
  DEFAULT_HISTORIAN_TIMEOUT_MS,
265
266
  DREAM_TASK_PROMOTION_DEFAULTS,
266
267
  LIVE_RELOAD_CONFIG_PATHS
267
- } from "./index-1k729e4f.js";
268
+ } from "./index-bxmf4dhr.js";
268
269
  import {
269
270
  FAIL_CLOSED_DOCTOR_COMMAND,
270
271
  formatFailClosedBlockingMessage,
@@ -287,7 +288,7 @@ import {
287
288
  openCurrentDatabase,
288
289
  openDatabaseAsync,
289
290
  closeDatabase
290
- } from "./index-ccsscaap.js";
291
+ } from "./index-v8d4vgam.js";
291
292
  import {
292
293
  setHomeProjectPermission,
293
294
  ProjectIdentityError,
@@ -298,7 +299,7 @@ import {
298
299
  resolveProjectIdentityForSession,
299
300
  beginBootQuietPeriod,
300
301
  scheduleAfterBootQuiet
301
- } from "./index-6ex901g3.js";
302
+ } from "./index-y5c73caa.js";
302
303
  import {
303
304
  detectThinkingBindingMismatch,
304
305
  detectLatestTurnThinkingMismatch,
@@ -457,7 +458,7 @@ import {
457
458
  getRawSessionTagKeysThrough2,
458
459
  getLegacyProtectedTailStartOrdinal2,
459
460
  readSessionChunk2
460
- } from "./index-75ah9413.js";
461
+ } from "./index-44h64qza.js";
461
462
  import {
462
463
  UNKNOWN_FIT_RATIO,
463
464
  hasMeasuredDecisionCalibration,
@@ -544,7 +545,7 @@ import {
544
545
  getToolTagNumberByOwner2,
545
546
  getNullOwnerToolTag2,
546
547
  adoptNullOwnerToolTag2
547
- } from "./index-j0n09wtp.js";
548
+ } from "./index-dne4ja7a.js";
548
549
  import {
549
550
  textMentionsRecentCommit,
550
551
  hasMeaningfulUserText2,
@@ -590,7 +591,7 @@ import"./index-399p688g.js";
590
591
  import {
591
592
  runSessionWarmupWorker,
592
593
  RAW_SUMMARY_TEXT_MAX_CHARS2
593
- } from "./index-he9s4qsj.js";
594
+ } from "./index-qqxqwqhp.js";
594
595
  import {
595
596
  piHarnessKindFromExecutable
596
597
  } from "./index-apgwdby5.js";
@@ -616,13 +617,11 @@ import {
616
617
  indexSingleMessage2,
617
618
  indexMessagesAfterOrdinal2,
618
619
  sweepOrphanedOpenCodeMessageIndexes2
619
- } from "./index-a4pk5yv9.js";
620
+ } from "./index-fhyy4ave.js";
620
621
  import {
621
622
  formatSynapseLaneDescriptor
622
623
  } from "./index-6dz2ed1v.js";
623
- import {
624
- sameProjectDirectory
625
- } from "./index-djxc8w8c.js";
624
+ import"./index-s1xn8qfw.js";
626
625
  import {
627
626
  buildCanonicalChunkTextFromFts,
628
627
  buildCompartmentSummaryFallbackText,
@@ -632,7 +631,7 @@ import {
632
631
  replaceCompartmentChunkEmbeddings,
633
632
  deleteChunkEmbedBackoffForSession,
634
633
  chunkWindowSourceKey
635
- } from "./index-7qc73yk5.js";
634
+ } from "./index-afy3dzf9.js";
636
635
  import {
637
636
  recordSessionProjectIdentity,
638
637
  GIT_SWEEP_LEASE_RENEWAL_MS,
@@ -641,7 +640,7 @@ import {
641
640
  markGitSweepSuccessAndRelease,
642
641
  parkGitSweepNonIndexable,
643
642
  releaseGitSweepLease
644
- } from "./index-1mrvw9en.js";
643
+ } from "./index-mx59cve4.js";
645
644
  import {
646
645
  embedPauseBySession,
647
646
  embedRunStateBySession,
@@ -667,7 +666,7 @@ import {
667
666
  embedSessionCompartmentChunks2,
668
667
  getEmbeddingCoverageStatus2,
669
668
  getAutoEmbeddingSessionCoverage2
670
- } from "./index-nwbhe6qv.js";
669
+ } from "./index-n3r2d2pr.js";
671
670
  import {
672
671
  rememberV1HiddenRun
673
672
  } from "./index-6x556c2q.js";
@@ -682,7 +681,7 @@ import {
682
681
  expandWorkspaceIdentitySetWithAliases,
683
682
  sourceNameForMemory,
684
683
  computeWorkspaceEpochFingerprint
685
- } from "./index-bet4sd3e.js";
684
+ } from "./index-tympym62.js";
686
685
  import {
687
686
  configureContextDatabasePragmas2
688
687
  } from "./index-fapenpch.js";
@@ -732,7 +731,7 @@ import {
732
731
  normalizeVerificationFiles,
733
732
  indexCommitsForProject,
734
733
  embedUnembeddedCommits
735
- } from "./index-0awvkeb5.js";
734
+ } from "./index-xmzhrht0.js";
736
735
  import {
737
736
  setEmbeddingSessionBusy2,
738
737
  isEmbeddingHostBusy2
@@ -763,19 +762,21 @@ import {
763
762
  import {
764
763
  pushNotification2
765
764
  } from "./index-q1yc6bs0.js";
766
- import"./index-9jvktm7k.js";
765
+ import"./index-657xh9w4.js";
767
766
  import {
768
767
  cosineSimilarity
769
- } from "./index-7wagp5jp.js";
768
+ } from "./index-p3evwech.js";
770
769
  import"./index-46q4e104.js";
771
770
  import {
772
771
  DREAMER_PRIMER_INVESTIGATOR_ALLOWED_TOOLS,
773
772
  buildHiddenAgentRegistrations,
774
773
  logTemperatureDecision,
774
+ readHostSystemPrompt,
775
775
  subagentStepCap,
776
776
  SubagentTelemetry,
777
- readHostSystemPrompt
778
- } from "./index-y29y2j2w.js";
777
+ HISTORIAN_MAX_OUTPUT_TOKENS_ENV2,
778
+ SUBAGENT_OUTPUT_CEILING_ENV2
779
+ } from "./index-ajfpyk0x.js";
779
780
  import {
780
781
  PiTagHydrationError,
781
782
  getPiTagSnapshotView,
@@ -786,8 +787,10 @@ import {
786
787
  drainPiTagSnapshotSession,
787
788
  assertPiTagSnapshotReady,
788
789
  ensurePiTagSnapshotReady
789
- } from "./index-1vw4f2pe.js";
790
+ } from "./index-x3k1530z.js";
790
791
  import"./index-f18ec69t.js";
792
+ import"./index-1cvyaw9a.js";
793
+ import"./index-ja1c33qa.js";
791
794
  import {
792
795
  __toESM
793
796
  } from "./index-22jkk6wg.js";
@@ -797,6 +800,9 @@ import {
797
800
  import {
798
801
  normalizeProtectedToolName
799
802
  } from "./index-674f6qs2.js";
803
+ import {
804
+ sameProjectDirectory
805
+ } from "./index-wrr9rp9a.js";
800
806
  import {
801
807
  logSlowWriteTransaction,
802
808
  WriteTransactionSteps
@@ -3506,7 +3512,7 @@ function startHostStallProfilerSwitch() {
3506
3512
  // package.json
3507
3513
  var package_default = {
3508
3514
  name: "@cortexkit/pi-magic-context",
3509
- version: "0.49.14",
3515
+ version: "0.49.16",
3510
3516
  type: "module",
3511
3517
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
3512
3518
  main: "dist/index.js",
@@ -3570,10 +3576,12 @@ var package_default = {
3570
3576
  "@types/better-sqlite3": "^7.6.13",
3571
3577
  "@types/bun": "^1.3.10",
3572
3578
  "@types/node": "^22.20.0",
3579
+ "omp-coding-agent-1812": "npm:@oh-my-pi/pi-coding-agent@18.12.3",
3573
3580
  "pi-agent-core-087": "npm:@earendil-works/pi-agent-core@0.87.1",
3574
3581
  "pi-ai-086": "npm:@earendil-works/pi-ai@0.86.0",
3575
3582
  "pi-coding-agent-086": "npm:@earendil-works/pi-coding-agent@0.86.0",
3576
3583
  "pi-coding-agent-087": "npm:@earendil-works/pi-coding-agent@0.87.1",
3584
+ "pi-coding-agent-130": "npm:@earendil-works/pi-coding-agent@1.3.0",
3577
3585
  typebox: "^1.3.1",
3578
3586
  typescript: "^5.8.0"
3579
3587
  },
@@ -4690,6 +4698,7 @@ var AGENT_STEPS = {
4690
4698
  [DREAMER_PRIMER_INVESTIGATOR_AGENT]: 40,
4691
4699
  [DREAMER_RETROSPECTIVE_AGENT]: 40
4692
4700
  };
4701
+ var DISPOSED_CHILDREN_KEY = Symbol.for("@cortexkit/magic-context/v2/disposed-hidden-children");
4693
4702
  class HiddenAgentStepLimit extends Error {
4694
4703
  agent;
4695
4704
  cap;
@@ -5030,14 +5039,14 @@ function throwWithPromptFailure(legacyError, failedAttempts, args, timeoutMs, tr
5030
5039
  });
5031
5040
  throw error;
5032
5041
  }
5033
- async function attemptOnce(client, args, timeoutMs, signal, callContext, label, transport) {
5042
+ async function attemptOnce(client, args, timeoutMs, signal, callContext, label, transport, allowModelSuggestions = true) {
5034
5043
  const originalBody = { ...args.body };
5035
5044
  const attemptArgs = copyPromptArgs(args, originalBody);
5036
5045
  try {
5037
5046
  await promptWithTimeout(client, attemptArgs, timeoutMs, signal, transport);
5038
5047
  return;
5039
5048
  } catch (error) {
5040
- if (isNonRetryable(error, signal))
5049
+ if (isNonRetryable(error, signal) || !allowModelSuggestions)
5041
5050
  throw error;
5042
5051
  const suggestion = parseModelSuggestion(error);
5043
5052
  if (!suggestion || !originalBody.model) {
@@ -5065,7 +5074,7 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
5065
5074
  const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
5066
5075
  let lastError = null;
5067
5076
  try {
5068
- await attemptOnce(client, baseArgs, timeoutMs, options.signal, callContext, explicitPrimaryLabel, options.transport);
5077
+ await attemptOnce(client, baseArgs, timeoutMs, options.signal, callContext, explicitPrimaryLabel, options.transport, options.allowModelSuggestions);
5069
5078
  return;
5070
5079
  } catch (error) {
5071
5080
  lastError = error;
@@ -5091,7 +5100,7 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
5091
5100
  ...fallback?.qualifier ? { variant: fallback.qualifier } : {}
5092
5101
  });
5093
5102
  try {
5094
- await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label, options.transport);
5103
+ await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label, options.transport, options.allowModelSuggestions);
5095
5104
  log2(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
5096
5105
  return;
5097
5106
  } catch (error) {
@@ -5109,7 +5118,7 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
5109
5118
  }
5110
5119
  async function attemptAndValidate(client, args, timeoutMs, signal, callContext, attempt, options) {
5111
5120
  try {
5112
- await attemptOnce(client, args, timeoutMs, signal, callContext, attempt.label, options.transport);
5121
+ await attemptOnce(client, args, timeoutMs, signal, callContext, attempt.label, options.transport, options.allowModelSuggestions);
5113
5122
  } catch (error) {
5114
5123
  throw {
5115
5124
  error,
@@ -5915,6 +5924,7 @@ Examples:
5915
5924
  - Every displayed raw message ordinal MUST appear in exactly one compartment. Gaps between compartments are invalid. When a displayed block is pure tool-only noise with no narrative text, do NOT skip it — extend the preceding compartment's \`end\` to absorb the range, or fold it into the current compartment if it's part of an ongoing work unit. Never create a dedicated compartment just to cover a tool-only run.
5916
5925
  - If a chunk is entirely tool-only with no narrative text (a long autonomous coding stretch), produce a single compartment whose narrative is derived from what the tools collectively accomplished.
5917
5926
  - If the chunk ends mid-topic, leave the unfinished portion out and report its first message index in \`<unprocessed_from>\`.
5927
+ - If every message in the chunk is covered by a compartment, nothing is unprocessed: set \`<unprocessed_from>\` to the chunk's last message index + 1. Never write \`0\` or the last covered index in that case.
5918
5928
 
5919
5929
  ---
5920
5930
 
@@ -6869,6 +6879,7 @@ function buildHistorianRepairPrompt(originalPrompt, previousOutput, validationEr
6869
6879
  "Return a corrected full XML response for the same existing state and new messages.",
6870
6880
  "Do not skip any displayed raw ordinal or displayed raw range, even if the message looks trivial.",
6871
6881
  "Every displayed message range must belong to exactly one compartment unless it is intentionally left in one trailing suffix marked by <unprocessed_from>.",
6882
+ "If every message in the chunk is covered by a compartment, nothing is unprocessed: set `<unprocessed_from>` to the chunk's last message index + 1.",
6872
6883
  "",
6873
6884
  "Previous invalid XML:",
6874
6885
  previousOutput
@@ -6920,16 +6931,19 @@ function validateParsedCompartments(compartments, chunkStart, chunkEnd, unproces
6920
6931
  expectedStart = compartment.endMessage + 1;
6921
6932
  }
6922
6933
  if (unprocessedFrom !== null) {
6934
+ if (expectedStart <= chunkEnd) {
6935
+ if (unprocessedFrom !== expectedStart) {
6936
+ return `<unprocessed_from> ${unprocessedFrom} does not match next uncovered message ${expectedStart}`;
6937
+ }
6938
+ return null;
6939
+ }
6923
6940
  if (unprocessedFrom === chunkEnd + 1) {
6924
6941
  return null;
6925
6942
  }
6926
6943
  if (unprocessedFrom < chunkStart || unprocessedFrom > chunkEnd) {
6927
6944
  return `<unprocessed_from> ${unprocessedFrom} is outside chunk ${chunkStart}-${chunkEnd}`;
6928
6945
  }
6929
- if (unprocessedFrom !== expectedStart) {
6930
- return `<unprocessed_from> ${unprocessedFrom} does not match next uncovered message ${expectedStart}`;
6931
- }
6932
- return null;
6946
+ return `<unprocessed_from> ${unprocessedFrom} does not match completed chunk boundary ${chunkEnd + 1}`;
6933
6947
  }
6934
6948
  if (expectedStart <= chunkEnd) {
6935
6949
  return `output left uncovered messages ${expectedStart}-${chunkEnd} without <unprocessed_from>`;
@@ -9427,6 +9441,7 @@ async function runHistorianPrompt(args) {
9427
9441
  return executor.attempt(opened, request);
9428
9442
  }, { childSessionId: opened.childSessionId }),
9429
9443
  timeoutMs: timeoutMs ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
9444
+ allowModelSuggestions: false,
9430
9445
  fallbackModels: modelOverride ? undefined : fallbackModels,
9431
9446
  callContext: agentId === HISTORIAN_EDITOR_AGENT ? "historian:editor" : "historian"
9432
9447
  });
@@ -9511,7 +9526,7 @@ async function runFallbackHistorianPass(args) {
9511
9526
  const primary = toModelEntry(args.model);
9512
9527
  for (const candidateInput of [
9513
9528
  ...args.fallbackModels ?? [],
9514
- ...args.fallbackModelId ? [{ model: args.fallbackModelId }] : []
9529
+ ...!primary && args.fallbackModelId ? [{ model: args.fallbackModelId }] : []
9515
9530
  ]) {
9516
9531
  const candidate = toModelEntry(candidateInput);
9517
9532
  if (!candidate)
@@ -16463,6 +16478,7 @@ var VERIFY_BATCH_SIZE = 5;
16463
16478
  var VERIFY_TOKENS_PER_MEMORY = 1e5;
16464
16479
  var VERIFY_RUN_TOKEN_BUDGET = 2500000;
16465
16480
  var VERIFY_RUN_SLICE_MS = 240000;
16481
+ var VERIFY_IN_FLIGHT_GRACE_MS = 120000;
16466
16482
  function verifyBatchTokenBudget(size, configured) {
16467
16483
  return Math.min(configured ?? Number.MAX_SAFE_INTEGER, size * VERIFY_TOKENS_PER_MEMORY);
16468
16484
  }
@@ -16549,7 +16565,15 @@ async function runVerifyWithCooldown(args) {
16549
16565
  const runTokenBudget = Math.min(args.tokenBudget ?? VERIFY_RUN_TOKEN_BUDGET, VERIFY_RUN_TOKEN_BUDGET);
16550
16566
  try {
16551
16567
  for (let i = 0;i < batches.length; i += 1) {
16552
- const remainingMs = Math.max(0, Math.min(args.deadline, sliceDeadline) - Date.now());
16568
+ const now = Date.now();
16569
+ const startCutoff = Math.min(args.deadline, sliceDeadline);
16570
+ const hardStop = Math.min(args.deadline, sliceDeadline + VERIFY_IN_FLIGHT_GRACE_MS);
16571
+ const remainingMs = Math.max(0, hardStop - now);
16572
+ if (now >= startCutoff) {
16573
+ result.stopReason = "deadline";
16574
+ log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: stopping before batch ${i + 1}/${batches.length} — the run deadline passed ${now - startCutoff}ms ago`);
16575
+ break;
16576
+ }
16553
16577
  if (remainingMs < VERIFY_BATCH_FLOOR_MS) {
16554
16578
  result.stopReason = "deadline";
16555
16579
  log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: stopping before batch ${i + 1}/${batches.length} — remaining budget ${remainingMs}ms is below the ${VERIFY_BATCH_FLOOR_MS}ms batch floor`);
@@ -19894,6 +19918,7 @@ import { createInterface } from "node:readline";
19894
19918
  import { StringDecoder } from "node:string_decoder";
19895
19919
  import { fileURLToPath } from "node:url";
19896
19920
  var PI_CODING_AGENT_MODULE = "@earendil-works/pi-coding-agent";
19921
+ var HIDDEN_CHILD_OUTPUT_CEILING = OPENCODE_OUTPUT_CAP;
19897
19922
  var PI_CODING_AGENT_PACKAGE_NAMES = new Set([
19898
19923
  PI_CODING_AGENT_MODULE,
19899
19924
  "@oh-my-pi/pi-coding-agent"
@@ -20631,6 +20656,8 @@ class PiSubagentRunner {
20631
20656
  let child;
20632
20657
  const parentEnv = { ...process.env };
20633
20658
  delete parentEnv.MAGIC_CONTEXT_HISTORIAN_TEMPERATURE;
20659
+ delete parentEnv[HISTORIAN_MAX_OUTPUT_TOKENS_ENV2];
20660
+ delete parentEnv[SUBAGENT_OUTPUT_CEILING_ENV2];
20634
20661
  try {
20635
20662
  child = inRootAsyncContext2(() => this.spawnImpl(this.invocation.command, [...this.invocation.prefixArgs, ...this.extraArgs, ...args], {
20636
20663
  windowsHide: true,
@@ -20645,8 +20672,10 @@ class PiSubagentRunner {
20645
20672
  MAGIC_CONTEXT_HISTORIAN_TEMPERATURE: String(options.temperature)
20646
20673
  } : {},
20647
20674
  ...options.maxOutputTokens !== undefined ? {
20648
- MAGIC_CONTEXT_HISTORIAN_MAX_OUTPUT_TOKENS: String(options.maxOutputTokens)
20649
- } : {}
20675
+ [HISTORIAN_MAX_OUTPUT_TOKENS_ENV2]: String(options.maxOutputTokens)
20676
+ } : {
20677
+ [SUBAGENT_OUTPUT_CEILING_ENV2]: String(HIDDEN_CHILD_OUTPUT_CEILING)
20678
+ }
20650
20679
  },
20651
20680
  stdio: [
20652
20681
  deliverViaStdin || rpcBudget ? "pipe" : "ignore",
@@ -28561,7 +28590,7 @@ async function runHistorianSubagentWithTransientRetriesGuarded(args) {
28561
28590
  }
28562
28591
  return historianAbortResult(startedAt);
28563
28592
  }
28564
- function buildHistorianFallbackChain(primaryModel, primaryThinkingLevel, fallbackModels, fallbackModelId) {
28593
+ function buildHistorianFallbackChain(primaryModel, primaryThinkingLevel, fallbackModels) {
28565
28594
  const seen = new Set([
28566
28595
  `${primaryModel}\x00${primaryThinkingLevel ?? ""}`
28567
28596
  ]);
@@ -28572,13 +28601,7 @@ function buildHistorianFallbackChain(primaryModel, primaryThinkingLevel, fallbac
28572
28601
  if (!entry.model || seen.has(key))
28573
28602
  continue;
28574
28603
  seen.add(key);
28575
- chain.push({ entry, kind: "configured" });
28576
- }
28577
- if (fallbackModelId) {
28578
- const entry = { model: fallbackModelId };
28579
- const key = `${entry.model}\x00`;
28580
- if (!seen.has(key))
28581
- chain.push({ entry, kind: "session" });
28604
+ chain.push(entry);
28582
28605
  }
28583
28606
  return chain;
28584
28607
  }
@@ -28981,9 +29004,11 @@ ${chunkText}`,
28981
29004
  });
28982
29005
  let validatedPass = await validateHistorianResult(firstResult, sessionId, chunk, priorCompartments, sequenceOffset);
28983
29006
  let validatedDraftText = firstResult.ok ? firstResult.assistantText : null;
29007
+ let fallbackPrompt = prompt;
28984
29008
  if (validatedPass.kind === "validation-failed") {
28985
29009
  sessionLog2(sessionId, `historian: first pass validation failed, retrying with repair prompt: ${validatedPass.error}`);
28986
29010
  const repairPrompt = buildHistorianRepairPrompt(prompt, validatedPass.rawText, validatedPass.error, deps.language);
29011
+ fallbackPrompt = repairPrompt;
28987
29012
  const repairResult = await runHistorianSubagentWithTransientRetries({
28988
29013
  runner,
28989
29014
  sessionId,
@@ -29010,31 +29035,31 @@ ${chunkText}`,
29010
29035
  validatedDraftText = repairResult.assistantText;
29011
29036
  }
29012
29037
  }
29013
- const fallbackChain = buildHistorianFallbackChain(historianModel, thinkingLevel, fallbackModels, fallbackModelId);
29038
+ const fallbackChain = buildHistorianFallbackChain(historianModel, thinkingLevel, fallbackModels);
29014
29039
  if (validatedPass.kind !== "ok" && !(validatedPass.kind === "spawn-failed" && validatedPass.reason === "abort") && fallbackChain.length > 0) {
29015
29040
  for (let i = 0;i < fallbackChain.length; i += 1) {
29016
29041
  const candidate = fallbackChain[i];
29017
- sessionLog2(sessionId, `historian: escalating to ${candidate.kind === "session" ? "session-model last resort" : "configured fallback model"} ${candidate.entry.model}`);
29042
+ sessionLog2(sessionId, `historian: escalating to configured fallback model ${candidate.model}`);
29018
29043
  const fbResult = await runHistorianSubagentWithTransientRetries({
29019
29044
  runner,
29020
29045
  sessionId,
29021
- passLabel: candidate.kind === "session" ? "fallback-session" : "fallback",
29046
+ passLabel: "fallback",
29022
29047
  retryBackoffMs,
29023
29048
  options: {
29024
29049
  agent: HISTORIAN_AGENT_NAME,
29025
29050
  systemPrompt: historianSystemPrompt,
29026
- userMessage: prompt,
29027
- model: candidate.entry.model,
29051
+ userMessage: fallbackPrompt,
29052
+ model: candidate.model,
29028
29053
  timeoutMs: historianTimeoutMs,
29029
29054
  cwd: directory,
29030
29055
  signal,
29031
- thinkingLevel: candidate.entry.qualifier,
29056
+ thinkingLevel: candidate.qualifier,
29032
29057
  temperature,
29033
29058
  maxOutputTokens,
29034
29059
  onProgress: buildProgressLogger("fallback"),
29035
29060
  accountingSessionId: sessionId,
29036
29061
  accountingSubagent: "historian",
29037
- accountingTask: candidate.kind === "session" ? "fallback-session" : "fallback"
29062
+ accountingTask: "fallback"
29038
29063
  }
29039
29064
  });
29040
29065
  const fbPass = await validateHistorianResult(fbResult, sessionId, chunk, priorCompartments, sequenceOffset);
@@ -34325,6 +34350,348 @@ function isOmpUnmanagedCaptureRequest(payload) {
34325
34350
  return last?.role === "user" && firstText(last.content, request.textType)?.startsWith(CAPTURE_PREFIX) === true;
34326
34351
  }
34327
34352
 
34353
+ // src/pi-dispatch-chain.ts
34354
+ import { isDeepStrictEqual } from "node:util";
34355
+
34356
+ // src/pi-dispatch-agent-history.ts
34357
+ function object(value) {
34358
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34359
+ }
34360
+ var DEVELOPER_ORIGIN = Symbol("custom developer history");
34361
+ function piIsDeveloperHistory(message) {
34362
+ return message.role === "developer" || Reflect.get(message, DEVELOPER_ORIGIN) === true;
34363
+ }
34364
+ function piAgentHistory(messages, api) {
34365
+ return messages.flatMap((value) => {
34366
+ const message = object(value);
34367
+ if (!message)
34368
+ return [value];
34369
+ if (message.role === "compactionSummary") {
34370
+ return [
34371
+ {
34372
+ ...message,
34373
+ role: "user",
34374
+ content: message.blocks !== undefined ? [
34375
+ { type: "text", text: message.summary },
34376
+ ...Array.isArray(message.blocks) ? message.blocks : []
34377
+ ] : [
34378
+ { type: "text", text: "Compaction context envelope" },
34379
+ ...Array.isArray(message.images) ? message.images : []
34380
+ ]
34381
+ }
34382
+ ];
34383
+ }
34384
+ if (message.role !== "custom" && message.role !== "hookMessage")
34385
+ return [value];
34386
+ if (typeof message.content !== "string" && !Array.isArray(message.content))
34387
+ return [];
34388
+ const content = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
34389
+ const userInvoked = message.role === "custom" && message.attribution === "user";
34390
+ if (userInvoked && message.customType === "collab-prompt") {
34391
+ const text = content.filter((part) => object(part)?.type === "text").map((part) => object(part)?.text).join(`
34392
+ `);
34393
+ return [
34394
+ {
34395
+ ...message,
34396
+ role: "user",
34397
+ content: [
34398
+ {
34399
+ type: "text",
34400
+ text: text.length ? "User interjection envelope" : ""
34401
+ },
34402
+ ...content.filter((part) => object(part)?.type === "image")
34403
+ ]
34404
+ }
34405
+ ];
34406
+ }
34407
+ if (userInvoked && message.customType === "skill-prompt")
34408
+ return [{ ...message, role: "user", content }];
34409
+ const images = content.filter((part) => object(part)?.type === "image");
34410
+ const developerRole = api === "ollama-chat" && message.attribution !== "user" ? "developer" : "user";
34411
+ if (!images.length)
34412
+ return [
34413
+ { ...message, role: developerRole, content, [DEVELOPER_ORIGIN]: true }
34414
+ ];
34415
+ const texts = content.filter((part) => object(part)?.type === "text");
34416
+ return [
34417
+ ...texts.length ? [
34418
+ {
34419
+ ...message,
34420
+ role: developerRole,
34421
+ content: texts,
34422
+ [DEVELOPER_ORIGIN]: true
34423
+ }
34424
+ ] : [],
34425
+ {
34426
+ ...message,
34427
+ role: "user",
34428
+ content: [
34429
+ { type: "text", text: `Images attached to ${message.customType}.` },
34430
+ ...images
34431
+ ]
34432
+ }
34433
+ ];
34434
+ });
34435
+ }
34436
+
34437
+ // src/pi-dispatch-tool-ids.ts
34438
+ function record4(value) {
34439
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34440
+ }
34441
+ var sanitize = (id) => id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
34442
+ function hash2(id) {
34443
+ return typeof Bun === "undefined" ? undefined : Bun.hash(id).toString(36);
34444
+ }
34445
+ function responsesComponent(id) {
34446
+ const sep = id.search(/[\n|]/);
34447
+ return sep > 0 ? id.slice(0, sep) : id;
34448
+ }
34449
+ function codexCallId(id) {
34450
+ if (!id) {
34451
+ const suffix = hash2("empty");
34452
+ return suffix === undefined ? undefined : `call_${suffix}`;
34453
+ }
34454
+ const sep = id.search(/[\n|]/);
34455
+ const base = sep > 0 ? id.slice(0, sep) : sep === 0 ? id.slice(1) : id;
34456
+ const normalized = base.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+$/, "");
34457
+ if (normalized && normalized.length <= 64 && normalized === base)
34458
+ return normalized;
34459
+ const suffix = hash2(base || id);
34460
+ if (suffix === undefined)
34461
+ return;
34462
+ return `${(normalized || "call").slice(0, Math.max(0, 63 - suffix.length))}_${suffix}`.slice(0, 64);
34463
+ }
34464
+ function piToolCallWireId(id, model, source) {
34465
+ const origin = record4(source);
34466
+ const same = origin !== undefined && origin.provider === model.provider && origin.api === model.api && origin.model === model.id;
34467
+ const compat = record4(model.compat);
34468
+ switch (model.api) {
34469
+ case "openai-completions": {
34470
+ if (compat?.requiresMistralToolIds === true) {
34471
+ const normalized = id.replace(/[^a-zA-Z0-9]/g, "");
34472
+ return (normalized + "ABCDEFGHI".slice(0, Math.max(0, 9 - normalized.length))).slice(0, 9);
34473
+ }
34474
+ if (!same && id.includes("|"))
34475
+ return id.split("|", 1)[0].replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
34476
+ return compat?.usesOpenAIToolCallIdLimit === true ? id.slice(0, 40) : id;
34477
+ }
34478
+ case "anthropic-messages": {
34479
+ if (same && compat?.officialEndpoint !== true)
34480
+ return id;
34481
+ const normalized = sanitize(id);
34482
+ if (normalized)
34483
+ return normalized;
34484
+ const suffix = hash2(id);
34485
+ return suffix === undefined ? undefined : `toolu_${suffix}`;
34486
+ }
34487
+ case "bedrock-converse-stream":
34488
+ return sanitize(id);
34489
+ case "google-generative-ai":
34490
+ case "google-gemini-cli":
34491
+ case "google-vertex":
34492
+ return same ? id : sanitize(id);
34493
+ case "openai-responses":
34494
+ case "azure-openai-responses": {
34495
+ const sep = id.search(/[\n|]/);
34496
+ const simple = sep < 0 && id.length <= 64 && /^[a-zA-Z0-9_-]+$/.test(id);
34497
+ const foreign = origin && (origin.provider !== model.provider || origin.api !== model.api);
34498
+ return !same && !simple && (foreign || sep >= 0 || id.length > 64) ? codexCallId(responsesComponent(id)) : responsesComponent(id);
34499
+ }
34500
+ case "openai-codex-responses":
34501
+ return codexCallId(responsesComponent(id));
34502
+ default:
34503
+ return id;
34504
+ }
34505
+ }
34506
+
34507
+ // src/pi-dispatch-chain-tail.ts
34508
+ function object2(value) {
34509
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34510
+ }
34511
+ var OMITTED_IMAGE = "[image omitted: model does not support vision]";
34512
+ function piEncodeChainTail(messages, assistant, responseItems, model) {
34513
+ const harmony = object2(model.identity)?.class === "gpt-oss";
34514
+ const text = (value) => {
34515
+ const wellFormed = value.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "�");
34516
+ return harmony ? wellFormed.replace(/<\|(start|end|message|channel|constrain|return|call)\|>/g, "<\\|$1\\|>") : wellFormed;
34517
+ };
34518
+ const supportsImages = model.input?.includes("image") === true;
34519
+ const image = (block) => {
34520
+ const detail = block.detail === "original" && object2(model.compat)?.supportsImageDetailOriginal !== true ? "auto" : block.detail ?? "auto";
34521
+ const file = object2(block.providerFile);
34522
+ if (file?.provider === "openai" && typeof file.id === "string" && file.id)
34523
+ return { type: "input_image", detail, file_id: file.id };
34524
+ if (typeof block.url !== "string" && (typeof block.mimeType !== "string" || typeof block.data !== "string"))
34525
+ return;
34526
+ return {
34527
+ type: "input_image",
34528
+ detail,
34529
+ image_url: block.url ?? `data:${block.mimeType};base64,${block.data}`
34530
+ };
34531
+ };
34532
+ const items = [];
34533
+ for (const value of messages) {
34534
+ let message = object2(value);
34535
+ if (!message || message.providerPayload !== undefined)
34536
+ return;
34537
+ if (message.role === "custom" || message.role === "hookMessage") {
34538
+ if (typeof message.customType !== "string" || message.attribution === "user")
34539
+ return;
34540
+ const converted = piAgentHistory([message], model.api);
34541
+ const developer = object2(converted[0]);
34542
+ if (converted.length !== 1 || !developer || !piIsDeveloperHistory(developer))
34543
+ return;
34544
+ message = {
34545
+ ...developer,
34546
+ role: model.api === "openai-codex-responses" ? "developer" : "user"
34547
+ };
34548
+ }
34549
+ const user = message.role === "user" || message.role === "developer";
34550
+ if (!user && message.role !== "toolResult")
34551
+ return;
34552
+ const content = typeof message.content === "string" && user ? [{ type: "text", text: message.content }] : message.content;
34553
+ if (!Array.isArray(content))
34554
+ return;
34555
+ const texts = [];
34556
+ const images = [];
34557
+ const ordered = [];
34558
+ for (const value of content) {
34559
+ const block = object2(value);
34560
+ if (block?.type === "text" && typeof block.text === "string") {
34561
+ texts.push(block.text);
34562
+ if (!user || block.text.trim())
34563
+ ordered.push({ type: "input_text", text: text(block.text) });
34564
+ } else if (block?.type === "image") {
34565
+ const encoded = image(block);
34566
+ if (!encoded)
34567
+ return;
34568
+ images.push(encoded);
34569
+ if (supportsImages)
34570
+ ordered.push(encoded);
34571
+ } else
34572
+ return;
34573
+ }
34574
+ if (user) {
34575
+ const input = texts.filter((value) => value.trim()).map((value) => ({ type: "input_text", text: text(value) }));
34576
+ if (supportsImages)
34577
+ input.push(...images);
34578
+ else if (images.length)
34579
+ input.push({ type: "input_text", text: OMITTED_IMAGE });
34580
+ if (input.length)
34581
+ items.push({ role: message.role, content: input });
34582
+ continue;
34583
+ }
34584
+ if (typeof message.toolCallId !== "string" || message.providerMetadata !== undefined)
34585
+ return;
34586
+ const id = piToolCallWireId(message.toolCallId, model, assistant);
34587
+ const call = responseItems.map(object2).find((item) => item?.call_id === id);
34588
+ if (!id || call?.type !== "function_call" && call?.type !== "custom_tool_call")
34589
+ return;
34590
+ const joined = texts.join(`
34591
+ `);
34592
+ const output = images.length && supportsImages ? ordered : text(images.length && !supportsImages ? joined ? `${joined}
34593
+ ${OMITTED_IMAGE}` : OMITTED_IMAGE : joined);
34594
+ items.push({
34595
+ type: call.type === "custom_tool_call" ? "custom_tool_call_output" : "function_call_output",
34596
+ call_id: id,
34597
+ output
34598
+ });
34599
+ }
34600
+ return items;
34601
+ }
34602
+
34603
+ // src/pi-dispatch-chain.ts
34604
+ function object3(value) {
34605
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34606
+ }
34607
+ function piChainCapableApi(api) {
34608
+ return api === "openai-codex-responses" || api === "openai-responses" || api === "azure-openai-responses";
34609
+ }
34610
+ function piPreparedHistory(messages, model) {
34611
+ const snapshots = [];
34612
+ const responseIds = [];
34613
+ for (const message of messages) {
34614
+ const fields = lkgContentFields(message);
34615
+ if (!fields)
34616
+ return;
34617
+ snapshots.push({ id: "", fields });
34618
+ const source = object3(message);
34619
+ responseIds.push(source?.role === "assistant" && typeof source.responseId === "string" && source.responseId.length > 0 ? source.responseId : undefined);
34620
+ }
34621
+ const prepared = { snapshots, responseIds };
34622
+ let index = responseIds.length - 1;
34623
+ while (index >= 0 && responseIds[index] === undefined)
34624
+ index--;
34625
+ const assistant = object3(messages[index]);
34626
+ const response = piChainResponse(assistant);
34627
+ if (model && assistant && response) {
34628
+ const delta = piEncodeChainTail(messages.slice(index + 1), assistant, response.responseItems, model);
34629
+ if (delta)
34630
+ prepared.continuation = { index, ...response, delta };
34631
+ }
34632
+ return prepared;
34633
+ }
34634
+ function piChainedRequest(payload) {
34635
+ const body = object3(payload);
34636
+ if (!body || body.previous_response_id === undefined)
34637
+ return;
34638
+ const id = body.previous_response_id;
34639
+ if (body.messages !== undefined || !Array.isArray(body.input) || typeof id !== "string" || !id)
34640
+ throw new Error("invalid chained continuation frame");
34641
+ return { previousResponseId: id, delta: body.input };
34642
+ }
34643
+ function piChainResponse(message) {
34644
+ const source = object3(message);
34645
+ if (source?.role !== "assistant")
34646
+ return;
34647
+ if (source.stopReason !== "stop" && source.stopReason !== "toolUse")
34648
+ return;
34649
+ if (typeof source.responseId !== "string" || !source.responseId)
34650
+ return;
34651
+ const payload = object3(source.providerPayload);
34652
+ if (payload?.type !== "openaiResponsesHistory" || payload.dt !== true || !Array.isArray(payload.items))
34653
+ return;
34654
+ return {
34655
+ responseId: source.responseId,
34656
+ responseItems: structuredClone(payload.items)
34657
+ };
34658
+ }
34659
+ function piExpandChainedRequest(payload, chained, anchor, prepared, pass) {
34660
+ if (!anchor)
34661
+ return {
34662
+ refusal: "no completed managed response is recorded for this continuation"
34663
+ };
34664
+ if (anchor.supersededBy !== undefined && (anchor.supersededBy !== pass.current || !pass.resend))
34665
+ return {
34666
+ refusal: "the last managed request has no completed response"
34667
+ };
34668
+ if (chained.previousResponseId !== anchor.responseId)
34669
+ return {
34670
+ refusal: "continuation does not follow the last managed request's response"
34671
+ };
34672
+ if (!prepared)
34673
+ return { refusal: "this pass's prepared history was not recorded" };
34674
+ const carried = anchor.prepared.snapshots.length;
34675
+ if (exactReusablePrefix(prepared.snapshots, anchor.prepared.snapshots) !== carried)
34676
+ return {
34677
+ refusal: "prepared history does not extend the previous managed request"
34678
+ };
34679
+ if (prepared.responseIds[carried] !== anchor.responseId)
34680
+ return {
34681
+ refusal: "prepared history does not continue from the previous managed response"
34682
+ };
34683
+ const continuation = prepared.continuation;
34684
+ if (!continuation || continuation.index !== carried || !isDeepStrictEqual(continuation.responseItems, anchor.responseItems))
34685
+ return {
34686
+ refusal: "prepared response or tail encoding cannot continue the recorded response"
34687
+ };
34688
+ if (!isDeepStrictEqual(continuation.delta, chained.delta))
34689
+ return { refusal: "delta differs from the prepared provider input tail" };
34690
+ const input = [...anchor.input, ...anchor.responseItems, ...chained.delta];
34691
+ const { previous_response_id: _previous, ...rest } = payload;
34692
+ return { payload: { ...rest, input }, input };
34693
+ }
34694
+
34328
34695
  // src/pi-dispatch-google.ts
34329
34696
  function piGoogleConversation(payload) {
34330
34697
  if (!payload || typeof payload !== "object")
@@ -34471,78 +34838,10 @@ function piHasManagedSignature(payload, signature) {
34471
34838
  return false;
34472
34839
  }
34473
34840
 
34474
- // src/pi-dispatch-agent-history.ts
34475
- function object(value) {
34476
- return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34477
- }
34478
- function piAgentHistory(messages, api) {
34479
- return messages.flatMap((value) => {
34480
- const message = object(value);
34481
- if (!message)
34482
- return [value];
34483
- if (message.role === "compactionSummary") {
34484
- return [
34485
- {
34486
- ...message,
34487
- role: "user",
34488
- content: message.blocks !== undefined ? [
34489
- { type: "text", text: message.summary },
34490
- ...Array.isArray(message.blocks) ? message.blocks : []
34491
- ] : [
34492
- { type: "text", text: "Compaction context envelope" },
34493
- ...Array.isArray(message.images) ? message.images : []
34494
- ]
34495
- }
34496
- ];
34497
- }
34498
- if (message.role !== "custom" && message.role !== "hookMessage")
34499
- return [value];
34500
- if (typeof message.content !== "string" && !Array.isArray(message.content))
34501
- return [];
34502
- const content = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
34503
- const userInvoked = message.role === "custom" && message.attribution === "user";
34504
- if (userInvoked && message.customType === "collab-prompt") {
34505
- const text = content.filter((part) => object(part)?.type === "text").map((part) => object(part)?.text).join(`
34506
- `);
34507
- return [
34508
- {
34509
- ...message,
34510
- role: "user",
34511
- content: [
34512
- {
34513
- type: "text",
34514
- text: text.length ? "User interjection envelope" : ""
34515
- },
34516
- ...content.filter((part) => object(part)?.type === "image")
34517
- ]
34518
- }
34519
- ];
34520
- }
34521
- if (userInvoked && message.customType === "skill-prompt")
34522
- return [{ ...message, role: "user", content }];
34523
- const images = content.filter((part) => object(part)?.type === "image");
34524
- const developerRole = api === "ollama-chat" && message.attribution !== "user" ? "developer" : "user";
34525
- if (!images.length)
34526
- return [{ ...message, role: developerRole, content }];
34527
- const texts = content.filter((part) => object(part)?.type === "text");
34528
- return [
34529
- ...texts.length ? [{ ...message, role: developerRole, content: texts }] : [],
34530
- {
34531
- ...message,
34532
- role: "user",
34533
- content: [
34534
- { type: "text", text: `Images attached to ${message.customType}.` },
34535
- ...images
34536
- ]
34537
- }
34538
- ];
34539
- });
34540
- }
34541
-
34542
34841
  // src/pi-dispatch-chat-history.ts
34543
34842
  var MAX_EXACT_UNITS = 32 * 1024 * 1024;
34544
34843
  var IMAGE_CAPTION = "Attached image(s) from tool result:";
34545
- function object2(value) {
34844
+ function object4(value) {
34546
34845
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34547
34846
  }
34548
34847
  function omitsAssistant(message, model, compat) {
@@ -34551,7 +34850,7 @@ function omitsAssistant(message, model, compat) {
34551
34850
  let thinking = false;
34552
34851
  let hasTextBlock = false;
34553
34852
  for (const value of message.content) {
34554
- const block = object2(value);
34853
+ const block = object4(value);
34555
34854
  if (!block)
34556
34855
  return false;
34557
34856
  if (block.type === "text") {
@@ -34576,14 +34875,14 @@ function omitsAssistant(message, model, compat) {
34576
34875
  function piChatHistoryPlan(messages, model) {
34577
34876
  if (model?.api !== "openai-completions")
34578
34877
  return;
34579
- const compat = object2(model.compat) ?? {};
34878
+ const compat = object4(model.compat) ?? {};
34580
34879
  const calls = new Set;
34581
34880
  for (const value of messages) {
34582
- const message = object2(value);
34881
+ const message = object4(value);
34583
34882
  if (message?.role !== "assistant" || !Array.isArray(message.content))
34584
34883
  continue;
34585
34884
  for (const value of message.content) {
34586
- const block = object2(value);
34885
+ const block = object4(value);
34587
34886
  if (block?.type === "toolCall" && typeof block.id === "string")
34588
34887
  calls.add(block.id);
34589
34888
  }
@@ -34592,7 +34891,7 @@ function piChatHistoryPlan(messages, model) {
34592
34891
  let pending = new Set;
34593
34892
  let exactUnits = 0;
34594
34893
  for (let index = 0;index < messages.length; index++) {
34595
- const message = object2(messages[index]);
34894
+ const message = object4(messages[index]);
34596
34895
  if (!message)
34597
34896
  return;
34598
34897
  if ((message.role === "bashExecution" || message.role === "pythonExecution") && message.excludeFromContext === true)
@@ -34604,7 +34903,7 @@ function piChatHistoryPlan(messages, model) {
34604
34903
  continue;
34605
34904
  if (Array.isArray(message.content))
34606
34905
  for (const value of message.content) {
34607
- const block = object2(value);
34906
+ const block = object4(value);
34608
34907
  if (block?.type === "toolCall" && typeof block.id === "string")
34609
34908
  pending.add(block.id);
34610
34909
  }
@@ -34616,7 +34915,7 @@ function piChatHistoryPlan(messages, model) {
34616
34915
  return;
34617
34916
  const parts = [];
34618
34917
  for (const value of message.content) {
34619
- const part = object2(value);
34918
+ const part = object4(value);
34620
34919
  if (part?.type === "text" && typeof part.text === "string" && part.text.trim())
34621
34920
  parts.push(part.text);
34622
34921
  }
@@ -34649,14 +34948,14 @@ ${parts.join(`
34649
34948
  };
34650
34949
  const vision = model.input?.includes("image") === true && compat.stripImageInput !== true;
34651
34950
  for (const step of transformed) {
34652
- const message = step.kind === "source" ? object2(messages[step.index]) : undefined;
34951
+ const message = step.kind === "source" ? object4(messages[step.index]) : undefined;
34653
34952
  if (message?.role !== "toolResult")
34654
34953
  flushImages();
34655
34954
  steps.push(step);
34656
34955
  if (message?.role !== "toolResult" || !vision || !Array.isArray(message.content))
34657
34956
  continue;
34658
34957
  for (const value of message.content) {
34659
- const block = object2(value);
34958
+ const block = object4(value);
34660
34959
  if (block?.type !== "image")
34661
34960
  continue;
34662
34961
  if (compat.requiresAssistantAfterToolResult === true)
@@ -34680,12 +34979,12 @@ ${parts.join(`
34680
34979
  function piMatchesChatImages(content, urls) {
34681
34980
  if (!Array.isArray(content) || content.length !== urls.length + 1)
34682
34981
  return false;
34683
- const caption = object2(content[0]);
34982
+ const caption = object4(content[0]);
34684
34983
  if (caption?.type !== "text" || caption.text !== IMAGE_CAPTION || Object.keys(caption).length !== 2)
34685
34984
  return false;
34686
34985
  for (let i = 0;i < urls.length; i++) {
34687
- const block = object2(content[i + 1]);
34688
- const image = object2(block?.image_url);
34986
+ const block = object4(content[i + 1]);
34987
+ const image = object4(block?.image_url);
34689
34988
  if (block?.type !== "image_url" || Object.keys(block).length !== 2 || !image || Object.keys(image).length !== 1 || image.url !== urls[i])
34690
34989
  return false;
34691
34990
  }
@@ -34693,22 +34992,22 @@ function piMatchesChatImages(content, urls) {
34693
34992
  }
34694
34993
 
34695
34994
  // src/pi-dispatch-image-budget.ts
34696
- function object3(value) {
34995
+ function object5(value) {
34697
34996
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34698
34997
  }
34699
34998
  function piImageBudgetPlan(model) {
34700
- if (!model?.input?.includes("image") || object3(model.compat)?.stripImageInput === true)
34999
+ if (!model?.input?.includes("image") || object5(model.compat)?.stripImageInput === true)
34701
35000
  return;
34702
35001
  return {
34703
35002
  count: 0,
34704
35003
  api: model.api,
34705
35004
  rows: new Map,
34706
- hoistToolImages: model.api?.startsWith("google-") === true && object3(model.compat)?.multimodalFunctionResponse !== true || model.api === "bedrock-converse-stream" && model.requiresToolResultImageHoisting === true,
35005
+ hoistToolImages: model.api?.startsWith("google-") === true && object5(model.compat)?.multimodalFunctionResponse !== true || model.api === "bedrock-converse-stream" && model.requiresToolResultImageHoisting === true,
34707
35006
  hoistErrorImages: model.api === "anthropic-messages" || model.api === "bedrock-converse-stream"
34708
35007
  };
34709
35008
  }
34710
35009
  function inputImage(block, api) {
34711
- const file = object3(block.providerFile);
35010
+ const file = object5(block.providerFile);
34712
35011
  if (api === "ollama-chat")
34713
35012
  return { kind: "bytes", value: String(block.data ?? "") };
34714
35013
  if ((api?.endsWith("responses") && file?.provider === "openai" || api === "anthropic-messages" && file?.provider === "anthropic") && typeof file?.id === "string")
@@ -34728,7 +35027,7 @@ function piRecordImages(plan, row, source) {
34728
35027
  return;
34729
35028
  const images = [];
34730
35029
  for (const value of source.content) {
34731
- const block = object3(value);
35030
+ const block = object5(value);
34732
35031
  if (block?.type === "image")
34733
35032
  images.push(inputImage(block, plan.api));
34734
35033
  }
@@ -34754,20 +35053,20 @@ function piWireImages(content, ollamaImages) {
34754
35053
  return [];
34755
35054
  const images = [];
34756
35055
  for (const value of content) {
34757
- const block = object3(value);
35056
+ const block = object5(value);
34758
35057
  if (!block)
34759
35058
  continue;
34760
- const source = object3(block.source);
34761
- const inline = object3(block.inlineData);
34762
- const file = object3(block.fileData);
34763
- const bedrock = object3(block.image);
35059
+ const source = object5(block.source);
35060
+ const inline = object5(block.inlineData);
35061
+ const file = object5(block.fileData);
35062
+ const bedrock = object5(block.image);
34764
35063
  if (block.type === "image_url" || block.type === "input_image") {
34765
35064
  if (typeof block.file_id === "string")
34766
35065
  images.push({ kind: "file", value: block.file_id });
34767
35066
  else
34768
35067
  images.push({
34769
35068
  kind: "url",
34770
- value: String(typeof block.image_url === "string" ? block.image_url : object3(block.image_url)?.url)
35069
+ value: String(typeof block.image_url === "string" ? block.image_url : object5(block.image_url)?.url)
34771
35070
  });
34772
35071
  } else if (block.type === "image") {
34773
35072
  if (source?.type === "file")
@@ -34791,7 +35090,7 @@ function piWireImages(content, ollamaImages) {
34791
35090
  else if (bedrock)
34792
35091
  images.push({
34793
35092
  kind: "data",
34794
- value: String(object3(bedrock.source)?.bytes),
35093
+ value: String(object5(bedrock.source)?.bytes),
34795
35094
  mime: `image/${bedrock.format}`
34796
35095
  });
34797
35096
  }
@@ -34813,11 +35112,11 @@ function piMatchesImages(actual, expected) {
34813
35112
  return true;
34814
35113
  }
34815
35114
  function piWireImageCount(payload) {
34816
- const body = object3(payload);
35115
+ const body = object5(payload);
34817
35116
  const visit = (value) => {
34818
35117
  if (Array.isArray(value))
34819
35118
  return value.reduce((n, item) => n + visit(item), 0);
34820
- const block = object3(value);
35119
+ const block = object5(value);
34821
35120
  if (!block)
34822
35121
  return 0;
34823
35122
  if (["image", "image_url", "input_image"].includes(String(block.type)) || block.inlineData || block.fileData || block.image)
@@ -34831,12 +35130,12 @@ function piWireImageCount(payload) {
34831
35130
  block.response
34832
35131
  ].reduce((n, item) => n + visit(item), Array.isArray(block.images) ? block.images.length : 0);
34833
35132
  };
34834
- return visit(body?.messages ?? body?.input ?? body?.contents ?? object3(body?.request)?.contents);
35133
+ return visit(body?.messages ?? body?.input ?? body?.contents ?? object5(body?.request)?.contents);
34835
35134
  }
34836
35135
 
34837
35136
  // src/pi-dispatch-responses-history.ts
34838
35137
  var MAX_TEXT_UNITS = 32 * 1024 * 1024;
34839
- function object4(value) {
35138
+ function object6(value) {
34840
35139
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34841
35140
  }
34842
35141
  function wellFormed(text) {
@@ -34851,7 +35150,7 @@ function textIdentity2(text, phase) {
34851
35150
  function signaturePhase(block) {
34852
35151
  try {
34853
35152
  if (typeof block.textSignature === "string") {
34854
- const signature = object4(JSON.parse(block.textSignature));
35153
+ const signature = object6(JSON.parse(block.textSignature));
34855
35154
  if (signature?.v === 1 && typeof signature.id === "string")
34856
35155
  return signature.phase;
34857
35156
  }
@@ -34871,17 +35170,17 @@ ${wellFormed(text)}
34871
35170
  return;
34872
35171
  }
34873
35172
  function piResponsesAssistantTexts(value, model) {
34874
- const message = object4(value);
35173
+ const message = object6(value);
34875
35174
  if (!message || !Array.isArray(message.content))
34876
35175
  return;
34877
- if (["length", "error", "aborted"].includes(String(message.stopReason)) && !message.content.some((value) => ["text", "toolCall"].includes(String(object4(value)?.type))))
35176
+ if (["length", "error", "aborted"].includes(String(message.stopReason)) && !message.content.some((value) => ["text", "toolCall"].includes(String(object6(value)?.type))))
34878
35177
  return [];
34879
35178
  const texts = [];
34880
35179
  const blocks = [];
34881
35180
  const sameModel = model !== undefined && typeof model.api === "string" && typeof model.id === "string" && typeof model.provider === "string" && message.api === model.api && message.model === model.id && message.provider === model.provider;
34882
35181
  let units = 0;
34883
35182
  for (const value of message.content) {
34884
- const block = object4(value);
35183
+ const block = object6(value);
34885
35184
  if (block?.type === "toolCall")
34886
35185
  continue;
34887
35186
  if (block?.type === "thinking") {
@@ -34891,7 +35190,7 @@ function piResponsesAssistantTexts(value, model) {
34891
35190
  return;
34892
35191
  if (!block.thinking.trim())
34893
35192
  continue;
34894
- const compat = object4(model.compat);
35193
+ const compat = object6(model.compat);
34895
35194
  if (block.summary === false && (compat?.requiresReasoningContentForToolCalls === true || compat?.requiresReasoningContentForAllAssistantTurns === true))
34896
35195
  return;
34897
35196
  const text = demotedThinking(block.thinking, model);
@@ -34911,14 +35210,14 @@ function piResponsesAssistantTexts(value, model) {
34911
35210
  texts.push(textIdentity2(wellFormed(block.text), sameModel ? signaturePhase(block) : undefined));
34912
35211
  blocks.push(block);
34913
35212
  }
34914
- const payload = object4(message.providerPayload);
35213
+ const payload = object6(message.providerPayload);
34915
35214
  if (message.api !== model?.api || typeof model?.id !== "string" || typeof model?.provider !== "string" || message.model !== model?.id || (payload?.provider ?? message.provider) !== model?.provider || payload?.type !== "openaiResponsesHistory" || payload.dt !== true || !Array.isArray(payload.items))
34916
35215
  return texts;
34917
35216
  const replay = [];
34918
35217
  let bound = 0;
34919
35218
  let output = false;
34920
35219
  for (const value of payload.items) {
34921
- const item = object4(value);
35220
+ const item = object6(value);
34922
35221
  if (item?.type === "reasoning")
34923
35222
  continue;
34924
35223
  if (item?.type === "function_call" || item?.type === "custom_tool_call") {
@@ -34929,14 +35228,14 @@ function piResponsesAssistantTexts(value, model) {
34929
35228
  return texts;
34930
35229
  const itemTexts = [];
34931
35230
  for (const value of item.content) {
34932
- const part = object4(value);
35231
+ const part = object6(value);
34933
35232
  const block = blocks[bound];
34934
35233
  if (!block || part?.type !== "output_text" || typeof part.text !== "string")
34935
35234
  return texts;
34936
35235
  let signature;
34937
35236
  try {
34938
35237
  if (typeof block.textSignature === "string")
34939
- signature = object4(JSON.parse(block.textSignature));
35238
+ signature = object6(JSON.parse(block.textSignature));
34940
35239
  } catch {
34941
35240
  return texts;
34942
35241
  }
@@ -34963,7 +35262,7 @@ function piResponsesWireTexts(value, phase) {
34963
35262
  const texts = [];
34964
35263
  let units = 0;
34965
35264
  for (const partValue of value) {
34966
- const part = object4(partValue);
35265
+ const part = object6(partValue);
34967
35266
  if (part?.type !== "output_text" || typeof part.text !== "string")
34968
35267
  return;
34969
35268
  units += part.text.length;
@@ -34974,76 +35273,6 @@ function piResponsesWireTexts(value, phase) {
34974
35273
  return texts;
34975
35274
  }
34976
35275
 
34977
- // src/pi-dispatch-tool-ids.ts
34978
- function record4(value) {
34979
- return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
34980
- }
34981
- var sanitize = (id) => id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
34982
- function hash2(id) {
34983
- return typeof Bun === "undefined" ? undefined : Bun.hash(id).toString(36);
34984
- }
34985
- function responsesComponent(id) {
34986
- const sep = id.search(/[\n|]/);
34987
- return sep > 0 ? id.slice(0, sep) : id;
34988
- }
34989
- function codexCallId(id) {
34990
- if (!id) {
34991
- const suffix = hash2("empty");
34992
- return suffix === undefined ? undefined : `call_${suffix}`;
34993
- }
34994
- const sep = id.search(/[\n|]/);
34995
- const base = sep > 0 ? id.slice(0, sep) : sep === 0 ? id.slice(1) : id;
34996
- const normalized = base.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+$/, "");
34997
- if (normalized && normalized.length <= 64 && normalized === base)
34998
- return normalized;
34999
- const suffix = hash2(base || id);
35000
- if (suffix === undefined)
35001
- return;
35002
- return `${(normalized || "call").slice(0, Math.max(0, 63 - suffix.length))}_${suffix}`.slice(0, 64);
35003
- }
35004
- function piToolCallWireId(id, model, source) {
35005
- const origin = record4(source);
35006
- const same = origin !== undefined && origin.provider === model.provider && origin.api === model.api && origin.model === model.id;
35007
- const compat = record4(model.compat);
35008
- switch (model.api) {
35009
- case "openai-completions": {
35010
- if (compat?.requiresMistralToolIds === true) {
35011
- const normalized = id.replace(/[^a-zA-Z0-9]/g, "");
35012
- return (normalized + "ABCDEFGHI".slice(0, Math.max(0, 9 - normalized.length))).slice(0, 9);
35013
- }
35014
- if (!same && id.includes("|"))
35015
- return id.split("|", 1)[0].replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
35016
- return compat?.usesOpenAIToolCallIdLimit === true ? id.slice(0, 40) : id;
35017
- }
35018
- case "anthropic-messages": {
35019
- if (same && compat?.officialEndpoint !== true)
35020
- return id;
35021
- const normalized = sanitize(id);
35022
- if (normalized)
35023
- return normalized;
35024
- const suffix = hash2(id);
35025
- return suffix === undefined ? undefined : `toolu_${suffix}`;
35026
- }
35027
- case "bedrock-converse-stream":
35028
- return sanitize(id);
35029
- case "google-generative-ai":
35030
- case "google-gemini-cli":
35031
- case "google-vertex":
35032
- return same ? id : sanitize(id);
35033
- case "openai-responses":
35034
- case "azure-openai-responses": {
35035
- const sep = id.search(/[\n|]/);
35036
- const simple = sep < 0 && id.length <= 64 && /^[a-zA-Z0-9_-]+$/.test(id);
35037
- const foreign = origin && (origin.provider !== model.provider || origin.api !== model.api);
35038
- return !same && !simple && (foreign || sep >= 0 || id.length > 64) ? codexCallId(responsesComponent(id)) : responsesComponent(id);
35039
- }
35040
- case "openai-codex-responses":
35041
- return codexCallId(responsesComponent(id));
35042
- default:
35043
- return id;
35044
- }
35045
- }
35046
-
35047
35276
  // src/pi-dispatch-structure.ts
35048
35277
  var MAX_MESSAGES = 1e5;
35049
35278
  var ORPHAN_NOTE = Symbol("prepared orphan tool result");
@@ -35063,11 +35292,11 @@ var TRANSFORM_MESSAGES_APIS = new Set([
35063
35292
  "devin-agent",
35064
35293
  "apple-foundation-models"
35065
35294
  ]);
35066
- function object5(value) {
35295
+ function object7(value) {
35067
35296
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
35068
35297
  }
35069
35298
  function messageStructure(value) {
35070
- const message = object5(value);
35299
+ const message = object7(value);
35071
35300
  if (!message)
35072
35301
  return;
35073
35302
  const role = [
@@ -35079,7 +35308,7 @@ function messageStructure(value) {
35079
35308
  "bashExecution",
35080
35309
  "pythonExecution"
35081
35310
  ].includes(String(message.role)) ? "user" : message.role;
35082
- if (role !== "user" && role !== "assistant" && role !== "toolResult")
35311
+ if (role !== "user" && role !== "assistant" && role !== "toolResult" && role !== "system")
35083
35312
  return;
35084
35313
  const row = { role, calls: [], results: [] };
35085
35314
  if (ORPHAN_NOTE in message && typeof message.content === "string") {
@@ -35096,7 +35325,7 @@ function messageStructure(value) {
35096
35325
  }
35097
35326
  if (role === "assistant" && Array.isArray(message.content)) {
35098
35327
  for (const value of message.content) {
35099
- const block = object5(value);
35328
+ const block = object7(value);
35100
35329
  if (block?.type !== "toolCall" && block?.type !== "tool_use")
35101
35330
  continue;
35102
35331
  if (typeof block.id !== "string")
@@ -35118,11 +35347,11 @@ function projectMissingToolResults(messages, api) {
35118
35347
  return pipe > 0 ? id.slice(0, pipe) : id;
35119
35348
  };
35120
35349
  for (const value of messages) {
35121
- const message = object5(value);
35350
+ const message = object7(value);
35122
35351
  if (message?.role !== "assistant" || !Array.isArray(message.content))
35123
35352
  continue;
35124
35353
  for (const value of message.content) {
35125
- const block = object5(value);
35354
+ const block = object7(value);
35126
35355
  if (block?.type !== "toolCall" || typeof block.id !== "string")
35127
35356
  continue;
35128
35357
  if ([
@@ -35142,7 +35371,7 @@ function projectMissingToolResults(messages, api) {
35142
35371
  const pairingId = (id) => !opaqueIds.has(id) && responsesComponents.has(component(id)) ? component(id) : id;
35143
35372
  const lastResult = new Map;
35144
35373
  messages.forEach((value, index) => {
35145
- const message = object5(value);
35374
+ const message = object7(value);
35146
35375
  if (message?.role === "toolResult" && typeof message.toolCallId === "string")
35147
35376
  lastResult.set(pairingId(message.toolCallId), index);
35148
35377
  });
@@ -35173,7 +35402,7 @@ function projectMissingToolResults(messages, api) {
35173
35402
  };
35174
35403
  for (let index = 0;index < messages.length; index++) {
35175
35404
  const value = messages[index];
35176
- const message = object5(value);
35405
+ const message = object7(value);
35177
35406
  if ((message?.role === "bashExecution" || message?.role === "pythonExecution") && message.excludeFromContext === true)
35178
35407
  continue;
35179
35408
  if (message?.role !== "toolResult")
@@ -35184,7 +35413,7 @@ function projectMissingToolResults(messages, api) {
35184
35413
  if (pending.some((call) => !resolved.has(pairingId(call.id))))
35185
35414
  continue;
35186
35415
  const parts = message.content.flatMap((value) => {
35187
- const part = object5(value);
35416
+ const part = object7(value);
35188
35417
  return part?.type === "text" && typeof part.text === "string" && part.text.trim() ? [part.text] : [];
35189
35418
  });
35190
35419
  if (parts.length) {
@@ -35211,7 +35440,7 @@ ${parts.join(`
35211
35440
  if (aborted && typeof timestamp !== "number")
35212
35441
  continue;
35213
35442
  for (const value of message.content) {
35214
- const block = object5(value);
35443
+ const block = object7(value);
35215
35444
  if (block?.type === "toolCall" && typeof block.id === "string")
35216
35445
  pending.push({
35217
35446
  id: block.id,
@@ -35225,7 +35454,7 @@ ${parts.join(`
35225
35454
  function preparePiDispatch(messages, model, omp) {
35226
35455
  let output = messages;
35227
35456
  const structure = buildPiPreparedStructure(messages, model, omp ? (index, source) => {
35228
- if (object5(source.providerPayload)?.type !== "openaiResponsesHistory")
35457
+ if (object7(source.providerPayload)?.type !== "openaiResponsesHistory")
35229
35458
  return;
35230
35459
  if (output === messages)
35231
35460
  output = messages.slice();
@@ -35238,7 +35467,7 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35238
35467
  if (!messages.length || messages.length > MAX_MESSAGES)
35239
35468
  return;
35240
35469
  for (let index = 0;index < messages.length; index++) {
35241
- const source = object5(messages[index]);
35470
+ const source = object7(messages[index]);
35242
35471
  if (source?.role === "user" || source?.role === "compactionSummary")
35243
35472
  prepareUser?.(index, source);
35244
35473
  }
@@ -35254,7 +35483,7 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35254
35483
  let valid = true;
35255
35484
  for (let index = 0;index < projectedMessages.length; index++) {
35256
35485
  const message = projectedMessages[index];
35257
- const source = object5(message);
35486
+ const source = object7(message);
35258
35487
  if (rows.length === 0 && (source?.role === "system" || source?.role === "developer"))
35259
35488
  continue;
35260
35489
  if ((source?.role === "bashExecution" || source?.role === "pythonExecution") && source.excludeFromContext === true)
@@ -35278,7 +35507,7 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35278
35507
  "azure-openai-responses",
35279
35508
  "openai-codex-responses"
35280
35509
  ].includes(model?.api ?? "") && (source?.role === "user" || source?.role === "developer") && (typeof source.content === "string" ? !source.content.trim() : Array.isArray(source.content) && !source.content.some((value) => {
35281
- const block = object5(value);
35510
+ const block = object7(value);
35282
35511
  return block?.type === "image" || block?.type === "text" && typeof block.text === "string" && block.text.trim();
35283
35512
  })))
35284
35513
  continue;
@@ -35308,6 +35537,28 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35308
35537
  }
35309
35538
  if (!valid)
35310
35539
  return;
35540
+ const positionedRows = [...byIndex];
35541
+ for (let position = positionedRows.length - 1;position >= 0; position--) {
35542
+ const [index, row] = positionedRows[position];
35543
+ const source = object7(projectedMessages[index]);
35544
+ if (!source)
35545
+ return;
35546
+ const content = source.content;
35547
+ const parts = typeof content === "string" ? [{ type: "text", text: content }] : content;
35548
+ const textOnly = Array.isArray(parts) && parts.every((part) => object7(part)?.type === "text" && typeof object7(part)?.text === "string");
35549
+ if (piIsDeveloperHistory(source) && source.attribution !== "user") {
35550
+ const previous = rows[position - 1];
35551
+ const next = rows[position + 1];
35552
+ if (model?.api === "ollama-chat" || model?.api === "anthropic-messages" && object7(model.compat)?.supportsMidConversationSystem === true && textOnly && (previous?.role === "user" || previous?.role === "toolResult") && (!next || next.role === "assistant"))
35553
+ row.role = "system";
35554
+ }
35555
+ if (row.role === "system") {
35556
+ if (!textOnly)
35557
+ return;
35558
+ const texts = parts.map((part) => part.text);
35559
+ row.systemText = model?.api === "anthropic-messages" ? texts.filter((text) => text.trim()).map((text) => new TextDecoder().decode(new TextEncoder().encode(text))) : texts;
35560
+ }
35561
+ }
35311
35562
  const responsesApi = responsesLane(model?.api);
35312
35563
  let responsesMessages = responsesApi ? [] : undefined;
35313
35564
  if (responsesMessages) {
@@ -35371,7 +35622,7 @@ function buildPiPreparedStructure(messages, model, prepareUser) {
35371
35622
  ...responsesMessages ? { responsesMessages } : {},
35372
35623
  ...model?.api ? { api: model.api } : {},
35373
35624
  ...model?.api?.startsWith("google-") ? {
35374
- googleFunctionIds: object5(model.compat)?.supportsFunctionPartId === true
35625
+ googleFunctionIds: object7(model.compat)?.supportsFunctionPartId === true
35375
35626
  } : {}
35376
35627
  };
35377
35628
  }
@@ -35383,7 +35634,7 @@ function responsesLane(api) {
35383
35634
  ].includes(api ?? "");
35384
35635
  }
35385
35636
  function payloadStructure(payload, ollama = false, responsesItems = false, imageProjection = false) {
35386
- const body = object5(payload);
35637
+ const body = object7(payload);
35387
35638
  if (!body)
35388
35639
  return;
35389
35640
  const google = piGoogleConversation(payload);
@@ -35398,7 +35649,7 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
35398
35649
  return;
35399
35650
  const rows = [];
35400
35651
  for (const value of messages) {
35401
- const message = object5(value);
35652
+ const message = object7(value);
35402
35653
  if (!message)
35403
35654
  return;
35404
35655
  if (rows.length === 0 && (message.role === "system" || message.role === "developer"))
@@ -35458,7 +35709,7 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
35458
35709
  continue;
35459
35710
  }
35460
35711
  if (message.role === "user" && Array.isArray(message.content)) {
35461
- const results = message.content.filter((block) => object5(block)?.type === "tool_result" || bedrock && object5(block)?.toolResult);
35712
+ const results = message.content.filter((block) => object7(block)?.type === "tool_result" || bedrock && object7(block)?.toolResult);
35462
35713
  if (results.length) {
35463
35714
  for (const block of results) {
35464
35715
  const id = bedrock ? block.toolResult?.toolUseId : block.tool_use_id;
@@ -35481,7 +35732,7 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
35481
35732
  continue;
35482
35733
  }
35483
35734
  }
35484
- const row = messageStructure(ollama && message.role === "system" ? { ...message, role: "user" } : message);
35735
+ const row = messageStructure(message);
35485
35736
  if (!row)
35486
35737
  return;
35487
35738
  row.wireContent = message.content;
@@ -35505,11 +35756,11 @@ function payloadStructure(payload, ollama = false, responsesItems = false, image
35505
35756
  }
35506
35757
  if (Array.isArray(message.tool_calls)) {
35507
35758
  for (const call of message.tool_calls) {
35508
- const source = object5(call);
35759
+ const source = object7(call);
35509
35760
  if (!source)
35510
35761
  return;
35511
35762
  if (source.id === undefined && ollama) {
35512
- const fn = object5(source.function);
35763
+ const fn = object7(source.function);
35513
35764
  if (typeof fn?.name !== "string")
35514
35765
  return;
35515
35766
  row.calls.push("");
@@ -35545,7 +35796,7 @@ function googleStructure(contents, imageProjection = false) {
35545
35796
  return;
35546
35797
  const rows = [];
35547
35798
  for (const value of contents) {
35548
- const message = object5(value);
35799
+ const message = object7(value);
35549
35800
  if (!message || !Array.isArray(message.parts))
35550
35801
  return;
35551
35802
  if (message.role !== "user" && message.role !== "model")
@@ -35560,11 +35811,11 @@ function googleStructure(contents, imageProjection = false) {
35560
35811
  };
35561
35812
  const results = [];
35562
35813
  for (const value of message.parts) {
35563
- const part = object5(value);
35814
+ const part = object7(value);
35564
35815
  if (!part)
35565
35816
  return;
35566
35817
  if (part.functionCall) {
35567
- const call = object5(part.functionCall);
35818
+ const call = object7(part.functionCall);
35568
35819
  if (row.role !== "assistant" || typeof call?.name !== "string" || call.id !== undefined && typeof call.id !== "string")
35569
35820
  return;
35570
35821
  row.calls.push(call.id ?? "");
@@ -35572,7 +35823,7 @@ function googleStructure(contents, imageProjection = false) {
35572
35823
  row.callNames.push(call.name);
35573
35824
  }
35574
35825
  if (part.functionResponse) {
35575
- const result = object5(part.functionResponse);
35826
+ const result = object7(part.functionResponse);
35576
35827
  if (row.role !== "user" || typeof result?.name !== "string" || result.id !== undefined && typeof result.id !== "string")
35577
35828
  return;
35578
35829
  results.push({
@@ -35606,11 +35857,11 @@ function matchesUserText(content, text, api, responses, googleOrBedrock) {
35606
35857
  if (responses || googleOrBedrock) {
35607
35858
  if (!Array.isArray(content) || content.length !== 1)
35608
35859
  return false;
35609
- const block = object5(content[0]);
35860
+ const block = object7(content[0]);
35610
35861
  return !!block && block.text === text && (responses ? block.type === "input_text" : Object.keys(block).length === 1);
35611
35862
  }
35612
35863
  if ((api === "anthropic-messages" || api === "factory-droid-agent") && Array.isArray(content)) {
35613
- const block = content.length === 1 ? object5(content[0]) : undefined;
35864
+ const block = content.length === 1 ? object7(content[0]) : undefined;
35614
35865
  return block?.type === "text" && block.text === text;
35615
35866
  }
35616
35867
  return content === text;
@@ -35620,7 +35871,7 @@ function safeRole(row, readable) {
35620
35871
  return "unreadable";
35621
35872
  if (!row)
35622
35873
  return "missing";
35623
- return ["user", "assistant", "toolResult"].includes(row.role) ? row.role : "unknown";
35874
+ return ["user", "assistant", "toolResult", "system"].includes(row.role) ? row.role : "unknown";
35624
35875
  }
35625
35876
  function safeCount(value) {
35626
35877
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : "unreadable";
@@ -35678,7 +35929,7 @@ function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
35678
35929
  return "comparison=image count";
35679
35930
  const imageProjection = trimmed > 0;
35680
35931
  stage = "wire rows";
35681
- const body = object5(payload);
35932
+ const body = object7(payload);
35682
35933
  const ollama = prepared?.api === "ollama-chat" && !!body && Array.isArray(body.messages) && body.input === undefined && body.system === undefined && body.inferenceConfig === undefined;
35683
35934
  const responses = body?.messages === undefined && Array.isArray(body?.input);
35684
35935
  rows = payloadStructure(payload, ollama, responses && !!prepared?.responsesMessages, imageProjection);
@@ -35700,6 +35951,14 @@ function piPreparedStructureMismatch(payload, prepared, onImageTrim) {
35700
35951
  const actual = rows[i];
35701
35952
  if (actual.role !== expected.role)
35702
35953
  return structureDetail(i, expectedRows, rows, "role");
35954
+ if (expected.systemText !== undefined) {
35955
+ const texts = expected.systemText;
35956
+ const content = actual.wireContent;
35957
+ const actualTexts = typeof content === "string" ? [content] : Array.isArray(content) && content.every((part) => object7(part)?.type === "text" && typeof object7(part)?.text === "string") ? content.map((part) => part.text) : undefined;
35958
+ if (!actualTexts || (typeof content === "string" ? content !== texts.join(`
35959
+ `) : JSON.stringify(actualTexts) !== JSON.stringify(texts)))
35960
+ return structureDetail(i, expectedRows, rows, "content");
35961
+ }
35703
35962
  if (imageProjection && !piMatchesImages(actual.images ?? [], expected.images ?? []))
35704
35963
  return structureDetail(i, expectedRows, rows, "content");
35705
35964
  if (expected.responseTexts !== undefined && (expected.responseTexts.length !== actual.responseTexts?.length || expected.responseTexts.some((text, index) => text !== actual.responseTexts?.[index])))
@@ -37069,8 +37328,10 @@ function releasePiOperationPayloads(operation) {
37069
37328
  operation.inputMessages = undefined;
37070
37329
  operation.inputBranch = undefined;
37071
37330
  operation.dispatchFields = undefined;
37331
+ operation.chainDispatchFields = undefined;
37072
37332
  operation.managedSignature = undefined;
37073
37333
  operation.preparedStructure = undefined;
37334
+ operation.preparedHistory = undefined;
37074
37335
  }
37075
37336
  function operationKey(ctx) {
37076
37337
  return ctx.sessionManager?.getSessionId?.() ?? ctx.sessionManager ?? "no-session";
@@ -37207,6 +37468,8 @@ function registerPiGuardedContext(pi, handler, options = {}) {
37207
37468
  receiptMaps.add(structureWarnings);
37208
37469
  const imageTrimNotices = new Map;
37209
37470
  receiptMaps.add(imageTrimNotices);
37471
+ const chains = new Map;
37472
+ receiptMaps.add(chains);
37210
37473
  const refuse = (ctx, budget, reason, isCurrent) => {
37211
37474
  if (!isCurrent()) {
37212
37475
  log2(`[magic-context][pi] DISCARDED CONTEXT RESULT ${budget.diagnostic()}`, reason);
@@ -37267,6 +37530,19 @@ function registerPiGuardedContext(pi, handler, options = {}) {
37267
37530
  releasePiOperationPayloads(operation);
37268
37531
  }
37269
37532
  });
37533
+ pi.on("assistant_message", (event, ctx) => {
37534
+ const key = operationKey(ctx);
37535
+ try {
37536
+ const awaiting = chains.get(key)?.awaiting;
37537
+ const response = piChainResponse(event?.message);
37538
+ if (awaiting && response)
37539
+ chains.set(key, { anchor: { ...awaiting, ...response } });
37540
+ else
37541
+ chains.delete(key);
37542
+ } catch {
37543
+ chains.delete(key);
37544
+ }
37545
+ });
37270
37546
  pi.on("before_provider_request", (event, ctx) => {
37271
37547
  const cancelledOperation = operations.get(operationKey(ctx));
37272
37548
  const signal = ctx.signal;
@@ -37276,8 +37552,10 @@ function registerPiGuardedContext(pi, handler, options = {}) {
37276
37552
  cancelledOperation.ready = false;
37277
37553
  return;
37278
37554
  }
37279
- if (options.compactionOff?.(ctx))
37555
+ if (options.compactionOff?.(ctx)) {
37556
+ chains.delete(operationKey(ctx));
37280
37557
  return;
37558
+ }
37281
37559
  const payload = event.payload;
37282
37560
  const key = operationKey(ctx);
37283
37561
  if (sideSessions.get(key)?.sides)
@@ -37321,18 +37599,33 @@ function registerPiGuardedContext(pi, handler, options = {}) {
37321
37599
  }
37322
37600
  if (!budget.completed || !active.ready || active.refused || budget.abandoned)
37323
37601
  throw new Error("context pass ran without a managed context receipt");
37324
- if (!piHasManagedSignature(payload, active.managedSignature))
37602
+ const chained = piChainedRequest(payload);
37603
+ let checked = payload;
37604
+ let chainInput;
37605
+ if (chained) {
37606
+ const expanded = piExpandChainedRequest(payload, chained, chains.get(key)?.anchor, active.preparedHistory, {
37607
+ current: active.pass,
37608
+ resend: active.chainDispatchFields !== undefined
37609
+ });
37610
+ if ("refusal" in expanded)
37611
+ throw new Error(`provider request does not match this pass's managed dispatch (chained continuation: ${expanded.refusal})`);
37612
+ checked = expanded.payload;
37613
+ chainInput = expanded.input;
37614
+ }
37615
+ if (!piHasManagedSignature(checked, active.managedSignature))
37325
37616
  throw new Error("provider request does not match this pass's managed dispatch (missing current receipt signature)");
37326
37617
  const fields = piConversationFields(payload);
37327
37618
  if (!fields)
37328
37619
  throw new Error("provider conversation identity could not be established");
37329
- const body = payload;
37620
+ const body = checked;
37330
37621
  const skipReason = active.preparedStructure ? active.preparedStructure.structuralSkipReason ?? (active.preparedStructure.api && body?.messages === undefined && Array.isArray(body?.input) && !active.preparedStructure.responsesMessages ? "provider selected Responses items without a matching history plan" : undefined) : "prepared history representation is not modeled";
37622
+ if (chained && skipReason)
37623
+ throw new Error("provider request does not match this pass's managed dispatch (chained continuation requires a modeled prepared history)");
37331
37624
  if (skipReason && !structureWarnings.has(key)) {
37332
37625
  structureWarnings.set(key, true);
37333
37626
  log2(`[magic-context][pi] OMP structural comparison skipped: ${skipReason}; stale prepared requests are not detected on this pass; session=${String(key)}`);
37334
37627
  }
37335
- const structureMismatch = skipReason ? undefined : piPreparedStructureMismatch(payload, active.preparedStructure, (counts) => {
37628
+ const structureMismatch = skipReason ? undefined : piPreparedStructureMismatch(checked, active.preparedStructure, (counts) => {
37336
37629
  if (imageTrimNotices.has(key))
37337
37630
  return;
37338
37631
  imageTrimNotices.set(key, true);
@@ -37340,19 +37633,31 @@ function registerPiGuardedContext(pi, handler, options = {}) {
37340
37633
  });
37341
37634
  if (structureMismatch)
37342
37635
  throw new Error(`provider request does not match this pass's managed dispatch (prepared turn structure); ${structureMismatch}`);
37343
- if (active.dispatched) {
37344
- if (!active.dispatchFields || exactReusablePrefix([{ id: "conversation", fields }], [{ id: "conversation", fields: active.dispatchFields }]) !== 1)
37345
- throw new Error("provider request does not match this pass's managed dispatch");
37346
- }
37636
+ const admittedFields = chained ? active.chainDispatchFields : active.dispatchFields;
37637
+ if (admittedFields && exactReusablePrefix([{ id: "conversation", fields }], [{ id: "conversation", fields: admittedFields }]) !== 1)
37638
+ throw new Error("provider request does not match this pass's managed dispatch");
37347
37639
  if (!active.dispatched && active.inputMessages && (!active.inputBranch || active.inputBranch.anchorIndex < active.inputMessages.length - 1)) {
37348
37640
  const previous = active.inputBranch;
37349
37641
  const persisted = inputBranch(ctx, active.inputMessages);
37350
37642
  if (!previous || persisted && persisted.anchorIndex > previous.anchorIndex && persisted.entryIds[previous.anchorIndex] === previous.anchorId)
37351
37643
  active.inputBranch = persisted;
37352
37644
  }
37353
- if (!active.dispatched)
37354
- active.dispatchFields = fields;
37645
+ if (chained)
37646
+ active.chainDispatchFields ??= fields;
37647
+ else
37648
+ active.dispatchFields ??= fields;
37355
37649
  active.dispatched = true;
37650
+ const chain = chains.get(key);
37651
+ if (chain?.anchor && active.pass)
37652
+ chain.anchor.supersededBy ??= active.pass;
37653
+ const sentInput = chainInput ?? (Array.isArray(body?.input) && body.messages === undefined ? [...body.input] : undefined);
37654
+ if (sentInput && active.preparedHistory)
37655
+ chains.set(key, {
37656
+ anchor: chain?.anchor,
37657
+ awaiting: { input: sentInput, prepared: active.preparedHistory }
37658
+ });
37659
+ else
37660
+ chains.delete(key);
37356
37661
  } catch (error) {
37357
37662
  if (signal ? signal.aborted : budget.isCancelled(error)) {
37358
37663
  budget.cancel();
@@ -37414,6 +37719,8 @@ function registerPiGuardedContext(pi, handler, options = {}) {
37414
37719
  result.messages = prepared.messages;
37415
37720
  active.managedSignature = piManagedSignature(result.messages);
37416
37721
  active.preparedStructure = prepared.structure;
37722
+ if (fenceEnabled && !budget.sideTurn && piChainCapableApi(ctx.model?.api))
37723
+ active.preparedHistory = piPreparedHistory(result.messages, ctx.model);
37417
37724
  budget.completed = true;
37418
37725
  active.ready = true;
37419
37726
  if (inputs)
@@ -43480,10 +43787,7 @@ function registerPiContextHandler(pi, baseOptions) {
43480
43787
  messages: inputForThinkingFit,
43481
43788
  forceSignedRebuildForFit: true,
43482
43789
  forceMaterialization: true,
43483
- contextUsage: {
43484
- ...pipelineArgs.contextUsage,
43485
- percentage: Math.max(95, pipelineArgs.contextUsage.percentage)
43486
- }
43790
+ contextUsage: pipelineArgs.contextUsage
43487
43791
  }));
43488
43792
  observePipelineResultForTests(sessionId, result);
43489
43793
  fitReclaimedThisPass = true;
@@ -43594,7 +43898,7 @@ function registerPiContextHandler(pi, baseOptions) {
43594
43898
  sessionMeta: freshMeta
43595
43899
  }) : undefined,
43596
43900
  contextUsage: {
43597
- percentage: fitCase === "over-window-proof" ? Math.max(95, usagePercentage) : usagePercentage,
43901
+ percentage: usagePercentage,
43598
43902
  inputTokens: usageInputTokens
43599
43903
  }
43600
43904
  }));
@@ -49219,6 +49523,178 @@ function bindStaleBuildNotice(ctx, moduleUrl) {
49219
49523
  });
49220
49524
  }
49221
49525
 
49526
+ // src/stream-tag-prefix-strip.ts
49527
+ var MAX_TAG_DIGITS = 12;
49528
+ var LEADING_NOTATION = new RegExp(`^\\s*(?:§\\d{1,${MAX_TAG_DIGITS}}§\\s*)*`);
49529
+ var UNFINISHED_HANDLE = new RegExp(`^§\\d{0,${MAX_TAG_DIGITS}}$`);
49530
+ function classifyStreamHead(text) {
49531
+ const leading = LEADING_NOTATION.exec(text)?.[0] ?? "";
49532
+ const rest = text.slice(leading.length);
49533
+ if (rest.length === 0 || UNFINISHED_HANDLE.test(rest))
49534
+ return { kind: "hold" };
49535
+ if (leading.includes("§"))
49536
+ return { kind: "strip", prefixLength: leading.length };
49537
+ return { kind: "pass" };
49538
+ }
49539
+ function visibleText(text, state) {
49540
+ if (state?.mode === "pass")
49541
+ return text;
49542
+ if (state?.mode === "stripped") {
49543
+ return text.startsWith(state.prefix) ? text.slice(state.prefix.length) : text;
49544
+ }
49545
+ const decision = classifyStreamHead(text);
49546
+ if (decision.kind === "hold")
49547
+ return "";
49548
+ if (decision.kind === "strip")
49549
+ return text.slice(decision.prefixLength);
49550
+ return text;
49551
+ }
49552
+ function isRecord7(value) {
49553
+ return value !== null && typeof value === "object";
49554
+ }
49555
+ function canWrite(obj, key) {
49556
+ const descriptor = Object.getOwnPropertyDescriptor(obj, key);
49557
+ if (descriptor === undefined)
49558
+ return Object.isExtensible(obj);
49559
+ return descriptor.writable === true;
49560
+ }
49561
+ function visibleContent(content, blocks) {
49562
+ if (!Array.isArray(content))
49563
+ return;
49564
+ let copy;
49565
+ for (let index = 0;index < content.length; index++) {
49566
+ const part = content[index];
49567
+ if (!isRecord7(part) || part.type !== "text" || typeof part.text !== "string")
49568
+ continue;
49569
+ const shown = visibleText(part.text, blocks.get(index));
49570
+ if (shown === part.text)
49571
+ continue;
49572
+ copy ??= content.slice();
49573
+ copy[index] = { ...part, text: shown };
49574
+ }
49575
+ return copy;
49576
+ }
49577
+ function rewriteMessageUpdateEvent(event, state) {
49578
+ if (state.disabled || !isRecord7(event))
49579
+ return;
49580
+ const message = event.message;
49581
+ const update = event.assistantMessageEvent;
49582
+ if (!isRecord7(message) || message.role !== "assistant" || !isRecord7(update))
49583
+ return;
49584
+ if (typeof update.type !== "string")
49585
+ return;
49586
+ const index = update.contentIndex;
49587
+ const hasIndex = typeof index === "number" && Number.isInteger(index) && index >= 0;
49588
+ const writes = [];
49589
+ let nextBlock;
49590
+ if (update.type === "text_start" && hasIndex) {
49591
+ nextBlock = { mode: "holding", held: "" };
49592
+ } else if (update.type === "text_delta" && hasIndex) {
49593
+ if (typeof update.delta !== "string")
49594
+ return;
49595
+ const current = state.blocks.get(index) ?? { mode: "holding", held: "" };
49596
+ if (current.mode === "holding") {
49597
+ const held = current.held + update.delta;
49598
+ const decision = classifyStreamHead(held);
49599
+ let shown;
49600
+ if (decision.kind === "hold") {
49601
+ nextBlock = { mode: "holding", held };
49602
+ shown = "";
49603
+ } else if (decision.kind === "strip") {
49604
+ nextBlock = {
49605
+ mode: "stripped",
49606
+ prefix: held.slice(0, decision.prefixLength)
49607
+ };
49608
+ shown = held.slice(decision.prefixLength);
49609
+ } else {
49610
+ nextBlock = { mode: "pass" };
49611
+ shown = held;
49612
+ }
49613
+ if (shown !== update.delta)
49614
+ writes.push({ target: update, key: "delta", value: shown });
49615
+ }
49616
+ } else if (update.type === "text_end" && hasIndex) {
49617
+ if (typeof update.content !== "string")
49618
+ return;
49619
+ const current = state.blocks.get(index);
49620
+ const shown = visibleText(update.content, current);
49621
+ if (current === undefined || current.mode === "holding") {
49622
+ nextBlock = shown === "" ? { mode: "stripped", prefix: update.content } : shown === update.content ? { mode: "pass" } : {
49623
+ mode: "stripped",
49624
+ prefix: update.content.slice(0, update.content.length - shown.length)
49625
+ };
49626
+ }
49627
+ if (shown !== update.content)
49628
+ writes.push({ target: update, key: "content", value: shown });
49629
+ }
49630
+ let blocks = state.blocks;
49631
+ if (nextBlock !== undefined && hasIndex) {
49632
+ blocks = new Map(state.blocks);
49633
+ blocks.set(index, nextBlock);
49634
+ }
49635
+ const messageContent = visibleContent(message.content, blocks);
49636
+ if (messageContent !== undefined) {
49637
+ writes.push({ target: message, key: "content", value: messageContent });
49638
+ }
49639
+ const partial = update.partial;
49640
+ if (isRecord7(partial)) {
49641
+ const partialContent = visibleContent(partial.content, blocks);
49642
+ if (partialContent !== undefined) {
49643
+ writes.push({
49644
+ target: update,
49645
+ key: "partial",
49646
+ value: { ...partial, content: partialContent }
49647
+ });
49648
+ }
49649
+ }
49650
+ if (!writes.every((write) => canWrite(write.target, write.key))) {
49651
+ state.disabled = true;
49652
+ return;
49653
+ }
49654
+ for (const write of writes) {
49655
+ write.target[write.key] = write.value;
49656
+ }
49657
+ if (nextBlock !== undefined && hasIndex)
49658
+ state.blocks.set(index, nextBlock);
49659
+ }
49660
+ function createMessageStreamState() {
49661
+ return { blocks: new Map, disabled: false };
49662
+ }
49663
+ function registerStreamTagPrefixStrip(pi, isActive) {
49664
+ const states = new WeakMap;
49665
+ const fallbackKey = {};
49666
+ const keyFor = (ctx) => {
49667
+ const sessionManager = isRecord7(ctx) ? ctx.sessionManager : undefined;
49668
+ return isRecord7(sessionManager) ? sessionManager : fallbackKey;
49669
+ };
49670
+ const isAssistant = (event) => isRecord7(event) && isRecord7(event.message) && event.message.role === "assistant";
49671
+ pi.on("message_start", (event, ctx) => {
49672
+ try {
49673
+ if (isAssistant(event))
49674
+ states.set(keyFor(ctx), createMessageStreamState());
49675
+ } catch {}
49676
+ });
49677
+ pi.on("message_update", (event, ctx) => {
49678
+ try {
49679
+ if (!isActive() || !isAssistant(event))
49680
+ return;
49681
+ const key = keyFor(ctx);
49682
+ let state = states.get(key);
49683
+ if (state === undefined) {
49684
+ state = createMessageStreamState();
49685
+ states.set(key, state);
49686
+ }
49687
+ rewriteMessageUpdateEvent(event, state);
49688
+ } catch {}
49689
+ });
49690
+ pi.on("message_end", (event, ctx) => {
49691
+ try {
49692
+ if (isAssistant(event))
49693
+ states.delete(keyFor(ctx));
49694
+ } catch {}
49695
+ });
49696
+ }
49697
+
49222
49698
  // src/strip-tag-prefix.ts
49223
49699
  function stripTagPrefixFromAssistantMessage(message) {
49224
49700
  if (message.role !== "assistant")
@@ -49241,6 +49717,41 @@ function stripTagPrefixFromAssistantMessage(message) {
49241
49717
  }
49242
49718
  return mutated;
49243
49719
  }
49720
+ function strippedAssistantContent(content) {
49721
+ if (!Array.isArray(content))
49722
+ return;
49723
+ let copy;
49724
+ for (let index = 0;index < content.length; index++) {
49725
+ const part = content[index];
49726
+ if (part === null || typeof part !== "object" || part.type !== "text") {
49727
+ continue;
49728
+ }
49729
+ if (typeof part.text !== "string")
49730
+ continue;
49731
+ const stripped = stripPersistedAssistantText(part.text);
49732
+ if (stripped === part.text)
49733
+ continue;
49734
+ copy ??= content.slice();
49735
+ copy[index] = { ...part, text: stripped };
49736
+ }
49737
+ return copy;
49738
+ }
49739
+ function registerOmpAssistantMessageStrip(pi, isActive) {
49740
+ const api = pi;
49741
+ api.on("assistant_message", (event) => {
49742
+ try {
49743
+ if (!isActive())
49744
+ return;
49745
+ const message = event?.message;
49746
+ if (message?.role !== "assistant")
49747
+ return;
49748
+ const content = strippedAssistantContent(message.content);
49749
+ return content === undefined ? undefined : { content };
49750
+ } catch {
49751
+ return;
49752
+ }
49753
+ });
49754
+ }
49244
49755
 
49245
49756
  // src/subagent-host-tools.ts
49246
49757
  function registerPiSubagentHostTools(pi, harness) {
@@ -50645,6 +51156,11 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
50645
51156
  }
50646
51157
  });
50647
51158
  pi.on("session_before_compact", async (_event, ctx) => handlePiSessionBeforeCompact({ db, compactionOff, ctx }));
51159
+ if (PI_HARNESS_KIND !== "omp") {
51160
+ registerStreamTagPrefixStrip(pi, () => !compactionOff);
51161
+ } else {
51162
+ registerOmpAssistantMessageStrip(pi, () => !compactionOff);
51163
+ }
50648
51164
  pi.on("message_end", async (event, ctx) => {
50649
51165
  try {
50650
51166
  const leafId = ctx.sessionManager.getLeafId();