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
|
@@ -4,6 +4,8 @@ const acceptedTopLevelFields = new Set([
|
|
|
4
4
|
"thread",
|
|
5
5
|
"existingTab",
|
|
6
6
|
"preferExistingTab",
|
|
7
|
+
"experience",
|
|
8
|
+
"configuration",
|
|
7
9
|
"attachments",
|
|
8
10
|
"mode",
|
|
9
11
|
"tools",
|
|
@@ -14,7 +16,7 @@ const acceptedTopLevelFields = new Set([
|
|
|
14
16
|
"instructionsMode"
|
|
15
17
|
]);
|
|
16
18
|
const unsupportedAlternatives = {
|
|
17
|
-
model: "Use
|
|
19
|
+
model: "Use experience plus configuration for visible ChatGPT UI preferences. Legacy mode remains supported. These do not select an API model.",
|
|
18
20
|
temperature: "No browser-control equivalent. ChatGPT web does not expose API temperature.",
|
|
19
21
|
top_p: "No browser-control equivalent. ChatGPT web does not expose API nucleus sampling.",
|
|
20
22
|
seed: "No browser-control equivalent. Visible ChatGPT web does not expose deterministic API seeds.",
|
|
@@ -112,6 +114,10 @@ export function responsesCreateArgsToRunInput(args) {
|
|
|
112
114
|
runInput.existingTab = args.existingTab;
|
|
113
115
|
if (args.preferExistingTab !== undefined)
|
|
114
116
|
runInput.preferExistingTab = args.preferExistingTab;
|
|
117
|
+
if (args.experience !== undefined)
|
|
118
|
+
runInput.experience = args.experience;
|
|
119
|
+
if (args.configuration !== undefined)
|
|
120
|
+
runInput.configuration = args.configuration;
|
|
115
121
|
if (args.attachments !== undefined)
|
|
116
122
|
runInput.attachments = args.attachments;
|
|
117
123
|
if (args.mode !== undefined)
|
|
@@ -133,6 +139,15 @@ export function responseFromRunResult(result, now = new Date()) {
|
|
|
133
139
|
const reportPath = result.data?.reportPath ?? result.reportPath;
|
|
134
140
|
if (reportPath !== undefined)
|
|
135
141
|
browserControl.reportPath = reportPath;
|
|
142
|
+
const submissionState = result.state.submissionState ?? result.data?.submissionState;
|
|
143
|
+
const completionState = result.state.completionState ?? result.data?.completionState;
|
|
144
|
+
const generationActive = result.data?.generationActive;
|
|
145
|
+
if (submissionState !== undefined)
|
|
146
|
+
browserControl.submissionState = submissionState;
|
|
147
|
+
if (completionState !== undefined)
|
|
148
|
+
browserControl.completionState = completionState;
|
|
149
|
+
if (generationActive !== undefined)
|
|
150
|
+
browserControl.generationActive = generationActive;
|
|
136
151
|
if (result.output_text.length > 0) {
|
|
137
152
|
const envelopeArgs = {
|
|
138
153
|
outputText: result.output_text,
|
|
@@ -9,6 +9,15 @@ export function toRunResult(agent, result) {
|
|
|
9
9
|
const output = runItemsFromResult(result, outputText);
|
|
10
10
|
const state = runStateFromResult(result, interruptions);
|
|
11
11
|
const data = { outputText };
|
|
12
|
+
const submissionState = readSubmissionState(result.data);
|
|
13
|
+
const completionState = readCompletionState(result.data);
|
|
14
|
+
const generationActive = readGenerationActive(result.data);
|
|
15
|
+
if (submissionState !== undefined)
|
|
16
|
+
data.submissionState = submissionState;
|
|
17
|
+
if (completionState !== undefined)
|
|
18
|
+
data.completionState = completionState;
|
|
19
|
+
if (generationActive !== undefined)
|
|
20
|
+
data.generationActive = generationActive;
|
|
12
21
|
if (outputText.length > 0) {
|
|
13
22
|
const envelopeArgs = {
|
|
14
23
|
outputText,
|
|
@@ -73,15 +82,56 @@ function parseFinalOutput(agent, outputText) {
|
|
|
73
82
|
return outputText;
|
|
74
83
|
}
|
|
75
84
|
function runItemsFromResult(result, outputText) {
|
|
76
|
-
const items =
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
const items = lifecycleItemsFromSteps(result.steps);
|
|
86
|
+
items.push(...messageItemsFromData(result.data));
|
|
87
|
+
if (!items.some(item => item.type === "message.completed" || item.type === "message.in_progress") && outputText.length > 0) {
|
|
88
|
+
if (result.status === "partial" && readCompletionState(result.data) !== "complete") {
|
|
89
|
+
items.push(inProgressItem(outputText, readCompletionState(result.data), readGenerationActive(result.data)));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
items.push({ type: "message.completed", role: "assistant", output_text: outputText, format: "markdown" });
|
|
93
|
+
}
|
|
79
94
|
}
|
|
80
95
|
if (result.blocker !== undefined) {
|
|
81
96
|
items.push({ type: "run.blocked", blocker: augmentCommandBlocker(result.blocker) });
|
|
82
97
|
}
|
|
83
98
|
return items;
|
|
84
99
|
}
|
|
100
|
+
function lifecycleItemsFromSteps(steps) {
|
|
101
|
+
if (steps === undefined)
|
|
102
|
+
return [];
|
|
103
|
+
const items = [];
|
|
104
|
+
for (const step of steps) {
|
|
105
|
+
if (!step.ok || !isRecord(step.dataPreview))
|
|
106
|
+
continue;
|
|
107
|
+
if (step.command === "experience.open") {
|
|
108
|
+
const experience = step.dataPreview.experience;
|
|
109
|
+
if (experience === "chat" || experience === "work") {
|
|
110
|
+
const item = {
|
|
111
|
+
type: "experience.opened",
|
|
112
|
+
experience
|
|
113
|
+
};
|
|
114
|
+
if (typeof step.dataPreview.changed === "boolean")
|
|
115
|
+
item.changed = step.dataPreview.changed;
|
|
116
|
+
items.push(item);
|
|
117
|
+
}
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (step.command === "configuration.apply") {
|
|
121
|
+
const item = {
|
|
122
|
+
type: "configuration.applied"
|
|
123
|
+
};
|
|
124
|
+
if (isRecord(step.dataPreview.requested)) {
|
|
125
|
+
item.requested = step.dataPreview.requested;
|
|
126
|
+
}
|
|
127
|
+
if (typeof step.dataPreview.verified === "boolean") {
|
|
128
|
+
item.verified = step.dataPreview.verified;
|
|
129
|
+
}
|
|
130
|
+
items.push(item);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return items;
|
|
134
|
+
}
|
|
85
135
|
function messageItemsFromData(data) {
|
|
86
136
|
if (!isRecord(data))
|
|
87
137
|
return [];
|
|
@@ -95,7 +145,12 @@ function messageItemsFromData(data) {
|
|
|
95
145
|
});
|
|
96
146
|
}
|
|
97
147
|
if (typeof data.responseText === "string" && data.responseText.length > 0) {
|
|
98
|
-
|
|
148
|
+
if (readCompletionState(data) === "complete" || data.complete === true) {
|
|
149
|
+
items.push({ type: "message.completed", role: "assistant", output_text: data.responseText, format: "markdown" });
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
items.push(inProgressItem(data.responseText, readCompletionState(data), readGenerationActive(data)));
|
|
153
|
+
}
|
|
99
154
|
}
|
|
100
155
|
if (items.length > 0)
|
|
101
156
|
return items;
|
|
@@ -116,8 +171,78 @@ function runStateFromResult(result, interruptions) {
|
|
|
116
171
|
const thread = threadRefFromContext(result.context);
|
|
117
172
|
if (thread !== undefined)
|
|
118
173
|
state.thread = thread;
|
|
174
|
+
const submissionState = readSubmissionState(result.data);
|
|
175
|
+
const completionState = readCompletionState(result.data);
|
|
176
|
+
if (submissionState !== undefined)
|
|
177
|
+
state.submissionState = submissionState;
|
|
178
|
+
if (completionState !== undefined)
|
|
179
|
+
state.completionState = completionState;
|
|
119
180
|
return state;
|
|
120
181
|
}
|
|
182
|
+
function inProgressItem(outputText, completionState, generationActive) {
|
|
183
|
+
const item = {
|
|
184
|
+
type: "message.in_progress",
|
|
185
|
+
role: "assistant",
|
|
186
|
+
output_text: outputText,
|
|
187
|
+
preview: outputText.length > 160 ? `${outputText.slice(0, 159)}...` : outputText,
|
|
188
|
+
format: "markdown",
|
|
189
|
+
textLength: outputText.length,
|
|
190
|
+
textHash: hashText(outputText)
|
|
191
|
+
};
|
|
192
|
+
if (completionState !== undefined)
|
|
193
|
+
item.completionState = completionState;
|
|
194
|
+
if (generationActive !== undefined)
|
|
195
|
+
item.generationActive = generationActive;
|
|
196
|
+
return item;
|
|
197
|
+
}
|
|
198
|
+
function readCompletionState(data) {
|
|
199
|
+
if (!isRecord(data))
|
|
200
|
+
return undefined;
|
|
201
|
+
const value = data.completionState;
|
|
202
|
+
if (value === "complete" || value === "generating" || value === "stopped" || value === "partial" || value === "unknown") {
|
|
203
|
+
return value;
|
|
204
|
+
}
|
|
205
|
+
for (const nested of Object.values(data)) {
|
|
206
|
+
const nestedState = readCompletionState(nested);
|
|
207
|
+
if (nestedState !== undefined)
|
|
208
|
+
return nestedState;
|
|
209
|
+
}
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
function readSubmissionState(data) {
|
|
213
|
+
if (!isRecord(data))
|
|
214
|
+
return undefined;
|
|
215
|
+
const value = data.submissionState;
|
|
216
|
+
if (value === "not_submitted" || value === "submitted" || value === "submitted_unconfirmed" || value === "submitted_generating") {
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
for (const nested of Object.values(data)) {
|
|
220
|
+
const nestedState = readSubmissionState(nested);
|
|
221
|
+
if (nestedState !== undefined)
|
|
222
|
+
return nestedState;
|
|
223
|
+
}
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
function readGenerationActive(data) {
|
|
227
|
+
if (!isRecord(data))
|
|
228
|
+
return undefined;
|
|
229
|
+
if (typeof data.generationActive === "boolean")
|
|
230
|
+
return data.generationActive;
|
|
231
|
+
for (const nested of Object.values(data)) {
|
|
232
|
+
const value = readGenerationActive(nested);
|
|
233
|
+
if (value !== undefined)
|
|
234
|
+
return value;
|
|
235
|
+
}
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
function hashText(value) {
|
|
239
|
+
let hash = 2166136261;
|
|
240
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
241
|
+
hash ^= value.charCodeAt(index);
|
|
242
|
+
hash = Math.imul(hash, 16777619);
|
|
243
|
+
}
|
|
244
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
245
|
+
}
|
|
121
246
|
function threadRefFromContext(context) {
|
|
122
247
|
const thread = {};
|
|
123
248
|
if (context.url !== undefined)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ChatGPTRunItem, ChatGPTRunResult } from "./types.js";
|
|
2
|
-
export type ChatGPTRunStreamEventName = "thread_opened" | "mode_selected" | "tool_selected" | "file_attached" | "message_submitted" | "message_completed" | "file_downloaded" | "run_blocked";
|
|
2
|
+
export type ChatGPTRunStreamEventName = "thread_opened" | "experience_opened" | "configuration_applied" | "mode_selected" | "tool_selected" | "file_attached" | "message_submitted" | "message_in_progress" | "message_completed" | "file_downloaded" | "run_blocked";
|
|
3
3
|
export type ChatGPTRunStreamEvent = {
|
|
4
4
|
type: "run_item_stream_event";
|
|
5
5
|
name: ChatGPTRunStreamEventName;
|
|
@@ -47,6 +47,10 @@ function runItemEventName(item) {
|
|
|
47
47
|
switch (item.type) {
|
|
48
48
|
case "thread.opened":
|
|
49
49
|
return "thread_opened";
|
|
50
|
+
case "experience.opened":
|
|
51
|
+
return "experience_opened";
|
|
52
|
+
case "configuration.applied":
|
|
53
|
+
return "configuration_applied";
|
|
50
54
|
case "mode.selected":
|
|
51
55
|
return "mode_selected";
|
|
52
56
|
case "tool.selected":
|
|
@@ -55,6 +59,8 @@ function runItemEventName(item) {
|
|
|
55
59
|
return "file_attached";
|
|
56
60
|
case "message.submitted":
|
|
57
61
|
return "message_submitted";
|
|
62
|
+
case "message.in_progress":
|
|
63
|
+
return "message_in_progress";
|
|
58
64
|
case "message.completed":
|
|
59
65
|
return "message_completed";
|
|
60
66
|
case "file.downloaded":
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AttachedFile, CommandResult, CommandStatus, CopyResponseArgs, DownloadLatestArgs, BootstrapArgs, ReadLatestArgs, ResponseCaptureFidelity, ResponseCaptureSource, ResponseFormat, SequencePlan, SelectToolArgs, SetModeArgs, ThreadTarget, WaitArgs } from "../types.js";
|
|
1
|
+
import type { AttachedFile, ChatGPTExperience, CommandResult, CommandStatus, CompletionState, ConfigurationSelection, CopyResponseArgs, DownloadLatestArgs, BootstrapArgs, ReadLatestArgs, ResponseCaptureFidelity, ResponseCaptureSource, ResponseFormat, SequencePlan, SelectToolArgs, SetModeArgs, SubmissionState, ThreadTarget, WaitArgs } from "../types.js";
|
|
2
2
|
import type { RunReportOptions } from "../commands/reports.js";
|
|
3
3
|
import type { UntrustedOutputReturnEnvelope } from "../safety/untrusted-output.js";
|
|
4
4
|
import type { ChatGPTRunStream } from "./stream.js";
|
|
@@ -38,6 +38,10 @@ export type ChatGPTVisibleModePreference = SetModeArgs & {
|
|
|
38
38
|
required?: boolean;
|
|
39
39
|
ifUnavailable?: "continue" | "block" | "skip";
|
|
40
40
|
};
|
|
41
|
+
export type ChatGPTVisibleConfigurationPreference = ConfigurationSelection & {
|
|
42
|
+
required?: boolean;
|
|
43
|
+
ifUnavailable?: "continue" | "block" | "skip";
|
|
44
|
+
};
|
|
41
45
|
export type ChatGPTVisibleToolPreference = SelectToolArgs & {
|
|
42
46
|
required?: boolean;
|
|
43
47
|
ifUnavailable?: "continue" | "block" | "skip";
|
|
@@ -46,6 +50,8 @@ export type ChatGPTRunDefaults = {
|
|
|
46
50
|
thread?: ChatGPTThreadSelector | ThreadTarget;
|
|
47
51
|
existingTab?: BootstrapArgs["existingTab"];
|
|
48
52
|
preferExistingTab?: boolean;
|
|
53
|
+
experience?: Exclude<ChatGPTExperience, "unknown">;
|
|
54
|
+
configuration?: ChatGPTVisibleConfigurationPreference;
|
|
49
55
|
mode?: ChatGPTVisibleModePreference;
|
|
50
56
|
wait?: boolean | WaitArgs;
|
|
51
57
|
read?: boolean | ReadLatestArgs;
|
|
@@ -103,6 +109,8 @@ export type ChatGPTRunInput = string | {
|
|
|
103
109
|
thread?: ChatGPTThreadSelector;
|
|
104
110
|
existingTab?: BootstrapArgs["existingTab"];
|
|
105
111
|
preferExistingTab?: boolean;
|
|
112
|
+
experience?: Exclude<ChatGPTExperience, "unknown">;
|
|
113
|
+
configuration?: ChatGPTVisibleConfigurationPreference;
|
|
106
114
|
attachments?: ChatGPTAttachmentInput[];
|
|
107
115
|
mode?: ChatGPTVisibleModePreference;
|
|
108
116
|
tools?: ChatGPTVisibleToolPreference[];
|
|
@@ -126,6 +134,14 @@ export type DownloadedFileSummary = {
|
|
|
126
134
|
export type ChatGPTRunItem = {
|
|
127
135
|
type: "thread.opened";
|
|
128
136
|
thread: ChatGPTThreadRef;
|
|
137
|
+
} | {
|
|
138
|
+
type: "experience.opened";
|
|
139
|
+
experience: Exclude<ChatGPTExperience, "unknown">;
|
|
140
|
+
changed?: boolean;
|
|
141
|
+
} | {
|
|
142
|
+
type: "configuration.applied";
|
|
143
|
+
requested?: ConfigurationSelection;
|
|
144
|
+
verified?: boolean;
|
|
129
145
|
} | {
|
|
130
146
|
type: "mode.selected";
|
|
131
147
|
requested?: string;
|
|
@@ -144,6 +160,16 @@ export type ChatGPTRunItem = {
|
|
|
144
160
|
role: "user";
|
|
145
161
|
preview: string;
|
|
146
162
|
redacted: boolean;
|
|
163
|
+
} | {
|
|
164
|
+
type: "message.in_progress";
|
|
165
|
+
role: "assistant";
|
|
166
|
+
output_text?: string;
|
|
167
|
+
preview: string;
|
|
168
|
+
format: ResponseFormat;
|
|
169
|
+
completionState?: CompletionState;
|
|
170
|
+
generationActive?: boolean;
|
|
171
|
+
textLength?: number;
|
|
172
|
+
textHash?: string;
|
|
147
173
|
} | {
|
|
148
174
|
type: "message.completed";
|
|
149
175
|
role: "assistant";
|
|
@@ -216,6 +242,8 @@ export type ChatGPTRunState = {
|
|
|
216
242
|
resumable: boolean;
|
|
217
243
|
thread?: ChatGPTThreadRef;
|
|
218
244
|
nextStepId?: string;
|
|
245
|
+
submissionState?: SubmissionState;
|
|
246
|
+
completionState?: CompletionState;
|
|
219
247
|
};
|
|
220
248
|
export type ChatGPTRunData<TOutput = string> = {
|
|
221
249
|
finalOutput?: TOutput;
|
|
@@ -224,6 +252,9 @@ export type ChatGPTRunData<TOutput = string> = {
|
|
|
224
252
|
thread?: ChatGPTThreadRef;
|
|
225
253
|
downloads?: DownloadedFileSummary[];
|
|
226
254
|
reportPath?: string;
|
|
255
|
+
submissionState?: SubmissionState;
|
|
256
|
+
completionState?: CompletionState;
|
|
257
|
+
generationActive?: boolean;
|
|
227
258
|
};
|
|
228
259
|
export type ChatGPTRunResult<TOutput = string> = CommandResult<ChatGPTRunData<TOutput>> & {
|
|
229
260
|
finalOutput?: TOutput;
|
|
@@ -256,6 +287,9 @@ export type ChatGPTResponse = {
|
|
|
256
287
|
resultStatus: CommandStatus;
|
|
257
288
|
thread?: ChatGPTThreadRef;
|
|
258
289
|
reportPath?: string;
|
|
290
|
+
submissionState?: SubmissionState;
|
|
291
|
+
completionState?: CompletionState;
|
|
292
|
+
generationActive?: boolean;
|
|
259
293
|
untrustedOutput?: UntrustedOutputReturnEnvelope;
|
|
260
294
|
unsupported?: UnsupportedField[];
|
|
261
295
|
};
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
export type RiskLevel = "low" | "medium" | "high";
|
|
2
2
|
export declare const commandRisk: {
|
|
3
3
|
readonly "session.bootstrap": "low";
|
|
4
|
+
readonly "experience.detect": "low";
|
|
5
|
+
readonly "experience.open": "medium";
|
|
6
|
+
readonly "configuration.inspect": "low";
|
|
7
|
+
readonly "configuration.apply": "medium";
|
|
8
|
+
readonly "work.start": "medium";
|
|
9
|
+
readonly "work.status": "medium";
|
|
10
|
+
readonly "work.wait": "low";
|
|
11
|
+
readonly "work.steer": "medium";
|
|
12
|
+
readonly "work.readLatest": "medium";
|
|
4
13
|
readonly "threads.search": "medium";
|
|
5
14
|
readonly "threads.open": "medium";
|
|
6
15
|
readonly "threads.new": "low";
|
|
@@ -9,6 +18,7 @@ export declare const commandRisk: {
|
|
|
9
18
|
readonly "messages.ask": "medium";
|
|
10
19
|
readonly "messages.wait": "low";
|
|
11
20
|
readonly "messages.readLatest": "medium";
|
|
21
|
+
readonly "messages.status": "medium";
|
|
12
22
|
readonly "messages.waitAndRead": "medium";
|
|
13
23
|
readonly "artifacts.listLatest": "medium";
|
|
14
24
|
readonly "artifacts.wait": "low";
|
|
@@ -21,6 +31,7 @@ export declare const commandRisk: {
|
|
|
21
31
|
readonly "projects.sources.add": "medium";
|
|
22
32
|
readonly "response.copy": "medium";
|
|
23
33
|
readonly "modes.set": "medium";
|
|
34
|
+
readonly "modes.get": "low";
|
|
24
35
|
readonly "tools.select": "medium";
|
|
25
36
|
readonly "threads.delete": "high";
|
|
26
37
|
readonly "threads.archive": "high";
|
package/dist/src/safety/risk.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
export const commandRisk = {
|
|
2
2
|
"session.bootstrap": "low",
|
|
3
|
+
"experience.detect": "low",
|
|
4
|
+
"experience.open": "medium",
|
|
5
|
+
"configuration.inspect": "low",
|
|
6
|
+
"configuration.apply": "medium",
|
|
7
|
+
"work.start": "medium",
|
|
8
|
+
"work.status": "medium",
|
|
9
|
+
"work.wait": "low",
|
|
10
|
+
"work.steer": "medium",
|
|
11
|
+
"work.readLatest": "medium",
|
|
3
12
|
"threads.search": "medium",
|
|
4
13
|
"threads.open": "medium",
|
|
5
14
|
"threads.new": "low",
|
|
@@ -8,6 +17,7 @@ export const commandRisk = {
|
|
|
8
17
|
"messages.ask": "medium",
|
|
9
18
|
"messages.wait": "low",
|
|
10
19
|
"messages.readLatest": "medium",
|
|
20
|
+
"messages.status": "medium",
|
|
11
21
|
"messages.waitAndRead": "medium",
|
|
12
22
|
"artifacts.listLatest": "medium",
|
|
13
23
|
"artifacts.wait": "low",
|
|
@@ -20,6 +30,7 @@ export const commandRisk = {
|
|
|
20
30
|
"projects.sources.add": "medium",
|
|
21
31
|
"response.copy": "medium",
|
|
22
32
|
"modes.set": "medium",
|
|
33
|
+
"modes.get": "low",
|
|
23
34
|
"tools.select": "medium",
|
|
24
35
|
"threads.delete": "high",
|
|
25
36
|
"threads.archive": "high",
|
|
@@ -1 +1,7 @@
|
|
|
1
|
+
type IntelligenceModeOptionId = "instant" | "medium" | "high" | "extraHigh" | "pro";
|
|
1
2
|
export declare function main(argv?: string[]): Promise<number>;
|
|
3
|
+
export declare function mergeCapture(source: string, labels: readonly string[], modeOptions: Partial<Record<IntelligenceModeOptionId, string[]>>, generationLabels?: {
|
|
4
|
+
stopControl?: readonly string[];
|
|
5
|
+
stoppedAssistant?: readonly string[];
|
|
6
|
+
}): string;
|
|
7
|
+
export {};
|
|
@@ -3,7 +3,17 @@ import { dirname, resolve } from "node:path";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { readLanguageCoverage } from "./locale-capture/language-coverage.js";
|
|
5
5
|
const ENGLISH_MODE_LABELS = new Set(["Latest", "Instant", "Thinking", "Extended", "Medium", "High", "Extra High", "Pro"]);
|
|
6
|
-
const
|
|
6
|
+
const ENGLISH_STOP_CONTROL = new Set(["stop generating", "stop streaming", "stop answering", "cancel"]);
|
|
7
|
+
const ENGLISH_STOPPED_ASSISTANT = new Set(["stopped thinking", "stopped answering", "generation stopped"]);
|
|
8
|
+
const INTELLIGENCE_MODE_OPTION_IDS = ["instant", "medium", "high", "extraHigh", "pro"];
|
|
9
|
+
const ENGLISH_INTELLIGENCE_MODE_OPTIONS = {
|
|
10
|
+
instant: "Instant",
|
|
11
|
+
medium: "Medium",
|
|
12
|
+
high: "High",
|
|
13
|
+
extraHigh: "Extra High",
|
|
14
|
+
pro: "Pro",
|
|
15
|
+
};
|
|
16
|
+
const UPDATE_NOTE = " * Intelligence picker labels updated 2026-06-10 and stop-control labels updated 2026-06-15 from visible ChatGPT Pro sessions.";
|
|
7
17
|
class ApplyUsageError extends Error {
|
|
8
18
|
exitCode;
|
|
9
19
|
constructor(message, exitCode = 2) {
|
|
@@ -45,12 +55,18 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
45
55
|
throw new ApplyUsageError(`Missing successful capture for ${language.bcp47}.`, 1);
|
|
46
56
|
}
|
|
47
57
|
const labels = observedNonEnglishLabels(record);
|
|
48
|
-
|
|
58
|
+
const modeOptions = observedNonEnglishModeOptions(record);
|
|
59
|
+
const stopControl = observedNonEnglishGenerationLabels(record.generationStopLabels, ENGLISH_STOP_CONTROL);
|
|
60
|
+
const stoppedAssistant = observedNonEnglishGenerationLabels(record.generationStoppedLabels, ENGLISH_STOPPED_ASSISTANT);
|
|
61
|
+
if (labels.length === 0 && Object.keys(modeOptions).length === 0 && stopControl.length === 0 && stoppedAssistant.length === 0)
|
|
49
62
|
continue;
|
|
50
63
|
planned.push({
|
|
51
64
|
locale: language.bcp47,
|
|
52
65
|
file: resolve(root, "src/dom/locale", `${language.bcp47}.ts`),
|
|
53
66
|
labels,
|
|
67
|
+
modeOptions,
|
|
68
|
+
stopControl,
|
|
69
|
+
stoppedAssistant,
|
|
54
70
|
});
|
|
55
71
|
}
|
|
56
72
|
if (!options.reviewed) {
|
|
@@ -62,10 +78,13 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
62
78
|
}
|
|
63
79
|
for (const change of planned) {
|
|
64
80
|
const before = await readFile(change.file, "utf8");
|
|
65
|
-
const after =
|
|
81
|
+
const after = mergeCapture(before, change.labels, change.modeOptions, {
|
|
82
|
+
stopControl: change.stopControl,
|
|
83
|
+
stoppedAssistant: change.stoppedAssistant,
|
|
84
|
+
});
|
|
66
85
|
if (after !== before) {
|
|
67
86
|
await writeFile(change.file, after, "utf8");
|
|
68
|
-
console.log(`updated ${change.locale} labels=${change.labels.length}`);
|
|
87
|
+
console.log(`updated ${change.locale} labels=${change.labels.length} modeOptions=${Object.keys(change.modeOptions).length} stopControl=${change.stopControl.length} stoppedAssistant=${change.stoppedAssistant.length}`);
|
|
69
88
|
}
|
|
70
89
|
}
|
|
71
90
|
return 0;
|
|
@@ -93,18 +112,46 @@ function observedNonEnglishLabels(record) {
|
|
|
93
112
|
}
|
|
94
113
|
return labels;
|
|
95
114
|
}
|
|
96
|
-
function
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const line = ` modeLabels: [${merged.map(label => JSON.stringify(label)).join(", ")}],`;
|
|
101
|
-
if (/^\s*modeLabels:\s*\[[^\]]*\],/m.test(text)) {
|
|
102
|
-
return text.replace(/^\s*modeLabels:\s*\[[^\]]*\],/m, line);
|
|
115
|
+
function observedNonEnglishModeOptions(record) {
|
|
116
|
+
const labels = record.intelligenceLabels ?? [];
|
|
117
|
+
if (labels.length !== INTELLIGENCE_MODE_OPTION_IDS.length) {
|
|
118
|
+
throw new ApplyUsageError(`${record.requestedLocale} has ${labels.length} Intelligence labels; expected ${INTELLIGENCE_MODE_OPTION_IDS.length}.`, 1);
|
|
103
119
|
}
|
|
104
|
-
|
|
105
|
-
|
|
120
|
+
const modeOptions = {};
|
|
121
|
+
for (let index = 0; index < INTELLIGENCE_MODE_OPTION_IDS.length; index += 1) {
|
|
122
|
+
const id = INTELLIGENCE_MODE_OPTION_IDS[index];
|
|
123
|
+
const label = labels[index];
|
|
124
|
+
if (label !== ENGLISH_INTELLIGENCE_MODE_OPTIONS[id]) {
|
|
125
|
+
modeOptions[id] = [label];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return modeOptions;
|
|
129
|
+
}
|
|
130
|
+
function observedNonEnglishGenerationLabels(values, englishValues) {
|
|
131
|
+
return dedupe((values ?? [])
|
|
132
|
+
.map(value => value.replace(/\s+/g, " ").trim())
|
|
133
|
+
.filter(value => value.length > 0 && !englishValues.has(value.toLowerCase())));
|
|
134
|
+
}
|
|
135
|
+
export function mergeCapture(source, labels, modeOptions, generationLabels = {}) {
|
|
136
|
+
let text = updateComment(source);
|
|
137
|
+
if (labels.length > 0) {
|
|
138
|
+
const existing = parseExistingModeLabels(text);
|
|
139
|
+
const merged = dedupe([...existing, ...labels]);
|
|
140
|
+
const line = ` modeLabels: [${merged.map(label => JSON.stringify(label)).join(", ")}],`;
|
|
141
|
+
if (/^\s*modeLabels:\s*\[[^\]]*\],/m.test(text)) {
|
|
142
|
+
text = text.replace(/^\s*modeLabels:\s*\[[^\]]*\],/m, line);
|
|
143
|
+
}
|
|
144
|
+
else if (/^\s*copyResponse:\s*.*,\n/m.test(text)) {
|
|
145
|
+
text = text.replace(/^(\s*copyResponse:\s*.*,\n)/m, `$1${line}\n`);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
text = text.replace(/^export const \w+ = \{\n/m, match => `${match}${line}\n`);
|
|
149
|
+
}
|
|
106
150
|
}
|
|
107
|
-
|
|
151
|
+
text = mergeModeOptions(text, modeOptions);
|
|
152
|
+
text = mergeStringArrayProperty(text, "stopControl", generationLabels.stopControl ?? []);
|
|
153
|
+
text = mergeStringArrayProperty(text, "stoppedAssistant", generationLabels.stoppedAssistant ?? []);
|
|
154
|
+
return text;
|
|
108
155
|
}
|
|
109
156
|
function parseExistingModeLabels(source) {
|
|
110
157
|
const match = /^\s*modeLabels:\s*\[(?<body>[^\]]*)\],/m.exec(source);
|
|
@@ -117,6 +164,91 @@ function parseExistingModeLabels(source) {
|
|
|
117
164
|
}
|
|
118
165
|
return labels;
|
|
119
166
|
}
|
|
167
|
+
function mergeModeOptions(source, modeOptions) {
|
|
168
|
+
const existing = parseExistingModeOptions(source);
|
|
169
|
+
const merged = {};
|
|
170
|
+
for (const id of INTELLIGENCE_MODE_OPTION_IDS) {
|
|
171
|
+
const values = dedupe([...(existing[id] ?? []), ...(modeOptions[id] ?? [])]);
|
|
172
|
+
if (values.length > 0) {
|
|
173
|
+
merged[id] = values;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const block = formatModeOptions(merged);
|
|
177
|
+
if (block === undefined) {
|
|
178
|
+
return source;
|
|
179
|
+
}
|
|
180
|
+
if (/^\s*modeOptions:\s*\{[\s\S]*?^\s*\},\n/m.test(source)) {
|
|
181
|
+
return source.replace(/^\s*modeOptions:\s*\{[\s\S]*?^\s*\},\n/m, `${block}\n`);
|
|
182
|
+
}
|
|
183
|
+
if (/^\s*modeLabels:\s*\[[^\]]*\],\n/m.test(source)) {
|
|
184
|
+
return source.replace(/^(\s*modeLabels:\s*\[[^\]]*\],\n)/m, `$1${block}\n`);
|
|
185
|
+
}
|
|
186
|
+
return source.replace(/^export const \w+ = \{\n/m, match => `${match}${block}\n`);
|
|
187
|
+
}
|
|
188
|
+
function parseExistingModeOptions(source) {
|
|
189
|
+
const options = {};
|
|
190
|
+
const blockMatch = /^\s*modeOptions:\s*\{(?<body>[\s\S]*?)^\s*\},/m.exec(source);
|
|
191
|
+
const body = blockMatch?.groups?.body;
|
|
192
|
+
if (body === undefined)
|
|
193
|
+
return options;
|
|
194
|
+
for (const id of INTELLIGENCE_MODE_OPTION_IDS) {
|
|
195
|
+
const lineMatch = new RegExp(`^\\s*${id}:\\s*\\[(?<body>[^\\]]*)\\],`, "m").exec(body);
|
|
196
|
+
const lineBody = lineMatch?.groups?.body;
|
|
197
|
+
if (lineBody === undefined)
|
|
198
|
+
continue;
|
|
199
|
+
const values = [];
|
|
200
|
+
for (const stringMatch of lineBody.matchAll(/"((?:\\"|[^"])*)"/g)) {
|
|
201
|
+
values.push(JSON.parse(`"${stringMatch[1]}"`));
|
|
202
|
+
}
|
|
203
|
+
if (values.length > 0) {
|
|
204
|
+
options[id] = values;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return options;
|
|
208
|
+
}
|
|
209
|
+
function formatModeOptions(modeOptions) {
|
|
210
|
+
const lines = INTELLIGENCE_MODE_OPTION_IDS
|
|
211
|
+
.map(id => {
|
|
212
|
+
const values = modeOptions[id];
|
|
213
|
+
return values === undefined || values.length === 0
|
|
214
|
+
? undefined
|
|
215
|
+
: ` ${id}: [${values.map(value => JSON.stringify(value)).join(", ")}],`;
|
|
216
|
+
})
|
|
217
|
+
.filter((line) => line !== undefined);
|
|
218
|
+
if (lines.length === 0) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
return [" modeOptions: {", ...lines, " },"].join("\n");
|
|
222
|
+
}
|
|
223
|
+
function mergeStringArrayProperty(source, property, values) {
|
|
224
|
+
if (values.length === 0)
|
|
225
|
+
return source;
|
|
226
|
+
const existing = parseExistingStringArrayProperty(source, property);
|
|
227
|
+
const merged = dedupe([...existing, ...values]);
|
|
228
|
+
const line = ` ${property}: [${merged.map(value => JSON.stringify(value)).join(", ")}],`;
|
|
229
|
+
const propertyPattern = new RegExp(`^\\s*${property}:\\s*\\[[^\\]]*\\],`, "m");
|
|
230
|
+
if (propertyPattern.test(source)) {
|
|
231
|
+
return source.replace(propertyPattern, line);
|
|
232
|
+
}
|
|
233
|
+
if (/^\s*responseActions:\s*.*,\n/m.test(source)) {
|
|
234
|
+
return source.replace(/^(\s*responseActions:\s*.*,\n)/m, `$1${line}\n`);
|
|
235
|
+
}
|
|
236
|
+
if (/^\s*modeOptions:\s*\{[\s\S]*?^\s*\},\n/m.test(source)) {
|
|
237
|
+
return source.replace(/^(\s*modeOptions:\s*\{[\s\S]*?^\s*\},\n)/m, `$1${line}\n`);
|
|
238
|
+
}
|
|
239
|
+
return source.replace(/^export const \w+ = \{\n/m, match => `${match}${line}\n`);
|
|
240
|
+
}
|
|
241
|
+
function parseExistingStringArrayProperty(source, property) {
|
|
242
|
+
const match = new RegExp(`^\\s*${property}:\\s*\\[(?<body>[^\\]]*)\\],`, "m").exec(source);
|
|
243
|
+
const body = match?.groups?.body;
|
|
244
|
+
if (body === undefined)
|
|
245
|
+
return [];
|
|
246
|
+
const values = [];
|
|
247
|
+
for (const stringMatch of body.matchAll(/"((?:\\"|[^"])*)"/g)) {
|
|
248
|
+
values.push(JSON.parse(`"${stringMatch[1]}"`));
|
|
249
|
+
}
|
|
250
|
+
return values;
|
|
251
|
+
}
|
|
120
252
|
function updateComment(source) {
|
|
121
253
|
let text = source.replace(/\n \* Omitted because they match English case-insensitively: `modeLabels`[\s\S]*?blocker copy\.\n/g, "\n * Some non-Intelligence surfaces may still fall back to English + `selector_drift`.\n");
|
|
122
254
|
if (!text.includes(UPDATE_NOTE)) {
|
|
@@ -178,7 +310,7 @@ function requiredValue(argv, index, flag) {
|
|
|
178
310
|
function packageRoot() {
|
|
179
311
|
return resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
180
312
|
}
|
|
181
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
313
|
+
if (typeof process !== "undefined" && process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
182
314
|
const exitCode = await main();
|
|
183
315
|
process.exitCode = exitCode;
|
|
184
316
|
}
|
|
@@ -9,6 +9,9 @@ type CaptureOptions = {
|
|
|
9
9
|
limit: number | undefined;
|
|
10
10
|
locales: string[] | undefined;
|
|
11
11
|
openVersionSubmenu: boolean;
|
|
12
|
+
captureGenerationState: boolean;
|
|
13
|
+
generationPrompt: string;
|
|
14
|
+
generationCaptureTimeoutMs: number;
|
|
12
15
|
restore: boolean;
|
|
13
16
|
settleMs: number;
|
|
14
17
|
switchTimeoutMs: number;
|