@narumitw/pi-codex-compact 0.50.1 → 0.51.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/README.md +98 -91
- package/dist/chunks/chunk-3WRPJHG2.ts +13 -0
- package/dist/chunks/chunk-3WRPJHG2.ts.map +7 -0
- package/dist/chunks/settings-menu-4YW2GOKW.ts +191 -0
- package/dist/chunks/settings-menu-4YW2GOKW.ts.map +7 -0
- package/dist/index.ts +815 -0
- package/dist/index.ts.map +7 -0
- package/package.json +14 -10
- package/src/checkpoint.ts +11 -7
- package/src/codex-compact.ts +20 -19
- package/src/model-compatibility.ts +8 -0
- package/src/protocol.ts +2 -2
- package/src/remote.ts +1 -1
- package/src/settings-menu.ts +3 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/codex-compact.ts", "../src/checkpoint.ts", "../src/protocol.ts", "../src/remote.ts", "../src/settings.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Context, Model, Tool } from \"@earendil-works/pi-ai\";\nimport {\n\tbuildContextEntries,\n\tbuildSessionContext,\n\tconvertToLlm,\n\ttype ExtensionAPI,\n\ttype ExtensionContext,\n\ttype SessionBeforeCompactEvent,\n\tsessionEntryToContextMessages,\n} from \"@earendil-works/pi-coding-agent\";\nimport {\n\tbuildReplacementHistory,\n\ttype CodexCheckpointDetails,\n\tcheckpointMarker,\n\tcreateCheckpointDetails,\n\tfallbackSummary,\n\tlatestCheckpoint,\n\tprojectCheckpointContext,\n} from \"./checkpoint.js\";\nimport { isCodexRemoteCompactionModel } from \"./model-compatibility.js\";\nimport { hasCheckpointMarker, rewriteCheckpointMarker } from \"./protocol.js\";\nimport { requestRemoteCompaction } from \"./remote.js\";\nimport {\n\ttype CodexCompactSettings,\n\ttype CodexCompactSettingsRuntime,\n\ttype CodexCompactSettingsState,\n\tcreateCodexCompactSettingsRuntime,\n} from \"./settings.js\";\n\nconst STATUS_KEY = \"codex-compact\";\n\nfunction activeCheckpoint(ctx: ExtensionContext) {\n\treturn latestCheckpoint(ctx.sessionManager.getBranch());\n}\n\nfunction isCheckpointCompatible(\n\tdetails: CodexCheckpointDetails,\n\tmodel: Model<Api> | undefined,\n): model is Model<\"openai-codex-responses\"> {\n\treturn isCodexRemoteCompactionModel(model) && model.id === details.modelId;\n}\n\nfunction keptMessages(event: SessionBeforeCompactEvent): AgentMessage[] {\n\tconst leafId = event.branchEntries.at(-1)?.id ?? null;\n\tconst contextEntries = buildContextEntries(event.branchEntries, leafId);\n\tconst keptIndex = contextEntries.findIndex(\n\t\t(entry) => entry.id === event.preparation.firstKeptEntryId,\n\t);\n\tif (keptIndex < 0) {\n\t\tthrow new Error(\"Pi compaction cut point is not present in the active context\");\n\t}\n\treturn contextEntries.slice(keptIndex).flatMap(sessionEntryToContextMessages);\n}\n\nfunction activeTools(pi: ExtensionAPI): Tool[] {\n\tconst enabled = new Set(pi.getActiveTools());\n\treturn pi\n\t\t.getAllTools()\n\t\t.filter((tool) => enabled.has(tool.name))\n\t\t.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: tool.parameters,\n\t\t}));\n}\n\nfunction projectedCurrentMessages(\n\tevent: SessionBeforeCompactEvent,\n\tmodel: Model<\"openai-codex-responses\">,\n): { messages: AgentMessage[]; prior?: CodexCheckpointDetails } {\n\tconst leafId = event.branchEntries.at(-1)?.id ?? null;\n\tconst session = buildSessionContext(event.branchEntries, leafId);\n\tconst prior = latestCheckpoint(event.branchEntries);\n\tif (!prior) return { messages: session.messages };\n\tif (prior.details.modelId !== model.id) {\n\t\tthrow new Error(\"The active opaque checkpoint belongs to a different Codex model\");\n\t}\n\tconst projected = projectCheckpointContext(session.messages, prior.details, prior.entry.summary);\n\tif (!projected) {\n\t\tthrow new Error(\"The previous opaque checkpoint could not be projected safely\");\n\t}\n\treturn { messages: projected, prior: prior.details };\n}\n\nfunction notifyFailure(\n\tctx: ExtensionContext,\n\terror: unknown,\n\tsettings: CodexCompactSettings,\n): void {\n\tif (!ctx.hasUI || !settings.notifyOnFallback) return;\n\tconst message = error instanceof Error ? error.message : String(error);\n\tctx.ui.notify(`Codex remote compaction failed; using Pi compaction. ${message}`, \"warning\");\n}\n\nfunction sessionStillOwned(ctx: ExtensionContext, sessionId: string, signal: AbortSignal): boolean {\n\treturn !signal.aborted && ctx.sessionManager.getSessionId() === sessionId;\n}\n\nasync function compactRemotely(\n\tpi: ExtensionAPI,\n\tevent: SessionBeforeCompactEvent,\n\tctx: ExtensionContext,\n\tsettings: CodexCompactSettings,\n\tfetch?: typeof globalThis.fetch,\n) {\n\tconst model = ctx.model;\n\tif (!settings.enabled || !isCodexRemoteCompactionModel(model)) return undefined;\n\tconst sessionId = ctx.sessionManager.getSessionId();\n\tctx.ui.setStatus(STATUS_KEY, \"Codex remote compaction\u2026\");\n\ttry {\n\t\tconst auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\t\tif (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };\n\t\tif (!auth.ok) throw new Error(auth.error);\n\t\tconst provider = ctx.modelRegistry.getProvider(model.provider);\n\t\tif (!provider) throw new Error(\"The active Codex Responses provider is unavailable\");\n\t\tconst current = projectedCurrentMessages(event, model);\n\t\tconst context: Context = {\n\t\t\tsystemPrompt: ctx.getSystemPrompt(),\n\t\t\tmessages: convertToLlm(current.messages),\n\t\t\ttools: activeTools(pi),\n\t\t};\n\t\tconst response = await requestRemoteCompaction({\n\t\t\tprovider,\n\t\t\tmodel,\n\t\t\tcontext,\n\t\t\tapiKey: auth.apiKey,\n\t\t\theaders: auth.headers,\n\t\t\tenv: auth.env,\n\t\t\tsignal: event.signal,\n\t\t\tpriorCheckpoint: current.prior\n\t\t\t\t? {\n\t\t\t\t\t\tmarker: checkpointMarker(current.prior.checkpointId),\n\t\t\t\t\t\treplacementHistory: current.prior.replacementHistory,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\trequestTimeoutMs: settings.requestTimeoutMs,\n\t\t\tmaxRetries: settings.maxRetries,\n\t\t\tfetch,\n\t\t});\n\t\tif (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };\n\t\tconst replacementHistory = buildReplacementHistory(response.promptInput, response.item, {\n\t\t\ttokenBudget: settings.replacementTokenBudget,\n\t\t});\n\t\tconst details = createCheckpointDetails({\n\t\t\tprovider: model.provider,\n\t\t\tmodelId: model.id,\n\t\t\treplacementHistory,\n\t\t\tkeptMessages: keptMessages(event),\n\t\t});\n\t\treturn {\n\t\t\tcompaction: {\n\t\t\t\tsummary: fallbackSummary(details.checkpointId),\n\t\t\t\tfirstKeptEntryId: event.preparation.firstKeptEntryId,\n\t\t\t\ttokensBefore: event.preparation.tokensBefore,\n\t\t\t\tusage: response.usage,\n\t\t\t\tdetails,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (event.signal.aborted || ctx.sessionManager.getSessionId() !== sessionId) {\n\t\t\treturn { cancel: true };\n\t\t}\n\t\tnotifyFailure(ctx, error, settings);\n\t\treturn undefined;\n\t} finally {\n\t\tif (ctx.sessionManager.getSessionId() === sessionId) ctx.ui.setStatus(STATUS_KEY, undefined);\n\t}\n}\n\nexport function createCodexCompactExtension(\n\toptions: { fetch?: typeof globalThis.fetch; settingsRuntime?: CodexCompactSettingsRuntime } = {},\n): (pi: ExtensionAPI) => void {\n\treturn (pi) => {\n\t\tconst providerWarnings = new Set<string>();\n\t\tconst settingsRuntime = options.settingsRuntime ?? createCodexCompactSettingsRuntime();\n\t\tlet sessionController = new AbortController();\n\t\tlet generation = 0;\n\n\t\tpi.registerCommand(\"codex-compact\", {\n\t\t\tdescription: \"Compact now or configure Codex Remote Compaction V2\",\n\t\t\thandler: async (_args, ctx) => {\n\t\t\t\tconst ownerGeneration = generation;\n\t\t\t\tconst controller = sessionController;\n\t\t\t\tconst { showCodexCompactMenu } = await import(\"./settings-menu.js\");\n\t\t\t\tif (ownerGeneration !== generation || controller.signal.aborted) return;\n\t\t\t\tawait showCodexCompactMenu(settingsRuntime, ctx, {\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tisCurrent: () => ownerGeneration === generation && !controller.signal.aborted,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\t\tsessionController.abort();\n\t\t\tsessionController = new AbortController();\n\t\t\tgeneration += 1;\n\t\t\tconst ownerGeneration = generation;\n\t\t\tconst sessionId = ctx.sessionManager.getSessionId();\n\t\t\tproviderWarnings.clear();\n\t\t\tlet state: Readonly<CodexCompactSettingsState>;\n\t\t\ttry {\n\t\t\t\tstate = await settingsRuntime.reload(sessionController.signal);\n\t\t\t} catch (error) {\n\t\t\t\tif (sessionController.signal.aborted || ownerGeneration !== generation) return;\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Could not load pi-codex-compact.json; using defaults. ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tsessionController.signal.aborted ||\n\t\t\t\townerGeneration !== generation ||\n\t\t\t\tctx.sessionManager.getSessionId() !== sessionId\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (ctx.hasUI && state.kind === \"invalid\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Invalid pi-codex-compact.json; using defaults without overwriting it. ${state.issue}`,\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"session_before_compact\", (event, ctx) =>\n\t\t\tcompactRemotely(pi, event, ctx, settingsRuntime.get().settings, options.fetch),\n\t\t);\n\n\t\tpi.on(\"context\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return undefined;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return undefined;\n\t\t\tconst messages = projectCheckpointContext(\n\t\t\t\tevent.messages,\n\t\t\t\tcheckpoint.details,\n\t\t\t\tcheckpoint.entry.summary,\n\t\t\t);\n\t\t\treturn messages ? { messages } : undefined;\n\t\t});\n\n\t\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return undefined;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return undefined;\n\t\t\tconst marker = checkpointMarker(checkpoint.details.checkpointId);\n\t\t\tif (!hasCheckpointMarker(event.payload, marker)) return undefined;\n\t\t\treturn rewriteCheckpointMarker(event.payload, marker, checkpoint.details.replacementHistory);\n\t\t});\n\n\t\tpi.on(\"model_select\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || isCheckpointCompatible(checkpoint.details, event.model)) return;\n\t\t\tconst key = `${ctx.sessionManager.getSessionId()}:${event.model.provider}:${event.model.id}`;\n\t\t\tif (providerWarnings.has(key)) return;\n\t\t\tproviderWarnings.add(key);\n\t\t\tif (ctx.hasUI) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\"The active Codex checkpoint cannot replay on this model; Pi will expose only its fallback marker and retained recent messages.\",\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\t\tgeneration += 1;\n\t\t\tsessionController.abort();\n\t\t\tproviderWarnings.clear();\n\t\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\t\tawait settingsRuntime.flush();\n\t\t});\n\t};\n}\n\nexport default createCodexCompactExtension();\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { CompactionEntry, SessionEntry } from \"@earendil-works/pi-coding-agent\";\nimport { type JsonObject, validateCompactionItem } from \"./protocol.js\";\n\nexport const CHECKPOINT_KIND = \"pi-codex-remote-compaction\";\nexport const CHECKPOINT_VERSION = 1;\nexport const REPLACEMENT_TOKEN_BUDGET = 64_000;\nexport const REPLACEMENT_BYTE_BUDGET = 8 * 1024 * 1024;\nconst MAX_MEDIA_ITEM_BYTES = 2 * 1024 * 1024;\nconst MAX_PROVIDER_ID_LENGTH = 256;\n\nexport interface CodexCheckpointDetails {\n\tkind: typeof CHECKPOINT_KIND;\n\tversion: typeof CHECKPOINT_VERSION;\n\tcheckpointId: string;\n\tprovider: string;\n\tapi: \"openai-codex-responses\";\n\tmodelId: string;\n\tprotocol: \"remote-compaction-v2\";\n\treplacementHistory: JsonObject[];\n\tkeptMessageFingerprints: string[];\n\tcreatedAt: string;\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stableValue(value: unknown): unknown {\n\tif (Array.isArray(value)) return value.map(stableValue);\n\tif (!isObject(value)) return value;\n\treturn Object.fromEntries(\n\t\tObject.entries(value)\n\t\t\t.sort(([left], [right]) => left.localeCompare(right))\n\t\t\t.map(([key, child]) => [key, stableValue(child)]),\n\t);\n}\n\nfunction serializedBytes(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nexport function fingerprintMessage(message: AgentMessage): string {\n\treturn createHash(\"sha256\")\n\t\t.update(JSON.stringify(stableValue(message)))\n\t\t.digest(\"hex\");\n}\n\nexport function checkpointMarker(checkpointId: string): string {\n\treturn [\n\t\t`[PI_CODEX_REMOTE_CHECKPOINT:${checkpointId}]`,\n\t\t\"Opaque checkpoint injection failed. Do not infer missing history; tell the user to re-enable\",\n\t\t\"@narumitw/pi-codex-compact with a model using the openai-codex-responses API.\",\n\t].join(\" \");\n}\n\nexport function fallbackSummary(checkpointId: string): string {\n\treturn [\n\t\t`OpenAI Codex Remote Compaction V2 checkpoint ${checkpointId} stores the older history opaquely.`,\n\t\t\"Full replay requires @narumitw/pi-codex-compact and the same model through a compatible Codex Responses provider.\",\n\t\t\"Without them, only Pi's retained recent messages remain available.\",\n\t].join(\" \");\n}\n\nfunction markerMessage(checkpointId: string, timestamp: number): AgentMessage {\n\treturn {\n\t\trole: \"user\",\n\t\tcontent: [{ type: \"text\", text: checkpointMarker(checkpointId) }],\n\t\ttimestamp,\n\t};\n}\n\nexport function parseCheckpointDetails(value: unknown): CodexCheckpointDetails | undefined {\n\tif (!isObject(value)) return undefined;\n\tif (\n\t\tvalue.kind !== CHECKPOINT_KIND ||\n\t\tvalue.version !== CHECKPOINT_VERSION ||\n\t\ttypeof value.checkpointId !== \"string\" ||\n\t\tvalue.checkpointId.length < 8 ||\n\t\ttypeof value.provider !== \"string\" ||\n\t\tvalue.provider.length === 0 ||\n\t\tvalue.provider.length > MAX_PROVIDER_ID_LENGTH ||\n\t\tvalue.api !== \"openai-codex-responses\" ||\n\t\ttypeof value.modelId !== \"string\" ||\n\t\tvalue.protocol !== \"remote-compaction-v2\" ||\n\t\t!Array.isArray(value.replacementHistory) ||\n\t\t!Array.isArray(value.keptMessageFingerprints) ||\n\t\ttypeof value.createdAt !== \"string\"\n\t) {\n\t\treturn undefined;\n\t}\n\tif (\n\t\tvalue.replacementHistory.length === 0 ||\n\t\t!value.replacementHistory.every(isObject) ||\n\t\t!value.keptMessageFingerprints.every(\n\t\t\t(fingerprint) => typeof fingerprint === \"string\" && /^[a-f0-9]{64}$/.test(fingerprint),\n\t\t) ||\n\t\tserializedBytes(value.replacementHistory) > REPLACEMENT_BYTE_BUDGET\n\t) {\n\t\treturn undefined;\n\t}\n\tconst last = value.replacementHistory.at(-1);\n\ttry {\n\t\tvalidateCompactionItem(last);\n\t} catch {\n\t\treturn undefined;\n\t}\n\treturn structuredClone(value) as unknown as CodexCheckpointDetails;\n}\n\nexport function latestCheckpoint(entries: readonly SessionEntry[]):\n\t| {\n\t\t\tentry: CompactionEntry<CodexCheckpointDetails>;\n\t\t\tdetails: CodexCheckpointDetails;\n\t }\n\t| undefined {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry.type !== \"compaction\") continue;\n\t\tconst details = parseCheckpointDetails(entry.details);\n\t\treturn details\n\t\t\t? { entry: entry as CompactionEntry<CodexCheckpointDetails>, details }\n\t\t\t: undefined;\n\t}\n\treturn undefined;\n}\n\nfunction isOlderCompactionSummary(message: AgentMessage, timestamp: number): boolean {\n\treturn (\n\t\tmessage.role === \"compactionSummary\" &&\n\t\tNumber.isFinite(message.timestamp) &&\n\t\tNumber.isFinite(timestamp) &&\n\t\tmessage.timestamp < timestamp\n\t);\n}\n\nexport function projectCheckpointContext(\n\tmessages: readonly AgentMessage[],\n\tdetails: CodexCheckpointDetails,\n\tcheckpointSummary: string,\n): AgentMessage[] | undefined {\n\tconst summaryIndex = messages.findIndex(\n\t\t(message) => message.role === \"compactionSummary\" && message.summary === checkpointSummary,\n\t);\n\tif (summaryIndex < 0) return undefined;\n\tconst timestamp = messages[summaryIndex].timestamp;\n\tlet messageIndex = summaryIndex + 1;\n\tlet fingerprintIndex = 0;\n\twhile (fingerprintIndex < details.keptMessageFingerprints.length) {\n\t\tif (messageIndex >= messages.length) return undefined;\n\t\tconst message = messages[messageIndex];\n\t\tif (fingerprintMessage(message) === details.keptMessageFingerprints[fingerprintIndex]) {\n\t\t\tmessageIndex += 1;\n\t\t\tfingerprintIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isOlderCompactionSummary(message, timestamp)) {\n\t\t\tmessageIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\treturn undefined;\n\t}\n\twhile (\n\t\tmessageIndex < messages.length &&\n\t\tisOlderCompactionSummary(messages[messageIndex], timestamp)\n\t) {\n\t\tmessageIndex += 1;\n\t}\n\treturn [\n\t\t...messages.slice(0, summaryIndex),\n\t\tmarkerMessage(details.checkpointId, timestamp),\n\t\t...messages.slice(messageIndex),\n\t];\n}\n\nfunction rawText(item: JsonObject): string {\n\tif (!Array.isArray(item.content)) return \"\";\n\treturn item.content\n\t\t.flatMap((part) =>\n\t\t\tisObject(part) && typeof part.text === \"string\" && part.type === \"input_text\"\n\t\t\t\t? [part.text]\n\t\t\t\t: [],\n\t\t)\n\t\t.join(\"\\n\");\n}\n\nfunction hasMedia(item: JsonObject): boolean {\n\treturn (\n\t\tArray.isArray(item.content) &&\n\t\titem.content.some((part) => isObject(part) && part.type === \"input_image\")\n\t);\n}\n\nfunction truncateTextItem(item: JsonObject, maxChars: number): JsonObject | undefined {\n\tif (!Array.isArray(item.content) || maxChars <= 32) return undefined;\n\tlet remaining = maxChars - 16;\n\tconst content = [...item.content].reverse().flatMap((part) => {\n\t\tif (\n\t\t\t!isObject(part) ||\n\t\t\tpart.type !== \"input_text\" ||\n\t\t\ttypeof part.text !== \"string\" ||\n\t\t\tremaining <= 0\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\t\tconst text = part.text.slice(-remaining);\n\t\tremaining -= text.length;\n\t\treturn [{ ...part, text: `[truncated]\\n${text}` }];\n\t});\n\tif (content.length === 0) return undefined;\n\treturn { ...item, content: content.reverse() };\n}\n\nexport function buildReplacementHistory(\n\tinput: readonly unknown[],\n\tcompactionItem: JsonObject,\n\toptions: { tokenBudget?: number; byteBudget?: number } = {},\n): JsonObject[] {\n\tconst tokenBudget = options.tokenBudget ?? REPLACEMENT_TOKEN_BUDGET;\n\tconst byteBudget = options.byteBudget ?? REPLACEMENT_BYTE_BUDGET;\n\tconst opaque = validateCompactionItem(compactionItem);\n\tlet remainingBytes = byteBudget - serializedBytes(opaque);\n\tlet remainingChars = tokenBudget * 4;\n\tif (remainingBytes <= 0)\n\t\tthrow new Error(\"Opaque compaction item exceeds replacement history budget\");\n\tconst retainedNewestFirst: JsonObject[] = [];\n\tconst candidates = input.filter(\n\t\t(item): item is JsonObject =>\n\t\t\tisObject(item) && item.role === \"user\" && item.type !== \"compaction_trigger\",\n\t);\n\tfor (let index = candidates.length - 1; index >= 0; index--) {\n\t\tconst candidate = candidates[index];\n\t\tconst bytes = serializedBytes(candidate);\n\t\tif (hasMedia(candidate) && bytes > MAX_MEDIA_ITEM_BYTES) continue;\n\t\tconst text = rawText(candidate);\n\t\tlet retained = candidate;\n\t\tif (text.length > remainingChars) {\n\t\t\tif (hasMedia(candidate)) continue;\n\t\t\tconst truncated = truncateTextItem(candidate, remainingChars);\n\t\t\tif (!truncated) continue;\n\t\t\tretained = truncated;\n\t\t}\n\t\tif (serializedBytes(retained) > remainingBytes) {\n\t\t\tif (hasMedia(retained)) continue;\n\t\t\tconst maxCharsByBytes = Math.max(0, remainingBytes - 128);\n\t\t\tconst truncated = truncateTextItem(retained, Math.min(remainingChars, maxCharsByBytes));\n\t\t\tif (!truncated || serializedBytes(truncated) > remainingBytes) continue;\n\t\t\tretained = truncated;\n\t\t}\n\t\tretainedNewestFirst.push(structuredClone(retained));\n\t\tremainingBytes -= serializedBytes(retained);\n\t\tremainingChars -= Math.min(remainingChars, rawText(retained).length);\n\t\tif (remainingBytes <= 128 || remainingChars <= 32) break;\n\t}\n\treturn [...retainedNewestFirst.reverse(), opaque];\n}\n\nexport function createCheckpointDetails(input: {\n\tprovider: string;\n\tmodelId: string;\n\treplacementHistory: JsonObject[];\n\tkeptMessages: readonly AgentMessage[];\n\tcheckpointId?: string;\n\tcreatedAt?: string;\n}): CodexCheckpointDetails {\n\tconst details: CodexCheckpointDetails = {\n\t\tkind: CHECKPOINT_KIND,\n\t\tversion: CHECKPOINT_VERSION,\n\t\tcheckpointId: input.checkpointId ?? randomUUID(),\n\t\tprovider: input.provider,\n\t\tapi: \"openai-codex-responses\",\n\t\tmodelId: input.modelId,\n\t\tprotocol: \"remote-compaction-v2\",\n\t\treplacementHistory: structuredClone(input.replacementHistory),\n\t\tkeptMessageFingerprints: input.keptMessages.map(fingerprintMessage),\n\t\tcreatedAt: input.createdAt ?? new Date().toISOString(),\n\t};\n\tconst parsed = parseCheckpointDetails(details);\n\tif (!parsed) throw new Error(\"Created an invalid Codex checkpoint\");\n\treturn parsed;\n}\n", "export const MAX_SSE_BYTES = 8 * 1024 * 1024;\nexport const MAX_COMPACTION_ITEM_BYTES = 2 * 1024 * 1024;\n\nexport type JsonObject = Record<string, unknown>;\n\nexport class CodexCompactionProtocolError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CodexCompactionProtocolError\";\n\t}\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction byteLength(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nexport function isCompactionItem(value: unknown): value is JsonObject {\n\treturn (\n\t\tisObject(value) &&\n\t\tvalue.type === \"compaction\" &&\n\t\ttypeof value.encrypted_content === \"string\" &&\n\t\tvalue.encrypted_content.length > 0\n\t);\n}\n\nexport function validateCompactionItem(\n\tvalue: unknown,\n\tmaxBytes = MAX_COMPACTION_ITEM_BYTES,\n): JsonObject {\n\tif (!isCompactionItem(value)) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Remote response did not contain a valid compaction item\",\n\t\t);\n\t}\n\tif (byteLength(value) > maxBytes) {\n\t\tthrow new CodexCompactionProtocolError(\"Remote compaction item exceeded the size limit\");\n\t}\n\treturn structuredClone(value);\n}\n\nexport interface CollectedCompaction {\n\titem: JsonObject;\n\tcompletedResponse?: JsonObject;\n}\n\nfunction compactionItemsFromEvent(event: JsonObject): unknown[] {\n\tconst items: unknown[] = [];\n\tif (event.type === \"response.output_item.done\" && isObject(event.item)) {\n\t\titems.push(event.item);\n\t}\n\tif (event.type === \"response.completed\" && isObject(event.response)) {\n\t\tconst output = event.response.output;\n\t\tif (Array.isArray(output)) items.push(...output);\n\t}\n\treturn items.filter((item) => isObject(item) && item.type === \"compaction\");\n}\n\nexport async function collectCompactionSse(\n\tstream: ReadableStream<Uint8Array>,\n\toptions: {\n\t\tsignal?: AbortSignal;\n\t\tmaxBytes?: number;\n\t\tmaxItemBytes?: number;\n\t} = {},\n): Promise<CollectedCompaction> {\n\tconst maxBytes = options.maxBytes ?? MAX_SSE_BYTES;\n\tconst reader = stream.getReader();\n\tconst onAbort = () => {\n\t\tvoid reader.cancel(new DOMException(\"Compaction aborted\", \"AbortError\")).catch(() => undefined);\n\t};\n\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\tconst decoder = new TextDecoder();\n\tlet bytes = 0;\n\tlet pending = \"\";\n\tlet dataLines: string[] = [];\n\tlet completedResponse: JsonObject | undefined;\n\tconst items = new Map<string, JsonObject>();\n\n\tconst checkAbort = () => {\n\t\tif (options.signal?.aborted) throw new DOMException(\"Compaction aborted\", \"AbortError\");\n\t};\n\tconst dispatch = () => {\n\t\tif (dataLines.length === 0) return;\n\t\tconst data = dataLines.join(\"\\n\");\n\t\tdataLines = [];\n\t\tif (data === \"[DONE]\") return;\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(data);\n\t\t} catch {\n\t\t\tthrow new CodexCompactionProtocolError(\"Remote compaction returned malformed SSE JSON\");\n\t\t}\n\t\tif (!isObject(parsed)) return;\n\t\tif (parsed.type === \"response.completed\") {\n\t\t\tcompletedResponse = isObject(parsed.response) ? parsed.response : {};\n\t\t}\n\t\tfor (const candidate of compactionItemsFromEvent(parsed)) {\n\t\t\tconst item = validateCompactionItem(candidate, options.maxItemBytes);\n\t\t\titems.set(JSON.stringify(item), item);\n\t\t}\n\t};\n\tconst processLine = (line: string) => {\n\t\tif (line === \"\") {\n\t\t\tdispatch();\n\t\t\treturn;\n\t\t}\n\t\tif (line.startsWith(\":\")) return;\n\t\tif (line === \"data\") dataLines.push(\"\");\n\t\telse if (line.startsWith(\"data:\")) dataLines.push(line.slice(5).replace(/^ /, \"\"));\n\t};\n\n\ttry {\n\t\twhile (true) {\n\t\t\tcheckAbort();\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tbytes += value.byteLength;\n\t\t\tif (bytes > maxBytes) {\n\t\t\t\tthrow new CodexCompactionProtocolError(\"Remote compaction stream exceeded the size limit\");\n\t\t\t}\n\t\t\tpending += decoder.decode(value, { stream: true });\n\t\t\tlet newline = pending.indexOf(\"\\n\");\n\t\t\twhile (newline !== -1) {\n\t\t\t\tconst rawLine = pending.slice(0, newline);\n\t\t\t\tpending = pending.slice(newline + 1);\n\t\t\t\tprocessLine(rawLine.endsWith(\"\\r\") ? rawLine.slice(0, -1) : rawLine);\n\t\t\t\tnewline = pending.indexOf(\"\\n\");\n\t\t\t}\n\t\t}\n\t\tpending += decoder.decode();\n\t\tif (pending.length > 0) processLine(pending.endsWith(\"\\r\") ? pending.slice(0, -1) : pending);\n\t\tdispatch();\n\t\tcheckAbort();\n\t} catch (error) {\n\t\tawait reader.cancel(error).catch(() => undefined);\n\t\tthrow error;\n\t} finally {\n\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\treader.releaseLock();\n\t}\n\n\tif (!completedResponse) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Remote compaction stream ended without response.completed\",\n\t\t);\n\t}\n\tif (items.size !== 1) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t`Remote compaction returned ${items.size} distinct compaction items; expected exactly one`,\n\t\t);\n\t}\n\treturn { item: [...items.values()][0], completedResponse };\n}\n\nfunction markerTextFromItem(item: unknown): string | undefined {\n\tif (!isObject(item) || item.role !== \"user\" || !Array.isArray(item.content)) return undefined;\n\tif (item.content.length !== 1) return undefined;\n\tconst content = item.content[0];\n\tif (!isObject(content) || content.type !== \"input_text\" || typeof content.text !== \"string\") {\n\t\treturn undefined;\n\t}\n\treturn content.text;\n}\n\nexport function rewriteCheckpointMarker(\n\tpayload: unknown,\n\tmarker: string,\n\treplacementHistory: readonly unknown[],\n): JsonObject {\n\tif (!isObject(payload) || !Array.isArray(payload.input)) {\n\t\tthrow new CodexCompactionProtocolError(\"Codex Responses payload is missing an input array\");\n\t}\n\tconst matches = payload.input\n\t\t.map((item, index) => (markerTextFromItem(item) === marker ? index : -1))\n\t\t.filter((index) => index >= 0);\n\tif (matches.length !== 1) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t`Provider payload contained ${matches.length} checkpoint markers; expected exactly one`,\n\t\t);\n\t}\n\tconst index = matches[0];\n\treturn {\n\t\t...payload,\n\t\tinput: [\n\t\t\t...payload.input.slice(0, index),\n\t\t\t...structuredClone(replacementHistory),\n\t\t\t...payload.input.slice(index + 1),\n\t\t],\n\t};\n}\n\nexport function appendCompactionTrigger(payload: unknown): JsonObject {\n\tif (!isObject(payload) || !Array.isArray(payload.input)) {\n\t\tthrow new CodexCompactionProtocolError(\"Codex Responses payload is missing an input array\");\n\t}\n\tif (payload.input.some((item) => isObject(item) && item.type === \"compaction_trigger\")) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Provider payload already contains a compaction trigger\",\n\t\t);\n\t}\n\treturn { ...payload, input: [...payload.input, { type: \"compaction_trigger\" }] };\n}\n\nexport function prepareRemoteCompactionPayload(\n\tpayload: unknown,\n\tcheckpoint?: { marker: string; replacementHistory: readonly unknown[] },\n): JsonObject {\n\tconst expanded = checkpoint\n\t\t? rewriteCheckpointMarker(payload, checkpoint.marker, checkpoint.replacementHistory)\n\t\t: payload;\n\treturn appendCompactionTrigger(expanded);\n}\n\nexport function hasCheckpointMarker(payload: unknown, marker: string): boolean {\n\treturn (\n\t\tisObject(payload) &&\n\t\tArray.isArray(payload.input) &&\n\t\tpayload.input.some((item) => markerTextFromItem(item) === marker)\n\t);\n}\n", "import type { Context, Model, Provider, ProviderHeaders, Usage } from \"@earendil-works/pi-ai\";\nimport {\n\tCodexCompactionProtocolError,\n\ttype CollectedCompaction,\n\tcollectCompactionSse,\n\ttype JsonObject,\n\tprepareRemoteCompactionPayload,\n} from \"./protocol.js\";\n\ninterface PriorCheckpointPayload {\n\tmarker: string;\n\treplacementHistory: readonly unknown[];\n}\n\nexport interface RemoteCompactionRequest {\n\tprovider: Provider;\n\tmodel: Model<\"openai-codex-responses\">;\n\tcontext: Context;\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tenv?: Record<string, string>;\n\tsignal: AbortSignal;\n\tpriorCheckpoint?: PriorCheckpointPayload;\n\trequestTimeoutMs?: number;\n\tmaxRetries?: number;\n\tfetch?: typeof globalThis.fetch;\n}\n\nexport interface RemoteCompactionResponse {\n\titem: JsonObject;\n\tpromptInput: JsonObject[];\n\tusage: Usage;\n}\n\nconst EMPTY_USAGE: Usage = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction abortError(): DOMException {\n\treturn new DOMException(\"Compaction aborted\", \"AbortError\");\n}\n\nexport async function requestRemoteCompaction(\n\trequest: RemoteCompactionRequest,\n): Promise<RemoteCompactionResponse> {\n\tif (request.signal.aborted) throw abortError();\n\tlet sentInput: JsonObject[] | undefined;\n\tconst inspections: Promise<\n\t\t{ ok: true; value: CollectedCompaction } | { ok: false; error: unknown }\n\t>[] = [];\n\tconst baseFetch = request.fetch ?? globalThis.fetch;\n\tconst inspectedFetch: typeof globalThis.fetch = async (input, init) => {\n\t\tconst response = await baseFetch(input, init);\n\t\tif (!response.ok || !response.body) return response;\n\t\tconst [providerBody, inspectionBody] = response.body.tee();\n\t\tconst inspection = collectCompactionSse(inspectionBody, { signal: request.signal }).then(\n\t\t\t(value) => ({ ok: true as const, value }),\n\t\t\t(error: unknown) => ({ ok: false as const, error }),\n\t\t);\n\t\tinspections.push(inspection);\n\t\treturn new Response(providerBody, {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\theaders: response.headers,\n\t\t});\n\t};\n\n\tconst stream = request.provider.stream(request.model, request.context, {\n\t\tapiKey: request.apiKey,\n\t\theaders: request.headers,\n\t\tenv: request.env,\n\t\tsignal: request.signal,\n\t\ttransport: \"sse\",\n\t\tcacheRetention: \"none\",\n\t\ttimeoutMs: request.requestTimeoutMs ?? 5 * 60 * 1000,\n\t\tmaxRetries: request.maxRetries ?? 2,\n\t\tfetch: inspectedFetch,\n\t\tonPayload: (payload) => {\n\t\t\tconst prepared = prepareRemoteCompactionPayload(payload, request.priorCheckpoint);\n\t\t\tif (!Array.isArray(prepared.input) || !prepared.input.every(isObject)) {\n\t\t\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\t\t\"Prepared compaction payload has invalid input items\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tsentInput = structuredClone(prepared.input.slice(0, -1)) as JsonObject[];\n\t\t\treturn prepared;\n\t\t},\n\t});\n\n\tlet usage = EMPTY_USAGE;\n\tfor await (const event of stream) {\n\t\tif (request.signal.aborted) throw abortError();\n\t\tif (event.type === \"error\") {\n\t\t\tthrow new Error(event.error.errorMessage ?? \"Codex remote compaction request failed\");\n\t\t}\n\t\tif (event.type === \"done\") usage = event.message.usage;\n\t}\n\tif (request.signal.aborted) throw abortError();\n\tif (!sentInput)\n\t\tthrow new CodexCompactionProtocolError(\"Provider did not expose a request payload\");\n\tif (inspections.length === 0) {\n\t\tthrow new CodexCompactionProtocolError(\"Provider response did not expose an SSE body\");\n\t}\n\tconst inspection = await inspections.at(-1);\n\tif (request.signal.aborted) throw abortError();\n\tif (!inspection?.ok) throw inspection?.error ?? new Error(\"Remote compaction inspection failed\");\n\treturn { item: inspection.value.item, promptInput: sentInput, usage };\n}\n", "import { randomUUID } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport { mkdir, open, rename, rm, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join } from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\n\nexport const CODEX_COMPACT_SETTINGS_FILE = \"pi-codex-compact.json\";\nexport const MAX_SETTINGS_BYTES = 64 * 1024;\n\nexport interface CodexCompactSettings {\n\tenabled: boolean;\n\trequestTimeoutMs: number;\n\tmaxRetries: number;\n\treplacementTokenBudget: number;\n\tnotifyOnFallback: boolean;\n}\n\nexport const DEFAULT_CODEX_COMPACT_SETTINGS: Readonly<CodexCompactSettings> = Object.freeze({\n\tenabled: true,\n\trequestTimeoutMs: 300_000,\n\tmaxRetries: 2,\n\treplacementTokenBudget: 64_000,\n\tnotifyOnFallback: true,\n});\n\nconst LIMITS = Object.freeze({\n\trequestTimeoutMs: { minimum: 30_000, maximum: 600_000 },\n\tmaxRetries: { minimum: 0, maximum: 2 },\n\treplacementTokenBudget: { minimum: 8_000, maximum: 128_000 },\n});\n\nexport interface CodexCompactSettingsState {\n\tkind: \"missing\" | \"loaded\" | \"invalid\";\n\tpath: string;\n\tsettings: CodexCompactSettings;\n\tdocument?: Record<string, unknown>;\n\tissue?: string;\n}\n\nexport interface CodexCompactSettingsRuntime {\n\tget(): Readonly<CodexCompactSettingsState>;\n\treload(signal?: AbortSignal): Promise<Readonly<CodexCompactSettingsState>>;\n\tupdate(\n\t\tpatch: Partial<CodexCompactSettings>,\n\t\tsignal?: AbortSignal,\n\t): Promise<Readonly<CodexCompactSettingsState>>;\n\tflush(): Promise<void>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validInteger(value: unknown, minimum: number, maximum: number): value is number {\n\treturn (\n\t\ttypeof value === \"number\" && Number.isSafeInteger(value) && value >= minimum && value <= maximum\n\t);\n}\n\nexport function normalizeCodexCompactSettings(value: unknown): CodexCompactSettings | undefined {\n\tif (!isRecord(value)) return undefined;\n\tif (Object.hasOwn(value, \"enabled\") && typeof value.enabled !== \"boolean\") return undefined;\n\tif (Object.hasOwn(value, \"notifyOnFallback\") && typeof value.notifyOnFallback !== \"boolean\") {\n\t\treturn undefined;\n\t}\n\tfor (const [field, limits] of Object.entries(LIMITS) as Array<\n\t\t[keyof typeof LIMITS, { minimum: number; maximum: number }]\n\t>) {\n\t\tif (\n\t\t\tObject.hasOwn(value, field) &&\n\t\t\t!validInteger(value[field], limits.minimum, limits.maximum)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn {\n\t\tenabled:\n\t\t\ttypeof value.enabled === \"boolean\" ? value.enabled : DEFAULT_CODEX_COMPACT_SETTINGS.enabled,\n\t\trequestTimeoutMs:\n\t\t\ttypeof value.requestTimeoutMs === \"number\"\n\t\t\t\t? value.requestTimeoutMs\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.requestTimeoutMs,\n\t\tmaxRetries:\n\t\t\ttypeof value.maxRetries === \"number\"\n\t\t\t\t? value.maxRetries\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.maxRetries,\n\t\treplacementTokenBudget:\n\t\t\ttypeof value.replacementTokenBudget === \"number\"\n\t\t\t\t? value.replacementTokenBudget\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.replacementTokenBudget,\n\t\tnotifyOnFallback:\n\t\t\ttypeof value.notifyOnFallback === \"boolean\"\n\t\t\t\t? value.notifyOnFallback\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.notifyOnFallback,\n\t};\n}\n\nexport function codexCompactSettingsPath(): string {\n\treturn join(getAgentDir(), CODEX_COMPACT_SETTINGS_FILE);\n}\n\nfunction aborted(signal?: AbortSignal): void {\n\tif (signal?.aborted) throw new DOMException(\"Settings operation aborted\", \"AbortError\");\n}\n\nexport async function loadCodexCompactSettings(\n\tpath = codexCompactSettingsPath(),\n\tsignal?: AbortSignal,\n): Promise<CodexCompactSettingsState> {\n\taborted(signal);\n\ttry {\n\t\tconst handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);\n\t\tlet text: string;\n\t\ttry {\n\t\t\tconst stats = await handle.stat();\n\t\t\taborted(signal);\n\t\t\tif (!stats.isFile()) throw new Error(\"settings path is not a regular file\");\n\t\t\tif (stats.size > MAX_SETTINGS_BYTES) throw new Error(\"settings file exceeds 64 KiB\");\n\t\t\ttext = await handle.readFile(\"utf8\");\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\taborted(signal);\n\t\tconst document = JSON.parse(text) as unknown;\n\t\tconst settings = normalizeCodexCompactSettings(document);\n\t\tif (!settings || !isRecord(document)) throw new Error(\"invalid settings shape or bounds\");\n\t\treturn { kind: \"loaded\", path, settings, document };\n\t} catch (error) {\n\t\tif (signal?.aborted) throw error;\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\treturn {\n\t\t\t\tkind: \"missing\",\n\t\t\t\tpath,\n\t\t\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\t\t\tdocument: {},\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tkind: \"invalid\",\n\t\t\tpath,\n\t\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\t\tissue:\n\t\t\t\tisNodeError(error) && error.code === \"ELOOP\"\n\t\t\t\t\t? \"symbolic links are not accepted\"\n\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: String(error),\n\t\t};\n\t}\n}\n\nasync function savePatch(\n\tpath: string,\n\tpatch: Partial<CodexCompactSettings>,\n\tsignal?: AbortSignal,\n): Promise<CodexCompactSettingsState> {\n\tconst latest = await loadCodexCompactSettings(path, signal);\n\tif (latest.kind === \"invalid\") {\n\t\tthrow new Error(\n\t\t\t\"Cannot overwrite an invalid pi-codex-compact.json; repair it and reload first\",\n\t\t);\n\t}\n\tconst document = { ...latest.document, ...patch };\n\tconst settings = normalizeCodexCompactSettings(document);\n\tif (!settings) throw new Error(\"Refusing to save invalid Codex compaction settings\");\n\tconst temporaryPath = join(dirname(path), `.${basename(path)}.${randomUUID()}.tmp`);\n\tawait mkdir(dirname(path), { recursive: true });\n\taborted(signal);\n\ttry {\n\t\tawait writeFile(temporaryPath, `${JSON.stringify(document, null, 2)}\\n`, {\n\t\t\tencoding: \"utf8\",\n\t\t\tflag: \"wx\",\n\t\t\tmode: 0o600,\n\t\t});\n\t\taborted(signal);\n\t\tconst current = await loadCodexCompactSettings(path, signal);\n\t\tif (\n\t\t\tcurrent.kind === \"invalid\" ||\n\t\t\tcurrent.kind !== latest.kind ||\n\t\t\tJSON.stringify(current.document) !== JSON.stringify(latest.document)\n\t\t) {\n\t\t\tthrow new Error(\"pi-codex-compact.json changed while saving; reopen settings and retry\");\n\t\t}\n\t\tawait rename(temporaryPath, path);\n\t} finally {\n\t\tawait rm(temporaryPath, { force: true }).catch(() => undefined);\n\t}\n\treturn { kind: \"loaded\", path, settings, document };\n}\n\nexport function createCodexCompactSettingsRuntime(\n\tpath = codexCompactSettingsPath(),\n): CodexCompactSettingsRuntime {\n\tlet state: CodexCompactSettingsState = {\n\t\tkind: \"missing\",\n\t\tpath,\n\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\tdocument: {},\n\t};\n\tlet queue = Promise.resolve();\n\tconst enqueue = <T>(operation: () => Promise<T>): Promise<T> => {\n\t\tconst result = queue.then(operation, operation);\n\t\tqueue = result.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn result;\n\t};\n\treturn {\n\t\tget: () => structuredClone(state),\n\t\treload: (signal) =>\n\t\t\tenqueue(async () => {\n\t\t\t\tstate = await loadCodexCompactSettings(path, signal);\n\t\t\t\treturn structuredClone(state);\n\t\t\t}),\n\t\tupdate: (patch, signal) =>\n\t\t\tenqueue(async () => {\n\t\t\t\tstate = await savePatch(path, patch, signal);\n\t\t\t\treturn structuredClone(state);\n\t\t\t}),\n\t\tflush: () => queue,\n\t};\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n\treturn error instanceof Error && \"code\" in error;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["index", "isObject", "isObject", "inspection", "randomUUID"]
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narumitw/pi-codex-compact",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Codex Remote Compaction V2 for Pi
|
|
3
|
+
"version": "0.51.0",
|
|
4
|
+
"description": "Codex Remote Compaction V2 for compatible Pi providers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"private": false,
|
|
@@ -15,20 +15,23 @@
|
|
|
15
15
|
],
|
|
16
16
|
"files": [
|
|
17
17
|
"src",
|
|
18
|
+
"dist",
|
|
18
19
|
"README.md",
|
|
19
20
|
"LICENSE"
|
|
20
21
|
],
|
|
21
22
|
"pi": {
|
|
22
23
|
"extensions": [
|
|
23
|
-
"./
|
|
24
|
+
"./dist/index.ts"
|
|
24
25
|
]
|
|
25
26
|
},
|
|
26
27
|
"piExtension": {
|
|
27
28
|
"lifecycle": "stable"
|
|
28
29
|
},
|
|
29
30
|
"scripts": {
|
|
30
|
-
"
|
|
31
|
-
"
|
|
31
|
+
"build": "node scripts/build-runtime.mjs",
|
|
32
|
+
"check": "npm run build && biome check --vcs-use-ignore-file=false src test scripts package.json tsconfig.json README.md && npm run typecheck",
|
|
33
|
+
"format": "biome check --write --vcs-use-ignore-file=false src test scripts package.json tsconfig.json README.md",
|
|
34
|
+
"prepack": "npm run build",
|
|
32
35
|
"typecheck": "tsc --noEmit"
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {
|
|
@@ -40,11 +43,12 @@
|
|
|
40
43
|
"@earendil-works/pi-coding-agent": "*"
|
|
41
44
|
},
|
|
42
45
|
"devDependencies": {
|
|
43
|
-
"@biomejs/biome": "2.5.
|
|
44
|
-
"@earendil-works/pi-agent-core": "0.84.
|
|
45
|
-
"@earendil-works/pi-ai": "0.84.
|
|
46
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
47
|
-
"@types/node": "26.
|
|
46
|
+
"@biomejs/biome": "2.5.9",
|
|
47
|
+
"@earendil-works/pi-agent-core": "0.84.2",
|
|
48
|
+
"@earendil-works/pi-ai": "0.84.2",
|
|
49
|
+
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
50
|
+
"@types/node": "26.2.0",
|
|
51
|
+
"esbuild": "0.28.2",
|
|
48
52
|
"typescript": "7.0.2"
|
|
49
53
|
},
|
|
50
54
|
"repository": {
|
package/src/checkpoint.ts
CHANGED
|
@@ -8,12 +8,13 @@ export const CHECKPOINT_VERSION = 1;
|
|
|
8
8
|
export const REPLACEMENT_TOKEN_BUDGET = 64_000;
|
|
9
9
|
export const REPLACEMENT_BYTE_BUDGET = 8 * 1024 * 1024;
|
|
10
10
|
const MAX_MEDIA_ITEM_BYTES = 2 * 1024 * 1024;
|
|
11
|
+
const MAX_PROVIDER_ID_LENGTH = 256;
|
|
11
12
|
|
|
12
13
|
export interface CodexCheckpointDetails {
|
|
13
14
|
kind: typeof CHECKPOINT_KIND;
|
|
14
15
|
version: typeof CHECKPOINT_VERSION;
|
|
15
16
|
checkpointId: string;
|
|
16
|
-
provider:
|
|
17
|
+
provider: string;
|
|
17
18
|
api: "openai-codex-responses";
|
|
18
19
|
modelId: string;
|
|
19
20
|
protocol: "remote-compaction-v2";
|
|
@@ -50,14 +51,14 @@ export function checkpointMarker(checkpointId: string): string {
|
|
|
50
51
|
return [
|
|
51
52
|
`[PI_CODEX_REMOTE_CHECKPOINT:${checkpointId}]`,
|
|
52
53
|
"Opaque checkpoint injection failed. Do not infer missing history; tell the user to re-enable",
|
|
53
|
-
"@narumitw/pi-codex-compact with
|
|
54
|
+
"@narumitw/pi-codex-compact with a model using the openai-codex-responses API.",
|
|
54
55
|
].join(" ");
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
export function fallbackSummary(checkpointId: string): string {
|
|
58
59
|
return [
|
|
59
60
|
`OpenAI Codex Remote Compaction V2 checkpoint ${checkpointId} stores the older history opaquely.`,
|
|
60
|
-
"Full replay requires @narumitw/pi-codex-compact and
|
|
61
|
+
"Full replay requires @narumitw/pi-codex-compact and the same model through a compatible Codex Responses provider.",
|
|
61
62
|
"Without them, only Pi's retained recent messages remain available.",
|
|
62
63
|
].join(" ");
|
|
63
64
|
}
|
|
@@ -77,7 +78,9 @@ export function parseCheckpointDetails(value: unknown): CodexCheckpointDetails |
|
|
|
77
78
|
value.version !== CHECKPOINT_VERSION ||
|
|
78
79
|
typeof value.checkpointId !== "string" ||
|
|
79
80
|
value.checkpointId.length < 8 ||
|
|
80
|
-
value.provider !== "
|
|
81
|
+
typeof value.provider !== "string" ||
|
|
82
|
+
value.provider.length === 0 ||
|
|
83
|
+
value.provider.length > MAX_PROVIDER_ID_LENGTH ||
|
|
81
84
|
value.api !== "openai-codex-responses" ||
|
|
82
85
|
typeof value.modelId !== "string" ||
|
|
83
86
|
value.protocol !== "remote-compaction-v2" ||
|
|
@@ -135,10 +138,10 @@ function isOlderCompactionSummary(message: AgentMessage, timestamp: number): boo
|
|
|
135
138
|
export function projectCheckpointContext(
|
|
136
139
|
messages: readonly AgentMessage[],
|
|
137
140
|
details: CodexCheckpointDetails,
|
|
141
|
+
checkpointSummary: string,
|
|
138
142
|
): AgentMessage[] | undefined {
|
|
139
|
-
const summary = fallbackSummary(details.checkpointId);
|
|
140
143
|
const summaryIndex = messages.findIndex(
|
|
141
|
-
(message) => message.role === "compactionSummary" && message.summary ===
|
|
144
|
+
(message) => message.role === "compactionSummary" && message.summary === checkpointSummary,
|
|
142
145
|
);
|
|
143
146
|
if (summaryIndex < 0) return undefined;
|
|
144
147
|
const timestamp = messages[summaryIndex].timestamp;
|
|
@@ -254,6 +257,7 @@ export function buildReplacementHistory(
|
|
|
254
257
|
}
|
|
255
258
|
|
|
256
259
|
export function createCheckpointDetails(input: {
|
|
260
|
+
provider: string;
|
|
257
261
|
modelId: string;
|
|
258
262
|
replacementHistory: JsonObject[];
|
|
259
263
|
keptMessages: readonly AgentMessage[];
|
|
@@ -264,7 +268,7 @@ export function createCheckpointDetails(input: {
|
|
|
264
268
|
kind: CHECKPOINT_KIND,
|
|
265
269
|
version: CHECKPOINT_VERSION,
|
|
266
270
|
checkpointId: input.checkpointId ?? randomUUID(),
|
|
267
|
-
provider:
|
|
271
|
+
provider: input.provider,
|
|
268
272
|
api: "openai-codex-responses",
|
|
269
273
|
modelId: input.modelId,
|
|
270
274
|
protocol: "remote-compaction-v2",
|
package/src/codex-compact.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
2
2
|
import type { Api, Context, Model, Tool } from "@earendil-works/pi-ai";
|
|
3
|
-
import { hasApi } from "@earendil-works/pi-ai";
|
|
4
3
|
import {
|
|
5
4
|
buildContextEntries,
|
|
6
5
|
buildSessionContext,
|
|
@@ -19,6 +18,7 @@ import {
|
|
|
19
18
|
latestCheckpoint,
|
|
20
19
|
projectCheckpointContext,
|
|
21
20
|
} from "./checkpoint.js";
|
|
21
|
+
import { isCodexRemoteCompactionModel } from "./model-compatibility.js";
|
|
22
22
|
import { hasCheckpointMarker, rewriteCheckpointMarker } from "./protocol.js";
|
|
23
23
|
import { requestRemoteCompaction } from "./remote.js";
|
|
24
24
|
import {
|
|
@@ -27,14 +27,9 @@ import {
|
|
|
27
27
|
type CodexCompactSettingsState,
|
|
28
28
|
createCodexCompactSettingsRuntime,
|
|
29
29
|
} from "./settings.js";
|
|
30
|
-
import { showCodexCompactMenu } from "./settings-menu.js";
|
|
31
30
|
|
|
32
31
|
const STATUS_KEY = "codex-compact";
|
|
33
32
|
|
|
34
|
-
function isSupportedModel(model: Model<Api> | undefined): model is Model<"openai-codex-responses"> {
|
|
35
|
-
return model?.provider === "openai-codex" && hasApi(model, "openai-codex-responses");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
33
|
function activeCheckpoint(ctx: ExtensionContext) {
|
|
39
34
|
return latestCheckpoint(ctx.sessionManager.getBranch());
|
|
40
35
|
}
|
|
@@ -43,7 +38,7 @@ function isCheckpointCompatible(
|
|
|
43
38
|
details: CodexCheckpointDetails,
|
|
44
39
|
model: Model<Api> | undefined,
|
|
45
40
|
): model is Model<"openai-codex-responses"> {
|
|
46
|
-
return
|
|
41
|
+
return isCodexRemoteCompactionModel(model) && model.id === details.modelId;
|
|
47
42
|
}
|
|
48
43
|
|
|
49
44
|
function keptMessages(event: SessionBeforeCompactEvent): AgentMessage[] {
|
|
@@ -76,16 +71,16 @@ function projectedCurrentMessages(
|
|
|
76
71
|
): { messages: AgentMessage[]; prior?: CodexCheckpointDetails } {
|
|
77
72
|
const leafId = event.branchEntries.at(-1)?.id ?? null;
|
|
78
73
|
const session = buildSessionContext(event.branchEntries, leafId);
|
|
79
|
-
const prior = latestCheckpoint(event.branchEntries)
|
|
74
|
+
const prior = latestCheckpoint(event.branchEntries);
|
|
80
75
|
if (!prior) return { messages: session.messages };
|
|
81
|
-
if (prior.modelId !== model.id) {
|
|
76
|
+
if (prior.details.modelId !== model.id) {
|
|
82
77
|
throw new Error("The active opaque checkpoint belongs to a different Codex model");
|
|
83
78
|
}
|
|
84
|
-
const projected = projectCheckpointContext(session.messages, prior);
|
|
79
|
+
const projected = projectCheckpointContext(session.messages, prior.details, prior.entry.summary);
|
|
85
80
|
if (!projected) {
|
|
86
81
|
throw new Error("The previous opaque checkpoint could not be projected safely");
|
|
87
82
|
}
|
|
88
|
-
return { messages: projected, prior };
|
|
83
|
+
return { messages: projected, prior: prior.details };
|
|
89
84
|
}
|
|
90
85
|
|
|
91
86
|
function notifyFailure(
|
|
@@ -110,17 +105,15 @@ async function compactRemotely(
|
|
|
110
105
|
fetch?: typeof globalThis.fetch,
|
|
111
106
|
) {
|
|
112
107
|
const model = ctx.model;
|
|
113
|
-
if (!settings.enabled || !
|
|
108
|
+
if (!settings.enabled || !isCodexRemoteCompactionModel(model)) return undefined;
|
|
114
109
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
115
110
|
ctx.ui.setStatus(STATUS_KEY, "Codex remote compaction…");
|
|
116
111
|
try {
|
|
117
112
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
118
113
|
if (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };
|
|
119
|
-
if (!auth.ok
|
|
120
|
-
throw new Error(auth.ok ? "OpenAI Codex OAuth token is unavailable" : auth.error);
|
|
121
|
-
}
|
|
114
|
+
if (!auth.ok) throw new Error(auth.error);
|
|
122
115
|
const provider = ctx.modelRegistry.getProvider(model.provider);
|
|
123
|
-
if (!provider) throw new Error("
|
|
116
|
+
if (!provider) throw new Error("The active Codex Responses provider is unavailable");
|
|
124
117
|
const current = projectedCurrentMessages(event, model);
|
|
125
118
|
const context: Context = {
|
|
126
119
|
systemPrompt: ctx.getSystemPrompt(),
|
|
@@ -150,6 +143,7 @@ async function compactRemotely(
|
|
|
150
143
|
tokenBudget: settings.replacementTokenBudget,
|
|
151
144
|
});
|
|
152
145
|
const details = createCheckpointDetails({
|
|
146
|
+
provider: model.provider,
|
|
153
147
|
modelId: model.id,
|
|
154
148
|
replacementHistory,
|
|
155
149
|
keptMessages: keptMessages(event),
|
|
@@ -187,9 +181,12 @@ export function createCodexCompactExtension(
|
|
|
187
181
|
description: "Compact now or configure Codex Remote Compaction V2",
|
|
188
182
|
handler: async (_args, ctx) => {
|
|
189
183
|
const ownerGeneration = generation;
|
|
184
|
+
const controller = sessionController;
|
|
185
|
+
const { showCodexCompactMenu } = await import("./settings-menu.js");
|
|
186
|
+
if (ownerGeneration !== generation || controller.signal.aborted) return;
|
|
190
187
|
await showCodexCompactMenu(settingsRuntime, ctx, {
|
|
191
|
-
signal:
|
|
192
|
-
isCurrent: () => ownerGeneration === generation && !
|
|
188
|
+
signal: controller.signal,
|
|
189
|
+
isCurrent: () => ownerGeneration === generation && !controller.signal.aborted,
|
|
193
190
|
});
|
|
194
191
|
},
|
|
195
192
|
});
|
|
@@ -237,7 +234,11 @@ export function createCodexCompactExtension(
|
|
|
237
234
|
if (!settingsRuntime.get().settings.enabled) return undefined;
|
|
238
235
|
const checkpoint = activeCheckpoint(ctx);
|
|
239
236
|
if (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return undefined;
|
|
240
|
-
const messages = projectCheckpointContext(
|
|
237
|
+
const messages = projectCheckpointContext(
|
|
238
|
+
event.messages,
|
|
239
|
+
checkpoint.details,
|
|
240
|
+
checkpoint.entry.summary,
|
|
241
|
+
);
|
|
241
242
|
return messages ? { messages } : undefined;
|
|
242
243
|
});
|
|
243
244
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
2
|
+
import { hasApi } from "@earendil-works/pi-ai";
|
|
3
|
+
|
|
4
|
+
export function isCodexRemoteCompactionModel(
|
|
5
|
+
model: Model<Api> | undefined,
|
|
6
|
+
): model is Model<"openai-codex-responses"> {
|
|
7
|
+
return model !== undefined && hasApi(model, "openai-codex-responses");
|
|
8
|
+
}
|
package/src/protocol.ts
CHANGED
|
@@ -172,7 +172,7 @@ export function rewriteCheckpointMarker(
|
|
|
172
172
|
replacementHistory: readonly unknown[],
|
|
173
173
|
): JsonObject {
|
|
174
174
|
if (!isObject(payload) || !Array.isArray(payload.input)) {
|
|
175
|
-
throw new CodexCompactionProtocolError("
|
|
175
|
+
throw new CodexCompactionProtocolError("Codex Responses payload is missing an input array");
|
|
176
176
|
}
|
|
177
177
|
const matches = payload.input
|
|
178
178
|
.map((item, index) => (markerTextFromItem(item) === marker ? index : -1))
|
|
@@ -195,7 +195,7 @@ export function rewriteCheckpointMarker(
|
|
|
195
195
|
|
|
196
196
|
export function appendCompactionTrigger(payload: unknown): JsonObject {
|
|
197
197
|
if (!isObject(payload) || !Array.isArray(payload.input)) {
|
|
198
|
-
throw new CodexCompactionProtocolError("
|
|
198
|
+
throw new CodexCompactionProtocolError("Codex Responses payload is missing an input array");
|
|
199
199
|
}
|
|
200
200
|
if (payload.input.some((item) => isObject(item) && item.type === "compaction_trigger")) {
|
|
201
201
|
throw new CodexCompactionProtocolError(
|
package/src/remote.ts
CHANGED
|
@@ -100,7 +100,7 @@ export async function requestRemoteCompaction(
|
|
|
100
100
|
for await (const event of stream) {
|
|
101
101
|
if (request.signal.aborted) throw abortError();
|
|
102
102
|
if (event.type === "error") {
|
|
103
|
-
throw new Error(event.error.errorMessage ?? "
|
|
103
|
+
throw new Error(event.error.errorMessage ?? "Codex remote compaction request failed");
|
|
104
104
|
}
|
|
105
105
|
if (event.type === "done") usage = event.message.usage;
|
|
106
106
|
}
|
package/src/settings-menu.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { MenuDefinition } from "@narumitw/pi-tui-kit";
|
|
3
|
+
import { isCodexRemoteCompactionModel } from "./model-compatibility.js";
|
|
3
4
|
import type {
|
|
4
5
|
CodexCompactSettings,
|
|
5
6
|
CodexCompactSettingsRuntime,
|
|
@@ -217,11 +218,11 @@ export async function showCodexCompactMenu(
|
|
|
217
218
|
});
|
|
218
219
|
}
|
|
219
220
|
|
|
220
|
-
function compactMenuStatus(ctx: ExtensionCommandContext): CompactMenuStatus {
|
|
221
|
+
export function compactMenuStatus(ctx: ExtensionCommandContext): CompactMenuStatus {
|
|
221
222
|
const model = ctx.model;
|
|
222
223
|
return {
|
|
223
224
|
model: model ? `${model.provider}/${model.id}` : "none",
|
|
224
|
-
remoteCompatible: model
|
|
225
|
+
remoteCompatible: isCodexRemoteCompactionModel(model),
|
|
225
226
|
};
|
|
226
227
|
}
|
|
227
228
|
|