codex-chatgpt-control 0.1.0-alpha.1 → 0.3.0-alpha.1
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/CHANGELOG.md +14 -0
- package/README.md +55 -0
- package/contracts/v1/fixtures/backend-capabilities.json +8 -0
- package/contracts/v1/fixtures/blocker-explanation-profiles.json +114 -0
- package/contracts/v1/fixtures/command-descriptors.json +224 -16
- package/contracts/v1/fixtures/doctor-bridge-upload.json +8 -0
- package/contracts/v1/fixtures/doctor-scenario-preflight.json +119 -0
- package/contracts/v1/fixtures/existing-tab-diagnostics-blocker.json +57 -0
- package/contracts/v1/fixtures/files-preflight-success.json +32 -0
- package/contracts/v1/fixtures/help-root.json +1 -1
- package/contracts/v1/fixtures/output-json-parse-success.json +17 -2
- package/contracts/v1/fixtures/project-sources-plan-add.json +71 -0
- package/contracts/v1/fixtures/read-latest-clipped.json +31 -0
- package/contracts/v1/fixtures/reports-create-redacted.json +15 -0
- package/contracts/v1/fixtures/responses-basic-success.json +11 -0
- package/contracts/v1/fixtures/run-basic-success.json +15 -0
- package/contracts/v1/fixtures/run-browser-bridge-blocker.json +2 -2
- package/contracts/v1/fixtures/run-timeout-partial.json +2 -2
- package/contracts/v1/fixtures/runner-budget-blocker.json +1 -1
- package/contracts/v1/fixtures/stream-blocked.ndjson +1 -1
- package/contracts/v1/fixtures/stream-submitted-completed.ndjson +1 -1
- package/contracts/v1/manifest.json +30 -0
- package/contracts/v1/parity-suite.json +80 -7
- package/contracts/v1/schemas/backend-request.schema.json +3 -0
- package/contracts/v1/schemas/command-result.schema.json +48 -0
- package/contracts/v1/schemas/response.schema.json +28 -0
- package/contracts/v1/schemas/run-result.schema.json +84 -0
- package/contracts/v1/surface-drift-policy.json +210 -0
- package/dist/codex-chatgpt-control-backend.mjs +7478 -1789
- package/dist/codex-chatgpt-control.bundle.mjs +8023 -2266
- package/dist/src/backend/client.d.ts +6 -1
- package/dist/src/backend/client.js +5 -0
- package/dist/src/backend/protocol.d.ts +1 -1
- package/dist/src/backend/protocol.js +8 -0
- package/dist/src/backend/session.js +16 -0
- package/dist/src/browser/attach.js +128 -20
- package/dist/src/browser/clipboard.d.ts +11 -0
- package/dist/src/browser/clipboard.js +34 -7
- package/dist/src/browser/downloads.js +2 -1
- package/dist/src/browser/page-state.js +18 -5
- package/dist/src/client.d.ts +17 -1
- package/dist/src/client.js +89 -9
- package/dist/src/commands/artifacts.d.ts +5 -0
- package/dist/src/commands/artifacts.js +432 -0
- package/dist/src/commands/context.js +8 -3
- package/dist/src/commands/conversation.d.ts +15 -0
- package/dist/src/commands/conversation.js +44 -0
- package/dist/src/commands/deadline.d.ts +8 -0
- package/dist/src/commands/deadline.js +14 -0
- package/dist/src/commands/doctor.d.ts +10 -2
- package/dist/src/commands/doctor.js +249 -14
- package/dist/src/commands/files.d.ts +2 -1
- package/dist/src/commands/files.js +406 -18
- package/dist/src/commands/messages.d.ts +2 -1
- package/dist/src/commands/messages.js +430 -98
- package/dist/src/commands/modes.d.ts +4 -1
- package/dist/src/commands/modes.js +404 -37
- package/dist/src/commands/probes.d.ts +15 -0
- package/dist/src/commands/probes.js +64 -0
- package/dist/src/commands/project-sources.d.ts +10 -0
- package/dist/src/commands/project-sources.js +643 -0
- package/dist/src/commands/registry.js +108 -14
- package/dist/src/commands/reports.d.ts +9 -0
- package/dist/src/commands/reports.js +84 -7
- package/dist/src/commands/response-actions.js +33 -0
- package/dist/src/commands/sequence.js +14 -0
- package/dist/src/commands/threads.js +4 -25
- package/dist/src/commands/timeouts.d.ts +2 -0
- package/dist/src/commands/timeouts.js +18 -0
- package/dist/src/diagnostics/blockers.d.ts +54 -0
- package/dist/src/diagnostics/blockers.js +299 -0
- package/dist/src/dom/artifacts.d.ts +7 -0
- package/dist/src/dom/artifacts.js +198 -0
- package/dist/src/dom/generation-state.d.ts +15 -0
- package/dist/src/dom/generation-state.js +109 -0
- package/dist/src/dom/label-match.d.ts +3 -0
- package/dist/src/dom/label-match.js +25 -0
- package/dist/src/dom/locale/am.d.ts +34 -0
- package/dist/src/dom/locale/am.js +34 -0
- package/dist/src/dom/locale/ar.d.ts +35 -0
- package/dist/src/dom/locale/ar.js +35 -0
- package/dist/src/dom/locale/bg.d.ts +35 -0
- package/dist/src/dom/locale/bg.js +35 -0
- package/dist/src/dom/locale/bn.d.ts +35 -0
- package/dist/src/dom/locale/bn.js +35 -0
- package/dist/src/dom/locale/bs.d.ts +34 -0
- package/dist/src/dom/locale/bs.js +34 -0
- package/dist/src/dom/locale/ca.d.ts +34 -0
- package/dist/src/dom/locale/ca.js +34 -0
- package/dist/src/dom/locale/cs.d.ts +34 -0
- package/dist/src/dom/locale/cs.js +34 -0
- package/dist/src/dom/locale/da.d.ts +33 -0
- package/dist/src/dom/locale/da.js +33 -0
- package/dist/src/dom/locale/de.d.ts +36 -0
- package/dist/src/dom/locale/de.js +36 -0
- package/dist/src/dom/locale/el.d.ts +34 -0
- package/dist/src/dom/locale/el.js +34 -0
- package/dist/src/dom/locale/en.d.ts +64 -0
- package/dist/src/dom/locale/en.js +71 -0
- package/dist/src/dom/locale/es-419.d.ts +34 -0
- package/dist/src/dom/locale/es-419.js +34 -0
- package/dist/src/dom/locale/es-ES.d.ts +34 -0
- package/dist/src/dom/locale/es-ES.js +34 -0
- package/dist/src/dom/locale/et.d.ts +34 -0
- package/dist/src/dom/locale/et.js +34 -0
- package/dist/src/dom/locale/fa.d.ts +35 -0
- package/dist/src/dom/locale/fa.js +35 -0
- package/dist/src/dom/locale/fi.d.ts +34 -0
- package/dist/src/dom/locale/fi.js +34 -0
- package/dist/src/dom/locale/fr-CA.d.ts +35 -0
- package/dist/src/dom/locale/fr-CA.js +35 -0
- package/dist/src/dom/locale/fr-FR.d.ts +35 -0
- package/dist/src/dom/locale/fr-FR.js +35 -0
- package/dist/src/dom/locale/gu.d.ts +34 -0
- package/dist/src/dom/locale/gu.js +34 -0
- package/dist/src/dom/locale/hi.d.ts +34 -0
- package/dist/src/dom/locale/hi.js +34 -0
- package/dist/src/dom/locale/hr.d.ts +33 -0
- package/dist/src/dom/locale/hr.js +33 -0
- package/dist/src/dom/locale/hu.d.ts +34 -0
- package/dist/src/dom/locale/hu.js +34 -0
- package/dist/src/dom/locale/hy.d.ts +35 -0
- package/dist/src/dom/locale/hy.js +35 -0
- package/dist/src/dom/locale/id.d.ts +34 -0
- package/dist/src/dom/locale/id.js +34 -0
- package/dist/src/dom/locale/index.d.ts +83 -0
- package/dist/src/dom/locale/index.js +239 -0
- package/dist/src/dom/locale/is.d.ts +34 -0
- package/dist/src/dom/locale/is.js +34 -0
- package/dist/src/dom/locale/it.d.ts +33 -0
- package/dist/src/dom/locale/it.js +33 -0
- package/dist/src/dom/locale/ja.d.ts +33 -0
- package/dist/src/dom/locale/ja.js +33 -0
- package/dist/src/dom/locale/ka.d.ts +34 -0
- package/dist/src/dom/locale/ka.js +34 -0
- package/dist/src/dom/locale/kk.d.ts +34 -0
- package/dist/src/dom/locale/kk.js +34 -0
- package/dist/src/dom/locale/kn.d.ts +35 -0
- package/dist/src/dom/locale/kn.js +35 -0
- package/dist/src/dom/locale/ko.d.ts +34 -0
- package/dist/src/dom/locale/ko.js +34 -0
- package/dist/src/dom/locale/lt.d.ts +35 -0
- package/dist/src/dom/locale/lt.js +35 -0
- package/dist/src/dom/locale/lv.d.ts +34 -0
- package/dist/src/dom/locale/lv.js +34 -0
- package/dist/src/dom/locale/mk.d.ts +33 -0
- package/dist/src/dom/locale/mk.js +33 -0
- package/dist/src/dom/locale/ml.d.ts +35 -0
- package/dist/src/dom/locale/ml.js +35 -0
- package/dist/src/dom/locale/mn.d.ts +35 -0
- package/dist/src/dom/locale/mn.js +35 -0
- package/dist/src/dom/locale/mr.d.ts +35 -0
- package/dist/src/dom/locale/mr.js +35 -0
- package/dist/src/dom/locale/ms.d.ts +34 -0
- package/dist/src/dom/locale/ms.js +34 -0
- package/dist/src/dom/locale/my.d.ts +34 -0
- package/dist/src/dom/locale/my.js +34 -0
- package/dist/src/dom/locale/nb.d.ts +34 -0
- package/dist/src/dom/locale/nb.js +34 -0
- package/dist/src/dom/locale/nl.d.ts +34 -0
- package/dist/src/dom/locale/nl.js +34 -0
- package/dist/src/dom/locale/pa.d.ts +35 -0
- package/dist/src/dom/locale/pa.js +35 -0
- package/dist/src/dom/locale/pl.d.ts +34 -0
- package/dist/src/dom/locale/pl.js +34 -0
- package/dist/src/dom/locale/pt-BR.d.ts +34 -0
- package/dist/src/dom/locale/pt-BR.js +34 -0
- package/dist/src/dom/locale/pt-PT.d.ts +34 -0
- package/dist/src/dom/locale/pt-PT.js +34 -0
- package/dist/src/dom/locale/ro.d.ts +33 -0
- package/dist/src/dom/locale/ro.js +33 -0
- package/dist/src/dom/locale/ru.d.ts +31 -0
- package/dist/src/dom/locale/ru.js +31 -0
- package/dist/src/dom/locale/sk.d.ts +34 -0
- package/dist/src/dom/locale/sk.js +34 -0
- package/dist/src/dom/locale/sl.d.ts +34 -0
- package/dist/src/dom/locale/sl.js +34 -0
- package/dist/src/dom/locale/so.d.ts +34 -0
- package/dist/src/dom/locale/so.js +34 -0
- package/dist/src/dom/locale/sq.d.ts +34 -0
- package/dist/src/dom/locale/sq.js +34 -0
- package/dist/src/dom/locale/sr.d.ts +31 -0
- package/dist/src/dom/locale/sr.js +31 -0
- package/dist/src/dom/locale/sv.d.ts +34 -0
- package/dist/src/dom/locale/sv.js +34 -0
- package/dist/src/dom/locale/sw.d.ts +34 -0
- package/dist/src/dom/locale/sw.js +34 -0
- package/dist/src/dom/locale/ta.d.ts +35 -0
- package/dist/src/dom/locale/ta.js +35 -0
- package/dist/src/dom/locale/te.d.ts +35 -0
- package/dist/src/dom/locale/te.js +35 -0
- package/dist/src/dom/locale/th.d.ts +34 -0
- package/dist/src/dom/locale/th.js +34 -0
- package/dist/src/dom/locale/tl.d.ts +28 -0
- package/dist/src/dom/locale/tl.js +28 -0
- package/dist/src/dom/locale/tr.d.ts +34 -0
- package/dist/src/dom/locale/tr.js +34 -0
- package/dist/src/dom/locale/types.d.ts +52 -0
- package/dist/src/dom/locale/types.js +1 -0
- package/dist/src/dom/locale/uk.d.ts +34 -0
- package/dist/src/dom/locale/uk.js +34 -0
- package/dist/src/dom/locale/ur.d.ts +34 -0
- package/dist/src/dom/locale/ur.js +34 -0
- package/dist/src/dom/locale/vi.d.ts +34 -0
- package/dist/src/dom/locale/vi.js +34 -0
- package/dist/src/dom/locale/zh-HK.d.ts +35 -0
- package/dist/src/dom/locale/zh-HK.js +35 -0
- package/dist/src/dom/locale/zh-Hans.d.ts +35 -0
- package/dist/src/dom/locale/zh-Hans.js +35 -0
- package/dist/src/dom/locale/zh-TW.d.ts +36 -0
- package/dist/src/dom/locale/zh-TW.js +36 -0
- package/dist/src/dom/locale-labels.d.ts +26 -0
- package/dist/src/dom/locale-labels.js +26 -0
- package/dist/src/dom/menus.d.ts +6 -0
- package/dist/src/dom/menus.js +47 -10
- package/dist/src/dom/message-format.d.ts +2 -1
- package/dist/src/dom/message-format.js +67 -10
- package/dist/src/dom/messages.d.ts +2 -1
- package/dist/src/dom/messages.js +2 -4
- package/dist/src/dom/selectors.d.ts +1 -0
- package/dist/src/dom/selectors.js +42 -15
- package/dist/src/dom/wait-snapshot.d.ts +43 -0
- package/dist/src/dom/wait-snapshot.js +127 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +5 -0
- package/dist/src/platform/local-paths.d.ts +4 -0
- package/dist/src/platform/local-paths.js +20 -0
- package/dist/src/runner/interruptions.js +15 -4
- package/dist/src/runner/responses.js +18 -1
- package/dist/src/runner/result.js +15 -0
- package/dist/src/runner/resume.js +1 -0
- package/dist/src/runner/types.d.ts +3 -0
- package/dist/src/safety/risk.d.ts +8 -0
- package/dist/src/safety/risk.js +8 -0
- package/dist/src/safety/untrusted-output.d.ts +73 -0
- package/dist/src/safety/untrusted-output.js +199 -0
- package/dist/src/scripts/apply-intelligence-locale-captures.d.ts +1 -0
- package/dist/src/scripts/apply-intelligence-locale-captures.js +270 -0
- package/dist/src/scripts/capture-intelligence-locales.d.ts +25 -0
- package/dist/src/scripts/capture-intelligence-locales.js +669 -0
- package/dist/src/scripts/check-surface-drift.d.ts +1 -0
- package/dist/src/scripts/check-surface-drift.js +11 -0
- package/dist/src/scripts/live-smoke/scenarios.js +84 -0
- package/dist/src/scripts/locale-capture/language-coverage.d.ts +10 -0
- package/dist/src/scripts/locale-capture/language-coverage.js +39 -0
- package/dist/src/testing/surface-drift.d.ts +66 -0
- package/dist/src/testing/surface-drift.js +363 -0
- package/dist/src/types.d.ts +229 -2
- package/package.json +3 -2
- package/references/backend-protocol.md +96 -2
- package/references/language-coverage.md +142 -0
- package/references/localization.md +257 -0
- package/references/python-parity.md +67 -3
- package/references/safety.md +2 -0
- package/references/troubleshooting.md +83 -2
package/dist/src/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type CommandStatus = "ok" | "partial" | "timeout" | "blocked" | "needs_confirmation" | "not_found" | "unsupported" | "error";
|
|
2
|
-
export type BlockerKind = "browser_bridge_unavailable" | "login_required" | "captcha" | "rate_limit" | "modal" | "permission" | "confirmation" | "selector_drift" | "download_unavailable" | "upload_failed" | "not_found" | "unknown";
|
|
2
|
+
export type BlockerKind = "browser_bridge_unavailable" | "login_required" | "captcha" | "rate_limit" | "modal" | "permission" | "confirmation" | "selector_drift" | "artifact_unavailable" | "artifact_selector_drift" | "artifact_download_unavailable" | "download_unavailable" | "upload_failed" | "not_found" | "unknown";
|
|
3
3
|
export type CommandContext = {
|
|
4
4
|
url?: string;
|
|
5
5
|
conversationId?: string;
|
|
@@ -10,6 +10,32 @@ export type CommandContext = {
|
|
|
10
10
|
tabId?: string;
|
|
11
11
|
timestamp: string;
|
|
12
12
|
};
|
|
13
|
+
export type ExistingTabMismatchReason = "no_candidate" | "multiple_candidates" | "non_chatgpt_tab" | "conversation_id_mismatch" | "url_mismatch" | "title_mismatch" | "selected_tab_unavailable" | "explicit_tab_id_not_open" | "user_open_tabs_unavailable";
|
|
14
|
+
export type ExistingTabDiagnosticTarget = {
|
|
15
|
+
type: string;
|
|
16
|
+
host?: string;
|
|
17
|
+
tabId?: string;
|
|
18
|
+
conversationId?: string;
|
|
19
|
+
url?: string;
|
|
20
|
+
title?: string;
|
|
21
|
+
exact?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export type ExistingTabDiagnosticCandidate = {
|
|
24
|
+
id: string;
|
|
25
|
+
url?: string;
|
|
26
|
+
title?: string;
|
|
27
|
+
conversationId?: string;
|
|
28
|
+
lastOpened?: string;
|
|
29
|
+
tabGroup?: string;
|
|
30
|
+
};
|
|
31
|
+
export type ExistingTabDiagnostics = {
|
|
32
|
+
requestedTarget: ExistingTabDiagnosticTarget;
|
|
33
|
+
userOpenTabsAvailable: boolean;
|
|
34
|
+
chatgptTabCount: number;
|
|
35
|
+
mismatchReason: ExistingTabMismatchReason;
|
|
36
|
+
candidateTabs: ExistingTabDiagnosticCandidate[];
|
|
37
|
+
omittedCandidateCount?: number;
|
|
38
|
+
};
|
|
13
39
|
export type CommandResult<T = unknown> = {
|
|
14
40
|
ok: boolean;
|
|
15
41
|
status: CommandStatus;
|
|
@@ -37,6 +63,9 @@ export type CommandResult<T = unknown> = {
|
|
|
37
63
|
label: string;
|
|
38
64
|
role?: string;
|
|
39
65
|
}>;
|
|
66
|
+
diagnostics?: {
|
|
67
|
+
existingTab?: ExistingTabDiagnostics;
|
|
68
|
+
};
|
|
40
69
|
resumable?: boolean;
|
|
41
70
|
};
|
|
42
71
|
context: CommandContext;
|
|
@@ -154,10 +183,14 @@ export type WaitArgs = {
|
|
|
154
183
|
stableMs?: number;
|
|
155
184
|
pollMs?: number;
|
|
156
185
|
mode?: "normal" | "deep_research";
|
|
186
|
+
responseContent?: "include" | "metadata";
|
|
157
187
|
};
|
|
158
188
|
export type WaitData = {
|
|
159
189
|
complete: boolean;
|
|
160
190
|
responseText?: string;
|
|
191
|
+
responseChars?: number;
|
|
192
|
+
responseSha256?: string;
|
|
193
|
+
responseContent?: "include" | "metadata";
|
|
161
194
|
assistantTurnCount: number;
|
|
162
195
|
elapsedMs: number;
|
|
163
196
|
};
|
|
@@ -176,6 +209,11 @@ export type ResponseTable = {
|
|
|
176
209
|
};
|
|
177
210
|
export type ResponseCaptureSource = "semantic_dom" | "clipboard";
|
|
178
211
|
export type ResponseCaptureFidelity = "clipboard_markdown" | "semantic_markdown" | "visible_text" | "normalized_text" | "html" | "blocks" | "all";
|
|
212
|
+
export type ResponseCaptureLimit = {
|
|
213
|
+
maxChars: number;
|
|
214
|
+
originalChars: number;
|
|
215
|
+
clipped: boolean;
|
|
216
|
+
};
|
|
179
217
|
export type ResponseBranchState = {
|
|
180
218
|
current?: number;
|
|
181
219
|
total?: number;
|
|
@@ -225,6 +263,7 @@ export type ReadLatestData = {
|
|
|
225
263
|
format: Exclude<ResponseFormat, "text">;
|
|
226
264
|
source?: ResponseCaptureSource;
|
|
227
265
|
fidelity?: ResponseCaptureFidelity;
|
|
266
|
+
captureLimit?: ResponseCaptureLimit;
|
|
228
267
|
warnings?: string[];
|
|
229
268
|
markdown?: string;
|
|
230
269
|
visibleText?: string;
|
|
@@ -256,14 +295,101 @@ export type AskReadData = {
|
|
|
256
295
|
export type AttachFilesArgs = {
|
|
257
296
|
paths: string[];
|
|
258
297
|
timeoutMs?: number;
|
|
298
|
+
includeDiagnostics?: boolean;
|
|
299
|
+
includeHashes?: boolean;
|
|
259
300
|
};
|
|
260
301
|
export type AttachedFile = {
|
|
261
302
|
path: string;
|
|
262
303
|
name: string;
|
|
263
304
|
bytes: number;
|
|
264
305
|
};
|
|
306
|
+
export type FileCategory = "text" | "document" | "spreadsheet" | "data" | "image" | "audio" | "video" | "archive" | "unknown";
|
|
307
|
+
export type FilePreflightArgs = {
|
|
308
|
+
paths: string[];
|
|
309
|
+
maxBytesPerFile?: number;
|
|
310
|
+
maxTotalBytes?: number;
|
|
311
|
+
includeHashes?: boolean;
|
|
312
|
+
};
|
|
313
|
+
export type FilePreflightFile = AttachedFile & {
|
|
314
|
+
extension: string;
|
|
315
|
+
mimeType: string;
|
|
316
|
+
category: FileCategory;
|
|
317
|
+
sha256?: string;
|
|
318
|
+
};
|
|
319
|
+
export type FilePreflightData = {
|
|
320
|
+
files: FilePreflightFile[];
|
|
321
|
+
totalBytes: number;
|
|
322
|
+
};
|
|
265
323
|
export type AttachFilesData = {
|
|
266
324
|
files: AttachedFile[];
|
|
325
|
+
diagnostics?: FileUploadDiagnostics;
|
|
326
|
+
};
|
|
327
|
+
export type BrowserInputFileDiagnostic = {
|
|
328
|
+
name: string;
|
|
329
|
+
size: number;
|
|
330
|
+
type?: string;
|
|
331
|
+
lastModified?: number;
|
|
332
|
+
};
|
|
333
|
+
export type BrowserInputDiagnostic = {
|
|
334
|
+
files: BrowserInputFileDiagnostic[];
|
|
335
|
+
};
|
|
336
|
+
export type FileUploadDiagnostics = {
|
|
337
|
+
preflight: FilePreflightData;
|
|
338
|
+
browserInput?: BrowserInputDiagnostic;
|
|
339
|
+
};
|
|
340
|
+
export type ProjectSourceStatus = "ready" | "processing" | "failed" | "unknown";
|
|
341
|
+
export type ProjectSource = {
|
|
342
|
+
name: string;
|
|
343
|
+
status: ProjectSourceStatus;
|
|
344
|
+
};
|
|
345
|
+
export type ProjectSourcesUrl = {
|
|
346
|
+
projectId: string;
|
|
347
|
+
projectSlug?: string;
|
|
348
|
+
url: string;
|
|
349
|
+
};
|
|
350
|
+
export type ProjectSourcesListArgs = {
|
|
351
|
+
projectUrl: string;
|
|
352
|
+
existingTab?: boolean | ExistingTabPolicy;
|
|
353
|
+
preferExistingTab?: boolean;
|
|
354
|
+
timeoutMs?: number;
|
|
355
|
+
};
|
|
356
|
+
export type ProjectSourcesListData = ProjectSourcesUrl & {
|
|
357
|
+
sources: ProjectSource[];
|
|
358
|
+
};
|
|
359
|
+
export type ProjectSourcePlanFile = FilePreflightFile & {
|
|
360
|
+
displayPath: string;
|
|
361
|
+
};
|
|
362
|
+
export type ProjectSourceUploadBatch = {
|
|
363
|
+
index: number;
|
|
364
|
+
files: ProjectSourcePlanFile[];
|
|
365
|
+
totalBytes: number;
|
|
366
|
+
};
|
|
367
|
+
export type ProjectSourcesPlanAddArgs = {
|
|
368
|
+
projectUrl: string;
|
|
369
|
+
files: string[];
|
|
370
|
+
batchSize?: number;
|
|
371
|
+
maxBytesPerFile?: number;
|
|
372
|
+
maxTotalBytes?: number;
|
|
373
|
+
};
|
|
374
|
+
export type ProjectSourcesAddPlanData = ProjectSourcesUrl & {
|
|
375
|
+
projectUrl: string;
|
|
376
|
+
operation: "append_add";
|
|
377
|
+
dryRun: true;
|
|
378
|
+
files: ProjectSourcePlanFile[];
|
|
379
|
+
batches: ProjectSourceUploadBatch[];
|
|
380
|
+
totalBytes: number;
|
|
381
|
+
};
|
|
382
|
+
export type ProjectSourcesAddArgs = ProjectSourcesPlanAddArgs & {
|
|
383
|
+
confirmMutation?: boolean;
|
|
384
|
+
existingTab?: boolean | ExistingTabPolicy;
|
|
385
|
+
preferExistingTab?: boolean;
|
|
386
|
+
timeoutMs?: number;
|
|
387
|
+
};
|
|
388
|
+
export type ProjectSourcesAddData = Omit<ProjectSourcesAddPlanData, "dryRun"> & {
|
|
389
|
+
dryRun: false;
|
|
390
|
+
before: ProjectSource[];
|
|
391
|
+
after: ProjectSource[];
|
|
392
|
+
added: ProjectSource[];
|
|
267
393
|
};
|
|
268
394
|
export type DownloadLatestArgs = {
|
|
269
395
|
destDir: string;
|
|
@@ -278,6 +404,47 @@ export type DownloadedFile = {
|
|
|
278
404
|
suggestedFilename?: string;
|
|
279
405
|
bytes: number;
|
|
280
406
|
};
|
|
407
|
+
export type ArtifactKind = "image";
|
|
408
|
+
export type GeneratedArtifact = {
|
|
409
|
+
kind: ArtifactKind;
|
|
410
|
+
index: number;
|
|
411
|
+
visible: boolean;
|
|
412
|
+
width?: number;
|
|
413
|
+
height?: number;
|
|
414
|
+
alt?: string;
|
|
415
|
+
ariaLabel?: string;
|
|
416
|
+
src?: string;
|
|
417
|
+
turnId?: string;
|
|
418
|
+
downloadAvailable: boolean;
|
|
419
|
+
selectorProvenance: string;
|
|
420
|
+
};
|
|
421
|
+
export type ListArtifactsArgs = {
|
|
422
|
+
kind?: ArtifactKind;
|
|
423
|
+
max?: number;
|
|
424
|
+
timeoutMs?: number;
|
|
425
|
+
};
|
|
426
|
+
export type ArtifactListData = {
|
|
427
|
+
count: number;
|
|
428
|
+
artifacts: GeneratedArtifact[];
|
|
429
|
+
latest?: GeneratedArtifact;
|
|
430
|
+
};
|
|
431
|
+
export type ArtifactWaitArgs = ListArtifactsArgs & {
|
|
432
|
+
afterArtifactCount?: number;
|
|
433
|
+
requireDownload?: boolean;
|
|
434
|
+
timeoutMs?: number;
|
|
435
|
+
stableMs?: number;
|
|
436
|
+
pollMs?: number;
|
|
437
|
+
};
|
|
438
|
+
export type ArtifactWaitData = {
|
|
439
|
+
complete: boolean;
|
|
440
|
+
count: number;
|
|
441
|
+
latest?: GeneratedArtifact;
|
|
442
|
+
elapsedMs: number;
|
|
443
|
+
};
|
|
444
|
+
export type ArtifactDownloadArgs = DownloadLatestArgs & {
|
|
445
|
+
kind?: ArtifactKind;
|
|
446
|
+
prefer?: "download_control" | "visible_image_source";
|
|
447
|
+
};
|
|
281
448
|
export type CopyResponseArgs = {
|
|
282
449
|
which?: "latest" | {
|
|
283
450
|
assistantIndex: number;
|
|
@@ -291,6 +458,7 @@ export type CopiedResponse = {
|
|
|
291
458
|
source: "clipboard" | "dom";
|
|
292
459
|
format: Exclude<ResponseFormat, "text">;
|
|
293
460
|
fidelity?: ResponseCaptureFidelity;
|
|
461
|
+
captureLimit?: ResponseCaptureLimit;
|
|
294
462
|
warnings?: string[];
|
|
295
463
|
markdown?: string;
|
|
296
464
|
visibleText?: string;
|
|
@@ -309,8 +477,17 @@ export type CopiedResponse = {
|
|
|
309
477
|
export type SetModeArgs = {
|
|
310
478
|
model?: string;
|
|
311
479
|
effort?: string;
|
|
480
|
+
intelligence?: string;
|
|
481
|
+
modelVersion?: string;
|
|
482
|
+
version?: string;
|
|
483
|
+
timeoutMs?: number;
|
|
484
|
+
};
|
|
485
|
+
export type GetModeArgs = {
|
|
312
486
|
timeoutMs?: number;
|
|
313
487
|
};
|
|
488
|
+
export type GetModeData = {
|
|
489
|
+
modes: string[];
|
|
490
|
+
};
|
|
314
491
|
export type SelectToolArgs = {
|
|
315
492
|
tool: "web_search" | "deep_research" | "create_image" | string;
|
|
316
493
|
timeoutMs?: number;
|
|
@@ -355,6 +532,18 @@ export type SequenceStep = {
|
|
|
355
532
|
id: string;
|
|
356
533
|
command: "messages.waitAndRead";
|
|
357
534
|
args: WaitAndReadArgs;
|
|
535
|
+
} | {
|
|
536
|
+
id: string;
|
|
537
|
+
command: "artifacts.listLatest";
|
|
538
|
+
args?: ListArtifactsArgs;
|
|
539
|
+
} | {
|
|
540
|
+
id: string;
|
|
541
|
+
command: "artifacts.wait";
|
|
542
|
+
args?: ArtifactWaitArgs;
|
|
543
|
+
} | {
|
|
544
|
+
id: string;
|
|
545
|
+
command: "artifacts.downloadLatest";
|
|
546
|
+
args: ArtifactDownloadArgs;
|
|
358
547
|
} | {
|
|
359
548
|
id: string;
|
|
360
549
|
command: "files.attach";
|
|
@@ -363,6 +552,18 @@ export type SequenceStep = {
|
|
|
363
552
|
id: string;
|
|
364
553
|
command: "files.downloadLatest";
|
|
365
554
|
args: DownloadLatestArgs;
|
|
555
|
+
} | {
|
|
556
|
+
id: string;
|
|
557
|
+
command: "projects.sources.list";
|
|
558
|
+
args: ProjectSourcesListArgs;
|
|
559
|
+
} | {
|
|
560
|
+
id: string;
|
|
561
|
+
command: "projects.sources.planAdd";
|
|
562
|
+
args: ProjectSourcesPlanAddArgs;
|
|
563
|
+
} | {
|
|
564
|
+
id: string;
|
|
565
|
+
command: "projects.sources.add";
|
|
566
|
+
args: ProjectSourcesAddArgs;
|
|
366
567
|
} | {
|
|
367
568
|
id: string;
|
|
368
569
|
command: "response.copy";
|
|
@@ -411,10 +612,13 @@ export type BrowserLike = {
|
|
|
411
612
|
};
|
|
412
613
|
tabs?: {
|
|
413
614
|
create?: (url: string) => Promise<PageLike> | PageLike;
|
|
414
|
-
new?: (url
|
|
615
|
+
new?: (url?: string) => Promise<PageLike> | PageLike;
|
|
415
616
|
selected?: () => Promise<PageLike | undefined> | PageLike | undefined;
|
|
416
617
|
list?: () => Promise<PageLike[]> | PageLike[];
|
|
417
618
|
get?: (id: string) => Promise<PageLike> | PageLike;
|
|
619
|
+
finalize?: (options: {
|
|
620
|
+
keep?: unknown[];
|
|
621
|
+
}) => Promise<void>;
|
|
418
622
|
};
|
|
419
623
|
newPage?: () => Promise<PageLike> | PageLike;
|
|
420
624
|
};
|
|
@@ -462,10 +666,33 @@ export type PageLike = {
|
|
|
462
666
|
keyboard?: {
|
|
463
667
|
press?: (key: string) => Promise<void>;
|
|
464
668
|
};
|
|
669
|
+
mouse?: {
|
|
670
|
+
move?: (x: number, y: number) => Promise<void> | void;
|
|
671
|
+
click?: (x: number, y: number) => Promise<void> | void;
|
|
672
|
+
};
|
|
673
|
+
cua?: {
|
|
674
|
+
move?: (options: {
|
|
675
|
+
x: number;
|
|
676
|
+
y: number;
|
|
677
|
+
}) => Promise<void> | void;
|
|
678
|
+
click?: (options: {
|
|
679
|
+
x: number;
|
|
680
|
+
y: number;
|
|
681
|
+
button?: number;
|
|
682
|
+
}) => Promise<void> | void;
|
|
683
|
+
};
|
|
465
684
|
waitForTimeout?: (ms: number) => Promise<void>;
|
|
466
685
|
waitForEvent?: (event: string, optionsOrCallback?: WaitForEventOptions | unknown) => Promise<unknown>;
|
|
467
686
|
evaluate?: <T, A = unknown>(fn: (arg: A) => T | Promise<T>, arg?: A) => Promise<T>;
|
|
468
687
|
content?: () => Promise<string>;
|
|
688
|
+
close?: () => Promise<void>;
|
|
689
|
+
capabilities?: {
|
|
690
|
+
get?: (id: string) => Promise<unknown> | unknown;
|
|
691
|
+
};
|
|
692
|
+
playwright?: {
|
|
693
|
+
waitForTimeout?: (ms: number) => Promise<void>;
|
|
694
|
+
[key: string]: unknown;
|
|
695
|
+
};
|
|
469
696
|
};
|
|
470
697
|
export type AskHelperArgs = AskArgs & {
|
|
471
698
|
thread?: ThreadTarget;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-chatgpt-control",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-alpha.1",
|
|
4
4
|
"description": "Unofficial SDK for Codex agents controlling visible ChatGPT web sessions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"bundle:backend": "esbuild src/scripts/backend-server.ts --bundle --platform=node --format=esm --outfile=dist/codex-chatgpt-control-backend.mjs",
|
|
28
28
|
"bundle:live-smoke": "esbuild src/scripts/live-smoke-module.ts --bundle --platform=node --format=esm --outfile=dist/codex-chatgpt-control-live-smoke.bundle.mjs",
|
|
29
29
|
"contract:validate": "node scripts/validate-contract.mjs",
|
|
30
|
+
"docs:drift": "tsx src/scripts/check-surface-drift.ts",
|
|
30
31
|
"parity:fixtures": "node scripts/check-parity-fixtures.mjs",
|
|
31
32
|
"parity:suite": "tsx src/scripts/check-parity-suite.ts",
|
|
32
33
|
"test:backend-conformance": "vitest run tests/unit/backend-conformance.test.ts",
|
|
@@ -73,7 +74,7 @@
|
|
|
73
74
|
"devDependencies": {
|
|
74
75
|
"@types/node": "^24.13.1",
|
|
75
76
|
"ajv": "^8.17.1",
|
|
76
|
-
"esbuild": "^0.28.
|
|
77
|
+
"esbuild": "^0.28.1",
|
|
77
78
|
"tsx": "^4.20.0",
|
|
78
79
|
"typescript": "^5.8.0",
|
|
79
80
|
"vitest": "^4.1.8"
|
|
@@ -67,6 +67,8 @@ Current protocol error codes are:
|
|
|
67
67
|
|
|
68
68
|
Browser-control blockers are not protocol errors. They are normal command or runner results with `status: "blocked"`, `status: "partial"`, or `status: "needs_confirmation"` plus blocker/interruption details.
|
|
69
69
|
|
|
70
|
+
`status: "partial"` is the required result for incomplete response capture. A partial result may still include `output_text` and `data.responseText`, but consumers must treat that text as incomplete until a later wait confirms completion. Common causes are wait timeout after partial assistant text, active generation controls such as `Stop answering`, stopped-generation markers such as `Stopped thinking`, or a read fallback after the wait step could not confirm completion. For status-only polling, `messages.wait` accepts `responseContent: "metadata"`; partial and completed wait results then omit assistant text and instead return compact metadata such as `data.responseChars` and `data.responseSha256`. Intentional capture clipping uses `data.captureLimit` plus warnings; it is separate from ChatGPT generation length.
|
|
71
|
+
|
|
70
72
|
## Streaming
|
|
71
73
|
|
|
72
74
|
Streaming commands emit backend event lines until `completed` or `error`.
|
|
@@ -107,9 +109,56 @@ The backend must support:
|
|
|
107
109
|
- runner: `runner.run`, `runner.plan`, `runner.stream`
|
|
108
110
|
- Responses adapter: `responses.create`
|
|
109
111
|
- workflows: `ask`, `askInThread`, `askWithFiles`, `askAndDownload`, `runMessages`, `openThread`, `runPlan`
|
|
112
|
+
- diagnostics: `doctor`
|
|
110
113
|
- reports: `createReport`, `reports.create`, `reports.redact`, `reports.summarize`
|
|
111
114
|
- command discovery: `commands`, `describe`, `help`
|
|
112
|
-
- primitives: `session.bootstrap`, `threads.*`, `messages.*`, `
|
|
115
|
+
- primitives: `session.bootstrap`, `threads.*`, `messages.*`, `artifacts.*`, `files.preflight`, `files.attach`, `files.downloadLatest`, `projects.sources.list`, `projects.sources.planAdd`, `projects.sources.add`, `modes.set`, `modes.get`, `tools.select`, `response.copy`
|
|
116
|
+
|
|
117
|
+
`doctor` returns a normal `CommandResult` whose `data.checks` map is extensible. Scenario checks such as `existing_tab`, `artifacts`, `file_preflight`, `localization`, and `reports` may add optional `code`, `blockerKind`, `nextCommand`, and JSON `details` fields to individual check entries while preserving the existing `status`, `message`, and `remediation` fields.
|
|
118
|
+
|
|
119
|
+
## Host-Local Attachment Paths
|
|
120
|
+
|
|
121
|
+
Attachment paths are interpreted on the machine running the Node backend. Use an absolute path in that host operating system's native form. On macOS/Linux/WSL, use paths such as `/example/user/file.pdf`, `/home/you/file.pdf`, or `/mnt/c/example/user/file.pdf`. On Windows backend hosts, use fully qualified paths such as `C:\Users\you\file.pdf` or UNC paths such as `\\server\share\file.pdf`. Drive-relative paths like `C:Users\you\file.pdf`, root-relative paths like `\tmp\file.pdf`, and Windows-looking paths sent to a POSIX backend are rejected before filesystem access.
|
|
122
|
+
|
|
123
|
+
Use `files.preflight` for non-mutating local validation before browser upload workflows. It validates absolute paths, existence, readability, file-vs-directory status, configurable per-file and total byte limits, duplicate basenames, duplicate resolved paths, zero-byte files, and extension-based MIME/category guesses. Zero-byte files are blocked before browser interaction because ChatGPT rejects empty attachments. By default the command does not open ChatGPT, perform a live upload, read file contents for MIME detection, or return file-content fingerprints. Callers may pass `includeHashes: true` to include SHA-256 metadata for local diagnostics; file contents are never returned. `askWithFiles` and `files.attach` run the same preflight before upload attempts so obvious local file failures stop before browser interaction.
|
|
124
|
+
|
|
125
|
+
`files.attach` accepts `includeDiagnostics: true` to return metadata-only upload diagnostics in `data.diagnostics`: the preflight result plus the browser input's selected file names and sizes when the DOM exposes them. Pair `includeDiagnostics: true` with `includeHashes: true` when diagnosing whether a non-empty local file became an empty browser-side `File`; do not persist these diagnostics in public reports unless the user has approved content fingerprint metadata.
|
|
126
|
+
|
|
127
|
+
## Project Sources
|
|
128
|
+
|
|
129
|
+
Project Sources V1 is a narrow visible-UI surface for ChatGPT Project URLs such as `https://chatgpt.com/g/g-p-.../project`.
|
|
130
|
+
|
|
131
|
+
- `projects.sources.list` opens or claims the Project Sources UI and returns source names plus coarse statuses only.
|
|
132
|
+
- `projects.sources.planAdd` validates explicit local file paths with the same metadata-only preflight used by `files.preflight`, batches the upload plan, and does not open ChatGPT.
|
|
133
|
+
- `projects.sources.add` is append-only and requires `confirmMutation: true`; without it, the command returns a `needs_confirmation` blocker with the dry-run plan.
|
|
134
|
+
|
|
135
|
+
The implementation normalizes nested project chat URLs back to the project page before operating. It does not delete, replace, sync repository trees, read cookies/storage/auth headers, call private ChatGPT endpoints, or read source file contents while planning. Confirmed upload uses visible browser file chooser primitives and diffs before/after source names to report added sources.
|
|
136
|
+
|
|
137
|
+
## Generated Artifacts
|
|
138
|
+
|
|
139
|
+
Generated images are represented as visible artifacts, not assistant text. A
|
|
140
|
+
ChatGPT image-only result can be complete even when `messages.readLatest` returns
|
|
141
|
+
`not_found` and `assistantTurnCount` is `0`.
|
|
142
|
+
|
|
143
|
+
Use the artifact primitives for this surface:
|
|
144
|
+
|
|
145
|
+
- `artifacts.listLatest` detects visible generated artifacts.
|
|
146
|
+
- `artifacts.wait` waits for a generated artifact to appear and stabilize.
|
|
147
|
+
- `artifacts.downloadLatest` downloads via a visible artifact affordance, or
|
|
148
|
+
saves a visible image source when no browser download event fires.
|
|
149
|
+
|
|
150
|
+
When a claimed user-open ChatGPT tab stalls bridge page inspection, artifact
|
|
151
|
+
commands may recover by opening the same saved `https://chatgpt.com/c/...`
|
|
152
|
+
conversation in a temporary bridge-owned tab and using the bridge `pageAssets`
|
|
153
|
+
capability to inventory and bundle the latest non-SVG image asset. This is an
|
|
154
|
+
implementation detail of the TypeScript runtime; the wire command and result
|
|
155
|
+
shape are unchanged.
|
|
156
|
+
|
|
157
|
+
`files.downloadLatest` preserves the existing file-link behavior and falls back
|
|
158
|
+
to generated-artifact download only when no conventional ChatGPT file affordance
|
|
159
|
+
is visible. Artifact failures are reported as structured blockers such as
|
|
160
|
+
`artifact_unavailable`, `artifact_selector_drift`, or
|
|
161
|
+
`artifact_download_unavailable`, not protocol errors.
|
|
113
162
|
|
|
114
163
|
`session.bootstrap` accepts `existingTab` for explicit reuse of a user-open Chrome tab before any read or prompt step. The wire shape is shared by TypeScript and Python:
|
|
115
164
|
|
|
@@ -166,7 +215,7 @@ Important: in Codex, `globalThis.agent` is not present until the Chrome plugin r
|
|
|
166
215
|
The live Chrome bootstrap is:
|
|
167
216
|
|
|
168
217
|
```js
|
|
169
|
-
const { setupBrowserRuntime } = await import("/example/user/.codex/plugins/cache/openai-bundled/chrome/
|
|
218
|
+
const { setupBrowserRuntime } = await import("/example/user/.codex/plugins/cache/openai-bundled/chrome/latest/scripts/browser-client.mjs");
|
|
170
219
|
await setupBrowserRuntime({ globals: globalThis });
|
|
171
220
|
globalThis.browser = await agent.browsers.get("extension");
|
|
172
221
|
```
|
|
@@ -219,6 +268,49 @@ Python SDK -> stdio relay -> bridge-hosted Node backend -> Codex Chrome bridge -
|
|
|
219
268
|
|
|
220
269
|
The smoke covers `runner.run`, `runner.run_streamed`, `responses.create`, named `run_plan`, and redacted `reports.create`. It writes redacted JSON summaries and does not persist raw prompt/response content by default.
|
|
221
270
|
|
|
271
|
+
## Untrusted Output And Integrity
|
|
272
|
+
|
|
273
|
+
Assistant output captured from ChatGPT is untrusted third-party content. Runner results with non-empty `output_text` expose `data.untrustedOutput`; Responses-shaped results expose the same object at `browser_control.untrustedOutput`.
|
|
274
|
+
|
|
275
|
+
The envelope schema is:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"schemaVersion": "chatgpt.browser_control.untrusted_output_return.v1",
|
|
280
|
+
"trusted": false,
|
|
281
|
+
"source": "chatgpt",
|
|
282
|
+
"capturedAt": "2026-06-06T00:00:00.000Z",
|
|
283
|
+
"contentSha256": "8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4",
|
|
284
|
+
"contentBytes": 2,
|
|
285
|
+
"inline": true,
|
|
286
|
+
"maxInlineBytes": 12000,
|
|
287
|
+
"rendered": "UNTRUSTED OUTPUT RETURN ENVELOPE\n..."
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Use `rendered` when handing the captured answer to another agent, tool, or prompt. It places routing and hash metadata before the body, tells the consumer not to execute embedded instructions, and uses a markdown fence longer than any backtick run inside the content. Outputs larger than the inline byte guard are not inlined; the envelope points at the persisted output path when one is available.
|
|
292
|
+
|
|
293
|
+
Run report creation writes a sibling `*.meta.json` sidecar by default:
|
|
294
|
+
|
|
295
|
+
```json
|
|
296
|
+
{
|
|
297
|
+
"schemaVersion": "chatgpt.browser_control.integrity.v1",
|
|
298
|
+
"target": {
|
|
299
|
+
"path": "reports/runs/run.json",
|
|
300
|
+
"bytes": 123,
|
|
301
|
+
"sha256": "..."
|
|
302
|
+
},
|
|
303
|
+
"output": {
|
|
304
|
+
"untrusted": true,
|
|
305
|
+
"bytes": 2,
|
|
306
|
+
"sha256": "..."
|
|
307
|
+
},
|
|
308
|
+
"inputs": []
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
The sidecar hashes the report file, normalized prompt text when available, untrusted output text when available, and configured input file paths. Consumers that cross a process or trust boundary should rehash the sidecar targets before acting on the report. Report writes are atomic and refuse to overwrite an existing target path.
|
|
313
|
+
|
|
222
314
|
## Contract Fixtures
|
|
223
315
|
|
|
224
316
|
Shared fixtures live under:
|
|
@@ -231,7 +323,9 @@ Required gates:
|
|
|
231
323
|
|
|
232
324
|
```bash
|
|
233
325
|
npm run contract:validate
|
|
326
|
+
npm run docs:drift
|
|
234
327
|
npm run parity:fixtures
|
|
328
|
+
npm run parity:suite
|
|
235
329
|
npm run test:backend-conformance
|
|
236
330
|
```
|
|
237
331
|
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Language Coverage & Capture Tracker
|
|
2
|
+
|
|
3
|
+
The full set of languages ChatGPT exposes in **Settings → General → Language** (captured
|
|
4
|
+
2026-06-09), with a rough total-speaker estimate and capture status. Use this to track the
|
|
5
|
+
localization rollout described in [`localization.md`](./localization.md). Strings are
|
|
6
|
+
stored per-locale under `src/dom/locale/<bcp47>.ts`.
|
|
7
|
+
|
|
8
|
+
- Speaker counts are **crude guesstimates** (native + second-language, rounded), not
|
|
9
|
+
researched figures. They exist only to prioritize the rollout.
|
|
10
|
+
- `bcp47` is the suggested per-locale file name. Regional variants ChatGPT lists separately
|
|
11
|
+
(Spanish, French, Portuguese, Chinese) are separate registry entries — capture the
|
|
12
|
+
larger-reach variant first; the others can be filled later or alias the base.
|
|
13
|
+
- Status: ✅ done · 🟡 in progress · ⬜ pending.
|
|
14
|
+
|
|
15
|
+
## Capture queue — top 15 by crude speaker count
|
|
16
|
+
|
|
17
|
+
English is the canonical baseline (already in the registry), so the queue below is the top
|
|
18
|
+
15 **non-English** languages by rough world speaker count. Order is a best-effort
|
|
19
|
+
guesstimate; the tail (≈#11–15) is close and easily reordered.
|
|
20
|
+
|
|
21
|
+
| # | Language | Native | bcp47 | ~Speakers | Status |
|
|
22
|
+
|---|---|---|---|---|---|
|
|
23
|
+
| — | English (US) | English (US) | `en-US` | ~1.5B | ✅ baseline |
|
|
24
|
+
| 1 | Chinese (Simplified) | 简体中文 | `zh-Hans` | ~1.1B | ✅ |
|
|
25
|
+
| 2 | Hindi | हिन्दी | `hi` | ~600M | ✅ |
|
|
26
|
+
| 3 | Spanish (Latin America) | español (Latinoamérica) | `es-419` | ~450M | ✅ |
|
|
27
|
+
| 4 | Arabic | العربية | `ar` | ~400M | ✅ |
|
|
28
|
+
| 5 | French (France) | français (France) | `fr-FR` | ~300M | ✅ |
|
|
29
|
+
| 6 | Bengali | বাংলা | `bn` | ~270M | ✅ |
|
|
30
|
+
| 7 | Portuguese (Brazil) | português (Brasil) | `pt-BR` | ~260M | ✅ |
|
|
31
|
+
| 8 | Russian | русский | `ru` | ~255M | ✅ |
|
|
32
|
+
| 9 | Urdu | اردو | `ur` | ~230M | ✅ |
|
|
33
|
+
| 10 | Indonesian | Indonesia | `id` | ~200M | ✅ |
|
|
34
|
+
| 11 | German | Deutsch | `de` | ~135M | ✅ |
|
|
35
|
+
| 12 | Punjabi | ਪੰਜਾਬੀ | `pa` | ~130M | ✅ |
|
|
36
|
+
| 13 | Japanese | 日本語 | `ja` | ~125M | ✅ |
|
|
37
|
+
| 14 | Marathi | मराठी | `mr` | ~95M | ✅ |
|
|
38
|
+
| 15 | Turkish | Türkçe | `tr` | ~85M | ✅ |
|
|
39
|
+
|
|
40
|
+
> Note: this ranks by **raw speaker count** as requested. If you'd rather weight by likely
|
|
41
|
+
> ChatGPT user base, the order would tilt toward European/East-Asian locales (Japanese,
|
|
42
|
+
> German, French, Spanish, Portuguese, Korean, Italian) and away from Punjabi/Marathi/Bengali.
|
|
43
|
+
|
|
44
|
+
## Full language list
|
|
45
|
+
|
|
46
|
+
| Language | Native | bcp47 | ~Speakers | Status |
|
|
47
|
+
|---|---|---|---|---|
|
|
48
|
+
| English (US) | English (US) | `en-US` | ~1.5B | ✅ |
|
|
49
|
+
| Amharic | አማርኛ | `am` | ~60M | ✅ |
|
|
50
|
+
| Arabic | العربية | `ar` | ~400M | ✅ |
|
|
51
|
+
| Bulgarian | български | `bg` | ~8M | ✅ |
|
|
52
|
+
| Bengali | বাংলা | `bn` | ~270M | ✅ |
|
|
53
|
+
| Bosnian | bosanski | `bs` | ~3M | ✅ |
|
|
54
|
+
| Catalan | català | `ca` | ~10M | ✅ |
|
|
55
|
+
| Czech | čeština | `cs` | ~11M | ✅ |
|
|
56
|
+
| Danish | dansk | `da` | ~6M | ✅ |
|
|
57
|
+
| German | Deutsch | `de` | ~135M | ✅ |
|
|
58
|
+
| Greek | Ελληνικά | `el` | ~13M | ✅ |
|
|
59
|
+
| Spanish (Latin America) | español (Latinoamérica) | `es-419` | ~450M | ✅ |
|
|
60
|
+
| Spanish (Spain) | español (España) | `es-ES` | ~47M | ✅ |
|
|
61
|
+
| Estonian | eesti | `et` | ~1M | ✅ |
|
|
62
|
+
| Persian | فارسی | `fa` | ~80M | ✅ |
|
|
63
|
+
| Finnish | suomi | `fi` | ~5.5M | ✅ |
|
|
64
|
+
| French (Canada) | français (Canada) | `fr-CA` | ~10M | ✅ |
|
|
65
|
+
| French (France) | français (France) | `fr-FR` | ~300M | ✅ |
|
|
66
|
+
| Gujarati | ગુજરાતી | `gu` | ~60M | ✅ |
|
|
67
|
+
| Hindi | हिन्दी | `hi` | ~600M | ✅ |
|
|
68
|
+
| Croatian | hrvatski | `hr` | ~5M | ✅ |
|
|
69
|
+
| Hungarian | magyar | `hu` | ~13M | ✅ |
|
|
70
|
+
| Armenian | հայերեն | `hy` | ~7M | ✅ |
|
|
71
|
+
| Indonesian | Indonesia | `id` | ~200M | ✅ |
|
|
72
|
+
| Icelandic | íslenska | `is` | ~0.4M | ✅ |
|
|
73
|
+
| Italian | italiano | `it` | ~65M | ✅ |
|
|
74
|
+
| Japanese | 日本語 | `ja` | ~125M | ✅ |
|
|
75
|
+
| Georgian | ქართული | `ka` | ~4M | ✅ |
|
|
76
|
+
| Kazakh | қазақ тілі | `kk` | ~13M | ✅ |
|
|
77
|
+
| Kannada | ಕನ್ನಡ | `kn` | ~60M | ✅ |
|
|
78
|
+
| Korean | 한국어 | `ko` | ~80M | ✅ |
|
|
79
|
+
| Lithuanian | lietuvių | `lt` | ~3M | ✅ |
|
|
80
|
+
| Latvian | latviešu | `lv` | ~2M | ✅ |
|
|
81
|
+
| Macedonian | македонски | `mk` | ~2M | ✅ |
|
|
82
|
+
| Malayalam | മലയാളം | `ml` | ~38M | ✅ |
|
|
83
|
+
| Mongolian | монгол | `mn` | ~5M | ✅ |
|
|
84
|
+
| Marathi | मराठी | `mr` | ~95M | ✅ |
|
|
85
|
+
| Malay | Bahasa Melayu | `ms` | ~80M | ✅ |
|
|
86
|
+
| Burmese | မြန်မာ | `my` | ~43M | ✅ |
|
|
87
|
+
| Norwegian Bokmål | norsk bokmål | `nb` | ~5M | ✅ |
|
|
88
|
+
| Dutch | Nederlands | `nl` | ~25M | ✅ |
|
|
89
|
+
| Punjabi | ਪੰਜਾਬੀ | `pa` | ~130M | ✅ |
|
|
90
|
+
| Polish | polski | `pl` | ~45M | ✅ |
|
|
91
|
+
| Portuguese (Brazil) | português (Brasil) | `pt-BR` | ~210M | ✅ |
|
|
92
|
+
| Portuguese (Portugal) | português (Portugal) | `pt-PT` | ~10M | ✅ |
|
|
93
|
+
| Romanian | română | `ro` | ~24M | ✅ |
|
|
94
|
+
| Russian | русский | `ru` | ~255M | ✅ |
|
|
95
|
+
| Slovak | slovenčina | `sk` | ~5M | ✅ |
|
|
96
|
+
| Slovenian | slovenščina | `sl` | ~2.5M | ✅ |
|
|
97
|
+
| Somali | Soomaali | `so` | ~22M | ✅ |
|
|
98
|
+
| Albanian | shqip | `sq` | ~7.5M | ✅ |
|
|
99
|
+
| Serbian | српски | `sr` | ~9M | ✅ |
|
|
100
|
+
| Swedish | svenska | `sv` | ~10M | ✅ |
|
|
101
|
+
| Swahili | Kiswahili | `sw` | ~120M | ✅ |
|
|
102
|
+
| Tamil | தமிழ் | `ta` | ~85M | ✅ |
|
|
103
|
+
| Telugu | తెలుగు | `te` | ~95M | ✅ |
|
|
104
|
+
| Thai | ไทย | `th` | ~60M | ✅ |
|
|
105
|
+
| Tagalog (Filipino) | Tagalog | `tl` | ~70M | ✅ |
|
|
106
|
+
| Turkish | Türkçe | `tr` | ~85M | ✅ |
|
|
107
|
+
| Ukrainian | українська | `uk` | ~40M | ✅ |
|
|
108
|
+
| Urdu | اردو | `ur` | ~230M | ✅ |
|
|
109
|
+
| Vietnamese | Tiếng Việt | `vi` | ~85M | ✅ |
|
|
110
|
+
| Chinese (Simplified) | 简体中文 | `zh-Hans` | ~1.1B | ✅ |
|
|
111
|
+
| Chinese (Traditional, Hong Kong) | 繁體中文(香港) | `zh-HK` | ~85M | ✅ |
|
|
112
|
+
| Chinese (Traditional, Taiwan) | 繁體中文(台灣) | `zh-TW` | ~23M | ✅ |
|
|
113
|
+
|
|
114
|
+
## Automated capture
|
|
115
|
+
|
|
116
|
+
Use the repository capture script to drive the visible ChatGPT UI through Settings → General
|
|
117
|
+
→ Language, then open the composer Intelligence picker and record the localized labels:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm run capture:intelligence-locales -- --auto-switch --all --if-missing open
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The script uses the native language names from this tracker, verifies the rendered
|
|
124
|
+
`document.documentElement.lang`, writes JSONL evidence under
|
|
125
|
+
`outputs/intelligence-locale-captures/`, and restores the initially selected language by
|
|
126
|
+
default. It does not write cookies, storage, or private browser state directly; if ChatGPT
|
|
127
|
+
changes the settings or picker DOM, the run should emit a blocker record instead of guessing.
|
|
128
|
+
|
|
129
|
+
## Capture procedure (per language)
|
|
130
|
+
|
|
131
|
+
1. Switch ChatGPT **Settings → General → Language** to the target, reload, and confirm via
|
|
132
|
+
`document.documentElement.lang` + visible text.
|
|
133
|
+
2. Read static controls (composer, add-files, new chat, current model label) via JS.
|
|
134
|
+
3. Open the model switcher and the `+` menu with **real** clicks (Radix menus ignore
|
|
135
|
+
synthetic `.click()`) and read the menu items → mode + tool labels.
|
|
136
|
+
4. Open search → placeholder; observe a conversation → copy-response + response-actions.
|
|
137
|
+
`stopControl` is only present mid-generation; login/captcha/rate-limit copy needs a
|
|
138
|
+
logged-out/limited state — these may lag and rely on the English fallback + the
|
|
139
|
+
`selector_drift` safety net until captured.
|
|
140
|
+
5. Write the verified strings to `src/dom/locale/<bcp47>.ts` and register it in
|
|
141
|
+
`src/dom/locale/index.ts`. Build + test + bundle + sync.
|
|
142
|
+
6. Restore the account language to English (US) when the run is complete.
|