返回文章列表

Post

在 Arena 指定模型测 Kimi 前端:油猴脚本 + 短提示词

54 分钟读完

Arena(arena.ai / lmarena.ai)里,模型不一定都挂在前台可选列表。想点名测 Kimi 相关前端检查点,装下面这套油猴脚本,再在搜索里选模型开聊就行。

先说实测里比较稳的几点:

  • 前端观感经常能给惊喜
  • 复杂业务逻辑、后端别指望一次做稳
  • 提示词越短越好;写太长反而容易限制发挥
  • 脚本有时刷不出模型,刷新或换时段重试
  • kivine 和列表里第三个 kimi-2.7-code 不是同一个检测点,别混着比

安装

  1. 浏览器装 Tampermonkey(或兼容扩展)
  2. 油猴里新建脚本
  3. 把文末完整脚本粘进去保存

脚本匹配:

  • https://arena.ai/*
  • https://*.arena.ai/*
  • https://lmarena.ai/*
  • https://*.lmarena.ai/*

怎么测

打开 Arena,搜索框输入模型名,选中后直接聊,让它生成页面 / 小游戏 / 可视化。

优先试:

  • kivine
  • 第三个 kimi-2.7-code

列表没刷出来就刷新;高峰期慢是正常的。

控制台可以看注入状态:

window.__arenaInjectorStatus

提示词怎么写

只记一条:短、具体、能一眼验收

可以这样写:

做一个单关卡愤怒的小鸟,单 HTML,完成度尽量高。
生成一个 3D 城市交通模拟器:十字路口、红绿灯、高架桥、电车,日本街景车流。
写一个最难看的门户网站,要丑得有风格。

别一上来塞整本 PRD。复杂题拆两轮:先要可玩/可看,再补系统细节。

脚本干了什么

脚本名大致是 Arena Injector V5.5 Selectable Only。它主要做这些事:

  • 扫 Arena 返回的模型载荷(RSC / fetch / XHR)
  • 对已经 userSelectable: true 的模型,补前端展示字段(比如 providerorganization
  • 处理同名模型去重时的遮挡(Text 和 Code 同名时,尽量别把 Code/WebDev 挡掉)
  • 继续 hook Next.js 的 __next_f 分块、嵌套 JSON、后续 SPA 导航

注意:

  • 页面一改,脚本可能挂,得换版本
  • 这是前端注入,不是官方功能
  • 只建议自己做对比实验

已有样例

同一题材、不同检查点,先建立预期:

看材质、构图、UI 完成度、技能演出就够了。别当论文评测。

题库

游戏

请做一个像素骑士冒险放置游戏:3 个关卡,3 个豪华技能演出,6 个一般技能演出,6 个普通 buff,1 个 debuff;随机自动战斗,横版卷轴;带角色系统和装备系统。
制作一个单关卡的愤怒的小鸟,单 HTML,完成度尽量高。
做网页游戏:玩法以无人深空为主,画风以我的世界方块风为主;飞机与星球建模、UI 要酷;进入星球要有过渡动画;音效和交互尽量完整。

3D / 城市

生成一个 3D 城市交通模拟器,日本典型交通场景与车流,含十字路口、红绿灯、高架桥、电车。

工程前端

2.5D 化学工作流前端:React Flow 管 DAG,共享 WebGL Canvas 渲染悬浮分子;支持同 (x,y) 不同 z 层任务;Zustand 管状态;SSE/WebSocket 刷任务进度。

这类题更适合看架构表达和组件分层,别默认后端也能一次做稳。

教学可视化

做一个单页交互式网页,讲清格子玻尔兹曼方法(LBM)基本原理:D2Q9、碰撞、迁移、宏观量恢复;中文讲解,公式可渲染,带动画和自测题。

反例

反向思维:写一个最难看的门户网站。
制作一个比这个更糟糕的网站:https://www.richify.net/zh-hans/

想比得更公平

固定这几条就行:

  1. 同一提示词分别打 kivinekimi-2.7-code
  2. 同一浏览器、同一时段,少掺排队噪音
  3. 只评三件事:首屏观感、交互能不能点、代码能不能本地独立打开
  4. 复杂题拆两轮,别一次 dump 完整方案
  5. 要验收标准时,可以先让别的模型出 rubric,再回 Arena 看成品

能力边界

目前体感大概是:

  • 前端好看:经常有
  • 复杂状态机、联机、数值闭环:一般
  • 真实后端工程题:别默认能扛
  • 长提示词:容易限制发挥,短题更舒服

故障排查

现象先试什么
搜不到目标模型刷新;确认脚本已启用;看 window.__arenaInjectorStatus 有没有 patch
偶尔刷不出来换时段重试
生成很慢高峰排队正常;先用更短提示词验证通路
同名模型点错分清 Text / Code,确认 publicName
脚本装了没效果确认域名匹配 arena.ai / lmarena.ai,扩展对该站有权限

完整脚本

油猴新建脚本后,整段复制粘贴即可。Arena 前端一改,可能要换新版本。

// ==UserScript==
// @name         (仙之人兮列如麻) V5.5 Selectable Only
// @namespace    http://tampermonkey.net/
// @version      0.10.0
// @description  Reveals Arena userSelectable:true models and resolves duplicate model IDs safely
// @author       skuhrasr0plus1
// @match        https://arena.ai/*
// @match        https://*.arena.ai/*
// @match        https://lmarena.ai/*
// @match        https://*.lmarena.ai/*
// @grant        none
// @run-at       document-start
// @inject-into  page
// @sandbox      raw
// ==/UserScript==

(function () {
    'use strict';

    const W = window;
    const INSTALL_KEY = Symbol.for('arena.provider.injector.v5.5.installed');
    const PUSH_ACCESSOR_MARK = Symbol.for('arena.provider.injector.push.accessor');
    const PUSH_WRAPPER_MARK = Symbol.for('arena.provider.injector.push.wrapper');
    const WATCH_MARK = Symbol.for('arena.provider.injector.nextf.watcher');
    const FETCH_MARK = Symbol.for('arena.provider.injector.fetch');
    const PARSE_MARK = Symbol.for('arena.provider.injector.parse');
    const XHR_MARK = Symbol.for('arena.provider.injector.xhr');

    if (W[INSTALL_KEY]) {
        console.warn('[Arena Injector V5.5] 已运行,阻止重复安装。');
        return;
    }

    W[INSTALL_KEY] = true;

    const CONFIG = {
        provider: 'google',
        organization: 'google',
        // 不翻转 userSelectable:false;只补齐服务端已允许的模型。
        forceSelectablePublicNames: new Set(),
        // Arena 同时提供同名的 Text 与 Code Kivine。跳过 Text ID,
        // 避免前端按 publicName 去重时遮蔽 Code/WebDev 版本。
        excludedModelIds: new Set([
            '019f62a7-eda4-7659-9436-a4bd76fbc383'
        ]),
        debug: true,
        hookFetch: true,
        hookJSONParse: true,
        hookXHR: true,
        recoveryInterval: 1000
    };

    const status = {
        version: '5.5',
        startedAt: new Date().toISOString(),
        watcherInstallations: 0,
        nextArraysHooked: 0,
        nextPushCalls: 0,
        pushReplacements: 0,
        textPayloadsScanned: 0,
        textPayloadsPatched: 0,
        textModelsPatched: 0,
        objectModelsPatched: 0,
        fieldsAdded: 0,
        selectableForced: 0,
        fetchSeen: 0,
        fetchPatched: 0,
        jsonParseCalls: 0,
        xhrPatched: 0,
        lastPatchAt: null,
        lastError: null
    };

    try {
        Object.defineProperty(W, '__arenaInjectorStatus', {
            value: status,
            configurable: true
        });
    } catch {
        W.__arenaInjectorStatus = status;
    }

    const log = (...args) => {
        if (CONFIG.debug) {
            console.log('[Arena Injector V5.5]', ...args);
        }
    };

    const reportError = (area, error) => {
        status.lastError = {
            area,
            message: String(error?.message || error),
            time: new Date().toISOString()
        };
        console.warn(\`[Arena Injector V5.5] ${area}:\`, error);
    };

    const own = (object, key) =>
        Object.prototype.hasOwnProperty.call(object, key);

    const touchPatchTime = () => {
        status.lastPatchAt = new Date().toISOString();
    };

    /*
     * level 0:普通 JSON
     *     {"publicName":"..."}
     *
     * level 1:嵌套在字符串中的一次转义 JSON
     *     {\"publicName\":\"...\"}
     */
    function isStructuralQuote(text, index, level) {
        let slashCount = 0;

        for (let i = index - 1; i >= 0 && text[i] === '\\'; i--) {
            slashCount++;
        }

        if (level === 0) {
            return slashCount % 2 === 0;
        }

        return slashCount % 4 === 1;
    }

    function skipWhitespace(text, position) {
        while (
            position < text.length &&
            (
                text[position] === ' ' ||
                text[position] === '\t' ||
                text[position] === '\r' ||
                text[position] === '\n'
            )
        ) {
            position++;
        }

        return position;
    }

    function encodePair(key, value, level) {
        const raw = JSON.stringify(key) + ':' + JSON.stringify(value);

        if (level === 0) {
            return raw;
        }

        return raw
            .replace(/\\/g, '\\\\')
            .replace(/"/g, '\\"');
    }

    /*
     * 使用对象边界而不是“向后看 300 字符”。
     * provider/organization 只在同一个完整对象中检查。
     */
    function collectLevelInsertions(text, level) {
        const objects = [];
        const stack = [];
        const tokens = [];

        let inString = false;
        let opening = null;

        for (let i = 0; i < text.length; i++) {
            const character = text[i];

            if (
                character === '"' &&
                isStructuralQuote(text, i, level)
            ) {
                if (!inString) {
                    inString = true;
                    opening = {
                        quote: i,
                        start: level === 1 ? i - 1 : i,
                        parent: stack.length
                            ? stack[stack.length - 1]
                            : null
                    };
                } else {
                    tokens.push({
                        start: opening.start,
                        end: i + 1,
                        content: text.slice(
                            opening.quote + 1,
                            level === 1 ? i - 1 : i
                        ),
                        parent: opening.parent
                    });

                    inString = false;
                    opening = null;
                }

                continue;
            }

            if (inString) {
                continue;
            }

            if (character === '{') {
                const object = {
                    start: i,
                    end: -1,
                    keys: new Set(),
                    id: null,
                    publicName: null,
                    publicNameValueEnd: -1,
                    userSelectableValue: null,
                    userSelectableFalseStart: -1
                };

                objects.push(object);
                stack.push(object);
            } else if (character === '}' && stack.length) {
                const object = stack.pop();
                object.end = i;
            }
        }

        const tokenByStart = new Map();

        for (const token of tokens) {
            tokenByStart.set(token.start, token);
        }

        for (const token of tokens) {
            const object = token.parent;

            // 不处理跨分块后尚未闭合的对象。
            if (!object || object.end < 0) {
                continue;
            }

            let position = skipWhitespace(text, token.end);

            if (text[position] !== ':') {
                continue;
            }

            const key = token.content;

            if (
                key !== 'id' &&
                key !== 'publicName' &&
                key !== 'provider' &&
                key !== 'organization' &&
                key !== 'userSelectable'
            ) {
                continue;
            }

            object.keys.add(key);

            if (key === 'id' && object.id === null) {
                position = skipWhitespace(text, position + 1);

                const valueToken = tokenByStart.get(position);

                if (
                    valueToken &&
                    valueToken.parent === object
                ) {
                    object.id = valueToken.content;
                }
            } else if (
                key === 'publicName' &&
                object.publicNameValueEnd < 0
            ) {
                position = skipWhitespace(text, position + 1);

                const valueToken = tokenByStart.get(position);

                if (
                    valueToken &&
                    valueToken.parent === object
                ) {
                    object.publicName = valueToken.content;
                    object.publicNameValueEnd = valueToken.end;
                }
            } else if (
                key === 'userSelectable' &&
                object.userSelectableValue === null
            ) {
                position = skipWhitespace(text, position + 1);

                const literal = text.slice(position, position + 5);
                const valueLength = literal.startsWith('true')
                    ? 4
                    : literal === 'false'
                        ? 5
                        : 0;
                const afterValue = text[position + valueLength];

                if (
                    valueLength > 0 &&
                    (
                        afterValue === undefined ||
                        afterValue === ',' ||
                        afterValue === '}' ||
                        afterValue === ' ' ||
                        afterValue === '\t' ||
                        afterValue === '\r' ||
                        afterValue === '\n'
                    )
                ) {
                    object.userSelectableValue =
                        valueLength === 4;

                    if (valueLength === 5) {
                        object.userSelectableFalseStart =
                            position;
                    }
                }
            }
        }

        const insertions = [];

        for (const object of objects) {
            if (
                object.end < 0 ||
                object.publicNameValueEnd < 0 ||
                object.userSelectableValue !== true ||
                CONFIG.excludedModelIds.has(object.id)
            ) {
                continue;
            }

            const fields = [];

            if (!object.keys.has('organization')) {
                fields.push(
                    encodePair(
                        'organization',
                        CONFIG.organization,
                        level
                    )
                );
            }

            if (!object.keys.has('provider')) {
                fields.push(
                    encodePair(
                        'provider',
                        CONFIG.provider,
                        level
                    )
                );
            }

            if (fields.length) {
                insertions.push({
                    position: object.publicNameValueEnd,
                    value: ',' + fields.join(','),
                    fieldCount: fields.length,
                    selectableCount: 0
                });
            }

            if (
                CONFIG.forceSelectablePublicNames.has(
                    object.publicName
                ) &&
                object.userSelectableFalseStart >= 0
            ) {
                insertions.push({
                    position: object.userSelectableFalseStart,
                    end: object.userSelectableFalseStart + 5,
                    // 保持与 false 相同长度,便于跨 RSC chunk 原位替换。
                    value: 'true ',
                    fieldCount: 0,
                    selectableCount: 1
                });
            }
        }

        return insertions;
    }

    function collectAllInsertions(text) {
        if (
            typeof text !== 'string' ||
            !text.includes('publicName')
        ) {
            return [];
        }

        const candidates = [
            ...collectLevelInsertions(text, 0),
            ...collectLevelInsertions(text, 1)
        ];

        const result = [];
        const seen = new Set();

        for (const insertion of candidates) {
            const key = [
                insertion.position,
                insertion.end ?? insertion.position,
                insertion.value
            ].join('\u0000');

            if (!seen.has(key)) {
                seen.add(key);
                result.push(insertion);
            }
        }

        return result;
    }

    function recordTextInsertions(insertions) {
        if (!insertions.length) {
            return;
        }

        status.textModelsPatched += insertions.length;
        status.fieldsAdded += insertions.reduce(
            (sum, item) => sum + item.fieldCount,
            0
        );
        status.selectableForced += insertions.reduce(
            (sum, item) => sum + (item.selectableCount || 0),
            0
        );
        touchPatchTime();
    }

    function applyInsertions(text, insertions) {
        let output = text;

        const ordered = [...insertions].sort(
            (a, b) => b.position - a.position
        );

        for (const insertion of ordered) {
            const end = insertion.end ?? insertion.position;

            output =
                output.slice(0, insertion.position) +
                insertion.value +
                output.slice(end);
        }

        return output;
    }

    function patchText(text) {
        if (
            typeof text !== 'string' ||
            !text.includes('publicName')
        ) {
            return text;
        }

        status.textPayloadsScanned++;

        const insertions = collectAllInsertions(text);

        if (!insertions.length) {
            return text;
        }

        const output = applyInsertions(text, insertions);

        status.textPayloadsPatched++;
        recordTextInsertions(insertions);

        log(
            \`文本载荷修改 ${insertions.length} 处,\` +
            \`增加 ${insertions.reduce(
                (sum, item) => sum + item.fieldCount,
                0
            )} 个字段,强制开放 ${insertions.reduce(
                (sum, item) =>
                    sum + (item.selectableCount || 0),
                0
            )} 个目标模型。\`
        );

        return output;
    }

    /*
     * 处理跨 __next_f chunk 的对象。
     * 不重新切割原有字符,只把新增字段放回对应原始 chunk,
     * 避免破坏 Unicode 代理对以及 RSC 分块顺序。
     */
    function patchFlightGroup(entries) {
        if (!entries.length) {
            return;
        }

        const chunks = entries.map(entry => entry[1]);
        const combined = chunks.join('');

        if (!combined.includes('publicName')) {
            return;
        }

        status.textPayloadsScanned++;

        const insertions = collectAllInsertions(combined);

        if (!insertions.length) {
            return;
        }

        const starts = [];
        const ends = [];
        const buckets = chunks.map(() => []);

        let offset = 0;

        for (let i = 0; i < chunks.length; i++) {
            starts[i] = offset;
            offset += chunks[i].length;
            ends[i] = offset;
        }

        for (const insertion of insertions) {
            const insertionEnd =
                insertion.end ?? insertion.position;
            let index = 0;

            if (insertionEnd > insertion.position) {
                /*
                 * 长度保持不变的替换可能刚好跨 chunk。
                 * 按原始 chunk 边界拆开,避免残留 false 的尾部。
                 */
                let segmentStart = insertion.position;

                while (segmentStart < insertionEnd) {
                    index = 0;

                    while (
                        index < ends.length - 1 &&
                        ends[index] <= segmentStart
                    ) {
                        index++;
                    }

                    const segmentEnd = Math.min(
                        insertionEnd,
                        ends[index]
                    );
                    const valueOffset =
                        segmentStart - insertion.position;
                    const segmentLength =
                        segmentEnd - segmentStart;

                    buckets[index].push({
                        ...insertion,
                        position: segmentStart - starts[index],
                        end: segmentEnd - starts[index],
                        value: insertion.value.slice(
                            valueOffset,
                            valueOffset + segmentLength
                        )
                    });

                    segmentStart = segmentEnd;
                }

                continue;
            }

            while (
                index < ends.length - 1 &&
                ends[index] < insertion.position
            ) {
                index++;
            }

            buckets[index].push({
                ...insertion,
                position: insertion.position - starts[index]
            });
        }

        for (let i = 0; i < chunks.length; i++) {
            if (!buckets[i].length) {
                continue;
            }

            entries[i][1] = applyInsertions(
                chunks[i],
                buckets[i]
            );
        }

        status.textPayloadsPatched++;
        recordTextInsertions(insertions);

        log(
            \`跨 RSC chunk 修改 ${insertions.length} 处。\`
        );
    }

    function patchFlightEntries(nextArray) {
        let group = [];

        const flush = () => {
            if (group.length) {
                patchFlightGroup(group);
                group = [];
            }
        };

        for (const entry of nextArray) {
            if (
                Array.isArray(entry) &&
                entry[0] === 1 &&
                typeof entry[1] === 'string'
            ) {
                group.push(entry);
            } else {
                flush();
            }
        }

        flush();
    }

    function isPlainContainer(value) {
        if (!value || typeof value !== 'object') {
            return false;
        }

        if (Array.isArray(value)) {
            return true;
        }

        const prototype = Object.getPrototypeOf(value);

        return (
            prototype === Object.prototype ||
            prototype === null
        );
    }

    function setMissingField(object, key, value) {
        if (own(object, key)) {
            return false;
        }

        try {
            if (!Reflect.set(object, key, value)) {
                return false;
            }

            return own(object, key);
        } catch {
            return false;
        }
    }

    function replaceOwnField(
        object,
        key,
        expectedValue,
        replacementValue
    ) {
        if (!own(object, key)) {
            return false;
        }

        try {
            if (object[key] !== expectedValue) {
                return false;
            }

            if (!Reflect.set(object, key, replacementValue)) {
                return false;
            }

            return object[key] === replacementValue;
        } catch {
            return false;
        }
    }

    /*
     * JSON.parse、XHR responseType=json 等已经转成对象的数据,
     * 直接递归补字段。
     */
    function patchAny(value, seen = new WeakSet()) {
        if (typeof value === 'string') {
            return patchText(value);
        }

        if (!isPlainContainer(value) || seen.has(value)) {
            return value;
        }

        seen.add(value);

        if (!Array.isArray(value)) {
            let id;
            let publicName;
            let userSelectable;

            try {
                id = value.id;
                publicName = value.publicName;
                userSelectable = value.userSelectable;
            } catch {
                id = undefined;
                publicName = undefined;
                userSelectable = undefined;
            }

            if (
                own(value, 'publicName') &&
                typeof publicName === 'string' &&
                own(value, 'userSelectable') &&
                userSelectable === true &&
                !CONFIG.excludedModelIds.has(id)
            ) {
                let added = 0;
                let selectableForced = 0;

                if (
                    CONFIG.forceSelectablePublicNames.has(
                        publicName
                    ) &&
                    replaceOwnField(
                        value,
                        'userSelectable',
                        false,
                        true
                    )
                ) {
                    selectableForced++;
                }

                if (
                    setMissingField(
                        value,
                        'organization',
                        CONFIG.organization
                    )
                ) {
                    added++;
                }

                if (
                    setMissingField(
                        value,
                        'provider',
                        CONFIG.provider
                    )
                ) {
                    added++;
                }

                if (added || selectableForced) {
                    status.objectModelsPatched++;
                    status.fieldsAdded += added;
                    status.selectableForced +=
                        selectableForced;
                    touchPatchTime();
                }
            }
        }

        if (Array.isArray(value)) {
            for (let i = 0; i < value.length; i++) {
                const patched = patchAny(value[i], seen);

                if (patched !== value[i]) {
                    try {
                        value[i] = patched;
                    } catch {
                        // 忽略只读数组。
                    }
                }
            }
        } else {
            let keys;

            try {
                keys = Object.keys(value);
            } catch {
                return value;
            }

            for (const key of keys) {
                let child;

                try {
                    child = value[key];
                } catch {
                    continue;
                }

                const patched = patchAny(child, seen);

                if (patched !== child) {
                    try {
                        value[key] = patched;
                    } catch {
                        // 忽略只读属性。
                    }
                }
            }
        }

        return value;
    }

    /*
     * __next_f 处理。
     */
    const nextStates = new WeakMap();

    function processExisting(nextArray) {
        if (!Array.isArray(nextArray)) {
            return;
        }

        // 优先联合处理,解决模型对象跨 chunk。
        patchFlightEntries(nextArray);

        let state = nextStates.get(nextArray);

        if (!state) {
            state = {
                snapshot: [],
                delegate: null,
                wrapper: null
            };
            nextStates.set(nextArray, state);
        }

        for (let i = 0; i < nextArray.length; i++) {
            if (state.snapshot[i] === nextArray[i]) {
                continue;
            }

            const patched = patchAny(nextArray[i]);

            if (patched !== nextArray[i]) {
                try {
                    nextArray[i] = patched;
                } catch {
                    // 忽略只读项。
                }
            }

            state.snapshot[i] = nextArray[i];
        }

        state.snapshot.length = nextArray.length;
    }

    /*
     * 使用 push 访问器,而不是单纯 arr.push = wrapper。
     * Next.js 后续执行 arr.push = nextServerDataCallback 时,
     * setter 会立即捕获并继续包装,不再出现 hook 被覆盖的窗口。
     */
    function ensurePushHook(nextArray) {
        if (
            !Array.isArray(nextArray) ||
            typeof nextArray.push !== 'function'
        ) {
            return;
        }

        const currentDescriptor =
            Object.getOwnPropertyDescriptor(nextArray, 'push');

        if (
            currentDescriptor?.get?.[PUSH_ACCESSOR_MARK]
        ) {
            return;
        }

        let state = nextStates.get(nextArray);

        if (!state) {
            state = {
                snapshot: [],
                delegate: null,
                wrapper: null
            };
            nextStates.set(nextArray, state);
        }

        const currentPush = nextArray.push;

        if (
            currentPush !== state.wrapper &&
            typeof currentPush === 'function'
        ) {
            state.delegate = currentPush;
        }

        if (!state.wrapper) {
            state.wrapper = function (...args) {
                status.nextPushCalls++;

                for (let i = 0; i < args.length; i++) {
                    args[i] = patchAny(args[i]);
                }

                const delegate = state.delegate;

                if (typeof delegate !== 'function') {
                    throw new TypeError(
                        '__next_f.push delegate is not a function'
                    );
                }

                const result = Reflect.apply(
                    delegate,
                    this,
                    args
                );

                if (this === nextArray) {
                    // native push 阶段可在追加后联合检查所有分块。
                    processExisting(nextArray);
                }

                return result;
            };

            Object.defineProperty(
                state.wrapper,
                PUSH_WRAPPER_MARK,
                { value: true }
            );
        }

        const getter = function () {
            return state.wrapper;
        };

        const setter = function (newPush) {
            if (
                newPush !== state.wrapper &&
                typeof newPush === 'function'
            ) {
                state.delegate = newPush;
                status.pushReplacements++;
                log('捕获到 Next.js 替换 __next_f.push。');
            } else if (newPush !== state.wrapper) {
                state.delegate = newPush;
            }
        };

        Object.defineProperty(
            getter,
            PUSH_ACCESSOR_MARK,
            { value: true }
        );

        try {
            Object.defineProperty(nextArray, 'push', {
                get: getter,
                set: setter,
                configurable: true,
                enumerable: false
            });

            status.nextArraysHooked++;
            log('__next_f.push 已安装持久访问器。');
        } catch (error) {
            reportError('安装 push 访问器失败,使用普通包装', error);

            try {
                nextArray.push = state.wrapper;
            } catch (fallbackError) {
                reportError('普通 push 包装也失败', fallbackError);
            }
        }
    }

    function attachNextArray(value) {
        if (!Array.isArray(value)) {
            return;
        }

        processExisting(value);
        ensurePushHook(value);
    }

    function installNextWatcher() {
        let descriptor;

        try {
            descriptor =
                Object.getOwnPropertyDescriptor(W, '__next_f');
        } catch (error) {
            reportError('读取 __next_f descriptor 失败', error);
            return;
        }

        if (descriptor?.get?.[WATCH_MARK]) {
            try {
                attachNextArray(W.__next_f);
            } catch {
                // getter 自身异常时保持原行为。
            }
            return;
        }

        let currentValue;

        try {
            currentValue = descriptor?.get
                ? Reflect.apply(descriptor.get, W, [])
                : descriptor?.value;
        } catch {
            currentValue = undefined;
        }

        attachNextArray(currentValue);

        if (descriptor && !descriptor.configurable) {
            log('__next_f 不可配置,仅启用直接 hook/轮询恢复。');
            return;
        }

        const originalGetter = descriptor?.get;
        const originalSetter = descriptor?.set;
        let localValue = currentValue;

        const getter = function () {
            const value = originalGetter
                ? Reflect.apply(originalGetter, this, [])
                : localValue;

            attachNextArray(value);
            return value;
        };

        const setter = function (value) {
            if (originalSetter) {
                Reflect.apply(originalSetter, this, [value]);
            } else {
                localValue = value;
            }

            const actualValue = originalGetter
                ? Reflect.apply(originalGetter, this, [])
                : localValue;

            attachNextArray(actualValue);
        };

        Object.defineProperty(getter, WATCH_MARK, {
            value: true
        });

        try {
            Object.defineProperty(W, '__next_f', {
                get: getter,
                set: setter,
                configurable: true,
                enumerable: descriptor
                    ? descriptor.enumerable
                    : true
            });

            status.watcherInstallations++;
            log('__next_f 全局 watcher 已安装。');
        } catch (error) {
            reportError('安装 __next_f watcher 失败', error);
        }
    }

    /*
     * JSON.parse fallback。
     */
    function installJSONParseHook() {
        if (!CONFIG.hookJSONParse) {
            return;
        }

        const nativeParse = W.JSON?.parse;

        if (
            typeof nativeParse !== 'function' ||
            nativeParse[PARSE_MARK]
        ) {
            return;
        }

        const wrappedParse = function (...args) {
            status.jsonParseCalls++;

            const result = Reflect.apply(
                nativeParse,
                this,
                args
            );

            return patchAny(result);
        };

        Object.defineProperty(wrappedParse, PARSE_MARK, {
            value: true
        });

        try {
            W.JSON.parse = wrappedParse;
            log('JSON.parse fallback 已安装。');
        } catch (error) {
            reportError('安装 JSON.parse hook 失败', error);
        }
    }

    /*
     * SPA/RSC fetch。
     * Next.js 客户端导航不会继续使用初始 __next_f,
     * 因此必须处理 text/x-component 和 JSON 响应。
     */
    function shouldInspectResponse(response, input) {
        if (
            !response ||
            !response.body ||
            response.type === 'opaque' ||
            response.status === 204 ||
            response.status === 304
        ) {
            return false;
        }

        const contentType = (
            response.headers.get('content-type') || ''
        ).toLowerCase();

        if (
            contentType.includes('text/event-stream') ||
            contentType.includes('javascript') ||
            contentType.includes('text/css') ||
            contentType.startsWith('image/') ||
            contentType.startsWith('audio/') ||
            contentType.startsWith('video/') ||
            contentType.includes('font/')
        ) {
            return false;
        }

        let url = response.url || '';

        if (!url) {
            if (typeof input === 'string') {
                url = input;
            } else if (input?.url) {
                url = input.url;
            }
        }

        return (
            contentType.includes('text/x-component') ||
            contentType.includes('application/json') ||
            contentType.includes('application/graphql') ||
            /(?:[?&]_rsc=|\/api\/|graphql|models?)/i.test(url)
        );
    }

    function rebuildResponse(response, body) {
        const headers = new W.Headers(response.headers);

        // 原响应的压缩及长度头不再适用于新正文。
        headers.delete('content-length');
        headers.delete('content-encoding');
        headers.delete('transfer-encoding');
        headers.delete('etag');

        const replacement = new W.Response(body, {
            status: response.status,
            statusText: response.statusText,
            headers
        });

        for (const property of [
            'url',
            'redirected',
            'type'
        ]) {
            try {
                Object.defineProperty(replacement, property, {
                    value: response[property],
                    configurable: true
                });
            } catch {
                // 非关键元数据,忽略。
            }
        }

        return replacement;
    }

    function installFetchHook() {
        if (!CONFIG.hookFetch) {
            return;
        }

        const nativeFetch = W.fetch;

        if (
            typeof nativeFetch !== 'function' ||
            nativeFetch[FETCH_MARK]
        ) {
            return;
        }

        const wrappedFetch = async function (...args) {
            status.fetchSeen++;

            const response = await Reflect.apply(
                nativeFetch,
                this,
                args
            );

            if (!shouldInspectResponse(response, args[0])) {
                return response;
            }

            try {
                const clone = response.clone();
                const originalText = await clone.text();

                if (!originalText.includes('publicName')) {
                    return response;
                }

                const patchedText = patchText(originalText);

                if (patchedText === originalText) {
                    return response;
                }

                status.fetchPatched++;
                log('已修补 SPA/fetch 响应:', response.url);

                return rebuildResponse(
                    response,
                    patchedText
                );
            } catch (error) {
                reportError('处理 fetch 响应失败', error);
                return response;
            }
        };

        Object.defineProperty(wrappedFetch, FETCH_MARK, {
            value: true
        });

        try {
            W.fetch = wrappedFetch;
            log('fetch/RSC hook 已安装。');
        } catch (error) {
            reportError('安装 fetch hook 失败', error);
        }
    }

    /*
     * XHR fallback。
     */
    function installXHRHook() {
        if (!CONFIG.hookXHR || !W.XMLHttpRequest) {
            return;
        }

        const prototype = W.XMLHttpRequest.prototype;
        const textCache = new WeakMap();

        function patchCachedText(xhr, raw) {
            const cached = textCache.get(xhr);

            if (cached?.raw === raw) {
                return cached.patched;
            }

            const patched = patchText(raw);

            textCache.set(xhr, {
                raw,
                patched
            });

            if (patched !== raw) {
                status.xhrPatched++;
            }

            return patched;
        }

        function wrapGetter(name) {
            const descriptor =
                Object.getOwnPropertyDescriptor(
                    prototype,
                    name
                );

            if (
                !descriptor?.get ||
                !descriptor.configurable ||
                descriptor.get[XHR_MARK]
            ) {
                return;
            }

            const nativeGetter = descriptor.get;

            const getter = function () {
                const value = Reflect.apply(
                    nativeGetter,
                    this,
                    []
                );

                if (typeof value === 'string') {
                    return patchCachedText(this, value);
                }

                if (isPlainContainer(value)) {
                    return patchAny(value);
                }

                return value;
            };

            Object.defineProperty(getter, XHR_MARK, {
                value: true
            });

            Object.defineProperty(prototype, name, {
                ...descriptor,
                get: getter
            });
        }

        try {
            wrapGetter('responseText');
            wrapGetter('response');
            log('XHR fallback 已安装。');
        } catch (error) {
            reportError('安装 XHR hook 失败', error);
        }
    }

    /*
     * 安装顺序:先抢占 __next_f,再安装其他数据通道。
     */
    installNextWatcher();
    installJSONParseHook();
    installFetchHook();
    installXHRHook();

    /*
     * 恢复机制:
     * 应对页面通过 Object.defineProperty 覆盖 watcher/push。
     */
    W.setInterval(() => {
        try {
            installNextWatcher();
            attachNextArray(W.__next_f);
        } catch (error) {
            reportError('周期恢复检查失败', error);
        }
    }, CONFIG.recoveryInterval);

    log('启动完成。调试状态:window.__arenaInjectorStatus');
})();

本稿 published: false,审完再上线。