@youdie006/prodex 0.36.1 → 0.36.3
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/dist/chatgpt-browser.js +78 -4
- package/package.json +1 -1
package/dist/chatgpt-browser.js
CHANGED
|
@@ -632,6 +632,46 @@ export function responseChoiceBlocksThisSend(input) {
|
|
|
632
632
|
return false;
|
|
633
633
|
return !input.newChat && input.project === undefined && input.projectNew === undefined;
|
|
634
634
|
}
|
|
635
|
+
/**
|
|
636
|
+
* Why a requested Pro sub-mode did not make it onto a power-slider picker.
|
|
637
|
+
*
|
|
638
|
+
* The current picker is one five-step slider whose top step IS Pro, and it has
|
|
639
|
+
* no 기본/확장 anywhere - measured: `{ok:true, position:4, max:4, model:"GPT-5.6
|
|
640
|
+
* Sol", effort:"Pro"}`. The send takes that branch and returns, reading
|
|
641
|
+
* `effort ?? model`, so a sub-mode request was dropped on the way past. A run
|
|
642
|
+
* with `--model Pro --pro-mode 확장` finished clean and recorded no warning at
|
|
643
|
+
* all, having never applied 확장. The older picker refuses the same request
|
|
644
|
+
* out loud; silence on one machine and an error on another, for one command,
|
|
645
|
+
* is the half worth fixing. The send is still a correct Pro send, so this is a
|
|
646
|
+
* warning and not a refusal.
|
|
647
|
+
*/
|
|
648
|
+
export function proModeNotAppliedWarning(proMode, sliderEffort) {
|
|
649
|
+
if (!proMode)
|
|
650
|
+
return undefined;
|
|
651
|
+
const step = sliderEffort ? `the slider's "${sliderEffort}" step` : "the slider's current step";
|
|
652
|
+
return (`pro_mode_not_applied: this ChatGPT picker is a power slider with no "Pro ${proMode}" step, ` +
|
|
653
|
+
`so --pro-mode ${proMode} was not applied and the send used ${step}. ` +
|
|
654
|
+
"Drop --pro-mode here, or clear a saved default with `prodex setup --clear-pro-mode`.");
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Which of two flags the slider actually obeyed.
|
|
658
|
+
*
|
|
659
|
+
* On this picker one control carries both: "Pro" is the top EFFORT step, not a
|
|
660
|
+
* model. Naming a model AND an effort therefore asks for two positions of the
|
|
661
|
+
* same slider, and the send takes `effort ?? model` - so the model is dropped.
|
|
662
|
+
* Measured: `--model Pro --effort 중간` answered from gpt-5-6-thinking with an
|
|
663
|
+
* empty warnings list. Asking for Pro and quietly getting a cheaper model is
|
|
664
|
+
* the kind of thing a receipt exists to catch.
|
|
665
|
+
*/
|
|
666
|
+
export function modelIgnoredForEffortWarning(model, effort) {
|
|
667
|
+
if (!model || !effort)
|
|
668
|
+
return undefined;
|
|
669
|
+
if (model.trim().toLowerCase() === effort.trim().toLowerCase())
|
|
670
|
+
return undefined;
|
|
671
|
+
return (`model_ignored: this ChatGPT picker sets the model and the effort with one slider, ` +
|
|
672
|
+
`so --model ${model} and --effort ${effort} name two positions of it. The send used ${effort}. ` +
|
|
673
|
+
`Pass only one of them to say which you meant.`);
|
|
674
|
+
}
|
|
635
675
|
export function chatGptBusyBlocker(state) {
|
|
636
676
|
// Waiting for a choice is not generating. Conflating them turned a click
|
|
637
677
|
// away from ready into a full send budget spent on "still generating".
|
|
@@ -1614,6 +1654,14 @@ async function selectModelReasoning(cdp, options, selectionWarnings = []) {
|
|
|
1614
1654
|
if (wanted) {
|
|
1615
1655
|
await selectPowerStep(cdp, wanted);
|
|
1616
1656
|
}
|
|
1657
|
+
// This branch cannot honour a sub-mode, and used to return without
|
|
1658
|
+
// saying so - the caller got a clean receipt for a 확장 it never got.
|
|
1659
|
+
const proModeWarning = proModeNotAppliedWarning(options.proMode, sliderState.effort ?? undefined);
|
|
1660
|
+
if (proModeWarning)
|
|
1661
|
+
selectionWarnings.push(proModeWarning);
|
|
1662
|
+
const modelWarning = modelIgnoredForEffortWarning(options.model, options.effort);
|
|
1663
|
+
if (modelWarning)
|
|
1664
|
+
selectionWarnings.push(modelWarning);
|
|
1617
1665
|
await dispatchEscapeKey(cdp);
|
|
1618
1666
|
return;
|
|
1619
1667
|
}
|
|
@@ -3906,6 +3954,30 @@ export function transcriptMatchesSentPrompt(userText, sentPrompt) {
|
|
|
3906
3954
|
// separates, U+E201 closes) and keeps the real sources in content_references.
|
|
3907
3955
|
const CITATION_DELIMITER_PATTERN = /[\uE200-\uE206]/;
|
|
3908
3956
|
const CITATION_MARKER_PATTERN = /\uE200[^\uE200-\uE206]*(?:[\uE202\uE204-\uE206][^\uE200-\uE206]*)*[\uE201\uE203]/g;
|
|
3957
|
+
/**
|
|
3958
|
+
* The words a citation marker was wrapping, if any.
|
|
3959
|
+
*
|
|
3960
|
+
* The markers come in two shapes. `<E200>cite<E202>turn0search0<E201>` is a
|
|
3961
|
+
* bare anchor - kind then reference id, nothing a reader would miss. But
|
|
3962
|
+
* `<E200>url<E202>Timeanddate.com — World Clock<E202>turn0search0<E201>` puts a
|
|
3963
|
+
* visible title in the middle, and that title is part of the sentence. Caught by
|
|
3964
|
+
* diffing a saved answer against its thread: a web-search reply ended at a
|
|
3965
|
+
* dangling "Source:" because the title had been deleted along with the marker.
|
|
3966
|
+
*/
|
|
3967
|
+
export function citationMarkerText(marker) {
|
|
3968
|
+
// The first segment is the kind and the rest are a mix of reference tokens and,
|
|
3969
|
+
// for some kinds, prose. Sorting them by SHAPE rather than by kind keeps a
|
|
3970
|
+
// title from a kind not seen yet: `cite` can carry several ids
|
|
3971
|
+
// (`cite<E202>turn0search19<E202>turn0search5`), and dropping every
|
|
3972
|
+
// id-shaped segment leaves nothing there, which is right.
|
|
3973
|
+
const referenceToken = /^turn\d+[a-z]+\d+$/i;
|
|
3974
|
+
const segments = marker.replace(/^[\uE200-\uE206]|[\uE200-\uE206]$/g, "").split(/[\uE200-\uE206]/);
|
|
3975
|
+
return segments
|
|
3976
|
+
.slice(1)
|
|
3977
|
+
.filter((segment) => segment.length > 0 && !referenceToken.test(segment))
|
|
3978
|
+
.join(" ")
|
|
3979
|
+
.trim();
|
|
3980
|
+
}
|
|
3909
3981
|
/**
|
|
3910
3982
|
* Turn those markers into ordinary markdown links, so a saved answer keeps the
|
|
3911
3983
|
* sources instead of the private-use noise (or, as in the rendered DOM, nothing
|
|
@@ -3936,11 +4008,13 @@ export function resolveTranscriptCitations(text, references = []) {
|
|
|
3936
4008
|
};
|
|
3937
4009
|
let resolved = text;
|
|
3938
4010
|
for (const [marker, reference] of byMarker) {
|
|
3939
|
-
|
|
4011
|
+
// No items to link is not permission to delete the sentence: fall back to
|
|
4012
|
+
// whatever the marker was wrapping.
|
|
4013
|
+
resolved = resolved.split(marker).join(linksFor(reference) || citationMarkerText(marker));
|
|
3940
4014
|
}
|
|
3941
|
-
// Anything still delimited had no reference to restore
|
|
3942
|
-
//
|
|
3943
|
-
return resolved.replace(CITATION_MARKER_PATTERN,
|
|
4015
|
+
// Anything still delimited had no reference to restore. The delimiters must not
|
|
4016
|
+
// reach a receipt, but the words between them still belong to the answer.
|
|
4017
|
+
return resolved.replace(CITATION_MARKER_PATTERN, (marker) => citationMarkerText(marker));
|
|
3944
4018
|
}
|
|
3945
4019
|
export function deepResearchReportExpression(conversationId) {
|
|
3946
4020
|
return `(async () => {
|