pi-openai-toolkit 0.14.7 → 0.14.9

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 (47) hide show
  1. package/README.md +37 -8
  2. package/README.zh.md +37 -8
  3. package/docs/internals.md +27 -1
  4. package/extensions/auto-mode.ts +1 -1
  5. package/extensions/codex-astra.ts +1 -1
  6. package/extensions/compaction.ts +1 -1
  7. package/extensions/image-generation.ts +1 -1
  8. package/extensions/web-search.ts +1 -1
  9. package/package.json +6 -2
  10. package/src/auto-mode/classifier.ts +165 -165
  11. package/src/auto-mode/extension.ts +129 -20
  12. package/src/auto-mode/policy.ts +146 -146
  13. package/src/auto-mode/prompt.ts +279 -279
  14. package/src/auto-mode/reviewer.ts +325 -325
  15. package/src/auto-mode/tool-review-tui.ts +211 -0
  16. package/src/auto-mode/transcript.ts +133 -133
  17. package/src/auto-mode/types.ts +137 -137
  18. package/src/codex-astra/effort-planner.ts +175 -175
  19. package/src/codex-astra/extension.ts +122 -122
  20. package/src/compaction-projection.ts +31 -0
  21. package/src/config.ts +100 -1
  22. package/src/context-management/messages.ts +112 -112
  23. package/src/context-management/namespace-tools.ts +426 -426
  24. package/src/context-management/tool-contract.ts +23 -23
  25. package/src/context-management/tools.ts +291 -279
  26. package/src/context-management/window-budget.ts +83 -83
  27. package/src/context-management/window-manager.ts +110 -28
  28. package/src/context-management/window-request.ts +125 -125
  29. package/src/extension-runtime.ts +263 -34
  30. package/src/image-generation/artifacts.ts +237 -237
  31. package/src/image-generation/client.ts +248 -248
  32. package/src/image-generation/eligibility.ts +18 -18
  33. package/src/image-generation/references.ts +194 -194
  34. package/src/image-generation/render.ts +252 -252
  35. package/src/model-scope.ts +17 -17
  36. package/src/payload-rewrite.ts +55 -10
  37. package/src/pi-context-hook.ts +116 -0
  38. package/src/provider-headers.ts +23 -23
  39. package/src/request-context-cache.ts +16 -1
  40. package/src/runtime.ts +52 -0
  41. package/src/types.ts +46 -0
  42. package/src/web-search/alpha-client.ts +875 -0
  43. package/src/web-search/extension.ts +523 -80
  44. package/src/web-search/payload.ts +295 -96
  45. package/src/web-search/prompt.ts +59 -20
  46. package/src/web-search/types.ts +144 -45
  47. package/tsconfig.check.json +2 -0
@@ -1,3 +1,4 @@
1
+ import type { AgentMessage } from "@earendil-works/pi-agent-core";
1
2
  import type {
2
3
  BeforeProviderRequestEvent,
3
4
  ContextEvent,
@@ -18,8 +19,22 @@ import { loadHistoryNotesThreadHint } from "./context-management/history-notes";
18
19
  import { CodexContextWindowManager } from "./context-management/window-manager";
19
20
  import { registerContextManagementTools } from "./context-management/tools";
20
21
  import { writeDebugArtifact, writeReplayFailureArtifact } from "./debug";
22
+ import {
23
+ COMPACTION_CHECKPOINT_PROVENANCE_UNAVAILABLE,
24
+ COMPACTION_PROJECTION_UNAVAILABLE,
25
+ COMPACTION_SESSION_CONTEXT_UNAVAILABLE,
26
+ COMPACTION_PROJECTED_CONTEXT_UNAVAILABLE,
27
+ hasVerifiedCompactionInputProvenance,
28
+ type UnprojectedCompactionReason,
29
+ } from "./compaction-projection";
21
30
  import { CODEX_GATEWAY_FORWARD_HEADERS } from "./responses-headers";
22
31
  import { resolveLatestNativeCompactionEntry } from "./details-store";
32
+ import {
33
+ getPiContextHookProjector,
34
+ installPiContextHookPatch,
35
+ reportPiContextHookFailure,
36
+ type PiContextHookPatchResult,
37
+ } from "./pi-context-hook";
23
38
  import { runNativeFallbackCompaction } from "./native-fallback";
24
39
  import {
25
40
  rewriteResponsesPayloadWithNativeReplay,
@@ -27,29 +42,44 @@ import {
27
42
  serializeLiveTailToResponsesInput,
28
43
  } from "./payload-rewrite";
29
44
  import { getCompactionRequestExtras, rememberRequestContext } from "./request-context-cache";
45
+ import { resolveWebSearchRoute } from "./web-search/types";
30
46
  import { executeRemoteV2Compaction } from "./remote-v2-client";
31
47
  import {
32
48
  resolveNativeCompactionEnvironment,
33
49
  resolveRemoteCompactionExecution,
34
50
  type RemoteCompactionExecution,
35
51
  } from "./runtime";
36
- import { serializeMessagesToCompactRequest, type NativeCompactionRequestBody, type ResponsesInputItem } from "./serializer";
52
+ import {
53
+ serializeMessagesToCompactRequest,
54
+ serializeMessagesToResponsesInput,
55
+ type NativeCompactionRequestBody,
56
+ type ResponsesInputItem,
57
+ } from "./serializer";
37
58
  import {
38
59
  createNativeCompactionDetails,
39
60
  createNativeCompactionResult,
40
61
  COMPACTION_EXTENSION_ID,
41
62
  getLatestDeferredToolCarryover,
63
+ getRemoteV2InputProvenance,
42
64
  isNativeCompactionDetails,
43
65
  type CompactionConfig,
44
66
  type NativeCompactionDetails,
45
67
  type NativeCompactionRequestMeta,
46
68
  } from "./types";
47
69
 
70
+ type CompactionContextProjection = (
71
+ messages: readonly AgentMessage[],
72
+ ctx: ExtensionContext,
73
+ ) => readonly AgentMessage[] | undefined | Promise<readonly AgentMessage[] | undefined>;
74
+
48
75
  type CompactionDependencies = {
49
76
  loadConfig: typeof loadToolkitConfig;
50
77
  remoteCompact: typeof executeRemoteV2Compaction;
51
78
  nativeFallback: typeof runNativeFallbackCompaction;
52
79
  contextWindows: CodexContextWindowManager;
80
+ /** Test seam for the same ordered projection exposed by the Pi host patch. */
81
+ projectCompactionContext?: CompactionContextProjection;
82
+ piContextHookPatch: PiContextHookPatchResult;
53
83
  };
54
84
 
55
85
  type RemoteContextActive = (
@@ -61,7 +91,11 @@ type RemoteContextActive = (
61
91
  type ResponsesCompactOutcome =
62
92
  | { outcome: "success"; compaction: CompactionResult<NativeCompactionDetails> }
63
93
  | { outcome: "aborted" }
64
- | { outcome: "failed" };
94
+ | { outcome: "failed" }
95
+ | {
96
+ outcome: "unprojected-input";
97
+ reason: UnprojectedCompactionReason;
98
+ };
65
99
 
66
100
  function buildCompactionRequestMeta(event: SessionBeforeCompactEvent): NativeCompactionRequestMeta {
67
101
  return {
@@ -142,12 +176,86 @@ function buildCompactionInstructions(systemPrompt: string, customInstructions?:
142
176
  return `${systemPrompt}\n\nAdditional user guidance for this manual /compact request:\n${guidance}`;
143
177
  }
144
178
 
179
+ function findLatestProjectedCompactionSummaryIndex(
180
+ messages: readonly AgentMessage[],
181
+ summary: string,
182
+ ): number {
183
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
184
+ const message = messages[index];
185
+ if (message?.role === "compactionSummary" && message.summary === summary) {
186
+ return index;
187
+ }
188
+ }
189
+
190
+ return -1;
191
+ }
192
+
193
+ type SessionManagerWithOptionalContext = ExtensionContext["sessionManager"] & {
194
+ buildSessionContext?: () => { messages?: readonly AgentMessage[] };
195
+ };
196
+
197
+ function readSessionContextMessages(ctx: ExtensionContext): AgentMessage[] | undefined {
198
+ const sessionManager = ctx.sessionManager as SessionManagerWithOptionalContext;
199
+ if (typeof sessionManager.buildSessionContext !== "function") {
200
+ return undefined;
201
+ }
202
+
203
+ try {
204
+ const sessionContext = sessionManager.buildSessionContext();
205
+ if (!sessionContext || !Array.isArray(sessionContext.messages)) {
206
+ return undefined;
207
+ }
208
+ return structuredClone([...sessionContext.messages]);
209
+ } catch {
210
+ return undefined;
211
+ }
212
+ }
213
+
214
+ type CompactionProjectionResult =
215
+ | { ok: true; messages: readonly AgentMessage[] }
216
+ | { ok: false; reason: typeof COMPACTION_PROJECTION_UNAVAILABLE | typeof COMPACTION_SESSION_CONTEXT_UNAVAILABLE };
217
+
218
+ async function projectSessionContextForCompaction(
219
+ ctx: ExtensionContext,
220
+ projectCompactionContext: CompactionContextProjection | undefined,
221
+ ): Promise<CompactionProjectionResult> {
222
+ const messages = readSessionContextMessages(ctx);
223
+ if (!messages) {
224
+ return { ok: false, reason: COMPACTION_SESSION_CONTEXT_UNAVAILABLE };
225
+ }
226
+
227
+ const projector = projectCompactionContext ?? getPiContextHookProjector(ctx);
228
+ if (!projector) {
229
+ return { ok: false, reason: COMPACTION_PROJECTION_UNAVAILABLE };
230
+ }
231
+
232
+ try {
233
+ const projected = await projector(messages, ctx);
234
+ return Array.isArray(projected)
235
+ ? { ok: true, messages: projected }
236
+ : { ok: false, reason: COMPACTION_PROJECTION_UNAVAILABLE };
237
+ } catch {
238
+ return { ok: false, reason: COMPACTION_PROJECTION_UNAVAILABLE };
239
+ }
240
+ }
241
+
242
+ function getLegacySessionContextMessages(
243
+ event: SessionBeforeCompactEvent,
244
+ ctx: ExtensionContext,
245
+ ): AgentMessage[] {
246
+ return readSessionContextMessages(ctx) ?? [
247
+ ...event.preparation.messagesToSummarize,
248
+ ...event.preparation.turnPrefixMessages,
249
+ ];
250
+ }
251
+
145
252
  async function runResponsesNativeCompact(
146
253
  event: SessionBeforeCompactEvent,
147
254
  ctx: ExtensionContext,
148
255
  config: CompactionConfig,
149
256
  execution: RemoteCompactionExecution,
150
257
  remoteCompact: typeof executeRemoteV2Compaction,
258
+ projectCompactionContext: CompactionContextProjection | undefined,
151
259
  ): Promise<ResponsesCompactOutcome> {
152
260
  const { consumer, compactor } = execution;
153
261
  const instructions = buildCompactionInstructions(ctx.getSystemPrompt(), event.customInstructions);
@@ -157,24 +265,61 @@ async function runResponsesNativeCompact(
157
265
  baseUrl: consumer.baseUrl,
158
266
  });
159
267
 
268
+ const inputProvenance = getRemoteV2InputProvenance(config.remoteV2ContextSource);
160
269
  let requestSource: "session-context" | "non-native-session-context" | "latest-native-replay";
161
270
  let request: NativeCompactionRequestBody;
162
271
  if (latestNativeCompaction.ok) {
163
- const liveTailEntries = branchEntries.slice(latestNativeCompaction.index + 1);
164
272
  const details = latestNativeCompaction.entry.details;
165
273
  if (!details) {
166
274
  return { outcome: "failed" };
167
275
  }
276
+ if (!hasVerifiedCompactionInputProvenance(details, inputProvenance)) {
277
+ return {
278
+ outcome: "unprojected-input",
279
+ reason: COMPACTION_CHECKPOINT_PROVENANCE_UNAVAILABLE,
280
+ };
281
+ }
168
282
  requestSource = "latest-native-replay";
169
- const input: ResponsesInputItem[] = [
170
- ...(cloneOpaqueWindow(details.compactedWindow) as ResponsesInputItem[]),
171
- ...serializeLiveTailToResponsesInput({ model: compactor.currentModel, entries: liveTailEntries }),
172
- ];
173
- request = {
174
- model: compactor.model,
175
- input,
176
- instructions,
177
- };
283
+
284
+ if (config.remoteV2ContextSource === "pi-context-hook") {
285
+ const projection = await projectSessionContextForCompaction(ctx, projectCompactionContext);
286
+ if (!projection.ok) {
287
+ return { outcome: "unprojected-input", reason: projection.reason };
288
+ }
289
+ const summaryIndex = findLatestProjectedCompactionSummaryIndex(
290
+ projection.messages,
291
+ latestNativeCompaction.entry.summary,
292
+ );
293
+ if (summaryIndex < 0) {
294
+ return {
295
+ outcome: "unprojected-input",
296
+ reason: COMPACTION_PROJECTED_CONTEXT_UNAVAILABLE,
297
+ };
298
+ }
299
+ const input: ResponsesInputItem[] = [
300
+ ...(cloneOpaqueWindow(details.compactedWindow) as ResponsesInputItem[]),
301
+ ...serializeMessagesToResponsesInput(
302
+ compactor.currentModel,
303
+ [...projection.messages.slice(summaryIndex + 1)],
304
+ ),
305
+ ];
306
+ request = {
307
+ model: compactor.model,
308
+ input,
309
+ instructions,
310
+ };
311
+ } else {
312
+ const liveTailEntries = branchEntries.slice(latestNativeCompaction.index + 1);
313
+ const input: ResponsesInputItem[] = [
314
+ ...(cloneOpaqueWindow(details.compactedWindow) as ResponsesInputItem[]),
315
+ ...serializeLiveTailToResponsesInput({ model: compactor.currentModel, entries: liveTailEntries }),
316
+ ];
317
+ request = {
318
+ model: compactor.model,
319
+ input,
320
+ instructions,
321
+ };
322
+ }
178
323
  } else if (
179
324
  latestNativeCompaction.reason === "no-compaction" ||
180
325
  (latestNativeCompaction.reason === "latest-compaction-not-native" &&
@@ -182,18 +327,23 @@ async function runResponsesNativeCompact(
182
327
  ) {
183
328
  requestSource =
184
329
  latestNativeCompaction.reason === "no-compaction" ? "session-context" : "non-native-session-context";
185
- const sessionManagerWithContext = ctx.sessionManager as typeof ctx.sessionManager & {
186
- buildSessionContext?: () => { messages: Parameters<typeof serializeMessagesToCompactRequest>[0]["messages"] };
187
- };
188
- const messages = sessionManagerWithContext.buildSessionContext?.().messages ?? [
189
- ...event.preparation.messagesToSummarize,
190
- ...event.preparation.turnPrefixMessages,
191
- ];
192
- request = serializeMessagesToCompactRequest({
193
- model: compactor.currentModel,
194
- messages,
195
- instructions,
196
- });
330
+ if (config.remoteV2ContextSource === "pi-context-hook") {
331
+ const projection = await projectSessionContextForCompaction(ctx, projectCompactionContext);
332
+ if (!projection.ok) {
333
+ return { outcome: "unprojected-input", reason: projection.reason };
334
+ }
335
+ request = serializeMessagesToCompactRequest({
336
+ model: compactor.currentModel,
337
+ messages: [...projection.messages],
338
+ instructions,
339
+ });
340
+ } else {
341
+ request = serializeMessagesToCompactRequest({
342
+ model: compactor.currentModel,
343
+ messages: getLegacySessionContextMessages(event, ctx),
344
+ instructions,
345
+ });
346
+ }
197
347
  } else {
198
348
  writeDebugArtifact(
199
349
  "compaction-event",
@@ -275,6 +425,7 @@ async function runResponsesNativeCompact(
275
425
  compactResponseId: compactResult.compactResponseId,
276
426
  createdAt: compactResult.createdAt,
277
427
  requestMeta: buildCompactionRequestMeta(event),
428
+ inputProvenance,
278
429
  });
279
430
  } catch (error) {
280
431
  writeDebugArtifact(
@@ -324,6 +475,8 @@ async function runResponsesNativeCompact(
324
475
  baseUrl: compactor.baseUrl,
325
476
  },
326
477
  requestSource,
478
+ remoteV2ContextSource: config.remoteV2ContextSource,
479
+ inputProvenance,
327
480
  requestInputItems: request.input.length,
328
481
  requestExtras: extras ? Object.keys(extras) : [],
329
482
  compactResponseId: compactResult.compactResponseId,
@@ -405,13 +558,47 @@ async function handleSessionBeforeCompact(
405
558
  );
406
559
  if (resolution.ok) {
407
560
  remoteAttempted = true;
408
- const responsesOutcome = await runResponsesNativeCompact(event, ctx, config, resolution.execution, dependencies.remoteCompact);
561
+ const responsesOutcome = await runResponsesNativeCompact(
562
+ event,
563
+ ctx,
564
+ config,
565
+ resolution.execution,
566
+ dependencies.remoteCompact,
567
+ dependencies.projectCompactionContext,
568
+ );
409
569
  if (responsesOutcome.outcome === "success") {
410
570
  return { compaction: responsesOutcome.compaction };
411
571
  }
412
572
  if (responsesOutcome.outcome === "aborted") {
413
573
  return { cancel: true };
414
574
  }
575
+ if (responsesOutcome.outcome === "unprojected-input") {
576
+ const message = responsesOutcome.reason === COMPACTION_PROJECTION_UNAVAILABLE
577
+ ? "Pi's ordered context-hook projection is unavailable; Remote V2 was not sent raw session history."
578
+ : responsesOutcome.reason === COMPACTION_SESSION_CONTEXT_UNAVAILABLE
579
+ ? "Pi did not provide the current session context required by its context-hook projection."
580
+ : responsesOutcome.reason === COMPACTION_PROJECTED_CONTEXT_UNAVAILABLE
581
+ ? "Pi's projected context did not include the current compaction summary anchor."
582
+ : "The latest opaque checkpoint has no marker for the configured Remote V2 context source, or was created in the other mode.";
583
+ writeDebugArtifact(
584
+ "compaction-event",
585
+ {
586
+ event: "session_before_compact.remote-v2-unprojected-input",
587
+ reason: responsesOutcome.reason,
588
+ contextSource: config.remoteV2ContextSource,
589
+ inputProvenance: getRemoteV2InputProvenance(config.remoteV2ContextSource),
590
+ piContextHookPatch: dependencies.piContextHookPatch,
591
+ message,
592
+ },
593
+ config,
594
+ ctx,
595
+ );
596
+ notifyWarning(
597
+ ctx,
598
+ `Remote V2 compaction cancelled (${responsesOutcome.reason}); ${message} Keep the context-source setting aligned with the checkpoint or choose legacy mode explicitly.`,
599
+ );
600
+ return { cancel: true };
601
+ }
415
602
  // failed: fall through to the configured-model fallback below.
416
603
  } else {
417
604
  writeDebugArtifact(
@@ -492,7 +679,7 @@ async function handleSessionBeforeCompact(
492
679
  return undefined;
493
680
  }
494
681
 
495
- async function handleContext(
682
+ async function handleContextInternal(
496
683
  event: ContextEvent,
497
684
  ctx: ExtensionContext,
498
685
  pi: ExtensionAPI,
@@ -513,6 +700,7 @@ async function handleContext(
513
700
  contextWindows.synchronize(ctx);
514
701
  } catch {
515
702
  notifyRemoteContextFailure(ctx, "malformed-window-state");
703
+ reportPiContextHookFailure(ctx, "malformed-window-state");
516
704
  ctx.abort();
517
705
  return undefined;
518
706
  }
@@ -532,6 +720,7 @@ async function handleContext(
532
720
  : { messages: projected };
533
721
  } catch (error) {
534
722
  notifyRemoteContextFailure(ctx, "malformed-window-state");
723
+ reportPiContextHookFailure(ctx, "malformed-window-state");
535
724
  ctx.abort();
536
725
  return undefined;
537
726
  }
@@ -544,6 +733,7 @@ async function handleContext(
544
733
  if (isCodexContextModel(ctx.model, config)) {
545
734
  if (isCodexGatewayModel(ctx.model, config.gatewayContextModels)) {
546
735
  notifyRemoteContextFailure(ctx, "codex-context-unavailable");
736
+ reportPiContextHookFailure(ctx, "codex-context-unavailable");
547
737
  ctx.abort();
548
738
  return undefined;
549
739
  }
@@ -568,16 +758,43 @@ async function handleContext(
568
758
  const branchEntries = ctx.sessionManager.getBranch();
569
759
  const latest = resolveLatestNativeCompactionEntry(branchEntries, { baseUrl: resolution.runtime.baseUrl });
570
760
  if (!latest.ok) return undefined;
571
- const result = removeNativeCompactionRetainedMessages({ messages: replayEvent.messages, branchEntries, compactionEntry: latest.entry });
761
+ const result = removeNativeCompactionRetainedMessages({
762
+ messages: replayEvent.messages,
763
+ branchEntries,
764
+ compactionEntry: latest.entry,
765
+ expectedInputProvenance: getRemoteV2InputProvenance(config.remoteV2ContextSource),
766
+ });
572
767
  if (!result.ok) {
573
768
  writeReplayFailureArtifact({ reason: result.reason, compactionEntryId: latest.entry.id }, config, ctx);
574
769
  if (ctx.hasUI) ctx.ui.notify(`${COMPACTION_EXTENSION_ID}: replay failed (${result.reason}); request aborted`, "error");
770
+ reportPiContextHookFailure(ctx, `replay-failed:${result.reason}`);
575
771
  ctx.abort();
576
772
  return undefined;
577
773
  }
578
774
  return result.messages === replayEvent.messages ? undefined : { messages: result.messages };
579
775
  }
580
776
 
777
+ /**
778
+ * Pi's emitContext() catches handler exceptions. Re-throw as usual for Pi, but
779
+ * also report the failure so the compaction projector cannot mistake the
780
+ * caught exception for a successful projection.
781
+ */
782
+ async function handleContext(
783
+ event: ContextEvent,
784
+ ctx: ExtensionContext,
785
+ pi: ExtensionAPI,
786
+ loadConfig: typeof loadToolkitConfig,
787
+ contextWindows: CodexContextWindowManager,
788
+ remoteContextActive: RemoteContextActive,
789
+ ) {
790
+ try {
791
+ return await handleContextInternal(event, ctx, pi, loadConfig, contextWindows, remoteContextActive);
792
+ } catch (error) {
793
+ reportPiContextHookFailure(ctx, error instanceof Error ? error.message : String(error));
794
+ throw error;
795
+ }
796
+ }
797
+
581
798
  async function handleBeforeProviderRequest(
582
799
  event: BeforeProviderRequestEvent,
583
800
  ctx: ExtensionContext,
@@ -660,13 +877,20 @@ async function handleBeforeProviderRequest(
660
877
  // synthetic compact request using the active consumer's effective runtime identity.
661
878
  // This hook runs before the separate Web Search transform, so injected native search
662
879
  // tools are not copied into remote_compaction_v2.
663
- rememberRequestContext(payload, {
664
- provider: runtime.provider,
665
- api: runtime.api,
666
- model: runtime.model,
667
- baseUrl: runtime.baseUrl,
668
- sessionId: getSessionId(ctx),
669
- });
880
+ const webSearchRoute = resolveWebSearchRoute({ model: ctx.model, config: toolkitConfig.webSearch });
881
+ rememberRequestContext(
882
+ payload,
883
+ {
884
+ provider: runtime.provider,
885
+ api: runtime.api,
886
+ model: runtime.model,
887
+ baseUrl: runtime.baseUrl,
888
+ sessionId: getSessionId(ctx),
889
+ },
890
+ {
891
+ excludeWebSearchTools: webSearchRoute.route === "standalone-alpha",
892
+ },
893
+ );
670
894
 
671
895
  const branchEntries = ctx.sessionManager.getBranch();
672
896
  const latestNativeCompaction = resolveLatestNativeCompactionEntry(branchEntries, {
@@ -699,6 +923,7 @@ async function handleBeforeProviderRequest(
699
923
  payload,
700
924
  branchEntries,
701
925
  compactionEntry: latestNativeCompactionEntry,
926
+ expectedInputProvenance: getRemoteV2InputProvenance(config.remoteV2ContextSource),
702
927
  });
703
928
  if (!rewrite.ok) {
704
929
  writeDebugArtifact(
@@ -776,6 +1001,7 @@ export default function registerCompactionExtension(
776
1001
  overrides: Partial<CompactionDependencies> = {},
777
1002
  ) {
778
1003
  const loadConfig = overrides.loadConfig ?? loadToolkitConfig;
1004
+ const piContextHookPatch = installPiContextHookPatch();
779
1005
  const contextWindows = overrides.contextWindows ?? new CodexContextWindowManager((ctx, signal) =>
780
1006
  loadHistoryNotesThreadHint(ctx, signal, loadConfig().config.compaction.gatewayContextModels)
781
1007
  );
@@ -785,6 +1011,7 @@ export default function registerCompactionExtension(
785
1011
  nativeFallback: runNativeFallbackCompaction,
786
1012
  contextWindows,
787
1013
  ...overrides,
1014
+ piContextHookPatch: overrides.piContextHookPatch ?? piContextHookPatch,
788
1015
  };
789
1016
  let tools!: ReturnType<typeof registerContextManagementTools>;
790
1017
  tools = registerContextManagementTools(
@@ -847,9 +1074,11 @@ export default function registerCompactionExtension(
847
1074
  activation: {
848
1075
  active,
849
1076
  contextManagement: config.contextManagement,
1077
+ remoteV2ContextSource: config.remoteV2ContextSource,
850
1078
  model: ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined,
851
1079
  ...(activationReason ? { reason: activationReason } : {}),
852
1080
  },
1081
+ piContextHookPatch: dependencies.piContextHookPatch,
853
1082
  },
854
1083
  config,
855
1084
  ctx,