codex-chatgpt-control 0.2.0-alpha.1 → 0.5.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 +15 -0
- package/README.md +42 -2
- package/contracts/v1/fixtures/backend-capabilities.json +11 -0
- package/contracts/v1/fixtures/command-descriptors.json +289 -7
- package/contracts/v1/fixtures/describe-runner-run.json +5 -2
- package/contracts/v1/fixtures/doctor-scenario-preflight.json +45 -2
- package/contracts/v1/fixtures/help-root.json +1 -1
- package/contracts/v1/fixtures/output-json-parse-success.json +9 -0
- package/contracts/v1/fixtures/reports-create-redacted.json +1 -1
- package/contracts/v1/fixtures/run-timeout-partial.json +15 -4
- package/contracts/v1/fixtures/stream-in-progress.ndjson +3 -0
- package/contracts/v1/fixtures/stream-submitted-completed.ndjson +1 -1
- package/contracts/v1/fixtures/surface-chat-legacy.json +35 -0
- package/contracts/v1/fixtures/surface-chat-simplified.json +37 -0
- package/contracts/v1/fixtures/surface-sidebar-false-positive.json +29 -0
- package/contracts/v1/fixtures/surface-work-advanced.json +45 -0
- package/contracts/v1/fixtures/surface-work-basic.json +38 -0
- package/contracts/v1/fixtures/workflow-ask-success.json +8 -0
- package/contracts/v1/manifest.json +32 -1
- package/contracts/v1/parity-suite.json +121 -1
- package/contracts/v1/schemas/backend-request.schema.json +15 -0
- package/contracts/v1/schemas/manifest.schema.json +6 -3
- package/contracts/v1/schemas/surface-profile.schema.json +166 -0
- package/dist/codex-chatgpt-control-backend.mjs +3198 -340
- package/dist/codex-chatgpt-control.bundle.mjs +4454 -1555
- package/dist/src/backend/client.d.ts +26 -1
- package/dist/src/backend/client.js +23 -1
- package/dist/src/backend/protocol.d.ts +1 -1
- package/dist/src/backend/protocol.js +11 -0
- package/dist/src/backend/session.js +22 -0
- package/dist/src/browser/attach.d.ts +1 -0
- package/dist/src/browser/attach.js +3 -3
- package/dist/src/browser/clipboard.d.ts +11 -0
- package/dist/src/browser/clipboard.js +34 -7
- package/dist/src/browser/page-state.js +17 -4
- package/dist/src/client.d.ts +32 -1
- package/dist/src/client.js +72 -16
- package/dist/src/commands/artifacts.js +1 -7
- package/dist/src/commands/configuration.d.ts +15 -0
- package/dist/src/commands/configuration.js +674 -0
- package/dist/src/commands/context.js +3 -1
- 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.js +47 -3
- package/dist/src/commands/experience.d.ts +12 -0
- package/dist/src/commands/experience.js +288 -0
- package/dist/src/commands/files.js +61 -13
- package/dist/src/commands/messages.d.ts +2 -1
- package/dist/src/commands/messages.js +349 -87
- package/dist/src/commands/modes.d.ts +4 -1
- package/dist/src/commands/modes.js +243 -44
- package/dist/src/commands/probes.d.ts +15 -0
- package/dist/src/commands/probes.js +64 -0
- package/dist/src/commands/registry.js +102 -8
- package/dist/src/commands/reports.js +1 -1
- package/dist/src/commands/response-actions.js +1 -7
- package/dist/src/commands/sequence.js +24 -1
- package/dist/src/commands/session.d.ts +2 -0
- package/dist/src/commands/session.js +50 -1
- package/dist/src/commands/threads.js +3 -31
- package/dist/src/commands/work.d.ts +6 -0
- package/dist/src/commands/work.js +338 -0
- package/dist/src/dom/generation-state.d.ts +7 -0
- package/dist/src/dom/generation-state.js +7 -1
- 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 +8 -1
- package/dist/src/dom/locale/am.js +8 -1
- package/dist/src/dom/locale/ar.d.ts +9 -1
- package/dist/src/dom/locale/ar.js +9 -1
- package/dist/src/dom/locale/bg.d.ts +9 -1
- package/dist/src/dom/locale/bg.js +9 -1
- package/dist/src/dom/locale/bn.d.ts +9 -1
- package/dist/src/dom/locale/bn.js +9 -1
- package/dist/src/dom/locale/bs.d.ts +8 -1
- package/dist/src/dom/locale/bs.js +8 -1
- package/dist/src/dom/locale/ca.d.ts +8 -1
- package/dist/src/dom/locale/ca.js +8 -1
- package/dist/src/dom/locale/cs.d.ts +8 -1
- package/dist/src/dom/locale/cs.js +8 -1
- package/dist/src/dom/locale/da.d.ts +7 -1
- package/dist/src/dom/locale/da.js +7 -1
- package/dist/src/dom/locale/de.d.ts +10 -3
- package/dist/src/dom/locale/de.js +10 -3
- package/dist/src/dom/locale/el.d.ts +8 -1
- package/dist/src/dom/locale/el.js +8 -1
- package/dist/src/dom/locale/en.d.ts +40 -1
- package/dist/src/dom/locale/en.js +42 -1
- package/dist/src/dom/locale/es-419.d.ts +8 -1
- package/dist/src/dom/locale/es-419.js +8 -1
- package/dist/src/dom/locale/es-ES.d.ts +8 -1
- package/dist/src/dom/locale/es-ES.js +8 -1
- package/dist/src/dom/locale/et.d.ts +8 -1
- package/dist/src/dom/locale/et.js +8 -1
- package/dist/src/dom/locale/fa.d.ts +9 -1
- package/dist/src/dom/locale/fa.js +9 -1
- package/dist/src/dom/locale/fi.d.ts +8 -1
- package/dist/src/dom/locale/fi.js +8 -1
- package/dist/src/dom/locale/fr-CA.d.ts +8 -1
- package/dist/src/dom/locale/fr-CA.js +8 -1
- package/dist/src/dom/locale/fr-FR.d.ts +8 -3
- package/dist/src/dom/locale/fr-FR.js +8 -3
- package/dist/src/dom/locale/gu.d.ts +8 -1
- package/dist/src/dom/locale/gu.js +8 -1
- package/dist/src/dom/locale/hi.d.ts +8 -1
- package/dist/src/dom/locale/hi.js +8 -1
- package/dist/src/dom/locale/hr.d.ts +7 -1
- package/dist/src/dom/locale/hr.js +7 -1
- package/dist/src/dom/locale/hu.d.ts +8 -1
- package/dist/src/dom/locale/hu.js +8 -1
- package/dist/src/dom/locale/hy.d.ts +9 -1
- package/dist/src/dom/locale/hy.js +9 -1
- package/dist/src/dom/locale/id.d.ts +8 -1
- package/dist/src/dom/locale/id.js +8 -1
- package/dist/src/dom/locale/index.d.ts +20 -1
- package/dist/src/dom/locale/index.js +102 -0
- package/dist/src/dom/locale/is.d.ts +8 -1
- package/dist/src/dom/locale/is.js +8 -1
- package/dist/src/dom/locale/it.d.ts +8 -1
- package/dist/src/dom/locale/it.js +8 -1
- package/dist/src/dom/locale/ja.d.ts +8 -1
- package/dist/src/dom/locale/ja.js +8 -1
- package/dist/src/dom/locale/ka.d.ts +8 -1
- package/dist/src/dom/locale/ka.js +8 -1
- package/dist/src/dom/locale/kk.d.ts +8 -1
- package/dist/src/dom/locale/kk.js +8 -1
- package/dist/src/dom/locale/kn.d.ts +9 -1
- package/dist/src/dom/locale/kn.js +9 -1
- package/dist/src/dom/locale/ko.d.ts +8 -1
- package/dist/src/dom/locale/ko.js +8 -1
- package/dist/src/dom/locale/lt.d.ts +9 -1
- package/dist/src/dom/locale/lt.js +9 -1
- package/dist/src/dom/locale/lv.d.ts +8 -1
- package/dist/src/dom/locale/lv.js +8 -1
- package/dist/src/dom/locale/mk.d.ts +7 -1
- package/dist/src/dom/locale/mk.js +7 -1
- package/dist/src/dom/locale/ml.d.ts +9 -1
- package/dist/src/dom/locale/ml.js +9 -1
- package/dist/src/dom/locale/mn.d.ts +9 -1
- package/dist/src/dom/locale/mn.js +9 -1
- package/dist/src/dom/locale/mr.d.ts +9 -1
- package/dist/src/dom/locale/mr.js +9 -1
- package/dist/src/dom/locale/ms.d.ts +8 -1
- package/dist/src/dom/locale/ms.js +8 -1
- package/dist/src/dom/locale/my.d.ts +8 -1
- package/dist/src/dom/locale/my.js +8 -1
- package/dist/src/dom/locale/nb.d.ts +8 -1
- package/dist/src/dom/locale/nb.js +8 -1
- package/dist/src/dom/locale/nl.d.ts +8 -1
- package/dist/src/dom/locale/nl.js +8 -1
- package/dist/src/dom/locale/pa.d.ts +9 -1
- package/dist/src/dom/locale/pa.js +9 -1
- package/dist/src/dom/locale/pl.d.ts +8 -1
- package/dist/src/dom/locale/pl.js +8 -1
- package/dist/src/dom/locale/pt-BR.d.ts +8 -1
- package/dist/src/dom/locale/pt-BR.js +8 -1
- package/dist/src/dom/locale/pt-PT.d.ts +8 -1
- package/dist/src/dom/locale/pt-PT.js +8 -1
- package/dist/src/dom/locale/ro.d.ts +7 -1
- package/dist/src/dom/locale/ro.js +7 -1
- package/dist/src/dom/locale/ru.d.ts +5 -1
- package/dist/src/dom/locale/ru.js +5 -1
- package/dist/src/dom/locale/sk.d.ts +8 -1
- package/dist/src/dom/locale/sk.js +8 -1
- package/dist/src/dom/locale/sl.d.ts +8 -1
- package/dist/src/dom/locale/sl.js +8 -1
- package/dist/src/dom/locale/so.d.ts +8 -1
- package/dist/src/dom/locale/so.js +8 -1
- package/dist/src/dom/locale/sq.d.ts +8 -1
- package/dist/src/dom/locale/sq.js +8 -1
- package/dist/src/dom/locale/sr.d.ts +5 -1
- package/dist/src/dom/locale/sr.js +5 -1
- package/dist/src/dom/locale/sv.d.ts +8 -1
- package/dist/src/dom/locale/sv.js +8 -1
- package/dist/src/dom/locale/sw.d.ts +8 -1
- package/dist/src/dom/locale/sw.js +8 -1
- package/dist/src/dom/locale/ta.d.ts +9 -1
- package/dist/src/dom/locale/ta.js +9 -1
- package/dist/src/dom/locale/te.d.ts +9 -1
- package/dist/src/dom/locale/te.js +9 -1
- package/dist/src/dom/locale/th.d.ts +8 -1
- package/dist/src/dom/locale/th.js +8 -1
- package/dist/src/dom/locale/tl.d.ts +4 -5
- package/dist/src/dom/locale/tl.js +4 -5
- package/dist/src/dom/locale/tr.d.ts +8 -1
- package/dist/src/dom/locale/tr.js +8 -1
- package/dist/src/dom/locale/types.d.ts +25 -1
- package/dist/src/dom/locale/uk.d.ts +8 -1
- package/dist/src/dom/locale/uk.js +8 -1
- package/dist/src/dom/locale/ur.d.ts +8 -1
- package/dist/src/dom/locale/ur.js +8 -1
- package/dist/src/dom/locale/vi.d.ts +8 -1
- package/dist/src/dom/locale/vi.js +8 -1
- package/dist/src/dom/locale/zh-HK.d.ts +9 -1
- package/dist/src/dom/locale/zh-HK.js +10 -2
- package/dist/src/dom/locale/zh-Hans.d.ts +9 -1
- package/dist/src/dom/locale/zh-Hans.js +9 -1
- package/dist/src/dom/locale/zh-TW.d.ts +9 -1
- package/dist/src/dom/locale/zh-TW.js +9 -1
- package/dist/src/dom/menus.js +13 -2
- package/dist/src/dom/selectors.js +6 -1
- 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 +3 -0
- package/dist/src/index.js +3 -0
- package/dist/src/runner/responses.d.ts +3 -1
- package/dist/src/runner/responses.js +16 -1
- package/dist/src/runner/result.js +129 -4
- package/dist/src/runner/stream.d.ts +1 -1
- package/dist/src/runner/stream.js +6 -0
- package/dist/src/runner/types.d.ts +35 -1
- package/dist/src/safety/risk.d.ts +11 -0
- package/dist/src/safety/risk.js +11 -0
- package/dist/src/scripts/apply-intelligence-locale-captures.d.ts +6 -0
- package/dist/src/scripts/apply-intelligence-locale-captures.js +147 -15
- package/dist/src/scripts/capture-intelligence-locales.d.ts +3 -0
- package/dist/src/scripts/capture-intelligence-locales.js +372 -3
- package/dist/src/scripts/capture-surface-profile.d.ts +23 -0
- package/dist/src/scripts/capture-surface-profile.js +304 -0
- package/dist/src/scripts/live-smoke/scenarios.js +34 -1
- package/dist/src/scripts/live-smoke.js +1 -0
- package/dist/src/types.d.ts +273 -2
- package/package.json +4 -3
- package/references/2026-07-16-chat-work-surfaces.md +87 -0
- package/references/agents-runner.md +13 -2
- package/references/backend-protocol.md +19 -7
- package/references/language-coverage.md +40 -3
- package/references/localization.md +48 -10
- package/references/python-parity.md +16 -4
- package/references/responses-adapter.md +12 -1
- package/references/troubleshooting.md +49 -6
package/dist/src/types.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export type CommandStatus = "ok" | "partial" | "timeout" | "blocked" | "needs_confirmation" | "not_found" | "unsupported" | "error";
|
|
2
|
+
export type SubmissionState = "not_submitted" | "submitted" | "submitted_unconfirmed" | "submitted_generating";
|
|
3
|
+
export type CompletionState = "complete" | "generating" | "stopped" | "partial" | "unknown";
|
|
2
4
|
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
5
|
export type CommandContext = {
|
|
4
6
|
url?: string;
|
|
@@ -6,6 +8,8 @@ export type CommandContext = {
|
|
|
6
8
|
title?: string;
|
|
7
9
|
turnCount?: number;
|
|
8
10
|
assistantTurnCount?: number;
|
|
11
|
+
experience?: ChatGPTExperience;
|
|
12
|
+
selectorProfile?: SurfaceSelectorProfile;
|
|
9
13
|
browserName?: string;
|
|
10
14
|
tabId?: string;
|
|
11
15
|
timestamp: string;
|
|
@@ -174,6 +178,10 @@ export type SubmitData = {
|
|
|
174
178
|
submitted: boolean;
|
|
175
179
|
userTurnText?: string;
|
|
176
180
|
turnCount?: number;
|
|
181
|
+
submissionState?: SubmissionState;
|
|
182
|
+
completionState?: CompletionState;
|
|
183
|
+
generationActive?: boolean;
|
|
184
|
+
generationSignals?: string[];
|
|
177
185
|
};
|
|
178
186
|
export type WaitArgs = {
|
|
179
187
|
afterTurnCount?: number;
|
|
@@ -183,12 +191,19 @@ export type WaitArgs = {
|
|
|
183
191
|
stableMs?: number;
|
|
184
192
|
pollMs?: number;
|
|
185
193
|
mode?: "normal" | "deep_research";
|
|
194
|
+
responseContent?: "include" | "metadata";
|
|
186
195
|
};
|
|
187
196
|
export type WaitData = {
|
|
188
197
|
complete: boolean;
|
|
189
198
|
responseText?: string;
|
|
199
|
+
responseChars?: number;
|
|
200
|
+
responseSha256?: string;
|
|
201
|
+
responseContent?: "include" | "metadata";
|
|
190
202
|
assistantTurnCount: number;
|
|
191
203
|
elapsedMs: number;
|
|
204
|
+
completionState?: CompletionState;
|
|
205
|
+
generationActive?: boolean;
|
|
206
|
+
generationSignals?: string[];
|
|
192
207
|
};
|
|
193
208
|
export type ResponseFormat = "markdown" | "text" | "normalized_text" | "visible_text" | "html" | "blocks" | "all";
|
|
194
209
|
export type ResponseCitation = {
|
|
@@ -273,10 +288,14 @@ export type ReadLatestData = {
|
|
|
273
288
|
actions?: ResponseAction[];
|
|
274
289
|
thoughtDurationText?: string;
|
|
275
290
|
sourcesAvailable?: boolean;
|
|
291
|
+
completionState?: CompletionState;
|
|
292
|
+
generationActive?: boolean;
|
|
293
|
+
generationSignals?: string[];
|
|
276
294
|
};
|
|
277
295
|
export type WaitAndReadArgs = WaitArgs & ReadLatestArgs;
|
|
278
296
|
export type AskArgs = {
|
|
279
|
-
text
|
|
297
|
+
text?: string;
|
|
298
|
+
prompt?: string;
|
|
280
299
|
wait?: boolean | WaitArgs;
|
|
281
300
|
read?: boolean | ReadLatestArgs;
|
|
282
301
|
timeoutMs?: number;
|
|
@@ -287,10 +306,30 @@ export type AskReadData = {
|
|
|
287
306
|
complete?: boolean;
|
|
288
307
|
conversationId?: string;
|
|
289
308
|
title?: string;
|
|
309
|
+
submissionState?: SubmissionState;
|
|
310
|
+
completionState?: CompletionState;
|
|
311
|
+
generationActive?: boolean;
|
|
312
|
+
generationSignals?: string[];
|
|
313
|
+
};
|
|
314
|
+
export type MessageStatusArgs = {
|
|
315
|
+
maxPreviewChars?: number;
|
|
316
|
+
};
|
|
317
|
+
export type MessageStatusData = {
|
|
318
|
+
turnCount?: number;
|
|
319
|
+
assistantTurnCount: number;
|
|
320
|
+
latestAssistantTurnIndex?: number;
|
|
321
|
+
latestAssistantText?: string;
|
|
322
|
+
latestAssistantPreview?: string;
|
|
323
|
+
latestAssistantTextLength?: number;
|
|
324
|
+
completionState: CompletionState;
|
|
325
|
+
generationActive: boolean;
|
|
326
|
+
generationSignals: string[];
|
|
290
327
|
};
|
|
291
328
|
export type AttachFilesArgs = {
|
|
292
329
|
paths: string[];
|
|
293
330
|
timeoutMs?: number;
|
|
331
|
+
includeDiagnostics?: boolean;
|
|
332
|
+
includeHashes?: boolean;
|
|
294
333
|
};
|
|
295
334
|
export type AttachedFile = {
|
|
296
335
|
path: string;
|
|
@@ -302,11 +341,13 @@ export type FilePreflightArgs = {
|
|
|
302
341
|
paths: string[];
|
|
303
342
|
maxBytesPerFile?: number;
|
|
304
343
|
maxTotalBytes?: number;
|
|
344
|
+
includeHashes?: boolean;
|
|
305
345
|
};
|
|
306
346
|
export type FilePreflightFile = AttachedFile & {
|
|
307
347
|
extension: string;
|
|
308
348
|
mimeType: string;
|
|
309
349
|
category: FileCategory;
|
|
350
|
+
sha256?: string;
|
|
310
351
|
};
|
|
311
352
|
export type FilePreflightData = {
|
|
312
353
|
files: FilePreflightFile[];
|
|
@@ -314,6 +355,20 @@ export type FilePreflightData = {
|
|
|
314
355
|
};
|
|
315
356
|
export type AttachFilesData = {
|
|
316
357
|
files: AttachedFile[];
|
|
358
|
+
diagnostics?: FileUploadDiagnostics;
|
|
359
|
+
};
|
|
360
|
+
export type BrowserInputFileDiagnostic = {
|
|
361
|
+
name: string;
|
|
362
|
+
size: number;
|
|
363
|
+
type?: string;
|
|
364
|
+
lastModified?: number;
|
|
365
|
+
};
|
|
366
|
+
export type BrowserInputDiagnostic = {
|
|
367
|
+
files: BrowserInputFileDiagnostic[];
|
|
368
|
+
};
|
|
369
|
+
export type FileUploadDiagnostics = {
|
|
370
|
+
preflight: FilePreflightData;
|
|
371
|
+
browserInput?: BrowserInputDiagnostic;
|
|
317
372
|
};
|
|
318
373
|
export type ProjectSourceStatus = "ready" | "processing" | "failed" | "unknown";
|
|
319
374
|
export type ProjectSource = {
|
|
@@ -460,6 +515,178 @@ export type SetModeArgs = {
|
|
|
460
515
|
version?: string;
|
|
461
516
|
timeoutMs?: number;
|
|
462
517
|
};
|
|
518
|
+
export type GetModeArgs = {
|
|
519
|
+
timeoutMs?: number;
|
|
520
|
+
};
|
|
521
|
+
export type GetModeData = {
|
|
522
|
+
modes: string[];
|
|
523
|
+
};
|
|
524
|
+
export type ChatGPTExperience = "chat" | "work" | "unknown";
|
|
525
|
+
export type SurfaceSelectorProfile = "chat_legacy_v1" | "chat_simplified_v1" | "work_basic_v1" | "work_advanced_v1" | "unknown";
|
|
526
|
+
export type SurfaceProfileSupportState = "current" | "compatibility" | "unverified" | "retired";
|
|
527
|
+
export type SurfaceProfileObservation = {
|
|
528
|
+
observedAt: string;
|
|
529
|
+
provenance: string;
|
|
530
|
+
locale: string;
|
|
531
|
+
region: string;
|
|
532
|
+
accountScope: string;
|
|
533
|
+
planScope: string;
|
|
534
|
+
workspaceScope: string;
|
|
535
|
+
supportState: SurfaceProfileSupportState;
|
|
536
|
+
};
|
|
537
|
+
export type ExperienceConfidence = "high" | "medium" | "low";
|
|
538
|
+
export type ExperienceEvidence = {
|
|
539
|
+
source: "url" | "composer" | "control" | "menu" | "heading";
|
|
540
|
+
label: string;
|
|
541
|
+
};
|
|
542
|
+
export type DetectExperienceArgs = {
|
|
543
|
+
timeoutMs?: number;
|
|
544
|
+
};
|
|
545
|
+
export type DetectExperienceData = {
|
|
546
|
+
experience: ChatGPTExperience;
|
|
547
|
+
selectorProfile: SurfaceSelectorProfile;
|
|
548
|
+
confidence: ExperienceConfidence;
|
|
549
|
+
evidence: ExperienceEvidence[];
|
|
550
|
+
};
|
|
551
|
+
export type OpenExperienceArgs = {
|
|
552
|
+
experience: Exclude<ChatGPTExperience, "unknown">;
|
|
553
|
+
timeoutMs?: number;
|
|
554
|
+
};
|
|
555
|
+
export type OpenExperienceData = {
|
|
556
|
+
experience: Exclude<ChatGPTExperience, "unknown">;
|
|
557
|
+
previousExperience: ChatGPTExperience;
|
|
558
|
+
changed: boolean;
|
|
559
|
+
selectorProfile: SurfaceSelectorProfile;
|
|
560
|
+
};
|
|
561
|
+
export type ConfigurationAxis = "model" | "intelligence" | "effort" | "speed" | "modelVersion";
|
|
562
|
+
export type SurfaceProfileFixture = SurfaceProfileObservation & {
|
|
563
|
+
schemaVersion: "chatgpt.browser_control.surface_profile.v1";
|
|
564
|
+
id: string;
|
|
565
|
+
snapshot: {
|
|
566
|
+
url: string;
|
|
567
|
+
composerLabels: string[];
|
|
568
|
+
mainControls: string[];
|
|
569
|
+
mainText: string;
|
|
570
|
+
};
|
|
571
|
+
panel: {
|
|
572
|
+
openerLabel?: string;
|
|
573
|
+
axisRows: Array<{
|
|
574
|
+
axis: ConfigurationAxis;
|
|
575
|
+
label: string;
|
|
576
|
+
value?: string;
|
|
577
|
+
}>;
|
|
578
|
+
advancedVisible: boolean;
|
|
579
|
+
};
|
|
580
|
+
menuItems: Array<{
|
|
581
|
+
label: string;
|
|
582
|
+
normalized: string;
|
|
583
|
+
role?: string;
|
|
584
|
+
checked?: boolean;
|
|
585
|
+
expanded?: boolean;
|
|
586
|
+
hasPopup?: boolean;
|
|
587
|
+
testId?: string;
|
|
588
|
+
ariaLabel?: string;
|
|
589
|
+
}>;
|
|
590
|
+
expected: {
|
|
591
|
+
experience: ChatGPTExperience;
|
|
592
|
+
selectorProfile: SurfaceSelectorProfile;
|
|
593
|
+
availableAxes: ConfigurationAxis[];
|
|
594
|
+
active: Partial<Record<ConfigurationAxis, string>>;
|
|
595
|
+
};
|
|
596
|
+
};
|
|
597
|
+
export type ConfigurationOption = {
|
|
598
|
+
id: string;
|
|
599
|
+
label: string;
|
|
600
|
+
selected: boolean;
|
|
601
|
+
disabled?: boolean;
|
|
602
|
+
description?: string;
|
|
603
|
+
hasSubmenu?: boolean;
|
|
604
|
+
};
|
|
605
|
+
export type ConfigurationSelection = {
|
|
606
|
+
model?: string;
|
|
607
|
+
intelligence?: string;
|
|
608
|
+
effort?: string;
|
|
609
|
+
speed?: string;
|
|
610
|
+
modelVersion?: string;
|
|
611
|
+
/** Backward-compatible alias for modelVersion. */
|
|
612
|
+
version?: string;
|
|
613
|
+
};
|
|
614
|
+
export type InspectConfigurationArgs = {
|
|
615
|
+
experience?: Exclude<ChatGPTExperience, "unknown">;
|
|
616
|
+
includeOptions?: boolean;
|
|
617
|
+
timeoutMs?: number;
|
|
618
|
+
};
|
|
619
|
+
export type ConfigurationInspectionData = {
|
|
620
|
+
experience: ChatGPTExperience;
|
|
621
|
+
selectorProfile: SurfaceSelectorProfile;
|
|
622
|
+
availableAxes: ConfigurationAxis[];
|
|
623
|
+
active: Partial<Record<ConfigurationAxis, string>>;
|
|
624
|
+
options: Partial<Record<ConfigurationAxis, ConfigurationOption[]>>;
|
|
625
|
+
verified: boolean;
|
|
626
|
+
evidence: ExperienceEvidence[];
|
|
627
|
+
};
|
|
628
|
+
export type ApplyConfigurationArgs = {
|
|
629
|
+
experience?: Exclude<ChatGPTExperience, "unknown">;
|
|
630
|
+
desired: ConfigurationSelection;
|
|
631
|
+
strict?: boolean;
|
|
632
|
+
timeoutMs?: number;
|
|
633
|
+
};
|
|
634
|
+
export type AppliedConfigurationSelection = {
|
|
635
|
+
axis: ConfigurationAxis;
|
|
636
|
+
requested: string;
|
|
637
|
+
selected: string;
|
|
638
|
+
};
|
|
639
|
+
export type ApplyConfigurationData = {
|
|
640
|
+
requested: ConfigurationSelection;
|
|
641
|
+
selected: AppliedConfigurationSelection[];
|
|
642
|
+
before: ConfigurationInspectionData;
|
|
643
|
+
after: ConfigurationInspectionData;
|
|
644
|
+
verified: boolean;
|
|
645
|
+
};
|
|
646
|
+
export type WorkTaskRef = {
|
|
647
|
+
url?: string;
|
|
648
|
+
conversationId?: string;
|
|
649
|
+
title?: string;
|
|
650
|
+
baselineTurnCount?: number;
|
|
651
|
+
baselineAssistantTurnCount?: number;
|
|
652
|
+
};
|
|
653
|
+
export type StartWorkArgs = {
|
|
654
|
+
prompt: string;
|
|
655
|
+
/** Start from a blank Work task when possible. Defaults to true. */
|
|
656
|
+
newTask?: boolean;
|
|
657
|
+
files?: string[];
|
|
658
|
+
configuration?: ConfigurationSelection;
|
|
659
|
+
wait?: boolean | WaitArgs;
|
|
660
|
+
read?: boolean | ReadLatestArgs;
|
|
661
|
+
timeoutMs?: number;
|
|
662
|
+
};
|
|
663
|
+
export type StartWorkData = {
|
|
664
|
+
task: WorkTaskRef;
|
|
665
|
+
submitted: SubmitData;
|
|
666
|
+
configuration?: ApplyConfigurationData;
|
|
667
|
+
wait?: WaitData;
|
|
668
|
+
response?: ReadLatestData;
|
|
669
|
+
};
|
|
670
|
+
export type WorkStatusArgs = MessageStatusArgs & {
|
|
671
|
+
includeArtifacts?: boolean;
|
|
672
|
+
};
|
|
673
|
+
export type WorkStatusData = {
|
|
674
|
+
experience: "work";
|
|
675
|
+
task: WorkTaskRef;
|
|
676
|
+
message: MessageStatusData;
|
|
677
|
+
artifacts?: ArtifactListData;
|
|
678
|
+
};
|
|
679
|
+
export type WorkWaitArgs = WaitArgs;
|
|
680
|
+
export type WorkWaitData = WaitData;
|
|
681
|
+
export type SteerWorkArgs = {
|
|
682
|
+
prompt: string;
|
|
683
|
+
wait?: boolean | WaitArgs;
|
|
684
|
+
read?: boolean | ReadLatestArgs;
|
|
685
|
+
timeoutMs?: number;
|
|
686
|
+
};
|
|
687
|
+
export type SteerWorkData = AskReadData;
|
|
688
|
+
export type ReadWorkLatestArgs = ReadLatestArgs;
|
|
689
|
+
export type ReadWorkLatestData = ReadLatestData;
|
|
463
690
|
export type SelectToolArgs = {
|
|
464
691
|
tool: "web_search" | "deep_research" | "create_image" | string;
|
|
465
692
|
timeoutMs?: number;
|
|
@@ -468,6 +695,42 @@ export type SequenceStep = {
|
|
|
468
695
|
id: string;
|
|
469
696
|
command: "session.bootstrap";
|
|
470
697
|
args?: BootstrapArgs;
|
|
698
|
+
} | {
|
|
699
|
+
id: string;
|
|
700
|
+
command: "experience.detect";
|
|
701
|
+
args?: DetectExperienceArgs;
|
|
702
|
+
} | {
|
|
703
|
+
id: string;
|
|
704
|
+
command: "experience.open";
|
|
705
|
+
args: OpenExperienceArgs;
|
|
706
|
+
} | {
|
|
707
|
+
id: string;
|
|
708
|
+
command: "configuration.inspect";
|
|
709
|
+
args?: InspectConfigurationArgs;
|
|
710
|
+
} | {
|
|
711
|
+
id: string;
|
|
712
|
+
command: "configuration.apply";
|
|
713
|
+
args: ApplyConfigurationArgs;
|
|
714
|
+
} | {
|
|
715
|
+
id: string;
|
|
716
|
+
command: "work.start";
|
|
717
|
+
args: StartWorkArgs;
|
|
718
|
+
} | {
|
|
719
|
+
id: string;
|
|
720
|
+
command: "work.status";
|
|
721
|
+
args?: WorkStatusArgs;
|
|
722
|
+
} | {
|
|
723
|
+
id: string;
|
|
724
|
+
command: "work.wait";
|
|
725
|
+
args?: WorkWaitArgs;
|
|
726
|
+
} | {
|
|
727
|
+
id: string;
|
|
728
|
+
command: "work.steer";
|
|
729
|
+
args: SteerWorkArgs;
|
|
730
|
+
} | {
|
|
731
|
+
id: string;
|
|
732
|
+
command: "work.readLatest";
|
|
733
|
+
args?: ReadWorkLatestArgs;
|
|
471
734
|
} | {
|
|
472
735
|
id: string;
|
|
473
736
|
command: "threads.search";
|
|
@@ -500,6 +763,10 @@ export type SequenceStep = {
|
|
|
500
763
|
id: string;
|
|
501
764
|
command: "messages.readLatest";
|
|
502
765
|
args?: ReadLatestArgs;
|
|
766
|
+
} | {
|
|
767
|
+
id: string;
|
|
768
|
+
command: "messages.status";
|
|
769
|
+
args?: MessageStatusArgs;
|
|
503
770
|
} | {
|
|
504
771
|
id: string;
|
|
505
772
|
command: "messages.waitAndRead";
|
|
@@ -571,6 +838,7 @@ export type RuntimeEnv = {
|
|
|
571
838
|
page?: PageLike;
|
|
572
839
|
clipboard?: ClipboardLike;
|
|
573
840
|
now?: () => Date;
|
|
841
|
+
expectedTabId?: string;
|
|
574
842
|
};
|
|
575
843
|
export type ClipboardLike = {
|
|
576
844
|
read: () => Promise<string>;
|
|
@@ -628,6 +896,8 @@ export type WaitForEventOptions = {
|
|
|
628
896
|
timeoutMs?: number;
|
|
629
897
|
};
|
|
630
898
|
export type PageLike = {
|
|
899
|
+
id?: string;
|
|
900
|
+
tabId?: string;
|
|
631
901
|
url?: () => string | Promise<string>;
|
|
632
902
|
goto?: (url: string, options?: unknown) => Promise<unknown>;
|
|
633
903
|
title?: () => Promise<string>;
|
|
@@ -666,7 +936,8 @@ export type PageLike = {
|
|
|
666
936
|
[key: string]: unknown;
|
|
667
937
|
};
|
|
668
938
|
};
|
|
669
|
-
export type AskHelperArgs = AskArgs & {
|
|
939
|
+
export type AskHelperArgs = Omit<AskArgs, "text" | "prompt"> & {
|
|
940
|
+
text: string;
|
|
670
941
|
thread?: ThreadTarget;
|
|
671
942
|
};
|
|
672
943
|
export type AskInThreadArgs = AskHelperArgs & {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-chatgpt-control",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Unofficial SDK for
|
|
3
|
+
"version": "0.5.0-alpha.1",
|
|
4
|
+
"description": "Unofficial SDK for controlling visible ChatGPT Chat and Work sessions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"test": "vitest run",
|
|
35
35
|
"test:watch": "vitest",
|
|
36
36
|
"thread": "tsx src/scripts/continue-thread.ts",
|
|
37
|
+
"capture:surface-profile": "tsx src/scripts/capture-surface-profile.ts",
|
|
37
38
|
"smoke:hi": "tsx src/scripts/smoke-hi.ts",
|
|
38
39
|
"smoke:search": "tsx src/scripts/smoke-search-open-read.ts",
|
|
39
40
|
"smoke:attach": "tsx src/scripts/smoke-attach-file.ts",
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
"devDependencies": {
|
|
75
76
|
"@types/node": "^24.13.1",
|
|
76
77
|
"ajv": "^8.17.1",
|
|
77
|
-
"esbuild": "^0.28.
|
|
78
|
+
"esbuild": "^0.28.1",
|
|
78
79
|
"tsx": "^4.20.0",
|
|
79
80
|
"typescript": "^5.8.0",
|
|
80
81
|
"vitest": "^4.1.8"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Chat and Work Surfaces
|
|
3
|
+
date: 2026-07-16
|
|
4
|
+
type: reference
|
|
5
|
+
status: draft
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Chat and Work Surfaces
|
|
9
|
+
|
|
10
|
+
The SDK models visible ChatGPT as capabilities discovered from the active
|
|
11
|
+
composer, controls, and URL—not as one flat model picker.
|
|
12
|
+
|
|
13
|
+
## Experiences And Profiles
|
|
14
|
+
|
|
15
|
+
Experiences:
|
|
16
|
+
|
|
17
|
+
- `chat`
|
|
18
|
+
- `work`
|
|
19
|
+
- `unknown`
|
|
20
|
+
|
|
21
|
+
Observed selector profiles:
|
|
22
|
+
|
|
23
|
+
- `chat_legacy_v1`
|
|
24
|
+
- `chat_simplified_v1`
|
|
25
|
+
- `work_basic_v1`
|
|
26
|
+
- `work_advanced_v1`
|
|
27
|
+
- `unknown`
|
|
28
|
+
|
|
29
|
+
Profiles describe UI shape. They must not be presented as subscription plans,
|
|
30
|
+
entitlements, regions, or guaranteed underlying models. Sanitized fixtures
|
|
31
|
+
store observed date, locale, provenance, scoped surface evidence, visible
|
|
32
|
+
configuration, and expected semantic output without conversation content.
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
|
|
36
|
+
Chat may expose intelligence and nested model/version controls. Work exposes
|
|
37
|
+
model, effort, and speed axes. Inspection reports available axes, active values,
|
|
38
|
+
visible options, selector profile, and evidence.
|
|
39
|
+
|
|
40
|
+
Strict application:
|
|
41
|
+
|
|
42
|
+
1. detects or opens the requested experience;
|
|
43
|
+
2. inspects the current state;
|
|
44
|
+
3. changes only requested axes;
|
|
45
|
+
4. reopens nested controls as required;
|
|
46
|
+
5. inspects again;
|
|
47
|
+
6. blocks if every requested value is not visibly verified.
|
|
48
|
+
|
|
49
|
+
Legacy `modes.set/get` and runner `mode` inputs remain supported. They preserve
|
|
50
|
+
their pre-0.5 warning-oriented behavior. New code requiring a verified
|
|
51
|
+
postcondition should use `configuration.apply({ strict: true })`.
|
|
52
|
+
|
|
53
|
+
## Work Lifecycle
|
|
54
|
+
|
|
55
|
+
`work.start` defaults to `newTask: true`. If messages are already loaded and a
|
|
56
|
+
unique new-task control cannot be verified, it blocks rather than submitting
|
|
57
|
+
into the current task. `newTask: false` is an explicit request to continue the
|
|
58
|
+
currently visible task.
|
|
59
|
+
|
|
60
|
+
Submission uses matching-turn recovery. A no-op send click may be retried only
|
|
61
|
+
while the prompt remains in the composer and no matching user turn exists.
|
|
62
|
+
After a partial or timeout result, callers must preserve the task/thread
|
|
63
|
+
identity and use:
|
|
64
|
+
|
|
65
|
+
- `work.status`
|
|
66
|
+
- `work.wait`
|
|
67
|
+
- `work.steer`
|
|
68
|
+
- `work.readLatest`
|
|
69
|
+
- `work.artifacts.*`
|
|
70
|
+
|
|
71
|
+
The original prompt must not be blindly resubmitted.
|
|
72
|
+
|
|
73
|
+
## Locale And Rollout Policy
|
|
74
|
+
|
|
75
|
+
Shared semantic types and profile fixtures make locale and rollout support
|
|
76
|
+
incremental. New labels require sanitized evidence plus locale-registry and
|
|
77
|
+
fixture updates. Unknown or absent controls return structured capability or
|
|
78
|
+
selector-drift results.
|
|
79
|
+
|
|
80
|
+
Use `npm run capture:surface-profile -- --id <normalized-id>` against an
|
|
81
|
+
already-open authorized tab to create a local `unverified` draft. The capture
|
|
82
|
+
is read-only with respect to configuration, strips conversation identity and
|
|
83
|
+
content, and requires explicit normalized metadata before a fixture can be
|
|
84
|
+
promoted to `current` or `compatibility`.
|
|
85
|
+
|
|
86
|
+
The SDK does not spoof regions, guess account plans, infer effective models from
|
|
87
|
+
one label, or claim support for a native desktop surface from web fixtures.
|
|
@@ -11,11 +11,14 @@ const chatgpt = createChatGPT({ agent: globalThis.agent });
|
|
|
11
11
|
const reviewer = chatgpt.agent({ name: "reviewer", instructions: "Review deeply." });
|
|
12
12
|
const plan = chatgpt.runner.plan(reviewer, {
|
|
13
13
|
input: "Review this design.",
|
|
14
|
-
thread: { type: "new" }
|
|
14
|
+
thread: { type: "new" },
|
|
15
|
+
experience: "chat"
|
|
15
16
|
});
|
|
16
17
|
const result = await chatgpt.runner.run(reviewer, {
|
|
17
18
|
input: "Review this design.",
|
|
18
|
-
thread: { type: "new" }
|
|
19
|
+
thread: { type: "new" },
|
|
20
|
+
experience: "chat",
|
|
21
|
+
configuration: { intelligence: "Pro" }
|
|
19
22
|
});
|
|
20
23
|
```
|
|
21
24
|
|
|
@@ -27,6 +30,14 @@ const result = await chatgpt.runner.run(reviewer, {
|
|
|
27
30
|
|
|
28
31
|
`runner.run()` returns a `ChatGPTRunResult` with `output_text`, `finalOutput`, `output`, `interruptions`, and `state`. Browser-control blockers are surfaced as resumable interruptions when the underlying command can be retried after user approval, login, or permission repair.
|
|
29
32
|
|
|
33
|
+
`experience` and `configuration` are visible product preferences. When present,
|
|
34
|
+
the plan emits `experience.open` and strict `configuration.apply` steps before
|
|
35
|
+
the prompt. Successful results expose `experience.opened` and
|
|
36
|
+
`configuration.applied` milestone items. The legacy `mode` input remains
|
|
37
|
+
supported, but new callers should use the surface-aware fields. If both are
|
|
38
|
+
present, `configuration` takes precedence and the legacy `mode` request is not
|
|
39
|
+
executed.
|
|
40
|
+
|
|
30
41
|
For milestone streaming, call `chatgpt.runner.run(agent, input, { stream: true })` and iterate events before awaiting `stream.completed`. This is milestone streaming only, not token-delta streaming.
|
|
31
42
|
|
|
32
43
|
Do not pass API-only model controls such as `temperature`, `logprobs`, `seed`, or hidden system instructions.
|
|
@@ -67,7 +67,9 @@ 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. Intentional capture clipping uses `data.captureLimit` plus warnings; it is separate from ChatGPT generation length.
|
|
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. Message command data may include `submissionState`, `completionState`, `generationActive`, and `generationSignals`; `completionState: "generating"` or `generationActive: true` is explicit evidence that the visible ChatGPT turn is still running. 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
|
+
|
|
72
|
+
Use `messages.status({ maxPreviewChars })` for a compact latest-assistant progress snapshot when a host tool-call ceiling is shorter than the expected ChatGPT generation. It returns counts, latest-assistant preview length, `completionState`, `generationActive`, and generation signals without treating partial text as final, and without the cost of a full `readLatest`/`wait` probe.
|
|
71
73
|
|
|
72
74
|
## Streaming
|
|
73
75
|
|
|
@@ -78,9 +80,10 @@ Streaming commands emit backend event lines until `completed` or `error`.
|
|
|
78
80
|
"schemaVersion": "chatgpt.browser_control.backend_event.v1",
|
|
79
81
|
"requestId": "req_stream",
|
|
80
82
|
"type": "run_item_stream_event",
|
|
81
|
-
"name": "
|
|
83
|
+
"name": "message_in_progress",
|
|
82
84
|
"item": {
|
|
83
|
-
"type": "message.
|
|
85
|
+
"type": "message.in_progress",
|
|
86
|
+
"completionState": "generating"
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
89
|
```
|
|
@@ -99,7 +102,7 @@ The final event contains a normal runner result:
|
|
|
99
102
|
}
|
|
100
103
|
```
|
|
101
104
|
|
|
102
|
-
Streaming is milestone streaming only. It does not promise token deltas or OpenAI API stream-event parity.
|
|
105
|
+
Streaming is milestone streaming only. It does not promise token deltas or OpenAI API stream-event parity. Partial assistant text is emitted as `message_in_progress`; only completion-confirmed output is emitted as `message_completed`.
|
|
103
106
|
|
|
104
107
|
## Required Backend Commands
|
|
105
108
|
|
|
@@ -112,7 +115,14 @@ The backend must support:
|
|
|
112
115
|
- diagnostics: `doctor`
|
|
113
116
|
- reports: `createReport`, `reports.create`, `reports.redact`, `reports.summarize`
|
|
114
117
|
- command discovery: `commands`, `describe`, `help`
|
|
115
|
-
- primitives: `session.bootstrap`, `threads.*`, `messages.*`, `artifacts.*`, `files.preflight`, `files.attach`, `files.downloadLatest`, `projects.sources.list`, `projects.sources.planAdd`, `projects.sources.add`, `modes.set`, `tools.select`, `response.copy`
|
|
118
|
+
- primitives: `session.bootstrap`, `experience.detect`, `experience.open`, `configuration.inspect`, `configuration.apply`, `work.start`, `work.status`, `work.wait`, `work.steer`, `work.readLatest`, `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`
|
|
119
|
+
|
|
120
|
+
`experience.detect` and `configuration.inspect` are non-mutating capability
|
|
121
|
+
discovery. `configuration.apply` is strict by default and must verify the final
|
|
122
|
+
visible state. `work.start` defaults to a fresh task and must not append to a
|
|
123
|
+
loaded task unless the caller explicitly passes `newTask: false`. A partial or
|
|
124
|
+
timeout Work result is recovered through status/wait/read on the same task, not
|
|
125
|
+
by resubmitting the original prompt.
|
|
116
126
|
|
|
117
127
|
`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
128
|
|
|
@@ -120,7 +130,9 @@ The backend must support:
|
|
|
120
130
|
|
|
121
131
|
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
132
|
|
|
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.
|
|
133
|
+
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.
|
|
134
|
+
|
|
135
|
+
`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.
|
|
124
136
|
|
|
125
137
|
## Project Sources
|
|
126
138
|
|
|
@@ -213,7 +225,7 @@ Important: in Codex, `globalThis.agent` is not present until the Chrome plugin r
|
|
|
213
225
|
The live Chrome bootstrap is:
|
|
214
226
|
|
|
215
227
|
```js
|
|
216
|
-
const { setupBrowserRuntime } = await import("/example/user/.codex/plugins/cache/openai-bundled/chrome/
|
|
228
|
+
const { setupBrowserRuntime } = await import("/example/user/.codex/plugins/cache/openai-bundled/chrome/latest/scripts/browser-client.mjs");
|
|
217
229
|
await setupBrowserRuntime({ globals: globalThis });
|
|
218
230
|
globalThis.browser = await agent.browsers.get("extension");
|
|
219
231
|
```
|
|
@@ -5,6 +5,13 @@ The full set of languages ChatGPT exposes in **Settings → General → Language
|
|
|
5
5
|
localization rollout described in [`localization.md`](./localization.md). Strings are
|
|
6
6
|
stored per-locale under `src/dom/locale/<bcp47>.ts`.
|
|
7
7
|
|
|
8
|
+
The status table covers the pre-existing Chat/localization registry, not the new
|
|
9
|
+
Chat/Work profile graph introduced in July 2026. Work composer,
|
|
10
|
+
experience-switch, configuration-axis, and configuration-option coverage is
|
|
11
|
+
currently verified only for the sanitized English profiles. Do not interpret a
|
|
12
|
+
green row below as full Work support until that locale has matching profile
|
|
13
|
+
evidence.
|
|
14
|
+
|
|
8
15
|
- Speaker counts are **crude guesstimates** (native + second-language, rounded), not
|
|
9
16
|
researched figures. They exist only to prioritize the rollout.
|
|
10
17
|
- `bcp47` is the suggested per-locale file name. Regional variants ChatGPT lists separately
|
|
@@ -113,6 +120,18 @@ guesstimate; the tail (≈#11–15) is close and easily reordered.
|
|
|
113
120
|
|
|
114
121
|
## Automated capture
|
|
115
122
|
|
|
123
|
+
For a single current Chat or Work surface, generate a sanitized, unverified
|
|
124
|
+
profile draft from an already-open authorized tab:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npm run capture:surface-profile -- --id work-basic-en --locale en-US
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
This command does not submit a prompt or change configuration. It opens visible
|
|
131
|
+
menus for inspection, normalizes any conversation URL to `/c/sanitized`, and
|
|
132
|
+
writes only bounded composer/configuration structure under
|
|
133
|
+
`outputs/surface-profiles/`.
|
|
134
|
+
|
|
116
135
|
Use the repository capture script to drive the visible ChatGPT UI through Settings → General
|
|
117
136
|
→ Language, then open the composer Intelligence picker and record the localized labels:
|
|
118
137
|
|
|
@@ -120,6 +139,23 @@ Use the repository capture script to drive the visible ChatGPT UI through Settin
|
|
|
120
139
|
npm run capture:intelligence-locales -- --auto-switch --all --if-missing open
|
|
121
140
|
```
|
|
122
141
|
|
|
142
|
+
To also capture localized running-generation controls such as `stopControl`, run the same
|
|
143
|
+
sweep with the bounded generation probe enabled:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm run capture:intelligence-locales -- \
|
|
147
|
+
--auto-switch \
|
|
148
|
+
--all \
|
|
149
|
+
--capture-generation-state \
|
|
150
|
+
--generation-timeout-ms 12000 \
|
|
151
|
+
--if-missing open
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The generation-state probe submits one short real prompt per locale in the visible ChatGPT
|
|
155
|
+
session, waits for the localized stop control, stops generation, and records only compact
|
|
156
|
+
control/status labels. Use it only when operating the user's visible ChatGPT session is
|
|
157
|
+
acceptable.
|
|
158
|
+
|
|
123
159
|
The script uses the native language names from this tracker, verifies the rendered
|
|
124
160
|
`document.documentElement.lang`, writes JSONL evidence under
|
|
125
161
|
`outputs/intelligence-locale-captures/`, and restores the initially selected language by
|
|
@@ -134,9 +170,10 @@ changes the settings or picker DOM, the run should emit a blocker record instead
|
|
|
134
170
|
3. Open the model switcher and the `+` menu with **real** clicks (Radix menus ignore
|
|
135
171
|
synthetic `.click()`) and read the menu items → mode + tool labels.
|
|
136
172
|
4. Open search → placeholder; observe a conversation → copy-response + response-actions.
|
|
137
|
-
`stopControl` is only
|
|
138
|
-
|
|
139
|
-
`selector_drift` safety net
|
|
173
|
+
`stopControl` is present only mid-generation and should be captured with
|
|
174
|
+
`--capture-generation-state`; login/captcha/rate-limit copy needs a logged-out/limited
|
|
175
|
+
state — these may lag and rely on the English fallback + the `selector_drift` safety net
|
|
176
|
+
until captured.
|
|
140
177
|
5. Write the verified strings to `src/dom/locale/<bcp47>.ts` and register it in
|
|
141
178
|
`src/dom/locale/index.ts`. Build + test + bundle + sync.
|
|
142
179
|
6. Restore the account language to English (US) when the run is complete.
|