pi-openai-toolkit 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +28 -0
- package/README.md +46 -6
- package/README_zh.md +46 -6
- package/package.json +126 -116
- package/src/config.ts +39 -0
- package/src/context-management/codex-provider.ts +261 -0
- package/src/context-management/history-notes.ts +325 -0
- package/src/context-management/messages.ts +106 -0
- package/src/context-management/namespace-tools.ts +426 -0
- package/src/context-management/tool-contract.ts +23 -0
- package/src/context-management/tools.ts +313 -0
- package/src/context-management/types.ts +160 -0
- package/src/context-management/window-budget.ts +83 -0
- package/src/context-management/window-manager.ts +427 -0
- package/src/context-management/window-request.ts +125 -0
- package/src/debug.ts +3 -3
- package/src/extension-runtime.ts +253 -11
- package/src/types.ts +17 -1
package/src/extension-runtime.ts
CHANGED
|
@@ -7,6 +7,15 @@ import type {
|
|
|
7
7
|
SessionBeforeCompactEvent,
|
|
8
8
|
} from "@earendil-works/pi-coding-agent";
|
|
9
9
|
import { loadToolkitConfig } from "./config";
|
|
10
|
+
import {
|
|
11
|
+
codexContextProviderHeaders,
|
|
12
|
+
resolveCodexContextProvider,
|
|
13
|
+
isCodexGatewayModel,
|
|
14
|
+
isNativeCodexModel,
|
|
15
|
+
} from "./context-management/codex-provider";
|
|
16
|
+
import { routeContextNamespaceToolMessage } from "./context-management/namespace-tools";
|
|
17
|
+
import { CodexContextWindowManager } from "./context-management/window-manager";
|
|
18
|
+
import { registerContextManagementTools } from "./context-management/tools";
|
|
10
19
|
import { writeDebugArtifact, writeReplayFailureArtifact } from "./debug";
|
|
11
20
|
import { resolveLatestNativeCompactionEntry } from "./details-store";
|
|
12
21
|
import { runNativeFallbackCompaction } from "./native-fallback";
|
|
@@ -38,8 +47,15 @@ type CompactionDependencies = {
|
|
|
38
47
|
loadConfig: typeof loadToolkitConfig;
|
|
39
48
|
remoteCompact: typeof executeRemoteV2Compaction;
|
|
40
49
|
nativeFallback: typeof runNativeFallbackCompaction;
|
|
50
|
+
contextWindows: CodexContextWindowManager;
|
|
41
51
|
};
|
|
42
52
|
|
|
53
|
+
type RemoteContextActive = (
|
|
54
|
+
ctx: ExtensionContext,
|
|
55
|
+
config: CompactionConfig,
|
|
56
|
+
model?: ExtensionContext["model"],
|
|
57
|
+
) => Promise<boolean>;
|
|
58
|
+
|
|
43
59
|
type ResponsesCompactOutcome =
|
|
44
60
|
| { outcome: "success"; compaction: CompactionResult<NativeCompactionDetails> }
|
|
45
61
|
| { outcome: "aborted" }
|
|
@@ -87,6 +103,29 @@ function notifyWarning(ctx: ExtensionContext, message: string): void {
|
|
|
87
103
|
}
|
|
88
104
|
}
|
|
89
105
|
|
|
106
|
+
async function isRemoteContextActive(
|
|
107
|
+
ctx: ExtensionContext,
|
|
108
|
+
config: CompactionConfig,
|
|
109
|
+
model: ExtensionContext["model"] = ctx.model,
|
|
110
|
+
): Promise<boolean> {
|
|
111
|
+
if (!config.enabled || config.contextManagement !== "remote") return false;
|
|
112
|
+
const resolution = await resolveCodexContextProvider(ctx, model, config.codexGatewayModels);
|
|
113
|
+
return resolution.ok;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function isCodexContextModel(
|
|
117
|
+
model: ExtensionContext["model"] | undefined,
|
|
118
|
+
config: CompactionConfig,
|
|
119
|
+
): boolean {
|
|
120
|
+
return isNativeCodexModel(model) || isCodexGatewayModel(model, config.codexGatewayModels);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function notifyRemoteContextFailure(ctx: ExtensionContext, reason: string): void {
|
|
124
|
+
if (ctx.hasUI) {
|
|
125
|
+
ctx.ui.notify(`${COMPACTION_EXTENSION_ID}: Remote Context management inactive (${reason})`, "warning");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
90
129
|
function cloneOpaqueWindow(window: readonly unknown[]): unknown[] {
|
|
91
130
|
return window.map((item) => structuredClone(item));
|
|
92
131
|
}
|
|
@@ -299,6 +338,7 @@ async function handleSessionBeforeCompact(
|
|
|
299
338
|
event: SessionBeforeCompactEvent,
|
|
300
339
|
ctx: ExtensionContext,
|
|
301
340
|
dependencies: CompactionDependencies,
|
|
341
|
+
remoteContextActive: RemoteContextActive,
|
|
302
342
|
) {
|
|
303
343
|
const { config: toolkitConfig } = dependencies.loadConfig();
|
|
304
344
|
const config = toolkitConfig.compaction;
|
|
@@ -327,6 +367,28 @@ async function handleSessionBeforeCompact(
|
|
|
327
367
|
return { cancel: true };
|
|
328
368
|
}
|
|
329
369
|
|
|
370
|
+
// Remote Context management owns this eligible Codex session. It persists a
|
|
371
|
+
// no-summary boundary and deliberately never calls remote_compaction_v2.
|
|
372
|
+
if (config.contextManagement === "remote" && isCodexContextModel(ctx.model, config)) {
|
|
373
|
+
if (await remoteContextActive(ctx, config)) {
|
|
374
|
+
try {
|
|
375
|
+
dependencies.contextWindows.synchronize(ctx);
|
|
376
|
+
return dependencies.contextWindows.prepareCompaction(event);
|
|
377
|
+
} catch {
|
|
378
|
+
notifyRemoteContextFailure(ctx, "malformed-window-state");
|
|
379
|
+
return { cancel: true };
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// A configured native Codex Remote session must never re-enter this
|
|
383
|
+
// extension's Remote V2 compaction chain, and Pi's native compaction is
|
|
384
|
+
// deliberately disabled for Remote-managed models: cancelling here keeps
|
|
385
|
+
// the boundary the only rollover mechanism. The inactive reason is
|
|
386
|
+
// surfaced so the user can fix activation instead of losing context to a
|
|
387
|
+
// silent native summary.
|
|
388
|
+
notifyRemoteContextFailure(ctx, "native-codex-context-unavailable");
|
|
389
|
+
return { cancel: true };
|
|
390
|
+
}
|
|
391
|
+
|
|
330
392
|
// Branch 1: Responses-family APIs use remote_compaction_v2 on the normal Responses stream.
|
|
331
393
|
let remoteAttempted = false;
|
|
332
394
|
const resolution = await resolveRemoteCompactionExecution(
|
|
@@ -426,11 +488,67 @@ async function handleSessionBeforeCompact(
|
|
|
426
488
|
return undefined;
|
|
427
489
|
}
|
|
428
490
|
|
|
429
|
-
async function handleContext(
|
|
491
|
+
async function handleContext(
|
|
492
|
+
event: ContextEvent,
|
|
493
|
+
ctx: ExtensionContext,
|
|
494
|
+
pi: ExtensionAPI,
|
|
495
|
+
loadConfig: typeof loadToolkitConfig,
|
|
496
|
+
contextWindows: CodexContextWindowManager,
|
|
497
|
+
remoteContextActive: RemoteContextActive,
|
|
498
|
+
) {
|
|
430
499
|
const { config: { compaction: config } } = loadConfig();
|
|
431
|
-
if (!config.enabled)
|
|
432
|
-
|
|
433
|
-
|
|
500
|
+
if (!config.enabled) {
|
|
501
|
+
const visibleMessages = contextWindows.project(event.messages, "off");
|
|
502
|
+
return visibleMessages.length === event.messages.length && visibleMessages.every((message, index) => message === event.messages[index])
|
|
503
|
+
? undefined
|
|
504
|
+
: { messages: visibleMessages };
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if (config.contextManagement === "remote") {
|
|
508
|
+
try {
|
|
509
|
+
contextWindows.synchronize(ctx);
|
|
510
|
+
} catch {
|
|
511
|
+
notifyRemoteContextFailure(ctx, "malformed-window-state");
|
|
512
|
+
ctx.abort();
|
|
513
|
+
return undefined;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const remoteActive = await remoteContextActive(ctx, config);
|
|
517
|
+
if (remoteActive) {
|
|
518
|
+
try {
|
|
519
|
+
contextWindows.recordBudget(
|
|
520
|
+
pi,
|
|
521
|
+
ctx,
|
|
522
|
+
true,
|
|
523
|
+
config.contextReminderThresholdPercent,
|
|
524
|
+
);
|
|
525
|
+
const projected = contextWindows.project(event.messages, "remote");
|
|
526
|
+
return projected.length === event.messages.length && projected.every((message, index) => message === event.messages[index])
|
|
527
|
+
? undefined
|
|
528
|
+
: { messages: projected };
|
|
529
|
+
} catch (error) {
|
|
530
|
+
notifyRemoteContextFailure(ctx, "malformed-window-state");
|
|
531
|
+
ctx.abort();
|
|
532
|
+
return undefined;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// An eligible Codex Remote session is never allowed to fall through to the
|
|
537
|
+
// older compaction-replay path. Keep its internal markers hidden, but let
|
|
538
|
+
// Pi's normal request construction handle the inactive session.
|
|
539
|
+
if (isCodexContextModel(ctx.model, config)) {
|
|
540
|
+
const visibleMessages = contextWindows.project(event.messages, "off");
|
|
541
|
+
return visibleMessages.length === event.messages.length && visibleMessages.every((message, index) => message === event.messages[index])
|
|
542
|
+
? undefined
|
|
543
|
+
: { messages: visibleMessages };
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Inactive/ineligible Remote mode must not expose internal window markers to a
|
|
548
|
+
// gateway or another provider. The existing compaction replay path remains the
|
|
549
|
+
// owner for this safe fallback.
|
|
550
|
+
const visibleMessages = contextWindows.project(event.messages, "off");
|
|
551
|
+
const replayEvent = visibleMessages === event.messages ? event : { ...event, messages: visibleMessages };
|
|
434
552
|
const resolution = await resolveNativeCompactionEnvironment(ctx, {
|
|
435
553
|
enabled: config.enabled,
|
|
436
554
|
responsesApis: config.responsesApis,
|
|
@@ -439,20 +557,22 @@ async function handleContext(event: ContextEvent, ctx: ExtensionContext, loadCon
|
|
|
439
557
|
const branchEntries = ctx.sessionManager.getBranch();
|
|
440
558
|
const latest = resolveLatestNativeCompactionEntry(branchEntries, { baseUrl: resolution.runtime.baseUrl });
|
|
441
559
|
if (!latest.ok) return undefined;
|
|
442
|
-
const result = removeNativeCompactionRetainedMessages({ messages:
|
|
560
|
+
const result = removeNativeCompactionRetainedMessages({ messages: replayEvent.messages, branchEntries, compactionEntry: latest.entry });
|
|
443
561
|
if (!result.ok) {
|
|
444
562
|
writeReplayFailureArtifact({ reason: result.reason, compactionEntryId: latest.entry.id }, config, ctx);
|
|
445
563
|
if (ctx.hasUI) ctx.ui.notify(`${COMPACTION_EXTENSION_ID}: replay failed (${result.reason}); request aborted`, "error");
|
|
446
564
|
ctx.abort();
|
|
447
565
|
return undefined;
|
|
448
566
|
}
|
|
449
|
-
return result.messages ===
|
|
567
|
+
return result.messages === replayEvent.messages ? undefined : { messages: result.messages };
|
|
450
568
|
}
|
|
451
569
|
|
|
452
570
|
async function handleBeforeProviderRequest(
|
|
453
571
|
event: BeforeProviderRequestEvent,
|
|
454
572
|
ctx: ExtensionContext,
|
|
455
573
|
loadConfig: typeof loadToolkitConfig,
|
|
574
|
+
contextWindows: CodexContextWindowManager,
|
|
575
|
+
remoteContextActive: RemoteContextActive,
|
|
456
576
|
) {
|
|
457
577
|
const { config: toolkitConfig } = loadConfig();
|
|
458
578
|
const config = toolkitConfig.compaction;
|
|
@@ -460,6 +580,30 @@ async function handleBeforeProviderRequest(
|
|
|
460
580
|
return undefined;
|
|
461
581
|
}
|
|
462
582
|
|
|
583
|
+
if (config.contextManagement === "remote") {
|
|
584
|
+
try {
|
|
585
|
+
contextWindows.synchronize(ctx);
|
|
586
|
+
} catch {
|
|
587
|
+
notifyRemoteContextFailure(ctx, "malformed-window-state");
|
|
588
|
+
ctx.abort();
|
|
589
|
+
return undefined;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
if (config.contextManagement === "remote" && await remoteContextActive(ctx, config)) {
|
|
593
|
+
try {
|
|
594
|
+
return contextWindows.rewritePayload(event.payload, ctx);
|
|
595
|
+
} catch {
|
|
596
|
+
notifyRemoteContextFailure(ctx, "malformed-request-state");
|
|
597
|
+
ctx.abort();
|
|
598
|
+
return undefined;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (config.contextManagement === "remote" && isCodexContextModel(ctx.model, config)) {
|
|
602
|
+
// Keep Codex Remote mutually exclusive with the legacy replay
|
|
603
|
+
// pipeline when authentication or tool ownership is unavailable.
|
|
604
|
+
return undefined;
|
|
605
|
+
}
|
|
606
|
+
|
|
463
607
|
const resolution = await resolveNativeCompactionEnvironment(
|
|
464
608
|
ctx,
|
|
465
609
|
{
|
|
@@ -613,17 +757,59 @@ export default function registerCompactionExtension(
|
|
|
613
757
|
pi: ExtensionAPI,
|
|
614
758
|
overrides: Partial<CompactionDependencies> = {},
|
|
615
759
|
) {
|
|
760
|
+
const loadConfig = overrides.loadConfig ?? loadToolkitConfig;
|
|
761
|
+
const contextWindows = overrides.contextWindows ?? new CodexContextWindowManager(
|
|
762
|
+
undefined,
|
|
763
|
+
() => loadConfig().config.compaction.codexGatewayModels,
|
|
764
|
+
);
|
|
616
765
|
const dependencies: CompactionDependencies = {
|
|
617
|
-
loadConfig
|
|
766
|
+
loadConfig,
|
|
618
767
|
remoteCompact: executeRemoteV2Compaction,
|
|
619
768
|
nativeFallback: runNativeFallbackCompaction,
|
|
769
|
+
contextWindows,
|
|
620
770
|
...overrides,
|
|
621
771
|
};
|
|
622
|
-
|
|
772
|
+
let tools!: ReturnType<typeof registerContextManagementTools>;
|
|
773
|
+
tools = registerContextManagementTools(
|
|
774
|
+
pi,
|
|
775
|
+
contextWindows,
|
|
776
|
+
async (ctx) => {
|
|
777
|
+
const config = dependencies.loadConfig().config.compaction;
|
|
778
|
+
return tools.isRegistered && await isRemoteContextActive(ctx, config);
|
|
779
|
+
},
|
|
780
|
+
() => dependencies.loadConfig().config.compaction.codexGatewayModels,
|
|
781
|
+
);
|
|
782
|
+
const remoteContextActive: RemoteContextActive = async (ctx, config, model = ctx.model) =>
|
|
783
|
+
tools.isRegistered && await isRemoteContextActive(ctx, config, model);
|
|
784
|
+
const syncTools = async (ctx: ExtensionContext, model = ctx.model): Promise<boolean> => {
|
|
785
|
+
const config = dependencies.loadConfig().config.compaction;
|
|
786
|
+
const active = await isRemoteContextActive(ctx, config, model);
|
|
787
|
+
return tools.sync(active);
|
|
788
|
+
};
|
|
789
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
790
|
+
const active = await syncTools(ctx);
|
|
623
791
|
const { config: toolkitConfig, source, warnings } = dependencies.loadConfig();
|
|
624
792
|
const config = toolkitConfig.compaction;
|
|
625
793
|
if (!config.enabled) return;
|
|
626
794
|
|
|
795
|
+
let activationReason: string | undefined;
|
|
796
|
+
if (config.contextManagement === "remote") {
|
|
797
|
+
if (active) {
|
|
798
|
+
try {
|
|
799
|
+
contextWindows.ensureInitialized(pi, ctx, true);
|
|
800
|
+
} catch {
|
|
801
|
+
notifyRemoteContextFailure(ctx, "malformed-window-state");
|
|
802
|
+
}
|
|
803
|
+
} else if (!tools.isRegistered) {
|
|
804
|
+
activationReason = "tool-name-conflict";
|
|
805
|
+
notifyRemoteContextFailure(ctx, activationReason);
|
|
806
|
+
} else {
|
|
807
|
+
const remoteResolution = await resolveCodexContextProvider(ctx, ctx.model, config.codexGatewayModels);
|
|
808
|
+
activationReason = remoteResolution.ok ? "codex-context-unavailable" : remoteResolution.reason;
|
|
809
|
+
notifyRemoteContextFailure(ctx, activationReason);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
627
813
|
if (warnings.length > 0 && ctx.hasUI && config.debug) {
|
|
628
814
|
ctx.ui.notify(`${COMPACTION_EXTENSION_ID}: ${warnings[0]}`, "warning");
|
|
629
815
|
}
|
|
@@ -635,6 +821,12 @@ export default function registerCompactionExtension(
|
|
|
635
821
|
config,
|
|
636
822
|
configSource: source,
|
|
637
823
|
warnings,
|
|
824
|
+
activation: {
|
|
825
|
+
active,
|
|
826
|
+
contextManagement: config.contextManagement,
|
|
827
|
+
model: ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined,
|
|
828
|
+
...(activationReason ? { reason: activationReason } : {}),
|
|
829
|
+
},
|
|
638
830
|
},
|
|
639
831
|
config,
|
|
640
832
|
ctx,
|
|
@@ -650,7 +842,57 @@ export default function registerCompactionExtension(
|
|
|
650
842
|
}
|
|
651
843
|
});
|
|
652
844
|
|
|
653
|
-
pi.on("context", (event, ctx) => handleContext(event, ctx, dependencies.loadConfig));
|
|
654
|
-
pi.on("session_before_compact", (event, ctx) => handleSessionBeforeCompact(event, ctx, dependencies));
|
|
655
|
-
pi.on("
|
|
845
|
+
pi.on("context", (event, ctx) => handleContext(event, ctx, pi, dependencies.loadConfig, contextWindows, remoteContextActive));
|
|
846
|
+
pi.on("session_before_compact", (event, ctx) => handleSessionBeforeCompact(event, ctx, dependencies, remoteContextActive));
|
|
847
|
+
pi.on("session_compact", (event, _ctx) => contextWindows.recordCompaction(event.compactionEntry.details));
|
|
848
|
+
pi.on("session_shutdown", () => {
|
|
849
|
+
contextWindows.reset();
|
|
850
|
+
tools.reset();
|
|
851
|
+
});
|
|
852
|
+
pi.on("model_select", async (event, ctx) => {
|
|
853
|
+
await syncTools(ctx, event.model);
|
|
854
|
+
});
|
|
855
|
+
pi.on("before_agent_start", async (_event, ctx) => {
|
|
856
|
+
await syncTools(ctx);
|
|
857
|
+
});
|
|
858
|
+
pi.on("before_provider_request", (event, ctx) => handleBeforeProviderRequest(event, ctx, dependencies.loadConfig, contextWindows, remoteContextActive));
|
|
859
|
+
pi.on("before_provider_headers", async (event, ctx) => {
|
|
860
|
+
const config = dependencies.loadConfig().config.compaction;
|
|
861
|
+
if (config.contextManagement !== "remote" || !isCodexContextModel(ctx.model, config)) return;
|
|
862
|
+
if (!(await remoteContextActive(ctx, config))) return;
|
|
863
|
+
const provider = await resolveCodexContextProvider(ctx, ctx.model, config.codexGatewayModels);
|
|
864
|
+
if (provider.ok && provider.provider.kind === "codex-gateway") {
|
|
865
|
+
const sessionId = getSessionId(ctx);
|
|
866
|
+
const gatewayHeaders = codexContextProviderHeaders(provider.provider, {
|
|
867
|
+
sessionId,
|
|
868
|
+
clientRequestId: sessionId,
|
|
869
|
+
});
|
|
870
|
+
for (const name of [
|
|
871
|
+
"authorization",
|
|
872
|
+
"originator",
|
|
873
|
+
"user-agent",
|
|
874
|
+
"version",
|
|
875
|
+
"session-id",
|
|
876
|
+
"x-client-request-id",
|
|
877
|
+
"x-codex-affinity-scope",
|
|
878
|
+
"x-codex-model",
|
|
879
|
+
]) {
|
|
880
|
+
for (const existing of Object.keys(event.headers)) {
|
|
881
|
+
if (existing.toLowerCase() === name) delete event.headers[existing];
|
|
882
|
+
}
|
|
883
|
+
const value = gatewayHeaders.get(name);
|
|
884
|
+
if (value) event.headers[name] = value;
|
|
885
|
+
}
|
|
886
|
+
for (const existing of Object.keys(event.headers)) {
|
|
887
|
+
if (["cookie", "chatgpt-account-id", "x-api-key"].includes(existing.toLowerCase())) delete event.headers[existing];
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
contextWindows.rewriteHeaders(event.headers, ctx);
|
|
891
|
+
});
|
|
892
|
+
pi.on("message_end", (event, ctx) => {
|
|
893
|
+
const config = dependencies.loadConfig().config.compaction;
|
|
894
|
+
if (config.contextManagement !== "remote" || !isCodexContextModel(ctx.model, config) || !tools.isRegistered) return undefined;
|
|
895
|
+
const message = routeContextNamespaceToolMessage(event.message);
|
|
896
|
+
return message === event.message ? undefined : { message };
|
|
897
|
+
});
|
|
656
898
|
}
|
package/src/types.ts
CHANGED
|
@@ -38,6 +38,8 @@ export type DebugArtifactKind =
|
|
|
38
38
|
| "compaction-event"
|
|
39
39
|
| "lifecycle";
|
|
40
40
|
|
|
41
|
+
export type ContextManagementMode = "off" | "remote";
|
|
42
|
+
|
|
41
43
|
/** Native-method fallback compaction: which model runs pi's compact() and how deeply. */
|
|
42
44
|
export type NativeFallbackConfig = {
|
|
43
45
|
enabled: boolean;
|
|
@@ -54,6 +56,10 @@ export type NativeFallbackConfig = {
|
|
|
54
56
|
|
|
55
57
|
export type CompactionConfig = {
|
|
56
58
|
enabled: boolean;
|
|
59
|
+
/** Optional Codex Remote Context management. Disabled by default for compatibility. */
|
|
60
|
+
contextManagement: ContextManagementMode;
|
|
61
|
+
/** Exact provider/model specs allowed to use the extension's CPA-backed Codex gateway. */
|
|
62
|
+
codexGatewayModels: string[];
|
|
57
63
|
/**
|
|
58
64
|
* Allow a Responses session whose latest compaction was not created by this extension
|
|
59
65
|
* to restart native compaction from Pi's current serialized session context.
|
|
@@ -66,8 +72,15 @@ export type CompactionConfig = {
|
|
|
66
72
|
remoteCompactModel?: string;
|
|
67
73
|
/** Native-method fallback compaction policy (non-Responses APIs, or when the compact endpoint fails). */
|
|
68
74
|
nativeFallback: NativeFallbackConfig;
|
|
69
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* Subset of RESPONSES_COMPACT_CAPABLE_APIS that should use remote compaction.
|
|
77
|
+
*/
|
|
70
78
|
responsesApis: string[];
|
|
79
|
+
/**
|
|
80
|
+
* Percentage of the context window that, when remaining tokens drop below it,
|
|
81
|
+
* triggers a checkpoint/new_context reminder (0-100; 0 disables reminders).
|
|
82
|
+
*/
|
|
83
|
+
contextReminderThresholdPercent: number;
|
|
71
84
|
notifyOnLoad: boolean;
|
|
72
85
|
debug: boolean;
|
|
73
86
|
logProviderPayloads: boolean;
|
|
@@ -491,10 +504,13 @@ export const DEFAULT_NATIVE_FALLBACK_CONFIG: NativeFallbackConfig = {
|
|
|
491
504
|
|
|
492
505
|
export const DEFAULT_COMPACTION_CONFIG: CompactionConfig = {
|
|
493
506
|
enabled: true,
|
|
507
|
+
contextManagement: "off",
|
|
508
|
+
codexGatewayModels: [],
|
|
494
509
|
allowCompactionContinuityBreak: false,
|
|
495
510
|
remoteCompactModel: undefined,
|
|
496
511
|
nativeFallback: { ...DEFAULT_NATIVE_FALLBACK_CONFIG },
|
|
497
512
|
responsesApis: [...RESPONSES_COMPACT_CAPABLE_APIS],
|
|
513
|
+
contextReminderThresholdPercent: 5,
|
|
498
514
|
notifyOnLoad: false,
|
|
499
515
|
debug: false,
|
|
500
516
|
logProviderPayloads: false,
|