@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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/assets/demo.gif +0 -0
  4. package/assets/hero-demo.png +0 -0
  5. package/assets/promo-dshmarket-official.png +0 -0
  6. package/cordis.patch.yml +4 -0
  7. package/lib/cli.js +239642 -0
  8. package/lib/plugin.js +195 -0
  9. package/package.json +88 -0
  10. package/screenshots.json +5 -0
  11. package/src/adapters/base.ts +16 -0
  12. package/src/adapters/chatgpt-web/adapter-error.ts +59 -0
  13. package/src/adapters/chatgpt-web/browser-helper-main.ts +513 -0
  14. package/src/adapters/chatgpt-web/browser-helper-prompt-selection.ts +27 -0
  15. package/src/adapters/chatgpt-web/browser-worker.ts +4944 -0
  16. package/src/adapters/chatgpt-web/codex-rollout-environment.ts +628 -0
  17. package/src/adapters/chatgpt-web/compaction-handoff.ts +533 -0
  18. package/src/adapters/chatgpt-web/compaction-transaction.ts +142 -0
  19. package/src/adapters/chatgpt-web/concurrency.ts +6 -0
  20. package/src/adapters/chatgpt-web/conversation-key.ts +58 -0
  21. package/src/adapters/chatgpt-web/environment.ts +669 -0
  22. package/src/adapters/chatgpt-web/index.ts +1544 -0
  23. package/src/adapters/chatgpt-web/input-tokens.ts +74 -0
  24. package/src/adapters/chatgpt-web/launcher-helper-client.ts +695 -0
  25. package/src/adapters/chatgpt-web/markdown.ts +418 -0
  26. package/src/adapters/chatgpt-web/mcp-main.ts +25 -0
  27. package/src/adapters/chatgpt-web/mcp-server.ts +933 -0
  28. package/src/adapters/chatgpt-web/model.ts +70 -0
  29. package/src/adapters/chatgpt-web/native-compaction-control.ts +74 -0
  30. package/src/adapters/chatgpt-web/output-validation.ts +62 -0
  31. package/src/adapters/chatgpt-web/process-line-writer.ts +46 -0
  32. package/src/adapters/chatgpt-web/prompt.ts +702 -0
  33. package/src/adapters/chatgpt-web/retry-policy.ts +73 -0
  34. package/src/adapters/chatgpt-web/rolling-checkpoint.ts +384 -0
  35. package/src/adapters/chatgpt-web/thread-environment.ts +238 -0
  36. package/src/adapters/chatgpt-web/tool-stream-parser.ts +601 -0
  37. package/src/adapters/chatgpt-web/turn-broker.ts +1481 -0
  38. package/src/adapters/chatgpt-web/turn-execution.ts +816 -0
  39. package/src/adapters/chatgpt-web/turn-progress.ts +292 -0
  40. package/src/adapters/chatgpt-web/usage.ts +121 -0
  41. package/src/adapters/image.ts +9 -0
  42. package/src/bridge.ts +1083 -0
  43. package/src/browser-login.ts +521 -0
  44. package/src/chatgpt-session.ts +240 -0
  45. package/src/chatgpt-web-models.ts +400 -0
  46. package/src/cli.ts +568 -0
  47. package/src/codex-integration-document.ts +824 -0
  48. package/src/codex-integration-journal.ts +212 -0
  49. package/src/codex-integration-route.ts +515 -0
  50. package/src/codex-integration-shared.ts +332 -0
  51. package/src/codex-integration.ts +529 -0
  52. package/src/codex-interrupt-hook.ts +158 -0
  53. package/src/config.ts +616 -0
  54. package/src/dev-chat/cli.ts +432 -0
  55. package/src/dev-chat/constants.ts +3 -0
  56. package/src/dev-chat/driver.ts +655 -0
  57. package/src/dev-chat/profile.ts +223 -0
  58. package/src/dev-chat/session.ts +287 -0
  59. package/src/dev-chat/transport.ts +54 -0
  60. package/src/doctor.ts +237 -0
  61. package/src/event-queue.ts +45 -0
  62. package/src/http-body.ts +30 -0
  63. package/src/launcher-browser-host.ts +695 -0
  64. package/src/lib/errors.ts +281 -0
  65. package/src/lib/token-estimate.ts +42 -0
  66. package/src/login-helper.cjs +140 -0
  67. package/src/model-catalog.ts +197 -0
  68. package/src/native-passthrough.ts +261 -0
  69. package/src/plugin.ts +191 -0
  70. package/src/process.ts +45 -0
  71. package/src/responses/compaction.ts +199 -0
  72. package/src/responses/parser.ts +633 -0
  73. package/src/responses/reasoning-envelope.ts +49 -0
  74. package/src/responses/schema.ts +172 -0
  75. package/src/responses/state.ts +230 -0
  76. package/src/server.ts +1111 -0
  77. package/src/service.ts +315 -0
  78. package/src/setup.ts +671 -0
  79. package/src/stall-timeout.ts +23 -0
  80. package/src/tunnel-service.ts +160 -0
  81. package/src/tunnel.ts +417 -0
  82. package/src/turndown-plugin-gfm.d.ts +5 -0
  83. package/src/types.ts +307 -0
  84. package/src/usage/totals.ts +12 -0
  85. package/src/version.ts +1 -0
@@ -0,0 +1,212 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { atomicWriteFile, stripUtf8Bom } from "./config";
4
+ import {
5
+ CODEX_REALTIME_WEBRTC_CALL_BASE_URL,
6
+ getCodexConfigPath,
7
+ getCodexJournalPath,
8
+ getCodexJournalRecoveryPath,
9
+ serializeJournal,
10
+ writeFilesWithCompensation,
11
+ } from "./codex-integration-shared";
12
+ import type {
13
+ AnyCodexIntegrationJournal,
14
+ CodexIntegrationJournal,
15
+ LegacyCodexIntegrationJournal,
16
+ LegacyCodexIntegrationJournalV9,
17
+ LegacyCodexIntegrationJournalV3,
18
+ LegacyCodexIntegrationJournalV4,
19
+ LegacyCodexIntegrationJournalV5,
20
+ LegacyCodexIntegrationJournalV6,
21
+ LegacyCodexIntegrationJournalV7,
22
+ LegacyCodexIntegrationJournalV8,
23
+ } from "./codex-integration-shared";
24
+ import { verifyManagedJournalState } from "./codex-integration-route";
25
+
26
+ function isPreviousAssignment(value: unknown): boolean {
27
+ if (!value || typeof value !== "object") return false;
28
+ const assignment = value as Record<string, unknown>;
29
+ if (typeof assignment.present !== "boolean") return false;
30
+ return !assignment.present
31
+ || (typeof assignment.rawLine === "string" && typeof assignment.value === "string");
32
+ }
33
+
34
+ function isInstalledInterruptHook(value: unknown): boolean {
35
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
36
+ const hook = value as Record<string, unknown>;
37
+ return typeof hook.command === "string" && hook.command.length > 0
38
+ && Number.isSafeInteger(hook.groupIndex) && (hook.groupIndex as number) >= 0
39
+ && typeof hook.stateKey === "string" && hook.stateKey.length > 0
40
+ && typeof hook.trustedHash === "string" && /^sha256:[a-f0-9]{64}$/.test(hook.trustedHash)
41
+ && typeof hook.fragment === "string" && hook.fragment.length > 0;
42
+ }
43
+
44
+ function parseJournal(path: string): AnyCodexIntegrationJournal {
45
+ const value = JSON.parse(stripUtf8Bom(readFileSync(path, "utf8"))) as Record<string, unknown>;
46
+ const installed = value.installed as Record<string, unknown> | undefined;
47
+ if (value.version === 10
48
+ && typeof value.active === "boolean"
49
+ && installed
50
+ && typeof installed.openai_base_url === "string"
51
+ && installed.experimental_realtime_webrtc_call_base_url === CODEX_REALTIME_WEBRTC_CALL_BASE_URL
52
+ && (installed.subagent_protocol === "compatibility-v1" || installed.subagent_protocol === "native")
53
+ && (installed.subagent_protocol !== "compatibility-v1"
54
+ || (value.previousMultiAgent && value.previousMultiAgentV2
55
+ && value.previousAgentMaxDepth
56
+ && typeof installed.agent_max_depth === "number"
57
+ && Number.isSafeInteger(installed.agent_max_depth)
58
+ && installed.agent_max_depth >= 2))
59
+ && value.previous
60
+ && isPreviousAssignment(value.previousRealtimeWebrtcCallBaseUrl)
61
+ && isInstalledInterruptHook(value.interruptHook)
62
+ && typeof value.configPath === "string") {
63
+ return value as unknown as CodexIntegrationJournal;
64
+ }
65
+ if (value.version === 9
66
+ && typeof value.active === "boolean"
67
+ && installed
68
+ && typeof installed.openai_base_url === "string"
69
+ && installed.experimental_realtime_webrtc_call_base_url === CODEX_REALTIME_WEBRTC_CALL_BASE_URL
70
+ && (installed.subagent_protocol === "compatibility-v1" || installed.subagent_protocol === "native")
71
+ && (installed.subagent_protocol !== "compatibility-v1"
72
+ || (value.previousMultiAgent && value.previousMultiAgentV2
73
+ && value.previousAgentMaxDepth
74
+ && typeof installed.agent_max_depth === "number"
75
+ && Number.isSafeInteger(installed.agent_max_depth)
76
+ && installed.agent_max_depth >= 2))
77
+ && value.previous
78
+ && isPreviousAssignment(value.previousRealtimeWebrtcCallBaseUrl)
79
+ && typeof value.configPath === "string") {
80
+ return value as unknown as LegacyCodexIntegrationJournalV9;
81
+ }
82
+ if (value.version === 8
83
+ && typeof value.active === "boolean"
84
+ && installed
85
+ && (installed.subagent_protocol === "compatibility-v1" || installed.subagent_protocol === "native")
86
+ && (installed.subagent_protocol !== "compatibility-v1"
87
+ || (value.previousMultiAgent && value.previousMultiAgentV2
88
+ && value.previousAgentMaxDepth
89
+ && typeof installed.agent_max_depth === "number"
90
+ && Number.isSafeInteger(installed.agent_max_depth)
91
+ && installed.agent_max_depth >= 2))
92
+ && value.previous
93
+ && typeof value.configPath === "string") {
94
+ return value as unknown as LegacyCodexIntegrationJournalV8;
95
+ }
96
+ if (value.version === 7
97
+ && typeof value.active === "boolean"
98
+ && value.installed
99
+ && value.previous
100
+ && typeof value.configPath === "string") {
101
+ return value as unknown as LegacyCodexIntegrationJournalV7;
102
+ }
103
+ if (value.version === 6
104
+ && typeof value.active === "boolean"
105
+ && value.installed
106
+ && value.previous
107
+ && value.previousRemoteCompactionV2
108
+ && value.previousMultiAgent
109
+ && value.previousMultiAgentV2
110
+ && typeof value.configPath === "string") {
111
+ return value as unknown as LegacyCodexIntegrationJournalV6;
112
+ }
113
+ if (value.version === 5
114
+ && typeof value.active === "boolean"
115
+ && value.installed
116
+ && value.previous
117
+ && value.previousRemoteCompactionV2
118
+ && value.previousMultiAgent
119
+ && typeof value.configPath === "string") {
120
+ return value as unknown as LegacyCodexIntegrationJournalV5;
121
+ }
122
+ if (value.version === 4
123
+ && typeof value.active === "boolean"
124
+ && value.installed
125
+ && value.previous
126
+ && typeof value.configPath === "string") {
127
+ return value as unknown as LegacyCodexIntegrationJournalV4;
128
+ }
129
+ if (value.version === 3 && value.installed && value.previous && typeof value.configPath === "string") {
130
+ return value as unknown as LegacyCodexIntegrationJournalV3;
131
+ }
132
+ if (value.version === 2 && value.installed && value.previous && typeof value.providerBlock === "string") {
133
+ return value as unknown as LegacyCodexIntegrationJournal;
134
+ }
135
+ throw new Error(`Invalid Codex integration journal: ${path}`);
136
+ }
137
+ function journalMatchesConfig(journal: AnyCodexIntegrationJournal): boolean {
138
+ try {
139
+ assertJournalTargetsConfig(journal, getCodexConfigPath());
140
+ if (!existsSync(journal.configPath)) return false;
141
+ const text = readFileSync(journal.configPath, "utf8");
142
+ if (journal.version === 2) return text.includes(journal.providerBlock);
143
+ verifyManagedJournalState(text, journal);
144
+ return true;
145
+ } catch {
146
+ return false;
147
+ }
148
+ }
149
+
150
+ export function readJournal(): AnyCodexIntegrationJournal | undefined {
151
+ const primaryPath = getCodexJournalPath();
152
+ const recoveryPath = getCodexJournalRecoveryPath();
153
+ let primary: AnyCodexIntegrationJournal | undefined;
154
+ let recovery: AnyCodexIntegrationJournal | undefined;
155
+ let primaryError: unknown;
156
+ let recoveryError: unknown;
157
+ if (existsSync(primaryPath)) {
158
+ try { primary = parseJournal(primaryPath); } catch (error) { primaryError = error; }
159
+ }
160
+ if (existsSync(recoveryPath)) {
161
+ try { recovery = parseJournal(recoveryPath); } catch (error) { recoveryError = error; }
162
+ }
163
+ if (!primary && !recovery) {
164
+ if (primaryError) throw primaryError;
165
+ if (recoveryError) throw recoveryError;
166
+ return undefined;
167
+ }
168
+ if (primary && recovery && serializeJournal(primary) === serializeJournal(recovery)) return primary;
169
+ if (primary && !recovery && !recoveryError) {
170
+ atomicWriteFile(recoveryPath, serializeJournal(primary));
171
+ return primary;
172
+ }
173
+ if (recovery && !primary && !primaryError) {
174
+ if (!journalMatchesConfig(recovery)) {
175
+ throw new Error("Codex integration recovery journal does not match the active config");
176
+ }
177
+ atomicWriteFile(primaryPath, serializeJournal(recovery));
178
+ return recovery;
179
+ }
180
+
181
+ const primaryMatches = primary ? journalMatchesConfig(primary) : false;
182
+ const recoveryMatches = recovery ? journalMatchesConfig(recovery) : false;
183
+ if (primaryMatches === recoveryMatches) {
184
+ throw new Error(
185
+ primaryMatches
186
+ ? "Codex integration journal copies contain different baselines for the same config"
187
+ : "Codex integration journal copies do not match the active config",
188
+ );
189
+ }
190
+ const selected = primaryMatches ? primary! : recovery!;
191
+ const data = serializeJournal(selected);
192
+ writeFilesWithCompensation([
193
+ { path: recoveryPath, data },
194
+ { path: primaryPath, data },
195
+ ]);
196
+ return selected;
197
+ }
198
+
199
+ export function assertJournalTargetsConfig(
200
+ journal: AnyCodexIntegrationJournal,
201
+ configPath: string,
202
+ ): void {
203
+ const pathIdentity = (value: string): string => {
204
+ const normalized = resolve(value);
205
+ return process.platform === "win32" ? normalized.toLowerCase() : normalized;
206
+ };
207
+ if (pathIdentity(journal.configPath) !== pathIdentity(configPath)) {
208
+ throw new Error(
209
+ `Codex integration journal belongs to ${journal.configPath}, not the active config ${configPath}`,
210
+ );
211
+ }
212
+ }