@wlv-zedd/dsh-chatgpt-web 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/assets/demo.gif +0 -0
- package/assets/hero-demo.png +0 -0
- package/assets/promo-dshmarket-official.png +0 -0
- package/cordis.patch.yml +4 -0
- package/lib/cli.js +239642 -0
- package/lib/plugin.js +195 -0
- package/package.json +88 -0
- package/screenshots.json +5 -0
- package/src/adapters/base.ts +16 -0
- package/src/adapters/chatgpt-web/adapter-error.ts +59 -0
- package/src/adapters/chatgpt-web/browser-helper-main.ts +513 -0
- package/src/adapters/chatgpt-web/browser-helper-prompt-selection.ts +27 -0
- package/src/adapters/chatgpt-web/browser-worker.ts +4944 -0
- package/src/adapters/chatgpt-web/codex-rollout-environment.ts +628 -0
- package/src/adapters/chatgpt-web/compaction-handoff.ts +533 -0
- package/src/adapters/chatgpt-web/compaction-transaction.ts +142 -0
- package/src/adapters/chatgpt-web/concurrency.ts +6 -0
- package/src/adapters/chatgpt-web/conversation-key.ts +58 -0
- package/src/adapters/chatgpt-web/environment.ts +669 -0
- package/src/adapters/chatgpt-web/index.ts +1544 -0
- package/src/adapters/chatgpt-web/input-tokens.ts +74 -0
- package/src/adapters/chatgpt-web/launcher-helper-client.ts +695 -0
- package/src/adapters/chatgpt-web/markdown.ts +418 -0
- package/src/adapters/chatgpt-web/mcp-main.ts +25 -0
- package/src/adapters/chatgpt-web/mcp-server.ts +933 -0
- package/src/adapters/chatgpt-web/model.ts +70 -0
- package/src/adapters/chatgpt-web/native-compaction-control.ts +74 -0
- package/src/adapters/chatgpt-web/output-validation.ts +62 -0
- package/src/adapters/chatgpt-web/process-line-writer.ts +46 -0
- package/src/adapters/chatgpt-web/prompt.ts +702 -0
- package/src/adapters/chatgpt-web/retry-policy.ts +73 -0
- package/src/adapters/chatgpt-web/rolling-checkpoint.ts +384 -0
- package/src/adapters/chatgpt-web/thread-environment.ts +238 -0
- package/src/adapters/chatgpt-web/tool-stream-parser.ts +601 -0
- package/src/adapters/chatgpt-web/turn-broker.ts +1481 -0
- package/src/adapters/chatgpt-web/turn-execution.ts +816 -0
- package/src/adapters/chatgpt-web/turn-progress.ts +292 -0
- package/src/adapters/chatgpt-web/usage.ts +121 -0
- package/src/adapters/image.ts +9 -0
- package/src/bridge.ts +1083 -0
- package/src/browser-login.ts +521 -0
- package/src/chatgpt-session.ts +240 -0
- package/src/chatgpt-web-models.ts +400 -0
- package/src/cli.ts +568 -0
- package/src/codex-integration-document.ts +824 -0
- package/src/codex-integration-journal.ts +212 -0
- package/src/codex-integration-route.ts +515 -0
- package/src/codex-integration-shared.ts +332 -0
- package/src/codex-integration.ts +529 -0
- package/src/codex-interrupt-hook.ts +158 -0
- package/src/config.ts +616 -0
- package/src/dev-chat/cli.ts +432 -0
- package/src/dev-chat/constants.ts +3 -0
- package/src/dev-chat/driver.ts +655 -0
- package/src/dev-chat/profile.ts +223 -0
- package/src/dev-chat/session.ts +287 -0
- package/src/dev-chat/transport.ts +54 -0
- package/src/doctor.ts +237 -0
- package/src/event-queue.ts +45 -0
- package/src/http-body.ts +30 -0
- package/src/launcher-browser-host.ts +695 -0
- package/src/lib/errors.ts +281 -0
- package/src/lib/token-estimate.ts +42 -0
- package/src/login-helper.cjs +140 -0
- package/src/model-catalog.ts +197 -0
- package/src/native-passthrough.ts +261 -0
- package/src/plugin.ts +191 -0
- package/src/process.ts +45 -0
- package/src/responses/compaction.ts +199 -0
- package/src/responses/parser.ts +633 -0
- package/src/responses/reasoning-envelope.ts +49 -0
- package/src/responses/schema.ts +172 -0
- package/src/responses/state.ts +230 -0
- package/src/server.ts +1111 -0
- package/src/service.ts +315 -0
- package/src/setup.ts +671 -0
- package/src/stall-timeout.ts +23 -0
- package/src/tunnel-service.ts +160 -0
- package/src/tunnel.ts +417 -0
- package/src/turndown-plugin-gfm.d.ts +5 -0
- package/src/types.ts +307 -0
- package/src/usage/totals.ts +12 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import type { AppConfig, SubagentProtocol } from "./config";
|
|
6
|
+
import { atomicWriteFile, expandUserPath, getConfigDir } from "./config";
|
|
7
|
+
|
|
8
|
+
export const MANAGED_COMMENT = "# Managed by codex-chatgpt-web; `codex-chatgpt-web uninstall` restores prior values.";
|
|
9
|
+
export const MANAGED_ROUTE_COMMENT =
|
|
10
|
+
"# Managed by codex-chatgpt-web: Responses use the local bridge; Voice stays on ChatGPT.";
|
|
11
|
+
export const CODEX_REALTIME_WEBRTC_CALL_BASE_URL = "https://chatgpt.com/backend-api/codex";
|
|
12
|
+
export const MANAGED_REMOTE_COMPACTION_LINE =
|
|
13
|
+
"remote_compaction_v2 = false # Managed by codex-chatgpt-web: bounds retained Web image history.";
|
|
14
|
+
export const MANAGED_MULTI_AGENT_LINE =
|
|
15
|
+
"multi_agent = true # Managed by codex-chatgpt-web: enables routed Web subagents.";
|
|
16
|
+
export const MANAGED_MULTI_AGENT_V2_LINE =
|
|
17
|
+
"multi_agent_v2 = false # Managed by codex-chatgpt-web: keeps routed Web subagent payloads readable.";
|
|
18
|
+
export const MANAGED_MULTI_AGENT_V2_TABLE_LINE =
|
|
19
|
+
"enabled = false # Managed by codex-chatgpt-web: keeps routed Web subagent payloads readable.";
|
|
20
|
+
export const MIN_COMPATIBILITY_V1_AGENT_DEPTH = 2;
|
|
21
|
+
export function managedAgentMaxDepthLine(value: number): string {
|
|
22
|
+
return `max_depth = ${value} # Managed by codex-chatgpt-web: allows nested routed Web subagents in Compatibility V1.`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PreviousAssignment {
|
|
26
|
+
present: boolean;
|
|
27
|
+
rawLine?: string;
|
|
28
|
+
value?: string;
|
|
29
|
+
index?: number;
|
|
30
|
+
}
|
|
31
|
+
export type ManagedAssignmentKey = "openai_base_url" | "model_provider" | "model_catalog_json";
|
|
32
|
+
|
|
33
|
+
export interface PreviousFeatureAssignment extends PreviousAssignment {
|
|
34
|
+
tablePresent: boolean;
|
|
35
|
+
tableName?: "features" | "features.multi_agent_v2";
|
|
36
|
+
inlineTable?: boolean;
|
|
37
|
+
separatorInserted?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface PreviousAgentAssignment extends PreviousAssignment {
|
|
41
|
+
tablePresent: boolean;
|
|
42
|
+
separatorInserted?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface InstalledCodexInterruptHook {
|
|
46
|
+
command: string;
|
|
47
|
+
groupIndex: number;
|
|
48
|
+
stateKey: string;
|
|
49
|
+
trustedHash: string;
|
|
50
|
+
fragment: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface CodexIntegrationJournal {
|
|
54
|
+
version: 10;
|
|
55
|
+
active: boolean;
|
|
56
|
+
configPath: string;
|
|
57
|
+
installed: {
|
|
58
|
+
openai_base_url: string;
|
|
59
|
+
experimental_realtime_webrtc_call_base_url: string;
|
|
60
|
+
subagent_protocol: SubagentProtocol;
|
|
61
|
+
agent_max_depth?: number;
|
|
62
|
+
};
|
|
63
|
+
previous: Record<ManagedAssignmentKey, PreviousAssignment>;
|
|
64
|
+
previousRealtimeWebrtcCallBaseUrl: PreviousAssignment;
|
|
65
|
+
interruptHook: InstalledCodexInterruptHook;
|
|
66
|
+
previousMultiAgent?: PreviousFeatureAssignment;
|
|
67
|
+
previousMultiAgentV2?: PreviousFeatureAssignment;
|
|
68
|
+
previousAgentMaxDepth?: PreviousAgentAssignment;
|
|
69
|
+
format?: {
|
|
70
|
+
lineEnding: "\n" | "\r\n" | "\r";
|
|
71
|
+
trailingNewline: boolean;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface LegacyCodexIntegrationJournalV9 {
|
|
76
|
+
version: 9;
|
|
77
|
+
active: boolean;
|
|
78
|
+
configPath: string;
|
|
79
|
+
installed: {
|
|
80
|
+
openai_base_url: string;
|
|
81
|
+
experimental_realtime_webrtc_call_base_url: string;
|
|
82
|
+
subagent_protocol: SubagentProtocol;
|
|
83
|
+
agent_max_depth?: number;
|
|
84
|
+
};
|
|
85
|
+
previous: Record<ManagedAssignmentKey, PreviousAssignment>;
|
|
86
|
+
previousRealtimeWebrtcCallBaseUrl: PreviousAssignment;
|
|
87
|
+
previousMultiAgent?: PreviousFeatureAssignment;
|
|
88
|
+
previousMultiAgentV2?: PreviousFeatureAssignment;
|
|
89
|
+
previousAgentMaxDepth?: PreviousAgentAssignment;
|
|
90
|
+
format?: {
|
|
91
|
+
lineEnding: "\n" | "\r\n" | "\r";
|
|
92
|
+
trailingNewline: boolean;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface LegacyCodexIntegrationJournalV8 {
|
|
97
|
+
version: 8;
|
|
98
|
+
active: boolean;
|
|
99
|
+
configPath: string;
|
|
100
|
+
installed: {
|
|
101
|
+
openai_base_url: string;
|
|
102
|
+
subagent_protocol: SubagentProtocol;
|
|
103
|
+
agent_max_depth?: number;
|
|
104
|
+
};
|
|
105
|
+
previous: Record<ManagedAssignmentKey, PreviousAssignment>;
|
|
106
|
+
previousMultiAgent?: PreviousFeatureAssignment;
|
|
107
|
+
previousMultiAgentV2?: PreviousFeatureAssignment;
|
|
108
|
+
previousAgentMaxDepth?: PreviousAgentAssignment;
|
|
109
|
+
format?: {
|
|
110
|
+
lineEnding: "\n" | "\r\n";
|
|
111
|
+
trailingNewline: boolean;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface LegacyCodexIntegrationJournalV7 {
|
|
116
|
+
version: 7;
|
|
117
|
+
active: boolean;
|
|
118
|
+
configPath: string;
|
|
119
|
+
installed: {
|
|
120
|
+
openai_base_url: string;
|
|
121
|
+
};
|
|
122
|
+
previous: Record<ManagedAssignmentKey, PreviousAssignment>;
|
|
123
|
+
format?: {
|
|
124
|
+
lineEnding: "\n" | "\r\n";
|
|
125
|
+
trailingNewline: boolean;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface LegacyCodexIntegrationJournalV6 {
|
|
130
|
+
version: 6;
|
|
131
|
+
active: boolean;
|
|
132
|
+
configPath: string;
|
|
133
|
+
installed: {
|
|
134
|
+
openai_base_url: string;
|
|
135
|
+
remote_compaction_v2: false;
|
|
136
|
+
multi_agent: true;
|
|
137
|
+
multi_agent_v2: false;
|
|
138
|
+
};
|
|
139
|
+
previous: Record<ManagedAssignmentKey, PreviousAssignment>;
|
|
140
|
+
previousRemoteCompactionV2: PreviousFeatureAssignment;
|
|
141
|
+
previousMultiAgent: PreviousFeatureAssignment;
|
|
142
|
+
previousMultiAgentV2: PreviousFeatureAssignment;
|
|
143
|
+
format?: {
|
|
144
|
+
lineEnding: "\n" | "\r\n";
|
|
145
|
+
trailingNewline: boolean;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface LegacyCodexIntegrationJournalV5 {
|
|
150
|
+
version: 5;
|
|
151
|
+
active: boolean;
|
|
152
|
+
configPath: string;
|
|
153
|
+
installed: {
|
|
154
|
+
openai_base_url: string;
|
|
155
|
+
remote_compaction_v2: false;
|
|
156
|
+
multi_agent: true;
|
|
157
|
+
};
|
|
158
|
+
previous: Record<ManagedAssignmentKey, PreviousAssignment>;
|
|
159
|
+
previousRemoteCompactionV2: PreviousFeatureAssignment;
|
|
160
|
+
previousMultiAgent: PreviousFeatureAssignment;
|
|
161
|
+
format?: {
|
|
162
|
+
lineEnding: "\n" | "\r\n";
|
|
163
|
+
trailingNewline: boolean;
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface LegacyCodexIntegrationJournalV4 {
|
|
168
|
+
version: 4;
|
|
169
|
+
active: boolean;
|
|
170
|
+
configPath: string;
|
|
171
|
+
installed: {
|
|
172
|
+
openai_base_url: string;
|
|
173
|
+
};
|
|
174
|
+
previous: Record<ManagedAssignmentKey, PreviousAssignment>;
|
|
175
|
+
format?: {
|
|
176
|
+
lineEnding: "\n" | "\r\n";
|
|
177
|
+
trailingNewline: boolean;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface LegacyCodexIntegrationJournalV3 {
|
|
182
|
+
version: 3;
|
|
183
|
+
configPath: string;
|
|
184
|
+
installed: {
|
|
185
|
+
openai_base_url: string;
|
|
186
|
+
};
|
|
187
|
+
previous: Record<ManagedAssignmentKey, PreviousAssignment>;
|
|
188
|
+
format?: {
|
|
189
|
+
lineEnding: "\n" | "\r\n";
|
|
190
|
+
trailingNewline: boolean;
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface LegacyCodexIntegrationJournal {
|
|
195
|
+
version: 2;
|
|
196
|
+
configPath: string;
|
|
197
|
+
catalogPath: string;
|
|
198
|
+
catalogSha256: string;
|
|
199
|
+
providerBlock: string;
|
|
200
|
+
installed: {
|
|
201
|
+
model_provider: string;
|
|
202
|
+
model_catalog_json: string;
|
|
203
|
+
};
|
|
204
|
+
previous: {
|
|
205
|
+
model_provider: PreviousAssignment;
|
|
206
|
+
model_catalog_json: PreviousAssignment;
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type ManagedRouteJournal =
|
|
211
|
+
| CodexIntegrationJournal
|
|
212
|
+
| LegacyCodexIntegrationJournalV9
|
|
213
|
+
| LegacyCodexIntegrationJournalV8
|
|
214
|
+
| LegacyCodexIntegrationJournalV7
|
|
215
|
+
| LegacyCodexIntegrationJournalV6
|
|
216
|
+
| LegacyCodexIntegrationJournalV5
|
|
217
|
+
| LegacyCodexIntegrationJournalV4
|
|
218
|
+
| LegacyCodexIntegrationJournalV3;
|
|
219
|
+
export type AnyCodexIntegrationJournal = ManagedRouteJournal | LegacyCodexIntegrationJournal;
|
|
220
|
+
|
|
221
|
+
export interface FileSnapshot {
|
|
222
|
+
path: string;
|
|
223
|
+
exists: boolean;
|
|
224
|
+
data?: Buffer;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface InstallCodexIntegrationOptions {
|
|
228
|
+
replaceExistingRoute?: boolean;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export interface UninstallCodexIntegrationResult {
|
|
232
|
+
changed: boolean;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface SetCodexIntegrationActiveResult {
|
|
236
|
+
changed: boolean;
|
|
237
|
+
active: boolean;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface CodexModelContextOverride {
|
|
241
|
+
contextWindow: number;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function getCodexHome(): string {
|
|
245
|
+
const configured = process.env.CODEX_HOME?.trim();
|
|
246
|
+
return resolve(expandUserPath(configured || join(homedir(), ".codex")));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function getCodexConfigPath(): string {
|
|
250
|
+
return join(getCodexHome(), "config.toml");
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function getCodexModelsCachePath(): string {
|
|
254
|
+
return join(getCodexHome(), "models_cache.json");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function getCodexJournalPath(): string {
|
|
258
|
+
return join(getConfigDir(), "codex", "integration-journal.json");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function getCodexJournalRecoveryPath(): string {
|
|
262
|
+
return join(getConfigDir(), "codex", "integration-journal.recovery.json");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export function routeUrl(config: AppConfig): string {
|
|
266
|
+
return `http://${config.host}:${config.port}/v1`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function sha256(value: string | Uint8Array): string {
|
|
270
|
+
return createHash("sha256").update(value).digest("hex");
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function snapshotFile(path: string): FileSnapshot {
|
|
274
|
+
return existsSync(path)
|
|
275
|
+
? { path, exists: true, data: readFileSync(path) }
|
|
276
|
+
: { path, exists: false };
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function restoreFileSnapshot(snapshot: FileSnapshot): void {
|
|
280
|
+
if (snapshot.exists) {
|
|
281
|
+
if (!snapshot.data) throw new Error(`File snapshot is missing data: ${snapshot.path}`);
|
|
282
|
+
atomicWriteFile(snapshot.path, snapshot.data);
|
|
283
|
+
} else {
|
|
284
|
+
rmSync(snapshot.path, { force: true });
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function writeFilesWithCompensation(
|
|
289
|
+
writes: Array<{ path: string; data: string | Uint8Array }>,
|
|
290
|
+
removals: string[] = [],
|
|
291
|
+
): void {
|
|
292
|
+
const paths = [...new Set([...writes.map(write => write.path), ...removals])];
|
|
293
|
+
const snapshots = paths.map(snapshotFile);
|
|
294
|
+
try {
|
|
295
|
+
for (const write of writes) atomicWriteFile(write.path, write.data);
|
|
296
|
+
for (const removal of removals) rmSync(removal, { force: true });
|
|
297
|
+
} catch (error) {
|
|
298
|
+
const rollbackFailures: string[] = [];
|
|
299
|
+
for (const snapshot of [...snapshots].reverse()) {
|
|
300
|
+
try {
|
|
301
|
+
restoreFileSnapshot(snapshot);
|
|
302
|
+
} catch (rollbackError) {
|
|
303
|
+
rollbackFailures.push(`${snapshot.path}: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const primary = error instanceof Error ? error.message : String(error);
|
|
307
|
+
throw new Error(
|
|
308
|
+
rollbackFailures.length > 0
|
|
309
|
+
? `${primary}; Codex integration rollback also failed: ${rollbackFailures.join("; ")}`
|
|
310
|
+
: primary,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export function serializeJournal(journal: AnyCodexIntegrationJournal): string {
|
|
316
|
+
return `${JSON.stringify(journal, null, 2)}\n`;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export function writeIntegrationState(
|
|
320
|
+
journal: AnyCodexIntegrationJournal,
|
|
321
|
+
configWrite?: { path: string; data: string },
|
|
322
|
+
removals: string[] = [],
|
|
323
|
+
): void {
|
|
324
|
+
const data = serializeJournal(journal);
|
|
325
|
+
// The recovery copy records intent and the primary copy records commit. If the process stops
|
|
326
|
+
// between those writes, the physical config unambiguously selects the completed state.
|
|
327
|
+
writeFilesWithCompensation([
|
|
328
|
+
{ path: getCodexJournalRecoveryPath(), data },
|
|
329
|
+
...(configWrite ? [configWrite] : []),
|
|
330
|
+
{ path: getCodexJournalPath(), data },
|
|
331
|
+
], removals);
|
|
332
|
+
}
|