chatgpt-pro-research 0.2.1 → 0.2.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/lib/client.js +132 -3
- package/lib/index.js +26 -3
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -34,8 +34,135 @@ var import_react = require("react");
|
|
|
34
34
|
var RESEARCH_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-40 -76 200 200"><title>Anyvia R</title><defs><mask id="R-mono-black-standard-gap" maskUnits="userSpaceOnUse" x="-100" y="-100" width="400" height="400"><rect x="-100" y="-100" width="400" height="400" fill="white"/><path d="M77.18032292691355 52.74975779269961 A3 3 0 0 1 79.72446721538282 48.16 L108.02474889607315 48.16 A3 3 0 0 1 110.56889318454242 49.57024220730038 L139.21290427606598 95.41024220730039 A3 3 0 0 1 136.6687599875967 100 L108.36847830690638 100 A3 3 0 0 1 105.82433401843711 98.58975779269961 Z" transform="translate(-30 -12)" fill="black" stroke="black" stroke-width="6" stroke-linejoin="round"/></mask></defs><g mask="url(#R-mono-black-standard-gap)"><path d="M3.46 -40 H67 A39 39 0 0 1 67 38 H36.81354211962983 V84.54 Q36.81354211962983 88 33.35354211962983 88 H3.46 Q0 88 0 84.54 V-36.54 Q0 -40 3.46 -40 Z M36.81354211962983 -14 V12 H67 A13 13 0 0 0 67 -14 Z" fill="currentColor" fill-rule="evenodd"/></g><path d="M77.18032292691355 52.74975779269961 A3 3 0 0 1 79.72446721538282 48.16 L108.02474889607315 48.16 A3 3 0 0 1 110.56889318454242 49.57024220730038 L139.21290427606598 95.41024220730039 A3 3 0 0 1 136.6687599875967 100 L108.36847830690638 100 A3 3 0 0 1 105.82433401843711 98.58975779269961 Z" transform="translate(-30 -12)" fill="currentColor"/></svg>';
|
|
35
35
|
var DESIGN_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-22.599456503942804 -56 200 200"><title>Anyvia X</title><defs><mask id="X-mono-black-standard-gap" maskUnits="userSpaceOnUse" x="-100" y="-100" width="400" height="400"><rect x="-100" y="-100" width="400" height="400" fill="white"/><path d="M77.18032292691355 52.74975779269961 A3 3 0 0 1 79.72446721538282 48.16 L108.02474889607315 48.16 A3 3 0 0 1 110.56889318454242 49.57024220730038 L139.21290427606598 95.41024220730039 A3 3 0 0 1 136.6687599875967 100 L108.36847830690638 100 A3 3 0 0 1 105.82433401843711 98.58975779269961 Z" transform="translate(-12 0)" fill="black" stroke="black" stroke-width="6" stroke-linejoin="round"/></mask></defs><g mask="url(#X-mono-black-standard-gap)"><path d="M89.67202319894069 -10.373520654246889 A3.46 3.46 0 0 1 92.60626961164192 -12 L127.85608887910462 -12 A3.46 3.46 0 0 1 130.79033529180586 -6.706479345753113 L65.12906379317373 98.37352065424689 A3.46 3.46 0 0 1 62.19481738047249 100 L26.94499811300981 100 A3.46 3.46 0 0 1 24.010751700308575 94.70647934575311 Z" fill="currentColor"/><path d="M28.027942559241307 -6.706479345753113 A3.46 3.46 0 0 1 30.96218897194254 -12 L58.17762652153973 -12 A3.46 3.46 0 0 1 61.111872934240964 -10.373520654246889 L91.78046072595076 38.70647934575311 A3.46 3.46 0 0 1 88.84621431324952 44 L61.63077676365233 44 A3.46 3.46 0 0 1 58.69653035095109 42.37352065424689 Z" fill="currentColor"/></g><path d="M77.18032292691355 52.74975779269961 A3 3 0 0 1 79.72446721538282 48.16 L108.02474889607315 48.16 A3 3 0 0 1 110.56889318454242 49.57024220730038 L139.21290427606598 95.41024220730039 A3 3 0 0 1 136.6687599875967 100 L108.36847830690638 100 A3 3 0 0 1 105.82433401843711 98.58975779269961 Z" transform="translate(-12 0)" fill="currentColor"/></svg>';
|
|
36
36
|
|
|
37
|
+
// client/sidebar-status.ts
|
|
38
|
+
var POLL_MS = 5e3;
|
|
39
|
+
function countTopics(topics) {
|
|
40
|
+
const counts = { active: 0, completed: 0, failed: 0 };
|
|
41
|
+
for (const topic of topics) {
|
|
42
|
+
switch (topic.status) {
|
|
43
|
+
case "queued":
|
|
44
|
+
case "uploading":
|
|
45
|
+
case "submitted":
|
|
46
|
+
case "waiting":
|
|
47
|
+
case "answered":
|
|
48
|
+
case "adjudicating":
|
|
49
|
+
counts.active += 1;
|
|
50
|
+
break;
|
|
51
|
+
case "completed":
|
|
52
|
+
counts.completed += 1;
|
|
53
|
+
break;
|
|
54
|
+
case "failed":
|
|
55
|
+
case "stalled":
|
|
56
|
+
counts.failed += 1;
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return counts;
|
|
63
|
+
}
|
|
64
|
+
function badgeText(counts) {
|
|
65
|
+
const parts = [];
|
|
66
|
+
if (counts.active > 0) parts.push(`${counts.active} \u8FDB\u884C`);
|
|
67
|
+
if (counts.completed > 0) parts.push(`${counts.completed} \u5B8C\u6210`);
|
|
68
|
+
if (counts.failed > 0) parts.push(`${counts.failed} \u5931\u8D25`);
|
|
69
|
+
return parts.join(" \xB7 ");
|
|
70
|
+
}
|
|
71
|
+
function mountSidebarStatus(options) {
|
|
72
|
+
if (typeof document === "undefined") return () => {
|
|
73
|
+
};
|
|
74
|
+
let badge;
|
|
75
|
+
let text = "";
|
|
76
|
+
let disposed = false;
|
|
77
|
+
let polling = false;
|
|
78
|
+
let attachTimer;
|
|
79
|
+
let observer;
|
|
80
|
+
const rowFor = () => {
|
|
81
|
+
const buttons = document.querySelectorAll("button[aria-label]");
|
|
82
|
+
for (const button of buttons) {
|
|
83
|
+
if (button.getAttribute("aria-label") === options.label) return button;
|
|
84
|
+
}
|
|
85
|
+
return void 0;
|
|
86
|
+
};
|
|
87
|
+
const applyText = (next) => {
|
|
88
|
+
text = next;
|
|
89
|
+
if (badge !== void 0 && badge.textContent !== text) badge.textContent = text;
|
|
90
|
+
ensureMounted();
|
|
91
|
+
};
|
|
92
|
+
const ensureMounted = () => {
|
|
93
|
+
if (disposed) return;
|
|
94
|
+
if (text === "") {
|
|
95
|
+
badge?.remove();
|
|
96
|
+
badge = void 0;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const row = rowFor();
|
|
100
|
+
if (row === void 0) return;
|
|
101
|
+
const title = row.querySelector('[class*="panelTitle"]');
|
|
102
|
+
if (title === null) {
|
|
103
|
+
badge?.remove();
|
|
104
|
+
badge = void 0;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (badge !== void 0 && badge.parentElement === row) {
|
|
108
|
+
if (badge.textContent !== text) badge.textContent = text;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
badge = document.createElement("span");
|
|
112
|
+
badge.dataset.dshProBadge = options.panelId;
|
|
113
|
+
badge.textContent = text;
|
|
114
|
+
badge.setAttribute("aria-hidden", "true");
|
|
115
|
+
badge.style.cssText = [
|
|
116
|
+
"margin-left:auto",
|
|
117
|
+
"display:inline-flex",
|
|
118
|
+
"align-items:center",
|
|
119
|
+
"flex:0 0 auto",
|
|
120
|
+
"font-size:10px",
|
|
121
|
+
"line-height:1",
|
|
122
|
+
"opacity:.62",
|
|
123
|
+
"white-space:nowrap",
|
|
124
|
+
"font-variant-numeric:tabular-nums",
|
|
125
|
+
"pointer-events:none"
|
|
126
|
+
].join(";");
|
|
127
|
+
row.appendChild(badge);
|
|
128
|
+
};
|
|
129
|
+
const refresh = async () => {
|
|
130
|
+
if (disposed || polling) return;
|
|
131
|
+
polling = true;
|
|
132
|
+
try {
|
|
133
|
+
const response = await fetch(`${options.routes}/topics`, { headers: { accept: "application/json" } });
|
|
134
|
+
if (!response.ok) return;
|
|
135
|
+
const data = await response.json();
|
|
136
|
+
applyText(badgeText(countTopics(data.topics ?? [])));
|
|
137
|
+
} catch {
|
|
138
|
+
} finally {
|
|
139
|
+
polling = false;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
observer = new MutationObserver(() => {
|
|
143
|
+
if (attachTimer !== void 0) return;
|
|
144
|
+
attachTimer = window.setTimeout(() => {
|
|
145
|
+
attachTimer = void 0;
|
|
146
|
+
ensureMounted();
|
|
147
|
+
}, 100);
|
|
148
|
+
});
|
|
149
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
150
|
+
const timer = window.setInterval(() => {
|
|
151
|
+
void refresh();
|
|
152
|
+
}, POLL_MS);
|
|
153
|
+
void refresh();
|
|
154
|
+
return () => {
|
|
155
|
+
disposed = true;
|
|
156
|
+
window.clearInterval(timer);
|
|
157
|
+
if (attachTimer !== void 0) window.clearTimeout(attachTimer);
|
|
158
|
+
observer?.disconnect();
|
|
159
|
+
badge?.remove();
|
|
160
|
+
badge = void 0;
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
37
164
|
// client/panel.tsx
|
|
38
|
-
var
|
|
165
|
+
var POLL_MS2 = 3e3;
|
|
39
166
|
var config = {
|
|
40
167
|
routes: "/chatgpt-pro-research",
|
|
41
168
|
panelId: "chatgpt-pro-research",
|
|
@@ -126,7 +253,7 @@ function Panel() {
|
|
|
126
253
|
void loadList();
|
|
127
254
|
const timer = setInterval(() => {
|
|
128
255
|
void loadList();
|
|
129
|
-
},
|
|
256
|
+
}, POLL_MS2);
|
|
130
257
|
return () => clearInterval(timer);
|
|
131
258
|
}, [loadList]);
|
|
132
259
|
(0, import_react.useEffect)(() => {
|
|
@@ -134,7 +261,7 @@ function Panel() {
|
|
|
134
261
|
void loadDetail(selected);
|
|
135
262
|
const timer = setInterval(() => {
|
|
136
263
|
void loadDetail(selected);
|
|
137
|
-
},
|
|
264
|
+
}, POLL_MS2);
|
|
138
265
|
return () => clearInterval(timer);
|
|
139
266
|
}, [selected, loadDetail, topics]);
|
|
140
267
|
const act = (0, import_react.useCallback)(async (action, conclusion) => {
|
|
@@ -315,6 +442,8 @@ function Icon({ kind }) {
|
|
|
315
442
|
function apply(ctx) {
|
|
316
443
|
ctx.slots.inject("main", () => ctx.slots.register({ name: "main", key: config.panelId }, () => (0, import_react.createElement)(Panel)));
|
|
317
444
|
ctx.slots.inject("sidebar.panellist", () => ctx.slots.register({ name: "sidebar.panellist", id: config.panelId, order: 21, label: () => config.label }, () => (0, import_react.createElement)(Icon, { kind: config.icon })));
|
|
445
|
+
const disposeBadge = mountSidebarStatus({ label: config.label, routes: config.routes, panelId: config.panelId });
|
|
446
|
+
if (typeof ctx.effect === "function") ctx.effect(() => disposeBadge, `${config.panelId}: sidebar status badge`);
|
|
318
447
|
}
|
|
319
448
|
|
|
320
449
|
// client/index.tsx
|
package/lib/index.js
CHANGED
|
@@ -733,7 +733,9 @@ var ResearchEngine = class {
|
|
|
733
733
|
try {
|
|
734
734
|
return await this.options.transport.fetch({ submissionId });
|
|
735
735
|
} catch (error) {
|
|
736
|
-
if (polled.answer !== void 0)
|
|
736
|
+
if (polled.answer !== void 0) {
|
|
737
|
+
return { answer: polled.answer.startsWith("image:") ? "" : polled.answer };
|
|
738
|
+
}
|
|
737
739
|
throw error;
|
|
738
740
|
}
|
|
739
741
|
}
|
|
@@ -932,6 +934,16 @@ function advanceCompletion(previous, text, streaming) {
|
|
|
932
934
|
return { lastText: text, stable: 1, answered: false };
|
|
933
935
|
}
|
|
934
936
|
|
|
937
|
+
// ../transport/src/assets.ts
|
|
938
|
+
function parseDataUrlImage(source) {
|
|
939
|
+
const match = /^data:([^;,]+);base64,(.*)$/s.exec(source);
|
|
940
|
+
if (match === null) return void 0;
|
|
941
|
+
const mime = match[1];
|
|
942
|
+
const base64 = match[2];
|
|
943
|
+
if (mime === void 0 || base64 === void 0) return void 0;
|
|
944
|
+
return { mime, base64: base64.replace(/\s/g, "") };
|
|
945
|
+
}
|
|
946
|
+
|
|
935
947
|
// ../transport/src/chatgpt.ts
|
|
936
948
|
function sha256(value) {
|
|
937
949
|
return createHash3("sha256").update(value, "utf8").digest("hex");
|
|
@@ -1140,6 +1152,17 @@ ${attachments.join("\n")}`);
|
|
|
1140
1152
|
const images = [];
|
|
1141
1153
|
for (const [index, source] of sources.slice(0, 8).entries()) {
|
|
1142
1154
|
try {
|
|
1155
|
+
if (source.startsWith("data:")) {
|
|
1156
|
+
const parsed = parseDataUrlImage(source);
|
|
1157
|
+
if (parsed === void 0) continue;
|
|
1158
|
+
if (Buffer.from(parsed.base64, "base64").byteLength < 2e4) continue;
|
|
1159
|
+
images.push({
|
|
1160
|
+
name: `image-${String(index + 1).padStart(2, "0")}.${extensionFor(parsed.mime)}`,
|
|
1161
|
+
mime: parsed.mime,
|
|
1162
|
+
base64: parsed.base64
|
|
1163
|
+
});
|
|
1164
|
+
continue;
|
|
1165
|
+
}
|
|
1143
1166
|
if (source.startsWith("blob:")) {
|
|
1144
1167
|
const dataUrl = await page.evaluate(async (src) => {
|
|
1145
1168
|
const response = await fetch(src);
|
|
@@ -1237,8 +1260,8 @@ ${attachments.join("\n")}`);
|
|
|
1237
1260
|
async richAnswerText(page) {
|
|
1238
1261
|
const text = await this.lastAssistantText(page);
|
|
1239
1262
|
if (text !== "") return text;
|
|
1240
|
-
const images = await page.evaluate(() => [...document.querySelectorAll("main img")].filter((image) => image.naturalWidth >= 300).map((image) => image.
|
|
1241
|
-
return images.length > 0 ? `image:${images.join("
|
|
1263
|
+
const images = await page.evaluate(() => [...document.querySelectorAll("main img")].filter((image) => image.naturalWidth >= 300).map((image) => `${image.naturalWidth}x${image.naturalHeight}`));
|
|
1264
|
+
return images.length > 0 ? `image:${images.length}:${images.join(",")}` : "";
|
|
1242
1265
|
}
|
|
1243
1266
|
async lastAssistantText(page) {
|
|
1244
1267
|
const messages = page.locator(SELECTORS.assistantMessage);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chatgpt-pro-research",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "ChatGPT Pro Research: unattended multi-round research through a real ChatGPT Pro web session, with local records and a DSH sidebar.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|