Files
PaperClipAI/packages/paperclip-runner/scripts/patch-kimi-runtime.mjs
T
DottaandPaperclip b866fa4bdc feat(runner): add pinned Kimi Code native runtime (#18028)
Add the pinned Kimi Code runtime, native instruction and model admission, scoped credentials, and pending-candidate recovery contracts. Retain current master release attestations and provider-pack compatibility.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 21:58:12 -05:00

161 lines
12 KiB
JavaScript

import { createHash } from "node:crypto";
import { readFile, writeFile } from "node:fs/promises";
import { pathToFileURL } from "node:url";
import { KIMI_INSTRUCTION_RUNTIME_SOURCE } from "./kimi-instructions-runtime.mjs";
export const KIMI_RUNTIME_PATCH = Object.freeze({
version: "paperclip-kimi-2.3.3-instructions-v6",
vendorSha256: "f18b711e22947d473175126d0c2da437d641187963a3bc300d66e183060703e3",
patchedSha256: "79980aa95c54f325a05cbdf883f74443705db28f3e412a1b5ae22929d939eb66",
});
const sha256 = value => createHash("sha256").update(value).digest("hex");
export function replaceKimiPatchAnchor(source, before, after) {
if (source.split(before).length !== 2) throw new Error("Kimi runtime patch requires exactly one source anchor");
return source.replace(before, () => after);
}
export function patchKimiRuntimeSource(input) {
if (sha256(input) !== KIMI_RUNTIME_PATCH.vendorSha256) throw new Error("Kimi runtime patch input digest mismatch");
let source = input;
const replace = (before, after) => { source = replaceKimiPatchAnchor(source, before, after); };
replace("#!/usr/bin/env node\n", `#!/usr/bin/env node
import { createHash as paperclipKimiCreateHash } from "node:crypto";
let paperclipKimiInstructionSnapshot;
function paperclipKimiInstructionState() {
if (paperclipKimiInstructionSnapshot) return paperclipKimiInstructionSnapshot;
const raw = process.env.PAPERCLIP_KIMI_INSTRUCTIONS;
delete process.env.PAPERCLIP_KIMI_INSTRUCTIONS;
return paperclipKimiInstructionSnapshot = (${KIMI_INSTRUCTION_RUNTIME_SOURCE})(raw, {
createHash: paperclipKimiCreateHash, byteLength: value => Buffer.byteLength(value, "utf8")
});
}
function paperclipKimiChildEnvironment(overrides) {
const environment = { ...process.env, ...overrides };
delete environment.KIMI_API_KEY;
delete environment.PAPERCLIP_KIMI_INSTRUCTIONS;
return environment;
}
`);
replace('function buildEnv(overrides) {\n\tif (overrides === void 0) return;\n\treturn {\n\t\t...process.env,\n\t\t...overrides\n\t};\n}',
'function buildEnv(overrides) {\n\treturn paperclipKimiChildEnvironment(overrides);\n}');
replace('env: globalThis.process.env', 'env: paperclipKimiChildEnvironment()');
replace('\t\tbindTerminalCapability(terminal) {\n\t\t\tthis._terminalEnabled = terminal === true;\n\t\t}',
'\t\tbindTerminalCapability(terminal) {\n\t\t\tthis._terminalEnabled = false;\n\t\t}');
replace("\t\tget systemPrompt() {\n\t\t\treturn this.profileState.systemPrompt;\n\t\t}",
"\t\tget systemPrompt() {\n\t\t\treturn paperclipKimiInstructionState().append(this.profileState.systemPrompt);\n\t\t}");
replace("async function runAcpServerWithStream(stream, opts = {}) {\n",
"async function runAcpServerWithStream(stream, opts = {}) {\n\tpaperclipKimiInstructionState();\n");
replace('\t\tmerged() {\n\t\t\treturn {\n\t\t\t\t...Object.fromEntries(this.pluginServers),\n\t\t\t\t...Object.fromEntries(this.fileServers)\n\t\t\t};\n\t\t}',
'\t\tmerged() {\n\t\t\treturn {};\n\t\t}');
replace('\tawait pushFirstExisting$1(roots, USER_GENERIC_DIRS$1, osHomeDir, "user");', '');
replace('async function projectRoots(workDir, options = {}) {\n', 'async function projectRoots(workDir, options = {}) {\n\treturn [];\n');
replace('async function projectAgentRoots(fs, workDir, warn) {\n', 'async function projectAgentRoots(fs, workDir, warn) {\n\treturn [];\n');
replace('async function userAgentRoots(fs, homeDir, osHomeDir, warn) {\n', 'async function userAgentRoots(fs, homeDir, osHomeDir, warn) {\n\treturn [];\n');
replace('this.byEvent = indexHooks([...configured ?? [], ...pluginHooks]);', 'this.byEvent = new Map();');
replace('\t\tasync evaluate(context) {\n\t\t\tfor (const policy of this.policies) {',
'\t\tasync evaluate(context) {\n\t\t\treturn { policyName: "paperclip-runner", result: { kind: "ask" } };\n\t\t\tfor (const policy of this.policies) {');
replace('if (req.display.kind !== "plan_review") return CANONICAL_OPTIONS;',
'if (req.display.kind !== "plan_review") return CANONICAL_OPTIONS.filter(option => option.kind !== "allow_always");');
replace('\t\t\t\ttoolName: name,\n\t\t\t\taction,\n\t\t\t\tdisplay\n\t\t\t};\n\t\t\tconst approvalContext = {',
'\t\t\t\ttoolName: name,\n\t\t\t\ttoolInput: context.args,\n\t\t\t\taction,\n\t\t\t\tdisplay\n\t\t\t};\n\t\t\tconst approvalContext = {');
replace('\t\ttitle: req.toolName,\n\t\tcontent\n', '\t\ttitle: req.toolName,\n\t\tkind: inferToolKind(req.toolName),\n\t\trawInput: req.toolInput,\n\t\tcontent\n');
const bindRuntime = '\t\t\thandle.accessor.get(IAgentLifecycleService).handleOf(agentContext.agentId).accessor.get(IAgentRuntimeBindingService).switch(runtimeId);';
replace(bindRuntime, `${bindRuntime}
\t\t\tconst paperclipProfile = handle.accessor.get(IAgentLifecycleService).handleOf(agentContext.agentId).accessor.get(IAgentProfileService);
\t\t\treturn paperclipKimiInstructionState().receipt(sessionId, paperclipProfile.getSystemPrompt());`);
replace("\t\t\tawait this.bindSessionRuntime?.(sessionId);\n",
"\t\t\tconst paperclipReceipt = await this.bindSessionRuntime?.(sessionId);\n\t\t\tif (!paperclipReceipt || paperclipReceipt.sessionId !== sessionId) throw new Error(\"Kimi native instruction receipt is missing\");\n\t\t\tthis.paperclipInstructionReceipts ??= new Map();\n\t\t\tthis.paperclipInstructionReceipts.set(sessionId, paperclipReceipt);\n");
replace("\t\t\t\t...await this.activateSession(meta.id)\n",
"\t\t\t\t...await this.activateSession(meta.id),\n\t\t\t\t_meta: { paperclipKimiInstructions: this.paperclipInstructionReceipts.get(meta.id) }\n");
const lifecycleState = "\t\t\t\tconfigOptions: await acpSession.configOptions(),\n\t\t\t\tmodes: acpSession.modeState()\n\t\t\t};\n\t\t}\n\t\tasync ";
replace(`${lifecycleState}resumeSession(params)`,
`${lifecycleState.replace("modes: acpSession.modeState()", "modes: acpSession.modeState(),\n\t\t\t\t_meta: { paperclipKimiInstructions: this.paperclipInstructionReceipts.get(params.sessionId) }")}resumeSession(params)`);
replace(`${lifecycleState}listSessions(params)`,
`${lifecycleState.replace("modes: acpSession.modeState()", "modes: acpSession.modeState(),\n\t\t\t\t_meta: { paperclipKimiInstructions: this.paperclipInstructionReceipts.get(params.sessionId) }")}listSessions(params)`);
replace('\t\t\t\tdriver.resolve({ stopReason: turnEndReasonToStopReason(event.reason, error) });',
'\t\t\t\tif (event.reason === "failed") {\n\t\t\t\t\tdriver.reject(RequestError$1.internalError({ schema: "paperclip.kimi.provider-error.v1", kind: "provider_failed" }, "Kimi provider turn failed"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdriver.resolve({ stopReason: turnEndReasonToStopReason(event.reason, error) });');
const stepSchema = 'object({ type: string(), turnId: number$1().int().nonnegative(), step: number$1().int().positive(), stepId: string().min(1).max(256).optional(), finishReason: string().max(32).optional(), reason: string().max(32).optional() })';
replace('\tagentEvents = {\n\t\t"turn.started": {', `\tagentEvents = {
\t\t"turn.step.started": { kind: "stream", name: "events", type: "turn.step.started", schema: ${stepSchema} },
\t\t"turn.step.completed": { kind: "stream", name: "events", type: "turn.step.completed", schema: ${stepSchema} },
\t\t"turn.step.interrupted": { kind: "stream", name: "events", type: "turn.step.interrupted", schema: ${stepSchema} },
\t\t"turn.started": {`);
replace('\t\t\tthis.subscriptions.push(events.on("assistant.delta", (event) => {', `\t\t\tthis.subscriptions.push(
\t\t\t\tevents.on("turn.step.started", event => this.dispatchTurnEvent(event.turnId, () => this.paperclipKimiStep(event, "start"))),
\t\t\t\tevents.on("turn.step.completed", event => this.dispatchTurnEvent(event.turnId, () => this.paperclipKimiStep(event, "end"))),
\t\t\t\tevents.on("turn.step.interrupted", event => this.dispatchTurnEvent(event.turnId, () => this.paperclipKimiStep(event, "interrupted"))),
\t\t\t\tevents.on("assistant.delta", (event) => {`);
replace('\t\tonAssistantDelta(event) {\n\t\t\tif (this.driverFor(event.turnId) === void 0) return;\n\t\t\tthis.emit(assistantDeltaToSessionUpdate(this.sessionId, event));\n\t\t}', `\t\tpaperclipKimiMessageFailure(driver) {
\t\t\tthis.settleDriver(driver, () => driver.reject(RequestError$1.internalError({ schema: "paperclip.kimi.provider-error.v1", kind: "message_boundary_invalid" }, "Kimi native message boundary is invalid")));
\t\t}
\t\tpaperclipKimiChunk(driver, text, kind, thought = false) {
\t\t\tthis.emit({ sessionId: this.sessionId, update: {
\t\t\t\tsessionUpdate: thought ? "agent_thought_chunk" : "agent_message_chunk",
\t\t\t\tmessageId: driver.paperclipKimiMessage.id, content: { type: "text", text },
\t\t\t\t_meta: { origin: "kimi-native-assistant", source: "kimi-turn-step-v1", kind }
\t\t\t} });
\t\t}
\t\tpaperclipKimiStep(event, phase) {
\t\t\tconst driver = this.driverFor(event.turnId);
\t\t\tif (driver === void 0) return;
\t\t\tconst current = driver.paperclipKimiMessage;
\t\t\tif (!Number.isSafeInteger(event.step) || event.step < 1 || !Number.isSafeInteger(event.turnId) || event.turnId < 0) return this.paperclipKimiMessageFailure(driver);
\t\t\tif (phase === "start") {
\t\t\t\tif (current?.active || typeof event.stepId !== "string" || !/^[A-Za-z0-9_-]{1,256}$/.test(event.stepId) || current && event.step <= current.step) return this.paperclipKimiMessageFailure(driver);
\t\t\t\tdriver.paperclipKimiMessageIds ??= new Set();
\t\t\t\tconst id = "kimi-message-" + paperclipKimiCreateHash("sha256").update(JSON.stringify([this.sessionId, event.turnId, event.stepId])).digest("hex");
\t\t\t\tif (driver.paperclipKimiMessageIds.size >= 4096 || driver.paperclipKimiMessageIds.has(id)) return this.paperclipKimiMessageFailure(driver);
\t\t\t\tdriver.paperclipKimiMessageIds.add(id);
\t\t\t\tdriver.paperclipKimiMessage = { id, step: event.step, stepId: event.stepId, active: true };
\t\t\t\tthis.paperclipKimiChunk(driver, "", "start");
\t\t\t\treturn;
\t\t\t}
\t\t\tif (!current || current.step !== event.step || event.stepId !== void 0 && event.stepId !== current.stepId) return this.paperclipKimiMessageFailure(driver);
\t\t\tconst reason = phase === "interrupted" ? event.reason : event.finishReason;
\t\t\tconst reasons = phase === "interrupted" ? ["aborted", "max_steps", "error"] : ["end_turn", "max_tokens", "tool_use", "filtered", "paused", "other"];
\t\t\tif (!reasons.includes(reason)) return this.paperclipKimiMessageFailure(driver);
\t\t\tif (!current.active) {
\t\t\t\tif (phase === "interrupted") return;
\t\t\t\treturn this.paperclipKimiMessageFailure(driver);
\t\t\t}
\t\t\tthis.paperclipKimiChunk(driver, "", "end:" + reason);
\t\t\tcurrent.active = false;
\t\t}
\t\tonAssistantDelta(event) {
\t\t\tconst driver = this.driverFor(event.turnId);
\t\t\tif (driver === void 0) return;
\t\t\tif (!driver.paperclipKimiMessage?.active || typeof event.delta !== "string") return this.paperclipKimiMessageFailure(driver);
\t\t\tthis.paperclipKimiChunk(driver, event.delta, "delta");
\t\t}`);
replace('\t\tonThinkingDelta(event) {\n\t\t\tif (this.driverFor(event.turnId) === void 0) return;\n\t\t\tthis.emit(thinkingDeltaToSessionUpdate(this.sessionId, event));\n\t\t}', `\t\tonThinkingDelta(event) {
\t\t\tconst driver = this.driverFor(event.turnId);
\t\t\tif (driver === void 0) return;
\t\t\tif (!driver.paperclipKimiMessage?.active || typeof event.delta !== "string") return this.paperclipKimiMessageFailure(driver);
\t\t\tthis.paperclipKimiChunk(driver, event.delta, "delta", true);
\t\t}`);
return source;
}
export async function patchKimiRuntime(path) {
const input = await readFile(path, "utf8");
const digest = sha256(input);
if (digest === KIMI_RUNTIME_PATCH.patchedSha256) return { ...KIMI_RUNTIME_PATCH };
const patched = patchKimiRuntimeSource(input);
if (sha256(patched) !== KIMI_RUNTIME_PATCH.patchedSha256) throw new Error("Kimi runtime patch output digest mismatch");
await writeFile(path, patched);
return { ...KIMI_RUNTIME_PATCH };
}
if (import.meta.url?.endsWith("/patch-kimi-runtime.mjs") && process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
const path = process.argv[2];
if (!path || process.argv.length !== 3) throw new Error("Usage: node patch-kimi-runtime.mjs <dist/main.mjs>");
patchKimiRuntime(path).then(result => {
process.stdout.write(`${JSON.stringify(result)}\n`);
}).catch(error => {
process.stderr.write(`${error instanceof Error ? error.message : "Kimi runtime patch failed"}\n`);
process.exitCode = 1;
});
}