@wlv-zedd/dsh-chatgpt-web 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,15 +1,22 @@
1
1
  # dsh-chatgpt-web
2
2
 
3
- [English](https://github.com/WLV-ZEDD/dsh-chatgpt-web#readme) | [中文](https://github.com/WLV-ZEDD/dsh-chatgpt-web/blob/main/docs/README.zh-CN.md)
3
+ [English](https://github.com/WLV-ZEDD/dsh-chatgpt-web#readme) | [中文](./README.zh-CN.md)
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@wlv-zedd/dsh-chatgpt-web.svg?style=flat&color=3b82f6)](https://www.npmjs.com/package/@wlv-zedd/dsh-chatgpt-web)
6
+ [![dsh-market](https://img.shields.io/badge/dsh--market-available-c0392b?style=flat)](https://dshmarket.com/p/WLV-ZEDD/dsh-chatgpt-web/)
6
7
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/WLV-ZEDD/dsh-chatgpt-web/blob/main/LICENSE)
7
8
  [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek%20Harness-Cordis%20Plugin-0078d4)](https://github.com/deepseek-ai/deepseek-harness)
8
9
  [![Mode](https://img.shields.io/badge/Mode-Pure%20Chat%20%26%20Markdown-success)](https://github.com/WLV-ZEDD/dsh-chatgpt-web)
9
10
 
10
11
  > **Zero-cost conversational AI model provider for DeepSeek Harness powered by free ChatGPT Web (GPT 5.6 Luna).**
11
12
 
12
- ![dsh-chatgpt-web Interactive Demo](https://raw.githubusercontent.com/WLV-ZEDD/dsh-chatgpt-web/main/assets/demo.gif?v=1.0.0)
13
+ <p align="center">
14
+ <img src="https://raw.githubusercontent.com/WLV-ZEDD/dsh-chatgpt-web/main/assets/promo-dshmarket-official.png?v=1.0.2" alt="dsh-chatgpt-web on DSH Market" width="100%">
15
+ </p>
16
+
17
+ <p align="center">
18
+ <img src="https://raw.githubusercontent.com/WLV-ZEDD/dsh-chatgpt-web/main/assets/demo.gif?v=1.0.0" alt="dsh-chatgpt-web Interactive Demo" width="100%">
19
+ </p>
13
20
 
14
21
  ---
15
22
 
@@ -0,0 +1,147 @@
1
+ # dsh-chatgpt-web
2
+
3
+ [English](./README.md) | [中文](./README.zh-CN.md)
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@wlv-zedd/dsh-chatgpt-web.svg?style=flat&color=3b82f6)](https://www.npmjs.com/package/@wlv-zedd/dsh-chatgpt-web)
6
+ [![dsh-market](https://img.shields.io/badge/dsh--market-available-c0392b?style=flat)](https://dshmarket.com/p/WLV-ZEDD/dsh-chatgpt-web/)
7
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/WLV-ZEDD/dsh-chatgpt-web/blob/main/LICENSE)
8
+ [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek%20Harness-Cordis%20Plugin-0078d4)](https://github.com/deepseek-ai/deepseek-harness)
9
+ [![Mode](https://img.shields.io/badge/Mode-Pure%20Chat%20%26%20Markdown-success)](https://github.com/WLV-ZEDD/dsh-chatgpt-web)
10
+
11
+ > **基于免费 ChatGPT Web(GPT 5.6 Luna)驱动的 DeepSeek Harness 零成本对话 AI 模型提供者。**
12
+
13
+ <p align="center">
14
+ <img src="https://raw.githubusercontent.com/WLV-ZEDD/dsh-chatgpt-web/main/assets/promo-dshmarket-official.png?v=1.0.2" alt="dsh-chatgpt-web DSH Market 官方海报" width="100%">
15
+ </p>
16
+
17
+ <p align="center">
18
+ <img src="https://raw.githubusercontent.com/WLV-ZEDD/dsh-chatgpt-web/main/assets/demo.gif?v=1.0.0" alt="dsh-chatgpt-web 交互演示" width="100%">
19
+ </p>
20
+
21
+ ---
22
+
23
+ ## 概述
24
+
25
+ **dsh-chatgpt-web** 将你本地的 ChatGPT 浏览器会话转变为 DeepSeek Harness (DSH) 内部无缝运行的 **$0.00 免 API 费用的对话模型提供者**。
26
+
27
+ 它通过无头(Headless)或可视 Chrome 浏览器自动化连接至 `chatgpt.com`,将实时的 Markdown 回答、代码方案、解释以及推理过程直接流式传输回 DSH 对话中,无需消耗任何 API 额度。
28
+
29
+ ### 为什么选择纯对话模式(Pure Chat)?
30
+ 轻量级对话网页模型(如 GPT 5.6 Luna)非常擅长解释、对话、问答、头脑风暴、代码片段生成以及侧边助手任务。通过运行在 **纯对话模式** 下,该桥接器消除了提示词开销、工具幻觉以及自主多工具循环中的语法错误,提供快速、稳定且零成本的 LLM 提供者。
31
+
32
+ ### 核心功能
33
+ - **100% 完全免费($0.00 成本):** 使用你现有的免费 ChatGPT 网页会话,无需 OpenAI API Key 或信用卡。
34
+ - **Cordis 插件优先生命周期:** 由 DSH 通过 `ctx.effect` 无缝管理。DeepSeek Harness 在启动时自动拉起后台 Sidecar 进程,并在退出时安全关闭。
35
+ - **动态模型自动检测:** 自动检测你的 ChatGPT 账户等级:
36
+ - **免费账户:** 默认为 `chatgpt-web/luna` (`gpt-5-6-luna`)。
37
+ - **Plus / Team 账户:** 自动检测并暴露可用的付费模型(如 `gpt-4o`, `o1`)。
38
+ - **完整流式 Markdown 与代码块:** 实时向 DSH Web UI 或 CLI 投递生成的内容。
39
+
40
+ ---
41
+
42
+ ## 快速上手
43
+
44
+ ### 1. 安装插件
45
+
46
+ 在你的 DeepSeek Harness 环境或配置文件中安装 `@wlv-zedd/dsh-chatgpt-web`:
47
+
48
+ ```bash
49
+ pnpm add @wlv-zedd/dsh-chatgpt-web
50
+ ```
51
+
52
+ ### 2. 一次性浏览器登录
53
+
54
+ 进行一次性的 ChatGPT 账号登录验证:
55
+
56
+ ```bash
57
+ npx @wlv-zedd/dsh-chatgpt-web login
58
+ ```
59
+
60
+ 系统将打开专用的 Chrome 窗口。登录你的 OpenAI / ChatGPT 账号。一旦看到 ChatGPT 输入框,浏览器会话凭证将安全保存在本地的 `~/.dsh/storages/chatgpt-web/` 目录中。
61
+
62
+ ### 3. 在 DeepSeek Harness 中启用
63
+
64
+ 将提供者配置添加到你的 `~/.dsh/settings.yaml` 中:
65
+
66
+ ```yaml
67
+ providers:
68
+ chatgpt-web:
69
+ displayName: "ChatGPT Web (Free)"
70
+ api: openai-responses
71
+ baseURL: http://127.0.0.1:17841/v1
72
+ headers:
73
+ Authorization: "Bearer chatgpt-web-free"
74
+ streamIdleTimeoutMs: 300000
75
+ models:
76
+ - id: chatgpt-web/luna
77
+ name: "ChatGPT Web — Luna (Free)"
78
+ contextWindow: 1050000
79
+ maxTokens: 32768
80
+ input:
81
+ - text
82
+ - image
83
+
84
+ agent-default-model:
85
+ provider: chatgpt-web
86
+ model: chatgpt-web/luna
87
+ ```
88
+
89
+ 并在 profile 的 `cordis.patch.yml`(或 `cordis.yml`)中添加 Sidecar 插件:
90
+
91
+ ```yaml
92
+ - insert:
93
+ - id: dsh-chatgpt-web
94
+ name: '@wlv-zedd/dsh-chatgpt-web'
95
+ ```
96
+
97
+ 现在启动 DeepSeek Harness:
98
+
99
+ ```bash
100
+ pnpm dsh web
101
+ ```
102
+
103
+ DSH 将自动启动后台 Sidecar 进程,连接已登录的 ChatGPT 会话并开始处理提问!
104
+
105
+ ---
106
+
107
+ ## 诊断与健康检查
108
+
109
+ 随时使用内置的诊断工具检查环境配置:
110
+
111
+ ```bash
112
+ npx @wlv-zedd/dsh-chatgpt-web doctor
113
+ ```
114
+
115
+ 正常输出示例:
116
+ ```text
117
+ ✓ Configuration is valid (~/.dsh/storages/chatgpt-web/config.json)
118
+ ✓ Chrome executable found: C:\Program Files\Google\Chrome\Application\chrome.exe
119
+ ✓ ChatGPT login state has authenticated browser evidence
120
+ ✓ Responses proxy is healthy on 127.0.0.1:17841
121
+ Doctor result: ready
122
+ ```
123
+
124
+ ---
125
+
126
+ ## 注意事项与使用限制
127
+
128
+ 1. **非官方桥接:** 通过本地 Playwright 自动化驱动 `chatgpt.com` 网页。与 OpenAI 官方无隶属或背书关系。
129
+ 2. **单会话并发:** 运行在单个浏览器标签页中。顺序查询和正常的 DSH 智能体对话完全顺畅;请避免同时对同一标签页发起多个高并发子智能体任务。
130
+ 3. **纯对话支持:** 该提供者专注于纯对话回复、解释、推理以及代码块生成。不支持执行本地文件系统、终端命令或自主工具循环。
131
+ 4. **免费额度频率限制:** 遵循 OpenAI 官方网页免费版的小时级调用频次限制。
132
+
133
+ ---
134
+
135
+ ## 支持与社区福利
136
+
137
+ [![Sponsor via PayPal](https://img.shields.io/badge/Sponsor-PayPal-0070ba?style=flat&logo=paypal&logoColor=white)](https://paypal.me/wlvzedd) 如果你觉得本插件对你有帮助,欢迎赞助支持。
138
+
139
+ [![Free AI Credits on AgentRouter](https://img.shields.io/badge/Free%20AI%20Credits-%24200-ff6b35?style=flat&logoColor=white)](https://agentrouter.org/register?aff=bIJf) GitHub 注册 AgentRouter 即可领取最高 **$200 免费额度**。
140
+
141
+ [![Free AI Credits on Vyce AI](https://img.shields.io/badge/Free%20AI%20Credits-%2450-7c3aed?style=flat&logoColor=white)](https://vyceai.com/signup?ref=VYCE_BL6YAG) 注册 Vyce AI 即可领取 **$50 免费额度**。
142
+
143
+ ---
144
+
145
+ ## 开源协议
146
+
147
+ MIT License © 2026 [WLV-ZEDD](https://github.com/WLV-ZEDD)。DeepSeek Harness 是 DeepSeek AI 的开源项目。
package/lib/cli.js CHANGED
@@ -203664,7 +203664,7 @@ function requireChatGptWebModelRoute(modelId, capabilities) {
203664
203664
  }
203665
203665
 
203666
203666
  // src/version.ts
203667
- var VERSION2 = "1.0.2";
203667
+ var VERSION2 = "1.0.3";
203668
203668
 
203669
203669
  // src/config.ts
203670
203670
  var CHATGPT_CONNECTOR_NAME = "Codex Native2";
@@ -224989,12 +224989,34 @@ turndown.addRule("removeMapAndWidgets", {
224989
224989
  if (/map|carousel|place-card|places|location-card|poi-/i.test(testId) || /map/i.test(ariaLabel) || /mapbox|leaflet|map-container|places-carousel|place-card/i.test(className)) {
224990
224990
  return true;
224991
224991
  }
224992
+ const text2 = el.textContent?.trim() || "";
224992
224993
  if (el.children?.length === 0) {
224993
- const text2 = el.textContent?.trim() || "";
224994
224994
  if (/Use two fingers to move the map|Hold Ctrl to zoom|Map data|Report a map error/i.test(text2)) {
224995
224995
  return true;
224996
224996
  }
224997
224997
  }
224998
+ if (/^\d+$/.test(text2)) {
224999
+ let insideListOrCode = false;
225000
+ for (let cur = el;cur; cur = cur.parentNode) {
225001
+ const tag = cur.nodeName?.toUpperCase();
225002
+ if (tag === "OL" || tag === "LI" || tag === "PRE" || tag === "CODE" || /^H[1-6]$/.test(tag)) {
225003
+ insideListOrCode = true;
225004
+ break;
225005
+ }
225006
+ }
225007
+ if (!insideListOrCode) {
225008
+ const tag = el.nodeName?.toLowerCase();
225009
+ if (["div", "p", "section"].includes(tag)) {
225010
+ return true;
225011
+ }
225012
+ if (tag === "span") {
225013
+ const parentText = el.parentNode?.textContent?.trim();
225014
+ if (!parentText || parentText === text2) {
225015
+ return true;
225016
+ }
225017
+ }
225018
+ }
225019
+ }
224998
225020
  return false;
224999
225021
  },
225000
225022
  replacement: () => ""
@@ -225113,10 +225135,26 @@ function restoreToolCallTags(markdown) {
225113
225135
  function cleanCitationBadges(markdown) {
225114
225136
  return markdown.replace(/\[([^\]]+?)\s*\+\d+\]\((https?:\/\/[^)]+)\)/g, "[$1]($2)");
225115
225137
  }
225138
+ function stripOrphanDigitBlocks(markdown) {
225139
+ if (!markdown.includes("```")) {
225140
+ return markdown.replace(/(?:^|\n\n)\d+(?=\n\n|$)/g, "").replace(/\n{3,}/g, `
225141
+
225142
+ `).trim();
225143
+ }
225144
+ const parts = markdown.split(/(```[\s\S]*?```)/g);
225145
+ return parts.map((part, index) => {
225146
+ if (index % 2 === 1)
225147
+ return part;
225148
+ return part.replace(/(?:^|\n\n)\d+(?=\n\n|$)/g, "");
225149
+ }).join("").replace(/\n{3,}/g, `
225150
+
225151
+ `).trim();
225152
+ }
225116
225153
  function chatGptHtmlToMarkdown(html) {
225117
225154
  if (!html.trim())
225118
225155
  return "";
225119
- return cleanCitationBadges(restoreToolCallTags(linkObsidianWikiLinks(preserveObsidianWikiLinks(turndown.turndown(html))))).trim();
225156
+ const cleaned = cleanCitationBadges(restoreToolCallTags(linkObsidianWikiLinks(preserveObsidianWikiLinks(turndown.turndown(html))))).trim();
225157
+ return stripOrphanDigitBlocks(cleaned);
225120
225158
  }
225121
225159
 
225122
225160
  class ChatGptMarkdownConsistencyError extends Error {
@@ -230744,13 +230782,19 @@ class ChatGptBrowserWorker {
230744
230782
  }
230745
230783
  if (candidate.tagName.toLowerCase() === "canvas")
230746
230784
  return true;
230785
+ const text2 = candidate.textContent?.trim() || "";
230747
230786
  if (candidate.children.length === 0) {
230748
- const text2 = candidate.textContent?.trim() || "";
230749
230787
  if (/Use two fingers to move the map|Hold Ctrl to zoom|Map data|Report a map error/i.test(text2)) {
230750
230788
  return true;
230751
230789
  }
230752
- if (/^\d+$/.test(text2) && candidate.tagName.toLowerCase() === "span") {
230753
- return true;
230790
+ }
230791
+ if (/^\d+$/.test(text2)) {
230792
+ const tag = candidate.tagName.toLowerCase();
230793
+ if (["div", "span", "p", "section"].includes(tag)) {
230794
+ const isSafeContext = candidate.closest?.("ol, li, pre, code, h1, h2, h3, h4, h5, h6");
230795
+ if (!isSafeContext) {
230796
+ return true;
230797
+ }
230754
230798
  }
230755
230799
  }
230756
230800
  return false;
@@ -230818,6 +230862,9 @@ class ChatGptBrowserWorker {
230818
230862
  const childRange = sourceRange(child);
230819
230863
  const listItems = tag === "ol" || tag === "ul" ? [...child.children].filter((candidate) => candidate.tagName === "LI") : [];
230820
230864
  if (listItems.length === 0) {
230865
+ if (tag !== "li" && /^\d+$/.test(child.innerText?.trim() ?? "")) {
230866
+ return;
230867
+ }
230821
230868
  flattenedMarkdownSegments.push({
230822
230869
  tag,
230823
230870
  html: child.outerHTML,
@@ -238630,7 +238677,7 @@ async function uninstallTunnelService2() {
238630
238677
  }
238631
238678
 
238632
238679
  // src/version.ts
238633
- var VERSION3 = "1.0.2";
238680
+ var VERSION3 = "1.0.3";
238634
238681
 
238635
238682
  // src/dev-chat/cli.ts
238636
238683
  import { createInterface as createInterface2 } from "node:readline/promises";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wlv-zedd/dsh-chatgpt-web",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "DeepSeek Harness Cordis plugin for free ChatGPT Web (GPT 5.6 Luna) pure chat and zero API fees.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -3693,13 +3693,19 @@ export class ChatGptBrowserWorker {
3693
3693
  return true;
3694
3694
  }
3695
3695
  if (candidate.tagName.toLowerCase() === "canvas") return true;
3696
+ const text = candidate.textContent?.trim() || "";
3696
3697
  if (candidate.children.length === 0) {
3697
- const text = candidate.textContent?.trim() || "";
3698
3698
  if (/Use two fingers to move the map|Hold Ctrl to zoom|Map data|Report a map error/i.test(text)) {
3699
3699
  return true;
3700
3700
  }
3701
- if (/^\d+$/.test(text) && candidate.tagName.toLowerCase() === "span") {
3702
- return true;
3701
+ }
3702
+ if (/^\d+$/.test(text)) {
3703
+ const tag = candidate.tagName.toLowerCase();
3704
+ if (["div", "span", "p", "section"].includes(tag)) {
3705
+ const isSafeContext = candidate.closest?.("ol, li, pre, code, h1, h2, h3, h4, h5, h6");
3706
+ if (!isSafeContext) {
3707
+ return true;
3708
+ }
3703
3709
  }
3704
3710
  }
3705
3711
  return false;
@@ -3784,6 +3790,9 @@ export class ChatGptBrowserWorker {
3784
3790
  ? [...child.children].filter(candidate => candidate.tagName === "LI") as HTMLElement[]
3785
3791
  : [];
3786
3792
  if (listItems.length === 0) {
3793
+ if (tag !== "li" && /^\d+$/.test(child.innerText?.trim() ?? "")) {
3794
+ return;
3795
+ }
3787
3796
  flattenedMarkdownSegments.push({
3788
3797
  tag,
3789
3798
  html: child.outerHTML,
@@ -37,13 +37,36 @@ turndown.addRule("removeMapAndWidgets", {
37
37
  return true;
38
38
  }
39
39
 
40
+ const text = el.textContent?.trim() || "";
40
41
  if (el.children?.length === 0) {
41
- const text = el.textContent?.trim() || "";
42
42
  if (/Use two fingers to move the map|Hold Ctrl to zoom|Map data|Report a map error/i.test(text)) {
43
43
  return true;
44
44
  }
45
45
  }
46
46
 
47
+ if (/^\d+$/.test(text)) {
48
+ let insideListOrCode = false;
49
+ for (let cur: Node | null = el; cur; cur = cur.parentNode) {
50
+ const tag = cur.nodeName?.toUpperCase();
51
+ if (tag === "OL" || tag === "LI" || tag === "PRE" || tag === "CODE" || /^H[1-6]$/.test(tag)) {
52
+ insideListOrCode = true;
53
+ break;
54
+ }
55
+ }
56
+ if (!insideListOrCode) {
57
+ const tag = el.nodeName?.toLowerCase();
58
+ if (["div", "p", "section"].includes(tag)) {
59
+ return true;
60
+ }
61
+ if (tag === "span") {
62
+ const parentText = el.parentNode?.textContent?.trim();
63
+ if (!parentText || parentText === text) {
64
+ return true;
65
+ }
66
+ }
67
+ }
68
+ }
69
+
47
70
  return false;
48
71
  },
49
72
  replacement: () => "",
@@ -167,11 +190,30 @@ function cleanCitationBadges(markdown: string): string {
167
190
  return markdown.replace(/\[([^\]]+?)\s*\+\d+\]\((https?:\/\/[^)]+)\)/g, "[$1]($2)");
168
191
  }
169
192
 
193
+ function stripOrphanDigitBlocks(markdown: string): string {
194
+ if (!markdown.includes("```")) {
195
+ return markdown
196
+ .replace(/(?:^|\n\n)\d+(?=\n\n|$)/g, "")
197
+ .replace(/\n{3,}/g, "\n\n")
198
+ .trim();
199
+ }
200
+ const parts = markdown.split(/(```[\s\S]*?```)/g);
201
+ return parts
202
+ .map((part, index) => {
203
+ if (index % 2 === 1) return part;
204
+ return part.replace(/(?:^|\n\n)\d+(?=\n\n|$)/g, "");
205
+ })
206
+ .join("")
207
+ .replace(/\n{3,}/g, "\n\n")
208
+ .trim();
209
+ }
210
+
170
211
  export function chatGptHtmlToMarkdown(html: string): string {
171
212
  if (!html.trim()) return "";
172
- return cleanCitationBadges(
213
+ const cleaned = cleanCitationBadges(
173
214
  restoreToolCallTags(linkObsidianWikiLinks(preserveObsidianWikiLinks(turndown.turndown(html))))
174
215
  ).trim();
216
+ return stripOrphanDigitBlocks(cleaned);
175
217
  }
176
218
 
177
219
  export interface ChatGptMarkdownSegment {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '1.0.2';
1
+ export const VERSION = '1.0.3';