@narumitw/pi-codex-compact 0.52.0 → 0.53.1
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/README.md +34 -46
- package/dist/chunks/{chunk-JYXZMCXD.js → chunk-7H7JJ7ZV.js} +9 -15
- package/dist/chunks/chunk-7H7JJ7ZV.js.map +7 -0
- package/dist/chunks/{settings-menu-VYQ6ABCP.js → settings-menu-OAWFW2PH.js} +5 -15
- package/dist/chunks/settings-menu-OAWFW2PH.js.map +7 -0
- package/dist/index.ts +91 -94
- package/dist/index.ts.map +2 -2
- package/package.json +53 -54
- package/src/checkpoint.ts +261 -249
- package/src/codex-compact.ts +250 -254
- package/src/model-api.ts +40 -29
- package/src/protocol.ts +293 -312
- package/src/remote-compact.ts +230 -252
- package/src/remote-shared.ts +12 -15
- package/src/remote-types.ts +27 -26
- package/src/remote-v2.ts +57 -61
- package/src/remote.ts +7 -9
- package/src/settings-menu.ts +207 -231
- package/src/settings.ts +227 -190
- package/src/terminal.ts +4 -4
- package/dist/chunks/chunk-JYXZMCXD.js.map +0 -7
- package/dist/chunks/settings-menu-VYQ6ABCP.js.map +0 -7
package/dist/index.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
2
|
// @ts-nocheck -- the generated entry uses a .ts extension for Pi's Jiti loader.
|
|
3
3
|
import {
|
|
4
|
-
RESPONSES_COMPACTION_APIS,
|
|
5
4
|
resolveCompactionRoute,
|
|
6
|
-
terminalText
|
|
7
|
-
|
|
8
|
-
} from "./chunks/chunk-JYXZMCXD.js";
|
|
5
|
+
terminalText
|
|
6
|
+
} from "./chunks/chunk-7H7JJ7ZV.js";
|
|
9
7
|
|
|
10
8
|
// src/codex-compact.ts
|
|
11
9
|
import {
|
|
@@ -39,9 +37,7 @@ function isCompactionItem(value) {
|
|
|
39
37
|
}
|
|
40
38
|
function validateCompactionItem(value, maxBytes = MAX_COMPACTION_ITEM_BYTES) {
|
|
41
39
|
if (!isCompactionItem(value)) {
|
|
42
|
-
throw new CodexCompactionProtocolError(
|
|
43
|
-
"Remote response did not contain a valid compaction item"
|
|
44
|
-
);
|
|
40
|
+
throw new CodexCompactionProtocolError("Remote response did not contain a valid compaction item");
|
|
45
41
|
}
|
|
46
42
|
if (byteLength(value) > maxBytes) {
|
|
47
43
|
throw new CodexCompactionProtocolError("Remote compaction item exceeded the size limit");
|
|
@@ -134,9 +130,7 @@ async function collectCompactionSse(stream, options = {}) {
|
|
|
134
130
|
reader.releaseLock();
|
|
135
131
|
}
|
|
136
132
|
if (!completedResponse) {
|
|
137
|
-
throw new CodexCompactionProtocolError(
|
|
138
|
-
"Remote compaction stream ended without response.completed"
|
|
139
|
-
);
|
|
133
|
+
throw new CodexCompactionProtocolError("Remote compaction stream ended without response.completed");
|
|
140
134
|
}
|
|
141
135
|
if (items.size !== 1) {
|
|
142
136
|
throw new CodexCompactionProtocolError(
|
|
@@ -177,9 +171,7 @@ function validateCompactedResponse(value, options = {}) {
|
|
|
177
171
|
throw new CodexCompactionProtocolError("Responses Compact returned a non-object output item");
|
|
178
172
|
}
|
|
179
173
|
if (byteLength(item2) > maxItemBytes) {
|
|
180
|
-
throw new CodexCompactionProtocolError(
|
|
181
|
-
"Responses Compact output item exceeded the size limit"
|
|
182
|
-
);
|
|
174
|
+
throw new CodexCompactionProtocolError("Responses Compact output item exceeded the size limit");
|
|
183
175
|
}
|
|
184
176
|
return structuredClone(item2);
|
|
185
177
|
});
|
|
@@ -191,9 +183,7 @@ function validateCompactedResponse(value, options = {}) {
|
|
|
191
183
|
}
|
|
192
184
|
for (const item2 of output.slice(0, -1)) {
|
|
193
185
|
if (!isRetainedCompactMessage(item2)) {
|
|
194
|
-
throw new CodexCompactionProtocolError(
|
|
195
|
-
"Responses Compact returned an unsupported retained output item"
|
|
196
|
-
);
|
|
186
|
+
throw new CodexCompactionProtocolError("Responses Compact returned an unsupported retained output item");
|
|
197
187
|
}
|
|
198
188
|
}
|
|
199
189
|
const item = validateCompactionItem(output.at(-1), maxItemBytes);
|
|
@@ -203,9 +193,7 @@ async function collectCompactResponse(response, options = {}) {
|
|
|
203
193
|
const maxBytes = options.maxBytes ?? MAX_COMPACT_JSON_BYTES;
|
|
204
194
|
const declaredLength = Number(response.headers.get("content-length"));
|
|
205
195
|
if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
|
|
206
|
-
const error = new CodexCompactionProtocolError(
|
|
207
|
-
"Responses Compact response exceeded the size limit"
|
|
208
|
-
);
|
|
196
|
+
const error = new CodexCompactionProtocolError("Responses Compact response exceeded the size limit");
|
|
209
197
|
await response.body?.cancel(error).catch(() => void 0);
|
|
210
198
|
throw error;
|
|
211
199
|
}
|
|
@@ -226,9 +214,7 @@ async function collectCompactResponse(response, options = {}) {
|
|
|
226
214
|
if (done) break;
|
|
227
215
|
bytes += value.byteLength;
|
|
228
216
|
if (bytes > maxBytes) {
|
|
229
|
-
throw new CodexCompactionProtocolError(
|
|
230
|
-
"Responses Compact response exceeded the size limit"
|
|
231
|
-
);
|
|
217
|
+
throw new CodexCompactionProtocolError("Responses Compact response exceeded the size limit");
|
|
232
218
|
}
|
|
233
219
|
chunks.push(value);
|
|
234
220
|
}
|
|
@@ -288,9 +274,7 @@ function appendCompactionTrigger(payload) {
|
|
|
288
274
|
throw new CodexCompactionProtocolError("Codex Responses payload is missing an input array");
|
|
289
275
|
}
|
|
290
276
|
if (payload.input.some((item) => isObject(item) && item.type === "compaction_trigger")) {
|
|
291
|
-
throw new CodexCompactionProtocolError(
|
|
292
|
-
"Provider payload already contains a compaction trigger"
|
|
293
|
-
);
|
|
277
|
+
throw new CodexCompactionProtocolError("Provider payload already contains a compaction trigger");
|
|
294
278
|
}
|
|
295
279
|
return { ...payload, input: [...payload.input, { type: "compaction_trigger" }] };
|
|
296
280
|
}
|
|
@@ -312,13 +296,14 @@ function hasCheckpointMarker(payload, marker) {
|
|
|
312
296
|
|
|
313
297
|
// src/checkpoint.ts
|
|
314
298
|
var CHECKPOINT_KIND = "pi-codex-remote-compaction";
|
|
315
|
-
var CHECKPOINT_VERSION =
|
|
299
|
+
var CHECKPOINT_VERSION = 3;
|
|
316
300
|
var REPLACEMENT_TOKEN_BUDGET = 64e3;
|
|
317
301
|
var REPLACEMENT_BYTE_BUDGET = 8 * 1024 * 1024;
|
|
318
302
|
var MAX_MEDIA_ITEM_BYTES = 2 * 1024 * 1024;
|
|
319
303
|
var MAX_CHECKPOINT_DETAILS_BYTES = 10 * 1024 * 1024;
|
|
320
304
|
var MAX_CHECKPOINT_ID_LENGTH = 128;
|
|
321
305
|
var MAX_PROVIDER_ID_LENGTH = 256;
|
|
306
|
+
var MAX_API_ID_LENGTH = 256;
|
|
322
307
|
var MAX_MODEL_ID_LENGTH = 512;
|
|
323
308
|
var MAX_KEPT_FINGERPRINTS = 1e5;
|
|
324
309
|
function isObject2(value) {
|
|
@@ -366,8 +351,14 @@ function parseCheckpointDetails(value) {
|
|
|
366
351
|
return void 0;
|
|
367
352
|
}
|
|
368
353
|
const isVersionOne = value.version === 1 && value.api === "openai-codex-responses" && value.protocol === "remote-compaction-v2";
|
|
369
|
-
const isVersionTwo = value.version ===
|
|
370
|
-
|
|
354
|
+
const isVersionTwo = value.version === 2 && (value.api === "openai-codex-responses" || value.api === "openai-responses" || value.api === "azure-openai-responses") && (value.protocol === "remote-v2" || value.protocol === "responses-compact");
|
|
355
|
+
const isVersionThree = value.version === CHECKPOINT_VERSION && typeof value.api === "string" && value.api.length > 0 && value.api.length <= MAX_API_ID_LENGTH && (value.profile === "codex-responses-v1" || value.profile === "openai-responses-v1") && (value.protocol === "remote-v2" || value.protocol === "responses-compact");
|
|
356
|
+
if (value.kind !== CHECKPOINT_KIND || !isVersionOne && !isVersionTwo && !isVersionThree || typeof value.checkpointId !== "string" || value.checkpointId.length < 8 || value.checkpointId.length > MAX_CHECKPOINT_ID_LENGTH || typeof value.provider !== "string" || value.provider.length === 0 || value.provider.length > MAX_PROVIDER_ID_LENGTH || typeof value.modelId !== "string" || value.modelId.length === 0 || value.modelId.length > MAX_MODEL_ID_LENGTH || !Array.isArray(value.replacementHistory) || !Array.isArray(value.keptMessageFingerprints) || value.keptMessageFingerprints.length > MAX_KEPT_FINGERPRINTS || typeof value.createdAt !== "string" || value.createdAt.length > 64) {
|
|
357
|
+
return void 0;
|
|
358
|
+
}
|
|
359
|
+
const api = value.api;
|
|
360
|
+
const profile = api === "openai-codex-responses" ? "codex-responses-v1" : api === "openai-responses" || api === "azure-openai-responses" ? "openai-responses-v1" : value.profile;
|
|
361
|
+
if (profile !== "codex-responses-v1" && profile !== "openai-responses-v1" || api !== "openai-codex-responses" && api !== "openai-responses" && api !== "azure-openai-responses" && profile !== "codex-responses-v1" || isVersionThree && value.profile !== profile) {
|
|
371
362
|
return void 0;
|
|
372
363
|
}
|
|
373
364
|
if (value.replacementHistory.length === 0 || !value.replacementHistory.every(isObject2) || !value.keptMessageFingerprints.every(
|
|
@@ -386,7 +377,8 @@ function parseCheckpointDetails(value) {
|
|
|
386
377
|
version: CHECKPOINT_VERSION,
|
|
387
378
|
checkpointId: value.checkpointId,
|
|
388
379
|
provider: value.provider,
|
|
389
|
-
api
|
|
380
|
+
api,
|
|
381
|
+
profile,
|
|
390
382
|
modelId: value.modelId,
|
|
391
383
|
protocol: isVersionOne ? "remote-v2" : value.protocol,
|
|
392
384
|
replacementHistory: structuredClone(value.replacementHistory),
|
|
@@ -467,8 +459,7 @@ function buildReplacementHistory(input, compactionItem, options = {}) {
|
|
|
467
459
|
const opaque = validateCompactionItem(compactionItem);
|
|
468
460
|
let remainingBytes = byteBudget - serializedBytes(opaque);
|
|
469
461
|
let remainingChars = tokenBudget * 4;
|
|
470
|
-
if (remainingBytes <= 0)
|
|
471
|
-
throw new Error("Opaque compaction item exceeds replacement history budget");
|
|
462
|
+
if (remainingBytes <= 0) throw new Error("Opaque compaction item exceeds replacement history budget");
|
|
472
463
|
const retainedNewestFirst = [];
|
|
473
464
|
const candidates = input.filter(
|
|
474
465
|
(item) => isObject2(item) && item.role === "user" && item.type !== "compaction_trigger"
|
|
@@ -506,6 +497,7 @@ function createCheckpointDetails(input) {
|
|
|
506
497
|
checkpointId: input.checkpointId ?? randomUUID(),
|
|
507
498
|
provider: input.provider,
|
|
508
499
|
api: input.api,
|
|
500
|
+
profile: input.profile,
|
|
509
501
|
modelId: input.modelId,
|
|
510
502
|
protocol: input.protocol,
|
|
511
503
|
replacementHistory: structuredClone(input.replacementHistory),
|
|
@@ -568,8 +560,8 @@ var CODEX_COMPACT_FIELDS = [
|
|
|
568
560
|
"text",
|
|
569
561
|
"access_programs"
|
|
570
562
|
];
|
|
571
|
-
function compactPayload(payload,
|
|
572
|
-
const fields =
|
|
563
|
+
function compactPayload(payload, profile) {
|
|
564
|
+
const fields = profile === "codex-responses-v1" ? CODEX_COMPACT_FIELDS : OFFICIAL_COMPACT_FIELDS;
|
|
573
565
|
const result = {};
|
|
574
566
|
for (const field of fields) {
|
|
575
567
|
if (Object.hasOwn(payload, field) && payload[field] !== void 0) {
|
|
@@ -588,9 +580,7 @@ function requestUrl(input) {
|
|
|
588
580
|
function responsesCompactUrl(input) {
|
|
589
581
|
const original = requestUrl(input);
|
|
590
582
|
if (!original.pathname.endsWith("/responses")) {
|
|
591
|
-
throw new CodexCompactionProtocolError(
|
|
592
|
-
"Provider request URL does not end with the Responses endpoint"
|
|
593
|
-
);
|
|
583
|
+
throw new CodexCompactionProtocolError("Provider request URL does not end with the Responses endpoint");
|
|
594
584
|
}
|
|
595
585
|
const compact = new URL(original);
|
|
596
586
|
compact.pathname = `${compact.pathname}/compact`;
|
|
@@ -640,9 +630,7 @@ function optionalUsageDetail(details, field) {
|
|
|
640
630
|
const value = details[field];
|
|
641
631
|
if (value === void 0 || value === null) return 0;
|
|
642
632
|
if (!nonNegativeInteger(value)) {
|
|
643
|
-
throw new CodexCompactionProtocolError(
|
|
644
|
-
`Responses Compact response has invalid usage detail ${field}`
|
|
645
|
-
);
|
|
633
|
+
throw new CodexCompactionProtocolError(`Responses Compact response has invalid usage detail ${field}`);
|
|
646
634
|
}
|
|
647
635
|
return value;
|
|
648
636
|
}
|
|
@@ -663,14 +651,10 @@ function validatedUsage(response) {
|
|
|
663
651
|
const cacheWriteTokens = optionalUsageDetail(usage.input_tokens_details, "cache_write_tokens");
|
|
664
652
|
const reasoningTokens = optionalUsageDetail(usage.output_tokens_details, "reasoning_tokens");
|
|
665
653
|
if (cachedTokens + cacheWriteTokens > inputTokens || reasoningTokens > outputTokens) {
|
|
666
|
-
throw new CodexCompactionProtocolError(
|
|
667
|
-
"Responses Compact response has inconsistent usage details"
|
|
668
|
-
);
|
|
654
|
+
throw new CodexCompactionProtocolError("Responses Compact response has inconsistent usage details");
|
|
669
655
|
}
|
|
670
656
|
if (totalTokens !== inputTokens + outputTokens) {
|
|
671
|
-
throw new CodexCompactionProtocolError(
|
|
672
|
-
"Responses Compact response has inconsistent total usage"
|
|
673
|
-
);
|
|
657
|
+
throw new CodexCompactionProtocolError("Responses Compact response has inconsistent total usage");
|
|
674
658
|
}
|
|
675
659
|
return structuredClone(usage);
|
|
676
660
|
}
|
|
@@ -710,21 +694,15 @@ async function requestResponsesCompact(request) {
|
|
|
710
694
|
const bridgeFetch = async (input, init) => {
|
|
711
695
|
if (request.signal.aborted) throw abortError();
|
|
712
696
|
if (successfulResponses > 0) {
|
|
713
|
-
bridgeError = new CodexCompactionProtocolError(
|
|
714
|
-
"Provider dispatched again after Responses Compact succeeded"
|
|
715
|
-
);
|
|
697
|
+
bridgeError = new CodexCompactionProtocolError("Provider dispatched again after Responses Compact succeeded");
|
|
716
698
|
return nonRetryableBridgeFailure(bridgeError);
|
|
717
699
|
}
|
|
718
700
|
if (dispatchInFlight) {
|
|
719
|
-
bridgeError = new CodexCompactionProtocolError(
|
|
720
|
-
"Provider dispatched overlapping Responses Compact requests"
|
|
721
|
-
);
|
|
701
|
+
bridgeError = new CodexCompactionProtocolError("Provider dispatched overlapping Responses Compact requests");
|
|
722
702
|
return nonRetryableBridgeFailure(bridgeError);
|
|
723
703
|
}
|
|
724
704
|
if (!preparedPayload) {
|
|
725
|
-
bridgeError = new CodexCompactionProtocolError(
|
|
726
|
-
"Provider dispatched before exposing its request payload"
|
|
727
|
-
);
|
|
705
|
+
bridgeError = new CodexCompactionProtocolError("Provider dispatched before exposing its request payload");
|
|
728
706
|
return nonRetryableBridgeFailure(bridgeError);
|
|
729
707
|
}
|
|
730
708
|
let compactUrl;
|
|
@@ -775,12 +753,10 @@ async function requestResponsesCompact(request) {
|
|
|
775
753
|
fetch: bridgeFetch,
|
|
776
754
|
onPayload: (payload) => {
|
|
777
755
|
if (preparedPayload) {
|
|
778
|
-
throw new CodexCompactionProtocolError(
|
|
779
|
-
"Provider exposed more than one compaction request payload"
|
|
780
|
-
);
|
|
756
|
+
throw new CodexCompactionProtocolError("Provider exposed more than one compaction request payload");
|
|
781
757
|
}
|
|
782
758
|
const expanded = expandRemoteCompactionPayload(payload, request.priorCheckpoint);
|
|
783
|
-
preparedPayload = compactPayload(expanded, request.
|
|
759
|
+
preparedPayload = compactPayload(expanded, request.profile);
|
|
784
760
|
sentInput = assertPreparedInput(preparedPayload);
|
|
785
761
|
return expanded;
|
|
786
762
|
}
|
|
@@ -795,9 +771,7 @@ async function requestResponsesCompact(request) {
|
|
|
795
771
|
if (request.signal.aborted) throw abortError();
|
|
796
772
|
if (bridgeError) throw bridgeError;
|
|
797
773
|
if (!preparedPayload || !sentInput || !compactResult || successfulResponses !== 1) {
|
|
798
|
-
throw new CodexCompactionProtocolError(
|
|
799
|
-
"Provider did not complete exactly one Responses Compact request"
|
|
800
|
-
);
|
|
774
|
+
throw new CodexCompactionProtocolError("Provider did not complete exactly one Responses Compact request");
|
|
801
775
|
}
|
|
802
776
|
return {
|
|
803
777
|
item: compactResult.item,
|
|
@@ -875,6 +849,7 @@ var MAX_SETTINGS_BYTES = 64 * 1024;
|
|
|
875
849
|
var DEFAULT_CODEX_COMPACT_SETTINGS = Object.freeze({
|
|
876
850
|
enabled: true,
|
|
877
851
|
protocol: "auto",
|
|
852
|
+
apiProfiles: {},
|
|
878
853
|
requestTimeoutMs: 3e5,
|
|
879
854
|
maxRetries: 2,
|
|
880
855
|
replacementTokenBudget: 64e3,
|
|
@@ -885,12 +860,44 @@ var LIMITS = Object.freeze({
|
|
|
885
860
|
maxRetries: { minimum: 0, maximum: 2 },
|
|
886
861
|
replacementTokenBudget: { minimum: 8e3, maximum: 128e3 }
|
|
887
862
|
});
|
|
863
|
+
var BUILT_IN_APIS = /* @__PURE__ */ new Set([
|
|
864
|
+
"openai-completions",
|
|
865
|
+
"mistral-conversations",
|
|
866
|
+
"openai-codex-responses",
|
|
867
|
+
"openai-responses",
|
|
868
|
+
"azure-openai-responses",
|
|
869
|
+
"anthropic-messages",
|
|
870
|
+
"bedrock-converse-stream",
|
|
871
|
+
"google-generative-ai",
|
|
872
|
+
"google-vertex",
|
|
873
|
+
"pi-messages"
|
|
874
|
+
]);
|
|
875
|
+
var MAX_API_PROFILE_ID_LENGTH = 256;
|
|
888
876
|
function isRecord(value) {
|
|
889
877
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
890
878
|
}
|
|
891
879
|
function validInteger(value, minimum, maximum) {
|
|
892
880
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= minimum && value <= maximum;
|
|
893
881
|
}
|
|
882
|
+
function hasWhitespaceOrControl(value) {
|
|
883
|
+
return [...value].some((character) => {
|
|
884
|
+
const code = character.codePointAt(0) ?? 0;
|
|
885
|
+
return code <= 32 || code === 127;
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
function normalizeApiProfiles(value) {
|
|
889
|
+
if (!isRecord(value) || Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
|
|
890
|
+
return void 0;
|
|
891
|
+
}
|
|
892
|
+
const profiles = {};
|
|
893
|
+
for (const [api, profile] of Object.entries(value)) {
|
|
894
|
+
if (api.length === 0 || api.length > MAX_API_PROFILE_ID_LENGTH || api.trim() !== api || hasWhitespaceOrControl(api) || BUILT_IN_APIS.has(api) || api === "__proto__" || api === "constructor" || api === "prototype" || profile !== "codex-responses-v1") {
|
|
895
|
+
return void 0;
|
|
896
|
+
}
|
|
897
|
+
profiles[api] = profile;
|
|
898
|
+
}
|
|
899
|
+
return profiles;
|
|
900
|
+
}
|
|
894
901
|
function normalizeCodexCompactSettings(value) {
|
|
895
902
|
if (!isRecord(value)) return void 0;
|
|
896
903
|
if (Object.hasOwn(value, "enabled") && typeof value.enabled !== "boolean") return void 0;
|
|
@@ -900,6 +907,7 @@ function normalizeCodexCompactSettings(value) {
|
|
|
900
907
|
if (Object.hasOwn(value, "notifyOnFallback") && typeof value.notifyOnFallback !== "boolean") {
|
|
901
908
|
return void 0;
|
|
902
909
|
}
|
|
910
|
+
if (Object.hasOwn(value, "apiProfiles") && normalizeApiProfiles(value.apiProfiles) === void 0) return void 0;
|
|
903
911
|
for (const [field, limits] of Object.entries(LIMITS)) {
|
|
904
912
|
if (Object.hasOwn(value, field) && !validInteger(value[field], limits.minimum, limits.maximum)) {
|
|
905
913
|
return void 0;
|
|
@@ -908,6 +916,7 @@ function normalizeCodexCompactSettings(value) {
|
|
|
908
916
|
return {
|
|
909
917
|
enabled: typeof value.enabled === "boolean" ? value.enabled : DEFAULT_CODEX_COMPACT_SETTINGS.enabled,
|
|
910
918
|
protocol: value.protocol === "remote-v2" || value.protocol === "responses-compact" ? value.protocol : DEFAULT_CODEX_COMPACT_SETTINGS.protocol,
|
|
919
|
+
apiProfiles: normalizeApiProfiles(value.apiProfiles) ?? structuredClone(DEFAULT_CODEX_COMPACT_SETTINGS.apiProfiles),
|
|
911
920
|
requestTimeoutMs: typeof value.requestTimeoutMs === "number" ? value.requestTimeoutMs : DEFAULT_CODEX_COMPACT_SETTINGS.requestTimeoutMs,
|
|
912
921
|
maxRetries: typeof value.maxRetries === "number" ? value.maxRetries : DEFAULT_CODEX_COMPACT_SETTINGS.maxRetries,
|
|
913
922
|
replacementTokenBudget: typeof value.replacementTokenBudget === "number" ? value.replacementTokenBudget : DEFAULT_CODEX_COMPACT_SETTINGS.replacementTokenBudget,
|
|
@@ -960,9 +969,7 @@ async function loadCodexCompactSettings(path = codexCompactSettingsPath(), signa
|
|
|
960
969
|
async function savePatch(path, patch, signal) {
|
|
961
970
|
const latest = await loadCodexCompactSettings(path, signal);
|
|
962
971
|
if (latest.kind === "invalid") {
|
|
963
|
-
throw new Error(
|
|
964
|
-
"Cannot overwrite an invalid pi-codex-compact.json; repair it and reload first"
|
|
965
|
-
);
|
|
972
|
+
throw new Error("Cannot overwrite an invalid pi-codex-compact.json; repair it and reload first");
|
|
966
973
|
}
|
|
967
974
|
const document = { ...latest.document, ...patch };
|
|
968
975
|
const settings = normalizeCodexCompactSettings(document);
|
|
@@ -1026,15 +1033,14 @@ var STATUS_KEY = "codex-compact";
|
|
|
1026
1033
|
function activeCheckpoint(ctx) {
|
|
1027
1034
|
return latestCheckpoint(ctx.sessionManager.getBranch());
|
|
1028
1035
|
}
|
|
1029
|
-
function isCheckpointCompatible(details, model) {
|
|
1030
|
-
|
|
1036
|
+
function isCheckpointCompatible(details, model, settings) {
|
|
1037
|
+
const route = resolveCompactionRoute(model, settings);
|
|
1038
|
+
return route.kind === "remote" && model !== void 0 && route.api === details.api && route.profile === details.profile && model.id === details.modelId;
|
|
1031
1039
|
}
|
|
1032
1040
|
function keptMessages(event) {
|
|
1033
1041
|
const leafId = event.branchEntries.at(-1)?.id ?? null;
|
|
1034
1042
|
const contextEntries = buildContextEntries(event.branchEntries, leafId);
|
|
1035
|
-
const keptIndex = contextEntries.findIndex(
|
|
1036
|
-
(entry) => entry.id === event.preparation.firstKeptEntryId
|
|
1037
|
-
);
|
|
1043
|
+
const keptIndex = contextEntries.findIndex((entry) => entry.id === event.preparation.firstKeptEntryId);
|
|
1038
1044
|
if (keptIndex < 0) {
|
|
1039
1045
|
throw new Error("Pi compaction cut point is not present in the active context");
|
|
1040
1046
|
}
|
|
@@ -1053,12 +1059,12 @@ function activeTools(pi) {
|
|
|
1053
1059
|
] : [];
|
|
1054
1060
|
});
|
|
1055
1061
|
}
|
|
1056
|
-
function projectedCurrentMessages(event, model) {
|
|
1062
|
+
function projectedCurrentMessages(event, model, route) {
|
|
1057
1063
|
const leafId = event.branchEntries.at(-1)?.id ?? null;
|
|
1058
1064
|
const session = buildSessionContext(event.branchEntries, leafId);
|
|
1059
1065
|
const prior = latestCheckpoint(event.branchEntries);
|
|
1060
1066
|
if (!prior) return { messages: session.messages };
|
|
1061
|
-
if (prior.details.api !==
|
|
1067
|
+
if (prior.details.api !== route.api || prior.details.profile !== route.profile || prior.details.modelId !== model.id) {
|
|
1062
1068
|
throw new Error("The active opaque checkpoint belongs to a different Responses model");
|
|
1063
1069
|
}
|
|
1064
1070
|
const projected = projectCheckpointContext(session.messages, prior.details, prior.entry.summary);
|
|
@@ -1078,21 +1084,18 @@ function sessionStillOwned(ctx, sessionId, signal) {
|
|
|
1078
1084
|
async function compactRemotely(pi, event, ctx, settings, ownerSignal, fetch) {
|
|
1079
1085
|
const model = ctx.model;
|
|
1080
1086
|
const route = resolveCompactionRoute(model, settings);
|
|
1081
|
-
if (route.kind === "native" || !
|
|
1087
|
+
if (route.kind === "native" || !model) return void 0;
|
|
1082
1088
|
const signal = AbortSignal.any([event.signal, ownerSignal]);
|
|
1083
1089
|
if (signal.aborted) return { cancel: true };
|
|
1084
1090
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
1085
|
-
ctx.ui.setStatus(
|
|
1086
|
-
STATUS_KEY,
|
|
1087
|
-
route.protocol === "remote-v2" ? "Responses Remote V2\u2026" : "Responses Compact API\u2026"
|
|
1088
|
-
);
|
|
1091
|
+
ctx.ui.setStatus(STATUS_KEY, route.protocol === "remote-v2" ? "Responses Remote V2\u2026" : "Responses Compact API\u2026");
|
|
1089
1092
|
try {
|
|
1090
1093
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
1091
1094
|
if (!sessionStillOwned(ctx, sessionId, signal)) return { cancel: true };
|
|
1092
1095
|
if (!auth.ok) throw new Error(auth.error);
|
|
1093
1096
|
const provider = ctx.modelRegistry.getProvider(model.provider);
|
|
1094
1097
|
if (!provider) throw new Error("The active Responses provider is unavailable");
|
|
1095
|
-
const current = projectedCurrentMessages(event, model);
|
|
1098
|
+
const current = projectedCurrentMessages(event, model, route);
|
|
1096
1099
|
const context = {
|
|
1097
1100
|
systemPrompt: ctx.getSystemPrompt(),
|
|
1098
1101
|
messages: convertToLlm(current.messages),
|
|
@@ -1103,6 +1106,7 @@ async function compactRemotely(pi, event, ctx, settings, ownerSignal, fetch) {
|
|
|
1103
1106
|
model,
|
|
1104
1107
|
context,
|
|
1105
1108
|
protocol: route.protocol,
|
|
1109
|
+
profile: route.profile,
|
|
1106
1110
|
apiKey: auth.apiKey,
|
|
1107
1111
|
headers: auth.headers,
|
|
1108
1112
|
env: auth.env,
|
|
@@ -1124,6 +1128,7 @@ async function compactRemotely(pi, event, ctx, settings, ownerSignal, fetch) {
|
|
|
1124
1128
|
const details = createCheckpointDetails({
|
|
1125
1129
|
provider: model.provider,
|
|
1126
1130
|
api: route.api,
|
|
1131
|
+
profile: route.profile,
|
|
1127
1132
|
modelId: model.id,
|
|
1128
1133
|
protocol: route.protocol,
|
|
1129
1134
|
replacementHistory,
|
|
@@ -1160,7 +1165,7 @@ function createCodexCompactExtension(options = {}) {
|
|
|
1160
1165
|
if (args.trim()) throw new Error("Usage: /codex-compact");
|
|
1161
1166
|
const ownerGeneration = generation;
|
|
1162
1167
|
const controller = sessionController;
|
|
1163
|
-
const { showCodexCompactMenu } = await import("./chunks/settings-menu-
|
|
1168
|
+
const { showCodexCompactMenu } = await import("./chunks/settings-menu-OAWFW2PH.js");
|
|
1164
1169
|
if (ownerGeneration !== generation || controller.signal.aborted) return;
|
|
1165
1170
|
await showCodexCompactMenu(settingsRuntime, ctx, {
|
|
1166
1171
|
signal: controller.signal,
|
|
@@ -1200,38 +1205,30 @@ function createCodexCompactExtension(options = {}) {
|
|
|
1200
1205
|
});
|
|
1201
1206
|
pi.on(
|
|
1202
1207
|
"session_before_compact",
|
|
1203
|
-
(event, ctx) => compactRemotely(
|
|
1204
|
-
pi,
|
|
1205
|
-
event,
|
|
1206
|
-
ctx,
|
|
1207
|
-
settingsRuntime.get().settings,
|
|
1208
|
-
sessionController.signal,
|
|
1209
|
-
options.fetch
|
|
1210
|
-
)
|
|
1208
|
+
(event, ctx) => compactRemotely(pi, event, ctx, settingsRuntime.get().settings, sessionController.signal, options.fetch)
|
|
1211
1209
|
);
|
|
1212
1210
|
pi.on("context", (event, ctx) => {
|
|
1213
1211
|
if (!settingsRuntime.get().settings.enabled) return void 0;
|
|
1212
|
+
const settings = settingsRuntime.get().settings;
|
|
1214
1213
|
const checkpoint = activeCheckpoint(ctx);
|
|
1215
|
-
if (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return void 0;
|
|
1216
|
-
const messages = projectCheckpointContext(
|
|
1217
|
-
event.messages,
|
|
1218
|
-
checkpoint.details,
|
|
1219
|
-
checkpoint.entry.summary
|
|
1220
|
-
);
|
|
1214
|
+
if (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model, settings)) return void 0;
|
|
1215
|
+
const messages = projectCheckpointContext(event.messages, checkpoint.details, checkpoint.entry.summary);
|
|
1221
1216
|
return messages ? { messages } : void 0;
|
|
1222
1217
|
});
|
|
1223
1218
|
pi.on("before_provider_request", (event, ctx) => {
|
|
1224
1219
|
if (!settingsRuntime.get().settings.enabled) return void 0;
|
|
1220
|
+
const settings = settingsRuntime.get().settings;
|
|
1225
1221
|
const checkpoint = activeCheckpoint(ctx);
|
|
1226
|
-
if (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return void 0;
|
|
1222
|
+
if (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model, settings)) return void 0;
|
|
1227
1223
|
const marker = checkpointMarker(checkpoint.details.checkpointId);
|
|
1228
1224
|
if (!hasCheckpointMarker(event.payload, marker)) return void 0;
|
|
1229
1225
|
return rewriteCheckpointMarker(event.payload, marker, checkpoint.details.replacementHistory);
|
|
1230
1226
|
});
|
|
1231
1227
|
pi.on("model_select", (event, ctx) => {
|
|
1232
1228
|
if (!settingsRuntime.get().settings.enabled) return;
|
|
1229
|
+
const settings = settingsRuntime.get().settings;
|
|
1233
1230
|
const checkpoint = activeCheckpoint(ctx);
|
|
1234
|
-
if (!checkpoint || isCheckpointCompatible(checkpoint.details, event.model)) return;
|
|
1231
|
+
if (!checkpoint || isCheckpointCompatible(checkpoint.details, event.model, settings)) return;
|
|
1235
1232
|
const key = `${ctx.sessionManager.getSessionId()}:${event.model.provider}:${event.model.id}`;
|
|
1236
1233
|
if (providerWarnings.has(key)) return;
|
|
1237
1234
|
providerWarnings.add(key);
|