[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-terminalcommandnewsletter--everything-chatgpt":3,"tool-terminalcommandnewsletter--everything-chatgpt":61},[4,18,28,37,45,53],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":17},4358,"openclaw","openclaw\u002Fopenclaw","OpenClaw 是一款专为个人打造的本地化 AI 助手，旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚，能够直接接入你日常使用的各类通讯渠道，包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息，OpenClaw 都能即时响应，甚至支持在 macOS、iOS 和 Android 设备上进行语音交互，并提供实时的画布渲染功能供你操控。\n\n这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地，用户无需依赖云端服务即可享受快速、私密的智能辅助，真正实现了“你的数据，你做主”。其独特的技术亮点在于强大的网关架构，将控制平面与核心助手分离，确保跨平台通信的流畅性与扩展性。\n\nOpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者，以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力（支持 macOS、Linux 及 Windows WSL2），即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你",349277,3,"2026-04-06T06:32:30",[13,14,15,16],"Agent","开发框架","图像","数据工具","ready",{"id":19,"name":20,"github_repo":21,"description_zh":22,"stars":23,"difficulty_score":24,"last_commit_at":25,"category_tags":26,"status":17},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",149489,2,"2026-04-10T11:32:46",[14,13,27],"语言模型",{"id":29,"name":30,"github_repo":31,"description_zh":32,"stars":33,"difficulty_score":24,"last_commit_at":34,"category_tags":35,"status":17},6121,"gemini-cli","google-gemini\u002Fgemini-cli","gemini-cli 是一款由谷歌推出的开源 AI 命令行工具，它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言，它提供了一条从输入提示词到获取模型响应的最短路径，无需切换窗口即可享受智能辅助。\n\n这款工具主要解决了开发过程中频繁上下文切换的痛点，让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用，还是执行复杂的 Git 操作，gemini-cli 都能通过自然语言指令高效处理。\n\n它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口，具备出色的逻辑推理能力；内置 Google 搜索、文件操作及 Shell 命令执行等实用工具；更独特的是，它支持 MCP（模型上下文协议），允许用户灵活扩展自定义集成，连接如图像生成等外部能力。此外，个人谷歌账号即可享受免费的额度支持，且项目基于 Apache 2.0 协议完全开源，是提升终端工作效率的理想助手。",100752,"2026-04-10T01:20:03",[36,13,15,14],"插件",{"id":38,"name":39,"github_repo":40,"description_zh":41,"stars":42,"difficulty_score":24,"last_commit_at":43,"category_tags":44,"status":17},4721,"markitdown","microsoft\u002Fmarkitdown","MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具，专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片（含 OCR）、音频（含语音转录）、HTML 乃至 YouTube 链接等多种格式的解析，能够精准提取文档中的标题、列表、表格和链接等关键结构信息。\n\n在人工智能应用日益普及的今天，大语言模型（LLM）虽擅长处理文本，却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点，它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式，成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外，它还提供了 MCP（模型上下文协议）服务器，可无缝集成到 Claude Desktop 等 LLM 应用中。\n\n这款工具特别适合开发者、数据科学家及 AI 研究人员使用，尤其是那些需要构建文档检索增强生成（RAG）系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性，但其核心优势在于为机器",93400,"2026-04-06T19:52:38",[36,14],{"id":46,"name":47,"github_repo":48,"description_zh":49,"stars":50,"difficulty_score":10,"last_commit_at":51,"category_tags":52,"status":17},4487,"LLMs-from-scratch","rasbt\u002FLLMs-from-scratch","LLMs-from-scratch 是一个基于 PyTorch 的开源教育项目，旨在引导用户从零开始一步步构建一个类似 ChatGPT 的大型语言模型（LLM）。它不仅是同名技术著作的官方代码库，更提供了一套完整的实践方案，涵盖模型开发、预训练及微调的全过程。\n\n该项目主要解决了大模型领域“黑盒化”的学习痛点。许多开发者虽能调用现成模型，却难以深入理解其内部架构与训练机制。通过亲手编写每一行核心代码，用户能够透彻掌握 Transformer 架构、注意力机制等关键原理，从而真正理解大模型是如何“思考”的。此外，项目还包含了加载大型预训练权重进行微调的代码，帮助用户将理论知识延伸至实际应用。\n\nLLMs-from-scratch 特别适合希望深入底层原理的 AI 开发者、研究人员以及计算机专业的学生。对于不满足于仅使用 API，而是渴望探究模型构建细节的技术人员而言，这是极佳的学习资源。其独特的技术亮点在于“循序渐进”的教学设计：将复杂的系统工程拆解为清晰的步骤，配合详细的图表与示例，让构建一个虽小但功能完备的大模型变得触手可及。无论你是想夯实理论基础，还是为未来研发更大规模的模型做准备",90106,"2026-04-06T11:19:32",[27,15,13,14],{"id":54,"name":55,"github_repo":56,"description_zh":57,"stars":58,"difficulty_score":24,"last_commit_at":59,"category_tags":60,"status":17},3704,"NextChat","ChatGPTNextWeb\u002FNextChat","NextChat 是一款轻量且极速的 AI 助手，旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性，以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发，NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。\n\n这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言，它也提供了便捷的自托管方案，支持一键部署到 Vercel 或 Zeabur 等平台。\n\nNextChat 的核心亮点在于其广泛的模型兼容性，原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型，让用户在一个界面即可自由切换不同 AI 能力。此外，它还率先支持 MCP（Model Context Protocol）协议，增强了上下文处理能力。针对企业用户，NextChat 提供专业版解决方案，具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能，满足公司对数据隐私和个性化管理的高标准要求。",87618,"2026-04-05T07:20:52",[14,27],{"id":62,"github_repo":63,"name":64,"description_en":65,"description_zh":66,"ai_summary_zh":66,"readme_en":67,"readme_zh":68,"quickstart_zh":69,"use_case_zh":70,"hero_image_url":71,"owner_login":72,"owner_name":73,"owner_avatar_url":74,"owner_bio":75,"owner_company":76,"owner_location":76,"owner_email":76,"owner_twitter":73,"owner_website":77,"owner_url":78,"languages":76,"stars":79,"forks":80,"last_commit_at":81,"license":82,"difficulty_score":83,"env_os":84,"env_gpu":85,"env_ram":85,"env_deps":86,"category_tags":89,"github_topics":90,"view_count":24,"oss_zip_url":76,"oss_zip_packed_at":76,"status":17,"created_at":95,"updated_at":96,"faqs":97,"releases":127},6390,"terminalcommandnewsletter\u002Feverything-chatgpt","everything-chatgpt","🔍 Explore what happens under the hood with the ChatGPT web app, its backend API calls and more. And some speculation, of course.","everything-chatgpt 是一个致力于揭示 ChatGPT 网页版内部运作机制的开源探索项目。它深入分析了该应用的前端架构、后端 API 调用逻辑以及数据交互细节，并包含了对部分未公开技术实现的专业推测。\n\n该项目主要解决了普通用户和开发者对 ChatGPT“黑盒”状态的好奇与需求，通过整理公开的字体资源列表、解析基于 NextJS 的应用架构、追踪 Cloudflare 路由下的服务器信息，以及演示如何获取会话数据等方式，将原本隐蔽的技术细节透明化。例如，它详细记录了从 CDN 加载的字体文件变化，并指出了分析过程中遇到的跨域策略等实际技术挑战。\n\neverything-chatgpt 非常适合前端开发者、安全研究人员以及对大模型应用架构感兴趣的技术爱好者使用。开发者可以借此了解大规模 AI 产品的工程落地方案；研究人员可将其作为分析 Web 应用行为模式的案例；设计师也能从中获取关于字体渲染等资源管理的参考。作为一个社区驱动的仓库，它不仅提供了现成的技术观察结论，还鼓励贡献者分享更多有趣的发现，是理解现代 AI Web 应用底层逻辑的优质入门资料。","\u003Cdiv align=\"center\">\n\n  # Everything ChatGPT\n  \u003Ci>A project by [@tercmd (on Twitter)](https:\u002F\u002Ftwitter.com\u002Ftercmd)\u003C\u002Fi>\n\n  ![Stars for the Everything ChatGPT repo](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fstars\u002Fterminalcommandnewsletter\u002Feverything-chatgpt?style=for-the-badge&logo=github)\n\n  Explore what happens under the hood with the ChatGPT web app. And some speculation, of course. [Contribute if you have something interesting related to ChatGPT.](.\u002FCONTRIBUTING.md)\n\n\u003C\u002Fdiv>\n\nThe repo no longer contains a Table of Contents because GitHub already shows this.\n\n## Fonts _([fonts.txt](.\u002Ffonts.txt))_\n> **Warning**\n> **All fonts in the previous list are no longer accessible at the `https:\u002F\u002Fchat.openai.com\u002Ffonts\u002F[font]` endpoint. The new fonts.txt file assumes the prefix of the URLs to be `https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002F`**\n\n**This is a _non exhaustive_ list of fonts that come from cdn.openai.com:**\n- [soehne-buch.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-buch.woff2)\n- [soehne-halbfett.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-halbfett.woff2)\n- [soehne-mono-buch.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-mono-buch.woff2)\n- [soehne-mono-halbfett.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-mono-halbfett.woff2)\n- [soehne-kraftig.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-kraftig.woff2)\n- [KaTeX_Main-Regular.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fkatex\u002FKaTeX_Main-Regular.woff2) (+ Main-Bold, Main-Italic, Main-BoldItalic)\n- [KaTeX_Math-Italic.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fkatex\u002FKaTeX_Math-Italic.woff2) (+ Math-BoldItalic)\n- [KaTeX_Size2-Regular.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fkatex\u002FKaTeX_Size2-Regular.woff2) (+ Size1, Size3, Size4)\n- [KaTeX_Caligraphic-Regular.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fkatex\u002FKaTeX_Caligraphic-Regular.woff2) (+ Caligraphic-Bold)\n\n**Earlier list of fonts that are no longer accessible:**\n\n- ~~[Signifier-Regular.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSignifier-Regular.otf)~~\n- ~~[Sohne-Buch.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSohne-Buch.otf)~~\n- ~~[Sohne-Halbfett.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSohne-Halbfett.otf)~~\n- ~~[SohneMono-Buch.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSohneMono-Buch.otf)~~\n- ~~[SohneMono-Halbfett.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSohneMono-Halbfett.otf)~~\n- ~~[KaTeX_Caligraphic-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Caligraphic-Bold.woff) (_Caligraphic-Regular_ for Regular font)~~\n- ~~[KaTeX_Fraktur-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Fraktur-Bold.woff) (_Fraktur-Regular_ for Regular font)~~\n- ~~[KaTeX_Main-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Main-Bold.woff) (_BoldItalic_, _Italic_, _Regular_ for font weights you can probably guess)~~\n- ~~[KaTeX_Math-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Math-Bold.woff) (_BoldItalic_, _Italic_, _Regular_ for font weights you can probably guess)~~\n- ~~[KaTeX_SansSerif-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_SansSerif-Bold.woff) (_Italic_, _Regular_ for font weights you can probably guess)~~\n- ~~[KaTeX_Script-Regular.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Script-Regular.woff)~~\n- ~~[KaTeX_Size1-Regular.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Size1-Regular.woff) (_Size1_, _Size2_, _Size3_, _Size4_)~~\n- ~~[KaTeX_Typewriter-Regular.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Typewriter-Regular.woff)~~\n\n## Application\nChatGPT is a NextJS application. Server information cannot be clearly found as the entirety of chat.openai.com is routed through Cloudflare. Sentry Analytics are requested ~~for the Thumbs Up\u002FThumbs Down feedback the user selects for a message~~ periodically. Statsig is attempted to be loaded but CORS blocks it due to the Same Origin Policy **(actually an effect of uBlock Origin)**.\n\n## Data\n### Session data\nA request can be made to `\u002Fapi\u002Fauth\u002Fsession` (without the `Authorization` header) to access data like the following:\n\n```\nuser: (Object)\n|__ id: \"user-[redacted]\"\n|__ name: \"[redacted]@[redacted].com\"\n|__ email: \"[redacted]@[redacted].com\"\n|__ image: \"https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F[MD5 hash of account email address]?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fte.png\"\n|__ picture: \"https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F[MD5 hash of account email address]?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fte.png\"\n|__ idp: \"auth0\"\n|__ iat: 1690111234\n|__ mfa: [redacted]\n|__ groups: (Array)\n|__ intercom_hash: \"[redacted]\"\nexpires: \"2023-08-01T23:45:12.345Z\"\naccessToken: \"ey..[redacted]..\"\nauthProvider: \"auth0\"\n```\n\n### User data\nThis requires an access token passed through the `Authorization` header, so this cannot be accessed using your browser directly, but here's what we have when we make a request to `\u002Fbackend-api\u002Faccounts\u002Fcheck\u002Fv4-2023-04-27` ~~(that URL's gonna be a regular pain to update)~~:\n\n```\naccounts: (Object)\n|__ default: (Object)\n|____ account: (Object)\n|______ account_user_role: \"account-owner\"\n|______ account_user_id: \"92[redacted]40\"\n|______ processor: (Object)\n|________ a001: (Object)\n|__________ has_customer_object: false\n|________ b001: (Object)\n|__________ has_transaction_history: false\n|______ account_id: \"34[redacted]71\"\n|______ is_most_recent_expired_subscription_gratis: false\n|______ has_previously_paid_subscription: false\n|______ name: null\n|______ structure: \"personal\"\n|____ features: (Array)\n|______ \"log_statsig_events\"\n|______ \"log_intercom_events\"\n|______ \"new_plugin_oauth_endpoint\"\n|______ \"arkose_enabled\"\n|______ \"infinite_scroll_history\"\n|______ \"model_switcher_upsell\"\n|______ \"shareable_links\"\n|______ \"layout_may_2023\"\n|______ \"dfw_message_feedback\"\n|______ \"ios_disable_citation_menu\"\n|______ \"dfw_inline_message_regen_comparison\"\n|____ entitlement: (Object)\n|______ subscription_id: null\n|______ has_active_subscription: false\n|______ subscription_plan: \"chatgptfreeplan\"\n|______ expires_at: null\n|____ last_active_subscription: (Object)\n|______ subscription_id: null\n|______ purchase_origin_platform: \"chatgpt_not_purchased\"\n|______ will_renew: false\n```\n\nThe returned data is different if you use ChatGPT Plus.\n\n### User data (using ~~chat.json~~ [chatId].json)\nWhen we make a request to `\u002F_next\u002Fdata\u002F[build ID]\u002Fc\u002F[conversation ID].json?chatId=[conversation ID]` (can be done in the browser, cannot be done without authentication), we get a response like this:\n```\npageProps:\n|__ user (Object):\n|____ id: user-[redacted]\n|____ name: [redacted]@[redacted].com\n|____ email: [redacted]@[redacted].com\n|____ image: https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F8c[redacted in case of possible unique identifier]c7?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2F[first two letters of email address].png\n|____ picture: https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F8c[redacted in case of possible unique identifier]c7?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2F[first two letters of email address].png\n|____ groups: []\n|__ serviceStatus: {}\n|__ userCountry: [redacted two letter country code]\n|__ geoOk: false\n|__ isUserInCanPayGroup: true\n|__ __N_SSP: true\n```\n\nThis is the some of the same data (excluding accessToken and expires, both relevant to an access token) you get using the method in [Session data](#session-data) except you also get info about the country the user is located in and whether ChatGPT Plus is available in their location.\n\n**EDIT:** When ChatGPT returns a message like \"_We're experiencing exceptionally high demand. Please hang tight as we work on scaling our systems._\", `serviceStatus` looks like this:\n```\ntype: warning\nmessage: We're experiencing exceptionally high demand. Please hang tight as we work on scaling our systems.\noof: true\n```\nI didn't make up the `oof` variable, that is actually part of the response 😂\n\n### Model data\n_This section has been corrected as per [issue #8](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F8) created by [@0xdevalias (on GitHub)](https:\u002F\u002Fgithub.com\u002F0xdevalias)._\n\nWhat model does ChatGPT use? Well, just query `\u002Fbackend-api\u002Fmodels`!\n```\nmodels: (Array)\n|__ (Object)\n|____ slug: \"text-davinci-002-render-sha\"\n|____ max_tokens: 8191\n|____ title: \"Default (GPT-3.5)\"\n|____ description: \"Our fastest model, great for most everyday tasks.\"\n|____ tags: (Array)\n|______ \"gpt3.5\"\n|____ capabilities: (Object)\n|____ product_features: (Object)\n categories: (Array)\n|__ (Object)\n|____ category: \"gpt_3.5\"\n|____ human_category_name: \"GPT-3.5\"\n|____ subscription_level: \"free\"\n|____ default_model: \"text-davinci-002-render-sha\"\n|____ browsing_model: \"text-davinci-002-render-sha-browsing\"\n|____ code_interpreter_model: \"text-davinci-002-render-sha-code-interpreter\"\n|____ plugins_model: \"text-davinci-002-render-sha-plugins\"\n```\n\n(There are more models if you use ChatGPT Plus, as shown in [issue #8](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F8), but this is what a Free user would see.)\n\n### Beta Features Settings\n_Thanks to [@0xdevalias (on GitHub)](https:\u002F\u002Fgithub.com\u002F0xdevalias) for creating [issue #7](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F7) about this feature._\n\nOn page load (as a Plus user), a request is made to `\u002Fbackend-api\u002Fsettings\u002Fbeta_features`. This returns a response similar to this:\n```\nbrowsing: false\nchat_preferences: true\ncode_interpreter: true\nplugins: true\n```\n\nThe `browsing` key seems to refer to \"Browse with Bing\" (a feature disabled from public access currently, likely why it's set to `false` in the above data).\n\nThe `chat_preferences` key refers to Custom Instructions, a new feature allowing users to set custom details persistent across chats.\n\nThe `code_interpreter` key refers to the Code Interpreter feature which allows GPT to run code in a Python sandbox.\n\nThe `plugins` key refers to ChatGPT Plugins.\n\n### Disabling\u002FEnabling \"Chat History & Training\"\nWhen you click your name\u002Femail address in the bottom-left corner of the screen (on desktop) > Settings > Show (next to Data Controls) > toggle next to Chat History and Training, the following happens:\n\nFirst, [the list of conversations is requested](#conversation-history).\n\nThen we make a request to the same path as [Model data](#model-data), except a query parameter is added to the URL `?history_and_training_disabled=true` or `?history_and_training_disabled=false` depending on whether the setting is disabled or enabled respectively.\n\nThen, we request `\u002F_next\u002Fdata\u002F[build ID]\u002Findex.json` (with the same data as [[chatId].json](#user-data-using-chatjson-chatidjson)).\n\n### Data Export\nWhen you use the \"Export data\" feature to export your data, a POST request is made to `\u002Fbackend-api\u002Faccounts\u002Fdata_export` with no request body and the response of `status: \"queued\"`.\n\nAs the name suggests, a data export is sent by email.\n\nThe data export is a `.zip` file containing `user.json`, `conversations.json`, `message_feedback.json`, `model_comparisons.json`, `chat.html`.\n\nThe data in `user.json` looks like this:\n```json\n{\"id\": \"user-[redacted]\", \"email\": \"[redacted]@[redacted].com\", \"chatgpt_plus_user\": false, \"phone_number\": \"+[redacted]\"}\n```\n\nSample data for `model_comparisons.json` is in [sample\u002Fmodel_comparisons.json](.\u002Fsample\u002Fmodel_comparisons.json)\n\nSample data for `message_feedback.json`:\n```json\n[{\"message_id\": \"[redacted]\", \"conversation_id\": \"[conversationidwithoutdashes]\", \"user_id\": \"user-[redacted]\", \"rating\": \"thumbsUp\", \"content\": \"{\\\"text\\\": \\\"This is a test.\\\"}\"}]\n```\n\nSample data for `conversations.json` is in [sample\u002Fconversations.json](.\u002Fsample\u002Fconversations.json)\n\n`chat.html` is a page that dynamically (using client-side JS) displays entire chat history for every conversation saved using conversation data (stored in the file) similar to that from `conversations.json`. You can find a sample in [sample\u002Fchat.html](.\u002Fsample\u002Fchat.html)\n\n\n## Conversation\n### Conversation History\nConversation history can be accessed (again, requires an access token, which seems to be the Authorization header) at `\u002Fbackend-api\u002Fconversations?offset=0&limit=28` (the web interface limits it to 28 chats) which returns something like this:\n```\nitems: []\nlimit: 28\noffset: 0\ntotal: 0\n```\nIt doesn't work because ChatGPT is having some issues at the time of writing:\n> \"_Not seeing what you expected here? Don't worry, your conversation data is preserved! Check back soon._\"\n\nBut this is probably what a person new to ChatGPT sees.\n\n**EDIT: If you log out and log back in, history works just fine. So, here's what I see**\n\n```\nitems (array)\n|__ (each conversation is an object)\n|____ id: [redacted conversation ID]\n|____ title: [conversation title]\n|____ create_time: 2023-03-09THH:MM:SS.MILLIS\n|__...\ntotal: [number of conversations] (can be greater than 28)\nlimit: 28\noffset: 0 (can be set to a higher number and it returns the conversations after that index, starting from 0)\n```\n\n**After 28 conversations listed, the ChatGPT UI shows a `Show more` button which sends a request with `offset=28`**\n\n### Getting the Conversation ID\nSpeaking of ChatGPT conversation history not being available, we can get the Conversation ID pretty easily (to someone who is familiar with DevTools, that is)\n\nWhy? Because ChatGPT forces you into a ~~\u002Fchat~~ `\u002F` path for a new conversation, creates a conversation, **BUT DOESN'T CHANGE THE URL**. This is also helpful when chat history isn't available.\n\n1. We get the Conversation ID using DevTools (this requires a message to be sent)\n![A ChatGPT window with Firefox DevTools open. In the list of requests, a request with the conversation ID can be seen. In addition, a request to a moderations endpoint has a response containing the conversation ID, along with the user's entered text 'How can I say \"MOOOOOOOOOOOOOOOOOOO\" as a cow in the terminal?'](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_f242ea3df81a.png)\n2. Then, we visit ~~`https:\u002F\u002Fchat.openai.com\u002Fchat\u002F\u003Cchat ID here>`~~ `https:\u002F\u002Fchat.openai.com\u002Fc\u002F\u003Cchat ID here>`.\n\n### Loading a Past Conversation\nWhen the user clicks on a past conversation, a request is made (requiring an access token, ~~likely the cookie with other factors to ensure genuine requests~~ an Authorization header) to `\u002Fbackend-api\u002Fconversation\u002F\u003Cconversation ID>` with a response like this:\n\n```\ntitle: \u003CTitle of Conversation>\ncreate_time: EPOCHEPOCH.MILLIS\nmapping (Object)\n|__ \u003Cmessage ID> (Array):\n|____ id: \u003Cmessage ID>\n|____ message (Object):\n|______ id: \u003Cmessage ID>\n|______ author (Object):\n|________ role: system (First message) | user | assistant\n|________ metadata: (Empty object)\n|______ create_time: EPOCHEPOCH.MILLIS \n|______ content (Object):\n|________ content_type: text\n|________ parts: [\"\"]\n|______ end_turn: true (system) | false\n|______ weight: 1.0\n|______ metadata: {}\n|______ recipient: all\n|____ parent: \u003Cparent message ID>\n|____ children (Array): \u003Cchild message ID(s)>\n```\n\n### The process of asking ChatGPT a question\n_This section has been corrected as per [issue #4](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F4) created by [@Snarik (on GitHub)](https:\u002F\u002Fgithub.com\u002FSnarik)._\n\nLet's say I ask ChatGPT a question `\"What is ChatGPT?\"`. First, we make a POST request to `\u002Fbackend-api\u002Fconversation` with a request body like this:\n```\naction: next\nmessages (Array):\n|__ (Object):\n|____ author (Object):\n|______ role: user\n|____ content (Object):\n|______ content_type: text\n|______ parts (Array):\n|________ What is ChatGPT?\n|__ id: 0c[redacted]91\n|__ role: user\nmodel: text-davinci-002-render-sha\nparent_message_id: a0[redacted]7f\n```\n\nThis responds with an EventStream which ends with a `[DONE]` signal. You can view a sample response in [sample\u002Fconversation-event-stream.txt](.\u002Fsample\u002Fconversation-event-stream.txt).\n\nThen [we get a list of past conversations](#conversation-history) that includes one \"New chat\".\n\nThen we make a request to `\u002Fbackend-api\u002Fmoderations` with a request body like this:\n\n```\nconversation_id: 05[redacted]2d\ninput:\tWhat is ChatGPT?\nmessage_id: 0c[redacted]91\nmodel: text-moderation-playground\n```\n\nThat returns a response like this:\n\n```\nflagged:\tfalse\nblocked:\tfalse\nmoderation_id\tmodr-6t[redacted]Bk\n```\n\nThen we make a request to `\u002Fbackend-api\u002Fconversation\u002Fgen_title\u002F\u003Cconversation ID>` with the request body like this:\n```\nmessage_id: c8[redacted]0e\nmodel: text-davinci-002-render-sha\n```\n\nThat gets a response like this:\n```\ntitle: \u003Ctitle for conversation>\n```\n\nThen we make **another** request to `\u002Fbackend-api\u002Fmoderations` with a request body that includes the AI response (marked as `\u003CAI response>`) looking like this:\n\n```\ninput: \\nWhat is ChatGPT?\\n\\n\u003CAI response>\nmodel: text-moderation-playground\nconversation_id: 05[redacted]2d\nmessage_id: c8[redacted]0e\n```\n\nThat gets a response in the exact same format as the previous request made to this path.\n\nThen [we **finally** get a list of past conversations](#conversation-history) including the proper title of the chat that appears on the sidebar.\n\n### (Soft)Deleting a conversation\nWhen you click Delete on a conversation, a PATCH request is made to `\u002Fbackend-api\u002Fconversation\u002F05[redacted]2d` with the body `is_visible: false` and gets a response of `success: true` back. This implies that a conversation is being soft-deleted, not deleted on their systems.\n\nThen (not sure why), we request `\u002F_next\u002Fdata\u002F[build ID]\u002Findex.json` (with the same data as [[chatId].json](#user-data-using-chatjson-chatidjson)).\n\nAfter that, we [get the list of conversations that appear on the sidebar](#conversation-history).\n\n### Can you revive a conversation?\nI had a question after the above section - can you revive a conversation by setting the request body to `is_visible: true`? The answer is **nope**, you can't. This just returns a 404 with the response `detail: Can't load conversation 94[redacted]9b`. But if you don't [get the list of conversations again](#conversation-history), you can still access the conversations. Although, trying to get a response from ChatGPT, you get a [Conversation not found](#conversation-not-found) error.\n\n### Clearing Conversations\nI was a bit unsure if I should do this. But I looked through and did it anyway. (The below is almost a one-to-one copy of [(Soft)Deleting a conversation](#softdeleting-a-conversation), with minor changes)\n\nWhen you click Delete on a conversation, a PATCH request is made to `\u002Fbackend-api\u002Fconversations` (conversation**s** rather than conversatio**n\u002F05[redacted]2d**) with the body `is_visible: false` and gets a response of `success: true` back. This implies that conversations are being soft-deleted, not deleted on their systems.\n\nThen (not sure why), we request `\u002F_next\u002Fdata\u002F[build ID]\u002Findex.json` (with the same data as [[chatId].json](#user-data-using-chatjson-chatidjson)).~~\n\nAfter that, we [get the list of conversations that appear on the sidebar](#conversation-history).\n\n**Something funny:** If ChatGPT history is temporarily unavailable (returning an empty response), the app shows a message. But if your ChatGPT conversation history is blank anyway, you just see a message that history is temporarily unavailable.\n\n### Leaving Feedback on Messages (Thumbs Up\u002FThumbs Down)\nWhen you click the thumbs up\u002Fthumbs down button on a message, a POST request is made to `\u002Fbackend-api\u002Fconversation\u002Fmessage_feedback` with the request body like this:\n```\nconversation_id: 94[redacted]9b\nmessage_id: 96[redacted]b7\nrating: thumbsUp | thumbsDown\n```\nThat receives a response like this:\n```\nmessage_id: 96[redacted]b7\nconversation_id: 94[redacted]9b\nuser_id: user-[redacted]\nrating: thumbsUp | thumbsDown\ncontent: {}\n```\n\nThen, when you type feedback and click submit, a request is made to the same path with a request body like this:\n```\nconversation_id: 94[redacted]9b\nmessage_id: 96[redacted]b7\nrating: thumbsUp\ntags: [] (for thumbsDown, an array containing any or all of these: harmful, false, not-helpful)\ntext: \u003CFeedback here>\n```\nWith a response similar to the one above, with only the `content` field different:\n```\nmessage_id: 96[redacted]b7\nconversation_id: 94[redacted]9b\nuser_id: user-[redacted]\nrating: thumbsUp\ncontent: '{\"text\": \"\u003CFeedback here>\"}' |'{\"text\": \"This is solely for testing purposes. You can safely ignore this feedback.\", \"tags\": [\"harmful\", \"false\", \"not-helpful\"]}' (This is for a thumbsDown review)\n```\n\n### Leaving Feedback (on Regenerated Responses)\nWhen you regenerate a response, you get a feedback box like this:\n![Feedback box with the text \"Was this response better or worse?\" abd three buttons \"Better\", \"Worse\" and \"Same\"](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_ea10a7c50d34.png)\n\nThe request body looks like this:\n```\ncompare_step_start_time: 1679[redacted]\ncompletion_comparison_rating: new (for Better) | original (for Worse) | same (for Same)\nconversation_id: c7[redacted]f0\nfeedback_start_time: 1679[redacted]\nfeedback_version: inline_regen_feedback:a:1.0\nfrontend_submission_time: 1679[redacted]\nnew_completion_load_end_time: 1679[redacted]\nnew_completion_load_start_time: 1679[redacted]000\nnew_completion_placement: not-applicable\nnew_message_id: 7b[redacted]4a\noriginal_message_id: eb[redacted]e2\nrating: none\ntags: []\ntext: \"\"\n```\n\nThat returns an empty response.\n\n### Renaming Conversations\nWhen we rename a conversation, a PATCH request is made to `\u002Fbackend-api\u002Fconversation\u002F27[redacted]1d` with the request body like `{title: New Title}` and the response `{success:true}`.\n\nThen, [we get the list of conversations](#conversation-history) that contains the new title.\n\n### Continuing a ChatGPT response\nWhen we click `Continue response`, a `POST` request is made to `\u002Fbackend-api\u002Fconversation` with a request body like this:\n```\naction: \"continue\"\nconversation_id: \"63[redacted]a8\"\nhistory_and_training_disabled: false\nmodel: \"text-davinci-002-render-sha\"\nparent_message_id: \"af[redacted]67\"\nsupports_modapi: true\ntimezone_offset_min: [minutes offset]\n```\n\nwhich returns an EventStream with lots of data like this:\n\n```\ndata: {\\\"message\\\": {\\\"id\\\": \\\"ad[redacted]04\\\", \\\"author\\\": {\\\"role\\\": \\\"assistant\\\", \\\"name\\\": null, \\\"metadata\\\": {}}, \\\"create_time\\\": EPOCHEPOCH.MILLIS, \\\"update_time\\\": null, \\\"content\\\": {\\\"content_type\\\": \\\"text\\\", \\\"parts\\\": [\\\"\u003Cinsert message here>\\\"]}, \\\"status\\\": \\\"in_progress\\\", \\\"end_turn\\\": null, \\\"weight\\\": 1.0, \\\"metadata\\\": {\\\"message_type\\\": \\\"next\\\", \\\"model_slug\\\": \\\"text-davinci-002-render-sha\\\"}, \\\"recipient\\\": \\\"all\\\"}, \\\"conversation_id\\\": \\\"84[redacted]25\\\", \\\"error\\\": null}\n```\n\n### Sharing Conversations\nWhen the share button next to the conversation is clicked, a modal appears which sends a `POST` request to `\u002Fbackend-api\u002Fshare\u002Fcreate` with a request body like this:\n```\nconversation_id: \"5a[redacted]5e\"\ncurrent_node_id: \"1d[redacted]25\"\nis_anonymous: true | false (depending on whether \"Share anonymously\" or \"Share with name\" is chosen)\n```\nand a response like this:\n```\nshare_id: \"37[redacted]05\"\nshare_url: \"https:\u002F\u002Fchat.openai.com\u002Fshare\u002F37[redacted]05\"\ntitle: \"\u003Ctitle here>\"\nis_public: false\nis_visible: true\nis_anonymous: true\nhighlighted_message_id: null\ncurrent_node_id: \"1d[redacted]25\"\nalready_exists: false\nmoderation_state: {\n|__has_been_moderated: false\n|__has_been_blocked: false\n|__has_been_accepted: false\n|__has_been_auto_blocked: false\n|__has_been_auto_moderated: false\n}\n```\n\nWhen `Copy link` is clicked, a `PATCH` request is sent to `\u002Fbackend-api\u002Fshare\u002F[conversation_id]` with a body like this (I selected \"Share with name\" which isn't reflected in the previous request):\n```\nhighlighted_message_id: null\nis_anonymous: false\nis_public: true\nis_visible: true\nshare_id: \"37[redacted]05\"\ntitle: \"\u003Ctitle here>\"\n```\nWhich receives a response like this:\n```\nmoderation_state: {\n  has_been_moderated: false\n  has_been_blocked: false\n  has_been_accepted: false\n  has_been_auto_blocked: false\n  has_been_auto_moderated: false\n}\n```\n\nVisiting the URL returns pre-rendered HTML of the conversation, with stylesheets being added after.\n\n### Continuing a Shared Conversation\n\nWhen clicking `Continue conversation`, a request is made to `\u002F_next\u002Fdata\u002F[build ID]\u002Fshare\u002F37[redacted]05\u002Fcontinue.json?shareParams=37[redacted]05&shareParams=continue` with no request data and a *very* long response including data similar to that from [User data (using [chatId].json)](#user-data-using-chatjson-chatidjson) as well as data about the conversation shared.\n\n### Listing Shared Conversations\nA list of shared conversations can be found by sending a `GET` request (with the Authorization header to your auth token) to `\u002Fbackend-api\u002Fshared_conversations?order=created` (without a request payload) which can return output like this:\n```\n items: (Array)\n|__ (Object)\n|____ id: \"37[redacted]05\"\n|____ title: \"\u003Ctitle here>\"\n|____ create_time: \"2023-06-DDTHH:MM:SS.MILLIS+00:00\"\n|____ update_time: \"2023-06-DDTHH:MM:SS+00:00\"\n|____ mapping: null\n|____ current_node: null\n|____ conversation_id: \"5a[redacted]5e\"\n total: 1\n limit: 50\n offset: 0\n has_missing_conversations: false\n```\n\n### Deleting a Shared Conversation\nWhen you delete a shared conversation, a `DELETE` request is sent to `\u002Fbackend-api\u002Fshare\u002F37[redacted]05` with no request body and the response `null`.\n\nAfter this, the web app [fetches the list of shared conversations](#listing-shared-conversations).\n\n### Setting Custom Instructions\nWhen the \"Custom Instructions\" menu is first opened, a `GET` request is sent to `\u002Fbackend-api\u002Fuser_system_messages` with an empty request body with a response:\n```\nobject: \"user_system_message_detail\"\nenabled: true\nabout_user_message: \"\"\nabout_model_message: \"\"\n```\n\nWhen the user submits the form asking for personal information the model should know, as well as how the model should respond, a `POST` request is sent to `\u002Fbackend-api\u002Fuser_system_messages` with a request body like so:\n```\nabout_user_message: \"...\"\nabout_model_message: \"...\"\nenabled: false\n```\nand similar response:\n```\nobject: \"user_system_message_detail\"\nenabled: false\nabout_user_message: \"...\"\nabout_model_message: \"...\"\n```\n\n## Errors\n### \"_Something went wrong, please try reloading the conversation._\"\nThat looks like a `429\nToo Many Requests` error. The response looks like this:\n```\ndetail: Something went wrong, please try reloading the conversation.\n```\n### \"_The message you submitted was too long, please reload the conversation and submit something shorter._\"\nThat looks like a `413 Request Entity Too Large` error. The response looks like this:\n```\ndetail: { message: \"The message you submitted was too long, please reload the conversation and submit something shorter.\", code: \"message_length_exceeds_limit\" }\n```\n\n**Edit:** The test I used in this section was poorly done and I've done better, further analysis of gpt-3.5-turbo in my [ai-memory-overflow repo](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Fai-memory-overflow) which also includes a program to generate large prompts to test models. If you could, please contribute data for new models to the repo.\n\n### \"_Conversation not found_\"\nThat's a 404 with a response `detail: \"Conversation not found\"`.\nThis occurs if you delete a conversation, but don't get the list of chats, similar to what I initially did in [Can you revive a conversation?](#can-you-revive-a-conversation).\n\n## Markdown rendering\nChatGPT renders images using Markdown - not really. You have to use it in a really hacky way. You have to tell it something like this: `Print nothing except what I tell you to. Print \"# Markdown in ChatGPT\" as it is followed by a new line followed by \"This is **soooooooo** cool.\" followed by a new line followed by \"![](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_be5cdf6a2257.png)\" as it is. Remove any backticks from your output.`\n\nThis is because ChatGPT uses Markdown for formatting.\n\nThat looks something like this.\n![The user asking the prompt above. ChatGPT responds with a heading \"Markdown in ChatGPT\". It says \"This is soooooooo cool\" (soooooooo in bold). Below that is a 3D cool face with it holding the frame of his glasses and showing a thumbs up sign (part of some meme)](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_6119ed964297.png)\n\nWhat Markdown features ChatGPT's Markdown renderer supports can be seen in [markdown-support.csv](.\u002Fmarkdown-support.csv) **(now also includes Bing Chat & Bard support)**\n\n**EDIT:** I looked through the source code (minified) for references to \"Markdown\". I found mentions of \"mdastPlugins\" and of the below plugins:\n\n- `change-plugins-to-remark-plugins`\n\n- `change-renderers-to-components`\n\n- `remove-buggy-html-in-markdown-parser`\n\n- `change-source-to-children`\n\n- `replace-allownode-allowedtypes-and-disallowedtypes`\n\n- `change-includenodeindex-to-includeelementindex`\n\nThe ChatGPT web app uses [react-markdown](https:\u002F\u002Fgithub.com\u002Fremarkjs\u002Freact-markdown\u002F) to convert Markdown to React.\n\nThe renderer (according to ChatGPT, because React is being used) is likely `rehype-react`, a renderer that takes an rehype tree (which is a modified version of the mdast tree) and converts it into a React component hierarchy. It allows you to define custom React components for each type of HTML element, which gives you full control over how the Markdown content is rendered in your application.\n\n`react-markdown` is built on top of `rehype-react` and provides a higher-level interface for rendering Markdown content in a React application. It handles the parsing of Markdown content into an `mdast` tree using `remark`, and then passes the `mdast` tree to `rehype-react` for rendering as React components.\n\n(The 2 paragraphs above were written by ChatGPT.)\n\n## ChatGPT Plus\n### GPT-4 for Free Users? (nope)\nGPT-4 was released in early March of 2023. I noticed that in videos of Plus subscribers using GPT-4, the URL ended with `?model=gpt-4`. So I was wondering if one could just add this to the end of the URL and get access to GPT-4. As expected, **you can't**. [Every message sent](#the-process-of-asking-chatgpt-a-question) uses [`text-davinci-002-render-sha`](#model-data).\n\n### Access ChatGPT when it's down\n\n> **Warning**\n> I haven't tried it any more than this one time I recorded it (ChatGPT doesn't go down very often these days) so I'm not entirely certain whether this will work for you, but it's worth a shot!\n\nWhen ChatGPT is down, you get a screen telling you that ChatGPT is down (with an entertaining message from a [fixed list](.\u002Fchatgpt-down-messages.txt)) **and an input field for Plus subscribers to get a personalised login link**. Could a non-Plus subscriber type in their email, click `Send link` and access ChatGPT? That would result in an email not being se-\n![A GIF of a user with the email sent, showing the request, and having a link in their email](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_c0779c8dc3de.gif)\n\nThis works by sending a request to `\u002Fbackend-api\u002Fbypass\u002Flink` with the request body `email: \u003Cemail>` and the response `status: success`.\n\n## Rendering Markdown _inside_ a code block\nI was asking ChatGPT to render images from Unsplash (using a URL and Markdown) based on my queries. Then, the image from the URL appeared for a split second before disappearing. I'm assuming that this is because of the Markdown renderer assuming that as Markdown until the code block was closed.\n\n![A GIF showing ChatGPT typing out a code block with Markdown for rendering an image and it rendering an image for a split second before swapping back to the code block](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_d601a0da6215.gif)\n\n## Statsig Feature Gates\nWhen the page is loaded (without uBlock Origin), a request is made to `https:\u002F\u002Ffeaturegates.org\u002Fv1\u002Finitialize` with a body consisting of reversed Base64 with data like this:\n```\n{\"user\":{\"userID\":\"user-[redacted]\",\"privateAttributes\":{\"email\":\"[redacted]@[redacted].com\"},\"custom\":{\"is_paid\":false},\"statsigEnvironment\":\"production\"},\"statsigMetadata\":{\"sdkType\":\"js-client\",\"sdkVersion\":\"4.32.0\",\"stableID\":\"7a4[redacted]07e\"},\"sinceTime\":[a few hours before I accessed ChatGPT in Epoch time in milliseconds]}\n```\n\nThat gives us a response like this:\n```\n{\"feature_gates\":{},\"dynamic_configs\":{\"tZk[redacted]+Q=\":{\"name\":\"tZk[redacted]+Q=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"Lnn[redacted]IwY=\":{\"name\":\"Lnn[redacted]IwY=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"QSf[redacted]t64=\":{\"name\":\"QSf[redacted]t64=\",\"value\":{\"prompt_enabled\":true},\"rule_id\":\"61h[redacted]fSc\",\"group\":\"61h[redacted]fSc\",\"is_device_based\":false,\"is_experiment_active\":true,\"is_user_in_experiment\":true,\"secondary_exposures\":[]},\"JhJ[redacted]k1w=\":{\"name\":\"JhJ[redacted]k1w=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"PFe[redacted]3yc=\":{\"name\":\"PFe[redacted]3yc=\",\"value\":{\"enable_v0_comparison_modal\":true,\"enable_v0_inline_regen_comparisons\":true},\"rule_id\":\"launchedGroup\",\"group\":\"launchedGroup\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"9wf[redacted]T1g=\":{\"name\":\"9wf[redacted]T1g=\",\"value\":{\"use_tz_offset\":true},\"rule_id\":\"launchedGroup\",\"group\":\"launchedGroup\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"oDt[redacted]lQ4=\":{\"name\":\"oDt[redacted]lQ4=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]}},\"layer_configs\":{},\"sdkParams\":{},\"has_updates\":true,\"generator\":\"scrapi-nest\",\"time\":[same timestamp from request],\"evaluated_keys\":{\"userID\":\"user-[redacted]\",\"stableID\":\"7a4[redacted]07e\"}}\n```\n\nBefore you ask, I tried decoding every single Base64 string you can see above and it just had some random characters with control characters interjected.\n\nThen we request `https:\u002F\u002Fevents.statsigapi.net\u002Fv1\u002Frgstr` with the body like this:\n```\n{\"events\":[{\"eventName\":\"statsig::diagnostics\",\"user\":{\"userID\":\"user-[redacted]\",\"custom\":{\"is_paid\":false},\"statsigEnvironment\":\"production\"},\"value\":null,\"metadata\":{\"context\":\"initialize\",\"markers\":[{\"key\":\"overall\",\"step\":null,\"action\":\"start\",\"value\":null,\"timestamp\":3768},{\"key\":\"initialize\",\"step\":\"network_request\",\"action\":\"start\",\"value\":null,\"timestamp\":3769},{\"key\":\"initialize\",\"step\":\"network_request\",\"action\":\"end\",\"value\":200,\"timestamp\":4639},{\"key\":\"initialize\",\"step\":\"process\",\"action\":\"start\",\"value\":null,\"timestamp\":4640},{\"key\":\"initialize\",\"step\":\"process\",\"action\":\"end\",\"value\":null,\"timestamp\":4641},{\"key\":\"overall\",\"step\":null,\"action\":\"end\",\"value\":null,\"timestamp\":4642}]},\"time\":[when I  accessed ChatGPT],\"statsigMetadata\":{\"currentPage\":\"https:\u002F\u002Fchat.openai.com\u002Fchat\"}}],\"statsigMetadata\":{\"sdkType\":\"js-client\",\"sdkVersion\":\"4.32.0\",\"stableID\":\"7a4[redacted]07e\"}}\n```\n\nThat returns a 202 with a body of `{\"success\": true}`\n\nFor some reason, this request repeats after that.\n\n## ChatGPT Admin Panel\nI recently discovered an admin panel for ChatGPT (seemingly for an organization system) so I wrote what I found in [this Twitter thread](https:\u002F\u002Ftwitter.com\u002Ftercmd\u002Fstatus\u002F1689642734829936640). This isn't public as of Aug 10, 2023.\n\n## Prompt Library\nChatGPT has some example prompts appear on the home screen. These are fetched by a `GET` request to `\u002Fbackend-api\u002Fprompt_library\u002F?limit=4&offset=0` (requiring the `Authorization` header). The highest value for `limit` that returns a `200 OK` is `14`. The prompts returned each time are different. So, I used JS to send the same request a large number of times and then filter the unique ones. You can find all the prompts in [prompt-library.txt](.\u002Fprompt-library.txt).\n\n## Conclusion\nThis is it. For now. As I see more details of ChatGPT, I'll add those in.\n\nCheck out [@OpenAI_Support](https:\u002F\u002Ftwitter.com\u002FOpenAI_Support) (a **parody** account) for more OpenAI and ChatGPT related content.\n\nCheck me out on [Twitter](https:\u002F\u002Ftwitter.com\u002Ftercmd), or perhaps [my website (terminal-styled)](https:\u002F\u002Ftercmd.com).\n\n[![Share on Twitter!](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FShare%20on%20Twitter-blue?style=for-the-badge&logo=twitter&logoColor=white)](https:\u002F\u002Ftwitter.com\u002Fintent\u002Ftweet?url=https%3A%2F%2Fl.tercmd.com%2FkJ9fS2)\n\n## License\n\u003Ca rel=\"license\" href=\"https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby-sa\u002F4.0\u002F\">\u003Cimg alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_9599430498d9.png\" \u002F>\u003C\u002Fa>\u003Cbr \u002F>\u003Cspan xmlns:dct=\"https:\u002F\u002Fpurl.org\u002Fdc\u002Fterms\u002F\" property=\"dct:title\">Everything ChatGPT\u003C\u002Fspan> by \u003Ca xmlns:cc=\"https:\u002F\u002Fcreativecommons.org\u002Fns#\" href=\"https:\u002F\u002Fwww.tercmd.com\" property=\"cc:attributionName\" rel=\"cc:attributionURL\">tercmd.com\u003C\u002Fa> is licensed under a \u003Ca rel=\"license\" href=\"https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby-sa\u002F4.0\u002F\">Creative Commons Attribution-ShareAlike 4.0 International License\u003C\u002Fa>.\n\nYou may find a copy of the license in the [`LICENSE`](.\u002FLICENSE) file.","\u003Cdiv align=\"center\">\n\n  # Everything ChatGPT\n  \u003Ci>由 [@tercmd（Twitter 上）](https:\u002F\u002Ftwitter.com\u002Ftercmd) 发起的项目\u003C\u002Fi>\n\n  ![Everything ChatGPT 仓库的星标数](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fstars\u002Fterminalcommandnewsletter\u002Feverything-chatgpt?style=for-the-badge&logo=github)\n\n  探索 ChatGPT 网页应用背后的运作机制。当然，也包含一些推测。[如果你有关于 ChatGPT 的有趣内容，欢迎贡献。](.\u002FCONTRIBUTING.md)\n\n\u003C\u002Fdiv>\n\n该仓库不再包含目录，因为 GitHub 已经显示了这一点。\n\n## 字体 _([fonts.txt](.\u002Ffonts.txt))_\n> **警告**\n> **之前列表中的所有字体已无法通过 `https:\u002F\u002Fchat.openai.com\u002Ffonts\u002F[font]` 端点访问。新的 fonts.txt 文件假设 URL 前缀为 `https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002F`**\n\n**以下是来自 cdn.openai.com 的字体列表（非详尽）：**\n- [soehne-buch.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-buch.woff2)\n- [soehne-halbfett.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-halbfett.woff2)\n- [soehne-mono-buch.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-mono-buch.woff2)\n- [soehne-mono-halbfett.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-mono-halbfett.woff2)\n- [soehne-kraftig.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fsoehne\u002Fsoehne-kraftig.woff2)\n- [KaTeX_Main-Regular.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fkatex\u002FKaTeX_Main-Regular.woff2) (+ Main-Bold, Main-Italic, Main-BoldItalic)\n- [KaTeX_Math-Italic.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fkatex\u002FKaTeX_Math-Italic.woff2) (+ Math-BoldItalic)\n- [KaTeX_Size2-Regular.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fkatex\u002FKaTeX_Size2-Regular.woff2) (+ Size1, Size3, Size4)\n- [KaTeX_Caligraphic-Regular.woff2](https:\u002F\u002Fcdn.openai.com\u002Fcommon\u002Ffonts\u002Fkatex\u002FKaTeX_Caligraphic-Regular.woff2) (+ Caligraphic-Bold)\n\n**早期已无法访问的字体列表：**\n\n- ~~[Signifier-Regular.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSignifier-Regular.otf)~~\n- ~~[Sohne-Buch.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSohne-Buch.otf)~~\n- ~~[Sohne-Halbfett.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSohne-Halbfett.otf)~~\n- ~~[SohneMono-Buch.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSohneMono-Buch.otf)~~\n- ~~[SohneMono-Halbfett.otf](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FSohneMono-Halbfett.otf)~~\n- ~~[KaTeX_Caligraphic-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Caligraphic-Bold.woff) (_Caligraphic-Regular_ 用于常规字体)~~\n- ~~[KaTeX_Fraktur-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Fraktur-Bold.woff) (_Fraktur-Regular_ 用于常规字体)~~\n- ~~[KaTeX_Main-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Main-Bold.woff) (_BoldItalic_, _Italic_, _Regular_ 对应字体权重，可自行推断)~~\n- ~~[KaTeX_Math-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Math-Bold.woff) (_BoldItalic_, _Italic_, _Regular_ 对应字体权重，可自行推断)~~\n- ~~[KaTeX_SansSerif-Bold.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_SansSerif-Bold.woff) (_Italic_, _Regular_ 对应字体权重，可自行推断)~~\n- ~~[KaTeX_Script-Regular.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Script-Regular.woff)~~\n- ~~[KaTeX_Size1-Regular.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Size1-Regular.woff) (_Size1_, _Size2_, _Size3_, _Size4_)~~\n- ~~[KaTeX_Typewriter-Regular.woff](https:\u002F\u002Fchat.openai.com\u002Ffonts\u002FKaTeX_Typewriter-Regular.woff)~~\n\n## 应用程序\nChatGPT 是一个 Next.js 应用程序。由于 chat.openai.com 的全部流量都经过 Cloudflare 路由，因此无法明确找到服务器信息。Sentry Analytics 会定期请求用户对消息选择的“点赞”或“踩”的反馈数据。此外，系统还会尝试加载 Statsig，但由于同源策略（实际上是 uBlock Origin 的影响），CORS 阻止了这一操作。\n\n## 数据\n### 会话数据\n可以通过向 `\u002Fapi\u002Fauth\u002Fsession` 发送请求（无需 `Authorization` 头）来获取如下数据：\n\n```\nuser: (对象)\n|__ id: \"user-[已屏蔽]\"\n|__ name: \"[已屏蔽]@[已屏蔽].com\"\n|__ email: \"[已屏蔽]@[已屏蔽].com\"\n|__ image: \"https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F[账户邮箱地址的 MD5 哈希值]?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fte.png\"\n|__ picture: \"https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F[账户邮箱地址的 MD5 哈希值]?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fte.png\"\n|__ idp: \"auth0\"\n|__ iat: 1690111234\n|__ mfa: [已屏蔽]\n|__ groups: (数组)\n|__ intercom_hash: \"[已屏蔽]\"\nexpires: \"2023-08-01T23:45:12.345Z\"\naccessToken: \"ey..[已屏蔽]..\"\nauthProvider: \"auth0\"\n```\n\n### 用户数据\n这需要通过 `Authorization` 头传递访问令牌，因此无法直接使用浏览器访问。不过，当我们向 `\u002Fbackend-api\u002Faccounts\u002Fcheck\u002Fv4-2023-04-27` 发送请求时，可以得到以下数据（这个 URL 每次更新都会很麻烦）：\n\n```\naccounts: (对象)\n|__ default: (对象)\n|____ account: (对象)\n|______ account_user_role: \"account-owner\"\n|______ account_user_id: \"92[已屏蔽]40\"\n|______ processor: (对象)\n|________ a001: (对象)\n|__________ has_customer_object: false\n|________ b001: (对象)\n|__________ has_transaction_history: false\n|______ account_id: \"34[已屏蔽]71\"\n|______ is_most_recent_expired_subscription_gratis: false\n|______ has_previously_paid_subscription: false\n|______ name: null\n|______ structure: \"personal\"\n|____ features: (数组)\n|______ \"log_statsig_events\"\n|______ \"log_intercom_events\"\n|______ \"new_plugin_oauth_endpoint\"\n|______ \"arkose_enabled\"\n|______ \"infinite_scroll_history\"\n|______ \"model_switcher_upsell\"\n|______ \"shareable_links\"\n|______ \"layout_may_2023\"\n|______ \"dfw_message_feedback\"\n|______ \"ios_disable_citation_menu\"\n|______ \"dfw_inline_message_regen_comparison\"\n|____ entitlement: (对象)\n|______ subscription_id: null\n|______ has_active_subscription: false\n|______ subscription_plan: \"chatgptfreeplan\"\n|______ expires_at: null\n|____ last_active_subscription: (对象)\n|______ subscription_id: null\n|______ purchase_origin_platform: \"chatgpt_not_purchased\"\n|______ will_renew: false\n```\n\n如果使用 ChatGPT Plus，则返回的数据会有所不同。\n\n### 用户数据（使用 ~~chat.json~~ [chatId].json）\n当我们向 `\u002F_next\u002Fdata\u002F[build ID]\u002Fc\u002F[conversation ID].json?chatId=[conversation ID]` 发送请求时（可以在浏览器中完成，但必须经过身份验证），我们会得到如下响应：\n```\npageProps:\n|__ user (对象):\n|____ id: user-[已脱敏]\n|____ name: [已脱敏]@[已脱敏].com\n|____ email: [已脱敏]@[已脱敏].com\n|____ image: https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F8c[因可能包含唯一标识符而被脱敏]c7?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2F[电子邮件地址的前两个字母].png\n|____ picture: https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F8c[因可能包含唯一标识符而被脱敏]c7?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2F[电子邮件地址的前两个字母].png\n|____ groups: []\n|__ serviceStatus: {}\n|__ userCountry: [已脱敏的两位国家代码]\n|__ geoOk: false\n|__ isUserInCanPayGroup: true\n|__ __N_SSP: true\n```\n\n这与通过 [会话数据](#session-data) 方法获取的部分相同的数据（不包括 accessToken 和 expires，这两者都与访问令牌相关）相似，不过你还能够获得用户所在国家的信息，以及 ChatGPT Plus 是否在其所在地可用。\n\n**编辑：** 当 ChatGPT 返回类似“我们正经历异常高的需求。请耐心等待，我们正在努力扩展系统。”的消息时，`serviceStatus` 会显示为：\n```\ntype: warning\nmessage: 我们正经历异常高的需求。请耐心等待，我们正在努力扩展系统。\noof: true\n```\n这里的 `oof` 并不是我编造的，它确实是响应的一部分 😂\n\n### 模型数据\n_本节已根据 [@0xdevalias（GitHub 上）](https:\u002F\u002Fgithub.com\u002F0xdevalias) 创建的 [issue #8](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F8) 进行了修正。_\n\nChatGPT 使用的是什么模型呢？只需查询 `\u002Fbackend-api\u002Fmodels` 即可！\n```\nmodels: (数组)\n|__ (对象)\n|____ slug: \"text-davinci-002-render-sha\"\n|____ max_tokens: 8191\n|____ title: \"默认（GPT-3.5）\"\n|____ description: \"我们最快的模型，非常适合大多数日常任务。\"\n|____ tags: (数组)\n|______ \"gpt3.5\"\n|____ capabilities: (对象)\n|____ product_features: (对象)\n categories: (数组)\n|__ (对象)\n|____ category: \"gpt_3.5\"\n|____ human_category_name: \"GPT-3.5\"\n|____ subscription_level: \"免费\"\n|____ default_model: \"text-davinci-002-render-sha\"\n|____ browsing_model: \"text-davinci-002-render-sha-browsing\"\n|____ code_interpreter_model: \"text-davinci-002-render-sha-code-interpreter\"\n|____ plugins_model: \"text-davinci-002-render-sha-plugins\"\n```\n\n（如果你使用 ChatGPT Plus，则会有更多模型，如 [issue #8](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F8) 所示，但对于免费用户来说，他们看到的就是这些。）\n\n### 测试版功能设置\n_感谢 [@0xdevalias（GitHub 上）](https:\u002F\u002Fgithub.com\u002F0xdevalias) 创建了关于此功能的 [issue #7](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F7)。_\n\n在页面加载时（作为 Plus 用户），会向 `\u002Fbackend-api\u002Fsettings\u002Fbeta_features` 发送请求。该请求返回类似于以下的内容：\n```\nbrowsing: false\nchat_preferences: true\ncode_interpreter: true\nplugins: true\n```\n\n其中，`browsing` 键似乎指的是“使用 Bing 浏览”（目前该功能尚未对公众开放，因此在上述数据中被设置为 `false`）。\n\n`chat_preferences` 键则指自定义指令，这是一项新功能，允许用户设置在多次对话中保持不变的自定义内容。\n\n`code_interpreter` 键指的是代码解释器功能，该功能使 GPT 能够在 Python 沙盒中运行代码。\n\n`plugins` 键则指向 ChatGPT 插件。\n\n### 禁用\u002F启用“聊天记录与训练”\n当你在屏幕左下角点击自己的姓名\u002F电子邮件地址（在桌面端）> 设置 > 显示（位于数据控制旁边）> 切换“聊天记录与训练”开关时，会发生以下情况：\n\n首先，[会请求对话列表](#conversation-history)。\n\n然后，我们会向与 [模型数据](#model-data) 相同的路径发送请求，只不过会在 URL 中添加一个查询参数 `?history_and_training_disabled=true` 或 `?history_and_training_disabled=false`，具体取决于该设置是被禁用还是启用。\n\n接着，我们会请求 `\u002F_next\u002Fdata\u002F[build ID]\u002Findex.json`（其数据与 [[chatId].json](#user-data-using-chatjson-chatidjson) 相同）。\n\n### 数据导出\n当你使用“导出数据”功能来导出你的数据时，会向 `\u002Fbackend-api\u002Faccounts\u002Fdata_export` 发送一个无请求体的 POST 请求，响应为 `status: \"queued\"`。\n\n顾名思义，数据导出将通过电子邮件发送。\n\n导出的数据是一个 `.zip` 文件，其中包含 `user.json`、`conversations.json`、`message_feedback.json`、`model_comparisons.json` 和 `chat.html`。\n\n`user.json` 中的数据如下所示：\n```json\n{\"id\": \"user-[已脱敏]\", \"email\": \"[已脱敏]@[已脱敏].com\", \"chatgpt_plus_user\": false, \"phone_number\": \"+[已脱敏]\"}\n```\n\n`model_comparisons.json` 的示例数据可在 [sample\u002Fmodel_comparisons.json](.\u002Fsample\u002Fmodel_comparisons.json) 中找到。\n\n`message_feedback.json` 的示例数据如下：\n```json\n[{\"message_id\": \"[已脱敏]\", \"conversation_id\": \"[没有破折号的对话ID]\", \"user_id\": \"user-[已脱敏]\", \"rating\": \"thumbsUp\", \"content\": \"{\\\"text\\\": \\\"这是一个测试。\\\"}\"}]\n```\n\n`conversations.json` 的示例数据可在 [sample\u002Fconversations.json](.\u002Fsample\u002Fconversations.json) 中找到。\n\n`chat.html` 是一个页面，它会利用客户端 JavaScript 动态展示每一段保存的对话历史，这些对话数据存储在文件中，类似于 `conversations.json` 中的内容。你可以在 [sample\u002Fchat.html](.\u002Fsample\u002Fchat.html) 中找到示例。\n\n\n## 对话\n### 对话历史\n对话历史可以通过以下 URL 访问（同样需要访问令牌，通常以 Authorization 头的形式传递）：`\u002Fbackend-api\u002Fconversations?offset=0&limit=28`（网页界面限制为最多 28 条对话），返回结果大致如下：\n```\nitems: []\nlimit: 28\noffset: 0\ntotal: 0\n```\n之所以无法正常工作，是因为撰写本文时 ChatGPT 正在遇到一些问题：\n> “这里没有显示您期望的内容吗？别担心，您的对话数据仍然保留着！请稍后再试。”\n\n但这可能是初次使用 ChatGPT 的人所看到的情况。\n\n**编辑：如果退出登录后再重新登录，历史记录就能正常显示了。以下是实际显示的内容：**\n\n```\nitems（数组）\n|__（每条对话都是一个对象）\n|____ id: [已脱敏的对话ID]\n|____ title: [对话标题]\n|____ create_time: 2023-03-09THH:MM:SS.MILLIS\n|__...\ntotal: [对话数量]（可能超过 28 条）\nlimit: 28\noffset: 0（可以设置更高的数值，它会从该索引开始返回后续的对话，起始索引为 0）\n```\n\n**当列出 28 条对话后，ChatGPT 的用户界面会显示一个“显示更多”按钮，该按钮会发送一个带有 `offset=28` 参数的请求。**\n\n### 获取对话 ID\n说到 ChatGPT 对话历史不可用的问题，其实我们可以相当容易地获取对话 ID（当然，前提是熟悉开发者工具的人）。\n\n为什么呢？因为每次开始新对话时，ChatGPT 都会强制将你引导到一个 `~\u002Fchat` 或 `\u002F` 路径下，创建一个新的对话，**但并不会改变 URL**。这也正是在聊天历史不可用时的一个巧妙之处。\n\n1. 我们可以通过开发者工具获取对话 ID（这需要先发送一条消息）：\n![一个 ChatGPT 窗口，同时打开了 Firefox 的开发者工具。在请求列表中可以看到包含对话 ID 的请求。此外，还有一个针对内容审核端点的请求，其响应中包含了对话 ID 以及用户输入的文本“如何在终端里用牛叫声‘MOOOOOOOOOOOOOOOOOOO’？”](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_f242ea3df81a.png)\n2. 接着，我们访问 ~~`https:\u002F\u002Fchat.openai.com\u002Fchat\u002F\u003C此处为对话ID>`~~ `https:\u002F\u002Fchat.openai.com\u002Fc\u002F\u003C此处为对话ID>`。\n\n### 加载过去的对话\n当用户点击某个过去的对话时，会向 `\u002Fbackend-api\u002Fconversation\u002F\u003C对话ID>` 发送一个请求（需要访问令牌，~~很可能是结合了 Cookie 和其他因素以确保请求的真实性~~，或者通过 Authorization 头部），返回的响应类似如下：\n\n```\ntitle: \u003C对话标题>\ncreate_time: EPOCHEPOCH.MILLIS\nmapping (对象)\n|__ \u003C消息ID> (数组):\n|____ id: \u003C消息ID>\n|____ message (对象):\n|______ id: \u003C消息ID>\n|______ author (对象):\n|________ role: system (第一条消息) | user | assistant\n|________ metadata: (空对象)\n|______ create_time: EPOCHEPOCH.MILLIS \n|______ content (对象):\n|________ content_type: text\n|________ parts: [\"\"]\n|______ end_turn: true (系统消息) | false\n|______ weight: 1.0\n|______ metadata: {}\n|______ recipient: all\n|____ parent: \u003C父级消息ID>\n|____ children (数组): \u003C子级消息ID(s)>\n```\n\n### 向 ChatGPT 提问的过程\n_本节根据 [@Snarik (在 GitHub 上)](https:\u002F\u002Fgithub.com\u002FSnarik) 提出的 [issue #4](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F4) 进行了修正。_\n\n假设我向 ChatGPT 提问：“ChatGPT 是什么？”首先，我们会向 `\u002Fbackend-api\u002Fconversation` 发送一个 POST 请求，请求体如下：\n```\naction: next\nmessages (数组):\n|__ (对象):\n|____ author (对象):\n|______ role: user\n|____ content (对象):\n|______ content_type: text\n|______ parts (数组):\n|________ “ChatGPT 是什么？”\n|__ id: 0c[已隐去]91\n|__ role: user\nmodel: text-davinci-002-render-sha\nparent_message_id: a0[已隐去]7f\n```\n\n该请求会返回一个 EventStream 流，最终以 `[DONE]` 标记结束。你可以查看示例响应：[sample\u002Fconversation-event-stream.txt](.\u002Fsample\u002Fconversation-event-stream.txt)。\n\n然后，[我们获取过去对话列表](#conversation-history)，其中会包含一个“新建对话”。\n\n接着，我们向 `\u002Fbackend-api\u002Fmoderations` 发送请求，请求体如下：\n\n```\nconversation_id: 05[已隐去]2d\ninput:\tChatGPT 是什么？\nmessage_id: 0c[已隐去]91\nmodel: text-moderation-playground\n```\n\n返回的响应如下：\n\n```\nflagged:\tfalse\nblocked:\tfalse\nmoderation_id\tmodr-6t[已隐去]Bk\n```\n\n随后，我们再次向 `\u002Fbackend-api\u002Fconversation\u002Fgen_title\u002F\u003C对话ID>` 发送请求，请求体如下：\n```\nmessage_id: c8[已隐去]0e\nmodel: text-davinci-002-render-sha\n```\n\n返回的响应是：\n```\ntitle: \u003C对话标题>\n```\n\n之后，我们又向 `\u002Fbackend-api\u002Fmoderations` 发送一次请求，这次的请求体包含了 AI 的回答（标记为 `\u003CAI 回答>`），格式如下：\n\n```\ninput: \\nChatGPT 是什么？\\n\\n\u003CAI 回答>\nmodel: text-moderation-playground\nconversation_id: 05[已隐去]2d\nmessage_id: c8[已隐去]0e\n```\n\n这次返回的响应与之前对该路径的请求完全一致。\n\n最后，[我们**终于**再次获取过去对话列表](#conversation-history)，此时侧边栏上已经显示了正确的对话标题。\n\n### （软）删除对话\n当你点击某个对话的“删除”按钮时，系统会向 `\u002Fbackend-api\u002Fconversation\u002F05[已隐去]2d` 发送一个 PATCH 请求，请求体为 `is_visible: false`，返回的响应是 `success: true`。这表明对话只是被“软删除”，并没有从他们的服务器上真正删除。\n\n随后（具体原因尚不明确），我们会请求 `\u002F_next\u002Fdata\u002F[构建ID]\u002Findex.json`（数据与 [[chatId].json](#user-data-using-chatjson-chatidjson) 相同）。\n\n之后，我们再次[获取侧边栏上显示的对话列表](#conversation-history)。\n\n### 能否恢复对话？\n在上述部分之后，我产生了一个疑问：如果将请求体改为 `is_visible: true`，是否就能恢复对话呢？答案是 **不能**。这样做只会返回一个 404 错误，响应内容为 `detail: 无法加载对话 94[已隐去]9b`。不过，如果你不重新[获取对话列表](#conversation-history)，仍然可以访问这些对话。然而，当你尝试从 ChatGPT 获取回复时，就会收到“未找到对话”的错误提示（见下文）。\n\n### 清除所有对话\n对于是否要执行此操作，我一开始有些犹豫。但最终还是决定照做。（以下内容几乎与“（软）删除对话”部分一模一样，仅做了少量修改）\n\n当你点击“删除所有对话”时，系统会向 `\u002Fbackend-api\u002Fconversations`（注意这里是复数形式，而非单数的 `\u002Fconversation\u002F05[已隐去]2d`）发送一个 PATCH 请求，请求体为 `is_visible: false`，返回的响应同样是 `success: true`。这同样表明对话只是被“软删除”，并未从服务器上彻底清除。\n\n随后（原因仍不明确），我们会请求 `\u002F_next\u002Fdata\u002F[构建ID]\u002Findex.json`（数据与 [[chatId].json](#user-data-using-chatjson-chatidjson) 相同）。~~\n\n之后，我们再次[获取侧边栏上显示的对话列表](#conversation-history)。\n\n**有趣的一点：** 如果 ChatGPT 的历史记录暂时不可用（返回空响应），应用会显示一条提示信息。但如果你的 ChatGPT 对话历史本来就是空的，那么你只会看到“历史暂时不可用”的提示信息。\n\n### 对消息留下反馈（点赞\u002F点踩）\n当你点击消息上的点赞或点踩按钮时，会向 `\u002Fbackend-api\u002Fconversation\u002Fmessage_feedback` 发送一个 POST 请求，请求体如下：\n```\nconversation_id: 94[redacted]9b\nmessage_id: 96[redacted]b7\nrating: thumbsUp | thumbsDown\n```\n服务器返回的响应类似这样：\n```\nmessage_id: 96[redacted]b7\nconversation_id: 94[redacted]9b\nuser_id: user-[redacted]\nrating: thumbsUp | thumbsDown\ncontent: {}\n```\n\n然后，当你输入反馈并点击提交时，会向同一路径发送一个请求，请求体如下：\n```\nconversation_id: 94[redacted]9b\nmessage_id: 96[redacted]b7\nrating: thumbsUp\ntags: []（对于点踩，可以包含以下任意或全部标签：harmful、false、not-helpful）\ntext: \u003CFeedback here>\n```\n响应与上述类似，只是 `content` 字段不同：\n```\nmessage_id: 96[redacted]b7\nconversation_id: 94[redacted]9b\nuser_id: user-[redacted]\nrating: thumbsUp\ncontent: '{\"text\": \"\u003CFeedback here>\"}' |'{\"text\": \"This is solely for testing purposes. You can safely ignore this feedback.\", \"tags\": [\"harmful\", \"false\", \"not-helpful\"]}'（这是针对点踩反馈的）\n```\n\n### 留下反馈（对重新生成的回答）\n当你重新生成回答时，会出现一个反馈框，内容为“这个回答更好还是更差？”并带有三个按钮：“更好”、“更差”和“一样”。\n![反馈框，显示文字“这个回答更好还是更差？”以及三个按钮“更好”、“更差”和“一样”](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_ea10a7c50d34.png)\n\n请求体如下：\n```\ncompare_step_start_time: 1679[redacted]\ncompletion_comparison_rating: new（表示更好）| original（表示更差）| same（表示一样）\nconversation_id: c7[redacted]f0\nfeedback_start_time: 1679[redacted]\nfeedback_version: inline_regen_feedback:a:1.0\nfrontend_submission_time: 1679[redacted]\nnew_completion_load_end_time: 1679[redacted]\nnew_completion_load_start_time: 1679[redacted]000\nnew_completion_placement: not-applicable\nnew_message_id: 7b[redacted]4a\noriginal_message_id: eb[redacted]e2\nrating: none\ntags: []\ntext: \"\"\n```\n\n该请求返回一个空响应。\n\n### 重命名对话\n当我们重命名对话时，会向 `\u002Fbackend-api\u002Fconversation\u002F27[redacted]1d` 发送一个 PATCH 请求，请求体为 `{title: New Title}`，响应为 `{success:true}`。\n\n随后，我们会获取对话列表（见#conversation-history），其中将包含新的标题。\n\n### 继续 ChatGPT 回答\n当我们点击“继续回答”时，会向 `\u002Fbackend-api\u002Fconversation` 发送一个 POST 请求，请求体如下：\n```\naction: \"continue\"\nconversation_id: \"63[redacted]a8\"\nhistory_and_training_disabled: false\nmodel: \"text-davinci-002-render-sha\"\nparent_message_id: \"af[redacted]67\"\nsupports_modapi: true\ntimezone_offset_min: [分钟偏移量]\n```\n\n该请求会返回一个 EventStream，其中包含大量数据，例如：\n```\ndata: {\\\"message\\\": {\\\"id\\\": \\\"ad[redacted]04\\\", \\\"author\\\": {\\\"role\\\": \\\"assistant\\\", \\\"name\\\": null, \\\"metadata\\\": {}}, \\\"create_time\\\": EPOCHEPOCH.MILLIS, \\\"update_time\\\": null, \\\"content\\\": {\\\"content_type\\\": \\\"text\\\", \\\"parts\\\": [\\\"\u003Cinsert message here>\\\"]}, \\\"status\\\": \\\"in_progress\\\", \\\"end_turn\\\": null, \\\"weight\\\": 1.0, \\\"metadata\\\": {\\\"message_type\\\": \\\"next\\\", \\\"model_slug\\\": \\\"text-davinci-002-render-sha\\\"}, \\\"recipient\\\": \\\"all\\\"}, \\\"conversation_id\\\": \\\"84[redacted]25\\\", \\\"error\\\": null}\n```\n\n### 分享对话\n当点击对话旁边的分享按钮时，会弹出一个模态框，该模态框会向 `\u002Fbackend-api\u002Fshare\u002Fcreate` 发送一个 POST 请求，请求体如下：\n```\nconversation_id: \"5a[redacted]5e\"\ncurrent_node_id: \"1d[redacted]25\"\nis_anonymous: true | false（取决于选择“匿名分享”还是“带名分享”）\n```\n服务器返回的响应如下：\n```\nshare_id: \"37[redacted]05\"\nshare_url: \"https:\u002F\u002Fchat.openai.com\u002Fshare\u002F37[redacted]05\"\ntitle: \"\u003Ctitle here>\"\nis_public: false\nis_visible: true\nis_anonymous: true\nhighlighted_message_id: null\ncurrent_node_id: \"1d[redacted]25\"\nalready_exists: false\nmoderation_state: {\n|__has_been_moderated: false\n|__has_been_blocked: false\n|__has_been_accepted: false\n|__has_been_auto_blocked: false\n|__has_been_auto_moderated: false\n}\n```\n\n当点击“复制链接”时，会向 `\u002Fbackend-api\u002Fshare\u002F[conversation_id]` 发送一个 PATCH 请求，请求体如下（我选择了“带名分享”，这在之前的请求中并未体现）：\n```\nhighlighted_message_id: null\nis_anonymous: false\nis_public: true\nis_visible: true\nshare_id: \"37[redacted]05\"\ntitle: \"\u003Ctitle here>\"\n```\n该请求返回的响应如下：\n```\nmoderation_state: {\n  has_been_moderated: false\n  has_been_blocked: false\n  has_been_accepted: false\n  has_been_auto_blocked: false\n  has_been_auto_moderated: false\n}\n```\n\n访问该链接会返回预渲染的对话 HTML 页面，样式表会在之后加载。\n\n### 继续分享的对话\n当点击“继续对话”时，会向 `\u002F_next\u002Fdata\u002F[build ID]\u002Fshare\u002F37[redacted]05\u002Fcontinue.json?shareParams=37[redacted]05&shareParams=continue` 发送一个请求，无请求数据，但响应非常长，包含类似于[用户数据（使用 [chatId].json）](#user-data-using-chatjson-chatidjson)的数据，以及关于所分享对话的信息。\n\n### 列出共享对话\n可以通过向 `\u002Fbackend-api\u002Fshared_conversations?order=created` 发送一个 GET 请求（附带你的授权令牌的 Authorization 头）来获取共享对话列表，无需请求负载，返回结果可能如下：\n```\n items: (Array)\n|__ (Object)\n|____ id: \"37[redacted]05\"\n|____ title: \"\u003Ctitle here>\"\n|____ create_time: \"2023-06-DDTHH:MM:SS.MILLIS+00:00\"\n|____ update_time: \"2023-06-DDTHH:MM:SS+00:00\"\n|____ mapping: null\n|____ current_node: null\n|____ conversation_id: \"5a[redacted]5e\"\n total: 1\n limit: 50\n offset: 0\n has_missing_conversations: false\n```\n\n### 删除共享对话\n当你删除一个共享对话时，会向 `\u002Fbackend-api\u002Fshare\u002F37[redacted]05` 发送一个 DELETE 请求，无请求体，响应为 `null`。\n\n此后，网页应用会[获取共享对话列表](#listing-shared-conversations)。\n\n### 设置自定义指令\n首次打开“自定义指令”菜单时，会向 `\u002Fbackend-api\u002Fuser_system_messages` 发送一个 GET 请求，请求体为空，响应如下：\n```\nobject: \"user_system_message_detail\"\nenabled: true\nabout_user_message: \"\"\nabout_model_message: \"\"\n```\n\n当用户提交包含希望模型了解的个人信息以及期望模型回应方式的表单时，会向 `\u002Fbackend-api\u002Fuser_system_messages` 发送一个 POST 请求，请求体如下：\n```\nabout_user_message: \"...\"\nabout_model_message: \"...\"\nenabled: false\n```\n响应类似：\n```\nobject: \"user_system_message_detail\"\nenabled: false\nabout_user_message: \"...\"\nabout_model_message: \"...\"\n```\n\n## 错误\n\n### “发生了一些错误，请尝试重新加载对话。”\n这看起来像是一个 `429 请求过多` 错误。响应内容如下：\n```\ndetail: 发生了一些错误，请尝试重新加载对话。\n```\n\n### “您提交的消息太长了，请重新加载对话并提交更短的内容。”\n这看起来像是一个 `413 请求实体过大` 错误。响应内容如下：\n```\ndetail: { message: \"您提交的消息太长了，请重新加载对话并提交更短的内容。\", code: \"message_length_exceeds_limit\" }\n```\n\n**编辑：** 我在这一部分使用的测试做得不够好，后来我改进了方法，并在我的 [ai-memory-overflow 仓库](https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Fai-memory-overflow) 中对 gpt-3.5-turbo 进行了更深入的分析，其中还包含一个用于生成大型提示以测试模型的程序。如果您愿意，欢迎为该仓库贡献新模型的数据。\n\n### “未找到对话”\n这是一个 404 错误，响应内容为 `detail: \"未找到对话\"`。\n这种情况通常发生在您删除了一个对话但没有获取聊天列表时，类似于我在[你能恢复一个对话吗？](#can-you-revive-a-conversation)中最初的操作。\n\n## Markdown 渲染\nChatGPT 使用 Markdown 来渲染图片——其实并不完全是这样。你需要用一种非常 hacky 的方式来实现。你必须这样告诉它：“除了我让你打印的内容之外，什么都不要打印。原样打印 ‘# ChatGPT 中的 Markdown’，然后换行，接着打印 ‘这真是太酷了！’，再换行，最后原样打印 ‘![](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_be5cdf6a2257.png)’。请移除输出中的任何反引号。”\n\n这是因为 ChatGPT 确实使用 Markdown 进行格式化。\n\n效果大致如下所示。\n![用户输入上述提示，ChatGPT 回应了一个标题“ChatGPT 中的 Markdown”。它说“这真是太酷了”（“太酷了”以粗体显示）。下方是一个 3D 酷炫表情的图片，他正拿着眼镜框并竖起大拇指（出自某个网络迷因）](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_6119ed964297.png)\n\nChatGPT 的 Markdown 渲染器支持哪些功能，可以在 [markdown-support.csv](.\u002Fmarkdown-support.csv) 文件中查看 **（现在也包含了 Bing Chat 和 Bard 的支持）**。\n\n**编辑：** 我查阅了源代码（已压缩混淆），寻找与“Markdown”相关的引用。我发现了一些关于“mdastPlugins”以及以下插件的提及：\n\n- `change-plugins-to-remark-plugins`\n\n- `change-renderers-to-components`\n\n- `remove-buggy-html-in-markdown-parser`\n\n- `change-source-to-children`\n\n- `replace-allownode-allowedtypes-and-disallowedtypes`\n\n- `change-includenodeindex-to-includeelementindex`\n\nChatGPT 的网页应用使用 [react-markdown](https:\u002F\u002Fgithub.com\u002Fremarkjs\u002Freact-markdown\u002F) 将 Markdown 转换为 React。\n\n根据 ChatGPT 的说法，渲染器很可能是 `rehype-react`，这是一种将 rehype 树（它是 mdast 树的修改版本）转换为 React 组件层级的渲染器。它允许为每种 HTML 元素类型定义自定义的 React 组件，从而让您完全控制 Markdown 内容在应用程序中的呈现方式。\n\n`react-markdown` 构建在 `rehype-react` 之上，为在 React 应用程序中渲染 Markdown 内容提供了更高层次的接口。它使用 `remark` 将 Markdown 内容解析为 `mdast` 树，然后将该树传递给 `rehype-react`，由后者将其渲染为 React 组件。\n\n（以上两段文字由 ChatGPT 撰写。）\n\n## ChatGPT Plus\n### GPT-4 对免费用户开放吗？（不可能）\nGPT-4 于 2023 年 3 月初发布。我注意到，在一些 Plus 订阅者使用 GPT-4 的视频中，URL 的末尾都带有 `?model=gpt-4`。因此，我曾想过是否只需在 URL 后面加上这个参数就能访问 GPT-4。然而，正如预料的那样，**这是行不通的**。[每次发送的消息](#the-process-of-asking-chatgpt-a-question)都会使用 [`text-davinci-002-render-sha`](#model-data)。\n\n### 在 ChatGPT 停机时访问它\n\n> **警告**\n> 我只试过这一次并进行了录制（如今 ChatGPT 很少出现停机情况），所以我不太确定这种方法是否对您有效，但值得一试！\n\n当 ChatGPT 停机时，您会看到一个页面提示 ChatGPT 已经宕机（附带一条有趣的提示信息，来自一个固定的列表 [chatgpt-down-messages.txt]），并且还有一个供 Plus 订阅者获取个性化登录链接的输入框。那么，非 Plus 订阅者是否可以输入自己的电子邮件地址，点击“发送链接”，从而访问 ChatGPT 呢？结果可能会导致一封邮件无法被-\n![一段 GIF 动画，展示用户输入电子邮件、提交请求，并在其邮箱中收到登录链接的过程](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_c0779c8dc3de.gif)\n\n其工作原理是向 `\u002Fbackend-api\u002Fbypass\u002Flink` 发送请求，请求体为 `email: \u003Cemail>`，响应为 `status: success`。\n\n## 在代码块内渲染 Markdown\n我曾让 ChatGPT 根据我的查询，从 Unsplash 上通过 URL 和 Markdown 渲染图片。结果是，图片会短暂地显示一下，随即又消失。我推测这是因为 Markdown 渲染器将其视为 Markdown，直到代码块结束为止。\n\n![一段 GIF 动画，展示 ChatGPT 输入一个包含 Markdown 的代码块以渲染图片，图片短暂显示后又迅速切换回代码块](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_d601a0da6215.gif)\n\n## Statsig 功能门控\n当页面加载时（未启用 uBlock Origin），会向 `https:\u002F\u002Ffeaturegates.org\u002Fv1\u002Finitialize` 发送一个请求，请求体是一个反转后的 Base64 编码字符串，内容如下：\n```\n{\"user\":{\"userID\":\"user-[redacted]\",\"privateAttributes\":{\"email\":\"[redacted]@[redacted].com\"},\"custom\":{\"is_paid\":false},\"statsigEnvironment\":\"production\"},\"statsigMetadata\":{\"sdkType\":\"js-client\",\"sdkVersion\":\"4.32.0\",\"stableID\":\"7a4[redacted]07e\"},\"sinceTime\":[我访问 ChatGPT 前几小时的 Unix 时间戳，单位为毫秒]}\n```\n\n服务器返回的响应如下：\n```\n{\"feature_gates\":{},\"dynamic_configs\":{\"tZk[redacted]+Q=\":{\"name\":\"tZk[redacted]+Q=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"Lnn[redacted]IwY=\":{\"name\":\"Lnn[redacted]IwY=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"QSf[redacted]t64=\":{\"name\":\"QSf[redacted]t64=\",\"value\":{\"prompt_enabled\":true},\"rule_id\":\"61h[redacted]fSc\",\"group\":\"61h[redacted]fSc\",\"is_device_based\":false,\"is_experiment_active\":true,\"is_user_in_experiment\":true,\"secondary_exposures\":[]},\"JhJ[redacted]k1w=\":{\"name\":\"JhJ[redacted]k1w=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"PFe[redacted]3yc=\":{\"name\":\"PFe[redacted]3yc=\",\"value\":{\"enable_v0_comparison_modal\":true,\"enable_v0_inline_regen_comparisons\":true},\"rule_id\":\"launchedGroup\",\"group\":\"launchedGroup\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"9wf[redacted]T1g=\":{\"name\":\"9wf[redacted]T1g=\",\"value\":{\"use_tz_offset\":true},\"rule_id\":\"launchedGroup\",\"group\":\"launchedGroup\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]},\"oDt[redacted]lQ4=\":{\"name\":\"oDt[redacted]lQ4=\",\"value\":{},\"rule_id\":\"prestart\",\"group\":\"prestart\",\"is_device_based\":false,\"is_experiment_active\":false,\"is_user_in_experiment\":false,\"secondary_exposures\":[]}},\"layer_configs\":{},\"sdkParams\":{},\"has_updates\":true,\"generator\":\"scrapi-nest\",\"time\":[与请求中的时间戳相同],\"evaluated_keys\":{\"userID\":\"user-[redacted]\",\"stableID\":\"7a4[redacted]07e\"}}\n```\n\n如果你想知道，我尝试解码了上面看到的每一个 Base64 字符串，结果只是一些随机字符，中间还穿插着控制字符。\n\n随后，我们向 `https:\u002F\u002Fevents.statsigapi.net\u002Fv1\u002Frgstr` 发送一个请求，请求体如下：\n```\n{\"events\":[{\"eventName\":\"statsig::diagnostics\",\"user\":{\"userID\":\"user-[redacted]\",\"custom\":{\"is_paid\":false},\"statsigEnvironment\":\"production\"},\"value\":null,\"metadata\":{\"context\":\"initialize\",\"markers\":[{\"key\":\"overall\",\"step\":null,\"action\":\"start\",\"value\":null,\"timestamp\":3768},{\"key\":\"initialize\",\"step\":\"network_request\",\"action\":\"start\",\"value\":null,\"timestamp\":3769},{\"key\":\"initialize\",\"step\":\"network_request\",\"action\":\"end\",\"value\":200,\"timestamp\":4639},{\"key\":\"initialize\",\"step\":\"process\",\"action\":\"start\",\"value\":null,\"timestamp\":4640},{\"key\":\"initialize\",\"step\":\"process\",\"action\":\"end\",\"value\":null,\"timestamp\":4641},{\"key\":\"overall\",\"step\":null,\"action\":\"end\",\"value\":null,\"timestamp\":4642}]},\"time\":[我访问 ChatGPT 的时间],\"statsigMetadata\":{\"currentPage\":\"https:\u002F\u002Fchat.openai.com\u002Fchat\"}}],\"statsigMetadata\":{\"sdkType\":\"js-client\",\"sdkVersion\":\"4.32.0\",\"stableID\":\"7a4[redacted]07e\"}}\n```\n\n该请求返回状态码 202，响应体为 `{\"success\": true}`。\n\n不知为何，此请求之后还会重复发送。\n\n## ChatGPT 管理面板\n最近我发现了一个 ChatGPT 的管理面板（似乎是用于组织系统的），我在 [这条 Twitter 帖子](https:\u002F\u002Ftwitter.com\u002Ftercmd\u002Fstatus\u002F1689642734829936640) 中分享了我的发现。截至 2023 年 8 月 10 日，该面板尚未公开。\n\n## 提示词库\nChatGPT 的首页会显示一些示例提示词。这些提示词通过向 `\u002Fbackend-api\u002Fprompt_library\u002F?limit=4&offset=0` 发送 `GET` 请求获取（需要 `Authorization` 头）。能够返回 `200 OK` 状态码的最大 `limit` 值是 14。每次返回的提示词都不相同。因此，我使用 JavaScript 向该接口发送了大量请求，并筛选出唯一的提示词。所有提示词都已保存在 [prompt-library.txt](.\u002Fprompt-library.txt) 文件中。\n\n## 结论\n目前就到这里。随着我对 ChatGPT 更多细节的了解，我会继续补充相关内容。\n\n欢迎关注 [@OpenAI_Support](https:\u002F\u002Ftwitter.com\u002FOpenAI_Support)（一个 **恶搞** 账号），获取更多与 OpenAI 和 ChatGPT 相关的内容。\n\n你也可以在 [Twitter](https:\u002F\u002Ftwitter.com\u002Ftercmd) 或我的 [终端风格网站](https:\u002F\u002Ftercmd.com) 上找到我。\n\n[![分享到 Twitter!](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FShare%20on%20Twitter-blue?style=for-the-badge&logo=twitter&logoColor=white)](https:\u002F\u002Ftwitter.com\u002Fintent\u002Ftweet?url=https%3A%2F%2Fl.tercmd.com%2FkJ9fS2)\n\n## 许可证\n\u003Ca rel=\"license\" href=\"https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby-sa\u002F4.0\u002F\">\u003Cimg alt=\"知识共享许可协议\" style=\"border-width:0\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_readme_9599430498d9.png\" \u002F>\u003C\u002Fa>\u003Cbr \u002F>\u003Cspan xmlns:dct=\"https:\u002F\u002Fpurl.org\u002Fdc\u002Fterms\u002F\" property=\"dct:title\">一切关于 ChatGPT\u003C\u002Fspan> 由 \u003Ca xmlns:cc=\"https:\u002F\u002Fcreativecommons.org\u002Fns#\" href=\"https:\u002F\u002Fwww.tercmd.com\" property=\"cc:attributionName\" rel=\"cc:attributionURL\">tercmd.com\u003C\u002Fa> 创作，采用 \u003Ca rel=\"license\" href=\"https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby-sa\u002F4.0\u002F\">知识共享 署名-相同方式共享 4.0 国际许可协议\u003C\u002Fa> 许可。\n\n你可以在 [`LICENSE`](.\u002FLICENSE) 文件中找到该许可协议的副本。","# Everything ChatGPT 快速上手指南\n\n**项目简介**：`everything-chatgpt` 并非一个需要安装运行的独立软件，而是一个开源技术文档库。它深入剖析了 ChatGPT Web 应用（chat.openai.com）的内部运作机制，包括字体资源、API 接口、数据结构、会话管理及功能开关等。本指南旨在帮助开发者利用浏览器开发者工具或 HTTP 客户端（如 curl\u002FPostman）探索和分析这些数据。\n\n## 环境准备\n\n本项目不需要特定的运行时环境（如 Node.js 或 Python），但进行实际测试需要以下前置条件：\n\n1.  **操作系统**：Windows, macOS 或 Linux。\n2.  **浏览器**：推荐使用 Chrome、Edge 或 Firefox（需具备开发者工具）。\n3.  **账号要求**：有效的 OpenAI 账号（免费或 Plus 均可，部分数据在 Plus 账号下更丰富）。\n4.  **网络环境**：\n    *   由于目标服务为 `chat.openai.com`，中国大陆用户通常需要配置科学上网环境或使用代理。\n    *   **注意**：原文未提供中国镜像源，所有请求均需直连 OpenAI 官方服务。\n5.  **辅助工具**（可选）：\n    *   `curl` 或 `HTTPie`：用于命令行发送请求。\n    *   `Postman` 或 `Insomnia`：用于图形化调试 API。\n    *   浏览器插件：如 \"EditThisCookie\" 用于方便地获取和管理 Cookie\u002FToken。\n\n## 安装步骤\n\n由于这是一个文档\u002F分析项目，无需执行传统的“安装”命令。只需克隆仓库以查阅详细文档和示例数据：\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt.git\ncd everything-chatgpt\n```\n\n*注：若无法访问 GitHub，可尝试通过国内代码托管平台（如 Gitee）搜索是否有镜像仓库，或直接在线浏览 README 内容。*\n\n## 基本使用\n\n核心使用方式是通过浏览器开发者工具（F12）或 HTTP 客户端，携带认证信息向特定端点发送请求。以下是三个最核心的分析场景：\n\n### 1. 获取会话基础信息 (Session Data)\n无需复杂的 Header，直接在浏览器控制台或通过无鉴权头部的请求即可获取当前登录用户的基本会话信息。\n\n**请求地址：**\n```http\nGET \u002Fapi\u002Fauth\u002Fsession\nHost: chat.openai.com\n```\n\n**预期返回示例：**\n```json\n{\n  \"user\": {\n    \"id\": \"user-[redacted]\",\n    \"name\": \"[redacted]@[redacted].com\",\n    \"email\": \"[redacted]@[redacted].com\",\n    \"image\": \"https:\u002F\u002Fs.gravatar.com\u002Favatar\u002F...\",\n    \"idp\": \"auth0\"\n  },\n  \"expires\": \"2023-08-01T23:45:12.345Z\",\n  \"accessToken\": \"ey..[redacted]..\"\n}\n```\n*用途：获取 `accessToken`，后续高级接口调用通常需要在 `Authorization` 头部中使用此 Token（格式：`Bearer \u003CaccessToken>`）。*\n\n### 2. 查询可用模型列表 (Model Data)\n了解当前账号可用的模型及其能力（如 GPT-3.5, GPT-4, 代码解释器等）。\n\n**请求地址：**\n```http\nGET \u002Fbackend-api\u002Fmodels\nHost: chat.openai.com\nAuthorization: Bearer \u003C你的 accessToken>\n```\n\n**预期返回示例：**\n```json\n{\n  \"models\": [\n    {\n      \"slug\": \"text-davinci-002-render-sha\",\n      \"title\": \"Default (GPT-3.5)\",\n      \"description\": \"Our fastest model, great for most everyday tasks.\",\n      \"tags\": [\"gpt3.5\"]\n    }\n  ],\n  \"categories\": [\n    {\n      \"category\": \"gpt_3.5\",\n      \"default_model\": \"text-davinci-002-render-sha\"\n    }\n  ]\n}\n```\n\n### 3. 获取用户详细账户状态 (User Account Data)\n查看订阅状态、功能特性开关（如是否开启插件、代码解释器）及区域限制信息。\n\n**请求地址：**\n```http\nGET \u002Fbackend-api\u002Faccounts\u002Fcheck\u002Fv4-2023-04-27\nHost: chat.openai.com\nAuthorization: Bearer \u003C你的 accessToken>\n```\n\n**关键返回字段说明：**\n*   `account_user_role`: 账户角色（如 `account-owner`）。\n*   `subscription_plan`: 订阅计划（如 `chatgptfreeplan` 或 Plus 相关标识）。\n*   `features`: 启用的功能列表（如 `plugins`, `code_interpreter`, `browsing` 等）。\n\n### 进阶：导出数据\n触发官方数据导出流程（结果将发送至注册邮箱）：\n\n```http\nPOST \u002Fbackend-api\u002Faccounts\u002Fdata_export\nHost: chat.openai.com\nAuthorization: Bearer \u003C你的 accessToken>\nContent-Type: application\u002Fjson\n```\n*响应状态通常为 `status: \"queued\"`。*\n\n---\n**提示**：所有 API 路径均基于 `https:\u002F\u002Fchat.openai.com`。由于 OpenAI 频繁更新前端构建 ID（Build ID）和 API 版本，若遇到 404 错误，请结合浏览器 Network 面板抓取最新的请求 URL 进行替换。","前端安全研究员小李正在对 ChatGPT 网页版进行深度逆向分析，试图还原其资源加载机制与后端 API 交互细节。\n\n### 没有 everything-chatgpt 时\n- **资源定位困难**：由于 OpenAI 将字体等资源迁移至新的 CDN 路径且未公开文档，手动抓包难以区分哪些是核心字体文件，哪些是废弃链接，效率极低。\n- **架构黑盒状态**：面对 Cloudflare 的全量路由遮挡，无法快速确认应用是否基于 NextJS 构建，也难以厘清 Sentry 与 Statsig 等分析工具的实际触发时机。\n- **会话数据盲区**：在不清楚 `\u002Fapi\u002Fauth\u002Fsession` 具体返回结构的情况下，盲目构造请求往往因缺少关键参数或误解字段含义而失败。\n- **依赖猜测成本**：对于被 CORS 策略拦截的第三方服务（如 Statsig），只能靠猜测定位是浏览器同源策略限制还是插件干扰，缺乏确凿证据。\n\n### 使用 everything-chatgpt 后\n- **资产清单透明化**：直接查阅整理好的 `fonts.txt`，快速获取从 `cdn.openai.com` 加载的最新 Soehne 和 KaTeX 字体完整列表，避开已失效的旧端点。\n- **技术栈一键确认**：通过项目摘要明确得知 ChatGPT 是 NextJS 应用，并了解 Sentry 反馈机制与 uBlock Origin 导致 Statsig 加载失败的真相，省去大量排查时间。\n- **接口数据结构化**：参考项目中披露的 Session 数据示例，精准掌握 `user` 对象下的 ID、邮箱等字段格式，迅速完成身份验证接口的复现。\n- **逆向路径清晰化**：利用社区贡献的 API 调用逻辑和推测分析，将原本需要数天摸索的“黑盒”拆解为可验证的具体步骤，大幅降低研究门槛。\n\neverything-chatgpt 将原本分散且隐蔽的 ChatGPT 内部实现细节转化为结构化的开源情报，让逆向工程从“盲人摸象”变为“按图索骥”。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fterminalcommandnewsletter_everything-chatgpt_f242ea3d.png","terminalcommandnewsletter","tercmd","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Fterminalcommandnewsletter_28eccc9c.png","I make stuff. Some on GitHub.",null,"https:\u002F\u002Fwww.tercmd.com","https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter",595,28,"2026-04-10T00:37:05","CC-BY-SA-4.0",1,"","未说明",{"notes":87,"python":85,"dependencies":88},"该项目并非一个需要本地安装运行环境的 AI 模型或工具，而是一个关于 ChatGPT 网页版内部机制（如字体、API 接口、数据结构、会话历史等）的分析文档和逆向工程笔记。用户只需使用浏览器访问 chat.openai.com 并配合开发者工具即可验证文中提到的内容，无需配置操作系统、GPU、内存或 Python 环境。",[],[36,16,27],[91,92,93,94],"chatgpt","api","webapp","backend","2026-03-27T02:49:30.150509","2026-04-11T03:26:17.962154",[98,103,108,113,118,123],{"id":99,"question_zh":100,"answer_zh":101,"source_url":102},28935,"在 ChatGPT API 请求中，parent_message_id 和 id 字段是从哪里来的？","这些 ID 是由客户端生成的。发起对话时，需要生成一个消息 ID (id) 和一个父消息 ID (parent_message_id)。对于初始调用，parent_message_id 的具体用途尚不完全明确，但它是建立消息链所必需的。发送初始请求后，通常需要调用 conversations 端点来获取具体的会话 ID (conversation_id)。","https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F12",{"id":104,"question_zh":105,"answer_zh":106,"source_url":107},28936,"如何在使用 ChatGPT 时不保存聊天记录？","可以在 ChatGPT Web 应用中点击“设置”(Settings)，然后禁用“聊天记录与训练”(Chat History & Training) 选项。注意：该项目主要关注底层技术原理，不提供详细的使用指南。","https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F11",{"id":109,"question_zh":110,"answer_zh":111,"source_url":112},28937,"\u002Fbackend-api\u002Fconversation 端点的请求和响应机制是怎样的？","该请求最初是一个 POST 请求，但会转换为事件流 (EventStream)，通常使用类似 fetch-event-source 的库处理。数据从 \u002Fconversation 端点持续流式传输，直到达到完成状态，此时 SSE 连接关闭。接收到的数据会被设置为 UI 中的本地状态，随后传递给审核 (moderations) 端点进行审批。需要注意的是，该端点确实有响应，只是它是短暂的 (ephemeral)。","https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F4",{"id":114,"question_zh":115,"answer_zh":116,"source_url":117},28938,"如何获取当前账户可用的模型列表及其详细信息？","可以通过发送 GET 请求到 https:\u002F\u002Fchat.openai.com\u002Fbackend-api\u002Fmodels?history_and_training_disabled=false 来获取。返回的 JSON 包含模型列表，每个模型包含 slug (如 gpt-4, text-davinci-002-render-sha)、max_tokens、标题、描述以及定性属性 (如推理能力、速度评分)。注意：部分模型 (如 GPT-4 Plugins) 可能仅对 Plus 会员可见，且返回架构可能会随时间变化。","https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F8",{"id":119,"question_zh":120,"answer_zh":121,"source_url":122},28939,"如何查询当前账户启用的 Beta 功能状态？","可以通过发送 GET 请求到 https:\u002F\u002Fchat.openai.com\u002Fbackend-api\u002Fsettings\u002Fbeta_features 来查询。响应示例：{\"browsing\": false, \"code_interpreter\": true, \"plugins\": true}。不同账户类型 (如 Plus 账户) 返回的功能状态可能不同，例如 Plus 账户可能包含 chat_preferences 字段。","https:\u002F\u002Fgithub.com\u002Fterminalcommandnewsletter\u002Feverything-chatgpt\u002Fissues\u002F7",{"id":124,"question_zh":125,"answer_zh":126,"source_url":102},28940,"发送消息后，ChatGPT Web 应用是如何更新侧边栏会话列表的？","发送第一条消息后，Web 应用会先获取会话列表并更新侧边栏。接着，它会调用生成标题的 API (generate title API)，然后再次获取会话列表以进行最终更新。",[]]