chatgpt-pro-research 0.2.0 → 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 +104 -18
- 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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/plugin.ts
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
|
-
import { dirname as dirname2, extname, isAbsolute, join as join3, resolve as
|
|
5
|
+
import { dirname as dirname2, extname, isAbsolute, join as join3, resolve as resolve3, sep } from "node:path";
|
|
6
6
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import z from "@deepseek-ai/schemastery";
|
|
@@ -597,7 +597,7 @@ var ResearchEngine = class {
|
|
|
597
597
|
if (this.active !== void 0) {
|
|
598
598
|
await this.active.promise;
|
|
599
599
|
} else {
|
|
600
|
-
await new Promise((
|
|
600
|
+
await new Promise((resolve4) => setTimeout(resolve4, 0));
|
|
601
601
|
}
|
|
602
602
|
}
|
|
603
603
|
}
|
|
@@ -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
|
}
|
|
@@ -838,14 +840,16 @@ ${result.summary}
|
|
|
838
840
|
if (topic.status === "completed" || topic.status === "cancelled") return;
|
|
839
841
|
if (error instanceof TransportError) {
|
|
840
842
|
if (error.failure === "worker") {
|
|
841
|
-
await this.transition(topic, "failed");
|
|
843
|
+
await this.transition(topic, "failed", { stopReason: error.message });
|
|
842
844
|
return;
|
|
843
845
|
}
|
|
844
846
|
const reason = error.failure === "login" || error.failure === "upload" || error.failure === "ui" ? error.failure : "timeout";
|
|
845
|
-
await this.transition(topic, "stalled", { stallReason: reason });
|
|
847
|
+
await this.transition(topic, "stalled", { stallReason: reason, stopReason: error.message });
|
|
846
848
|
return;
|
|
847
849
|
}
|
|
848
|
-
await this.transition(topic, "failed"
|
|
850
|
+
await this.transition(topic, "failed", {
|
|
851
|
+
stopReason: error instanceof Error ? error.message : String(error)
|
|
852
|
+
});
|
|
849
853
|
}
|
|
850
854
|
async transition(topic, next, extra) {
|
|
851
855
|
assertTransition(topic.status, next);
|
|
@@ -901,7 +905,15 @@ var SELECTORS = {
|
|
|
901
905
|
'[data-markdown-text-style="assistant-message"]',
|
|
902
906
|
'[data-message-author-role="assistant"]'
|
|
903
907
|
].join(", "),
|
|
904
|
-
|
|
908
|
+
// The composer has several file inputs (camera, photos, videos). The general
|
|
909
|
+
// attachment input is the one without an `accept` filter; the camera input
|
|
910
|
+
// rejects multiple files.
|
|
911
|
+
fileInput: [
|
|
912
|
+
'input[type="file"][aria-label="\u9644\u52A0\u6587\u4EF6"]',
|
|
913
|
+
'input[type="file"][aria-label*="Attach" i]:not([capture])',
|
|
914
|
+
'form input[type="file"][multiple]:not([accept]):not([capture])',
|
|
915
|
+
'input[type="file"][multiple]:not([accept]):not([capture])'
|
|
916
|
+
].join(", "),
|
|
905
917
|
modelPicker: [
|
|
906
918
|
'button[aria-label*="\u9009\u62E9 ChatGPT \u6A21\u578B"]',
|
|
907
919
|
'button[aria-label*="\u6A21\u578B"]',
|
|
@@ -922,6 +934,16 @@ function advanceCompletion(previous, text, streaming) {
|
|
|
922
934
|
return { lastText: text, stable: 1, answered: false };
|
|
923
935
|
}
|
|
924
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
|
+
|
|
925
947
|
// ../transport/src/chatgpt.ts
|
|
926
948
|
function sha256(value) {
|
|
927
949
|
return createHash3("sha256").update(value, "utf8").digest("hex");
|
|
@@ -947,6 +969,7 @@ async function firstVisible(page, selector, timeoutMs) {
|
|
|
947
969
|
}
|
|
948
970
|
var ChatGptWebTransport = class {
|
|
949
971
|
context;
|
|
972
|
+
launching;
|
|
950
973
|
submissions = /* @__PURE__ */ new Map();
|
|
951
974
|
options;
|
|
952
975
|
constructor(options) {
|
|
@@ -957,6 +980,15 @@ var ChatGptWebTransport = class {
|
|
|
957
980
|
}
|
|
958
981
|
async ensureContext() {
|
|
959
982
|
if (this.context !== void 0) return this.context;
|
|
983
|
+
if (this.launching !== void 0) return this.launching;
|
|
984
|
+
this.launching = this.launchContext();
|
|
985
|
+
try {
|
|
986
|
+
return await this.launching;
|
|
987
|
+
} finally {
|
|
988
|
+
this.launching = void 0;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
async launchContext() {
|
|
960
992
|
await mkdir2(this.options.profileDir, { recursive: true });
|
|
961
993
|
const base = {
|
|
962
994
|
headless: this.options.headless ?? false,
|
|
@@ -964,7 +996,12 @@ var ChatGptWebTransport = class {
|
|
|
964
996
|
args: ["--disable-blink-features=AutomationControlled"]
|
|
965
997
|
};
|
|
966
998
|
try {
|
|
967
|
-
|
|
999
|
+
const context = await chromium.launchPersistentContext(this.options.profileDir, { ...base, channel: "chrome" });
|
|
1000
|
+
context.on("close", () => {
|
|
1001
|
+
if (this.context === context) this.context = void 0;
|
|
1002
|
+
});
|
|
1003
|
+
this.context = context;
|
|
1004
|
+
return context;
|
|
968
1005
|
} catch (error) {
|
|
969
1006
|
throw new TransportError(
|
|
970
1007
|
`cannot launch Chrome with profile ${this.options.profileDir}; install Google Chrome or pass browser.headless=false plus a Playwright browser. ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -972,7 +1009,6 @@ var ChatGptWebTransport = class {
|
|
|
972
1009
|
{ cause: error }
|
|
973
1010
|
);
|
|
974
1011
|
}
|
|
975
|
-
return this.context;
|
|
976
1012
|
}
|
|
977
1013
|
async probe() {
|
|
978
1014
|
const context = await this.ensureContext();
|
|
@@ -1116,13 +1152,24 @@ ${attachments.join("\n")}`);
|
|
|
1116
1152
|
const images = [];
|
|
1117
1153
|
for (const [index, source] of sources.slice(0, 8).entries()) {
|
|
1118
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
|
+
}
|
|
1119
1166
|
if (source.startsWith("blob:")) {
|
|
1120
1167
|
const dataUrl = await page.evaluate(async (src) => {
|
|
1121
1168
|
const response = await fetch(src);
|
|
1122
1169
|
const blob = await response.blob();
|
|
1123
|
-
return await new Promise((
|
|
1170
|
+
return await new Promise((resolve4, reject) => {
|
|
1124
1171
|
const reader = new FileReader();
|
|
1125
|
-
reader.onload = () =>
|
|
1172
|
+
reader.onload = () => resolve4(String(reader.result));
|
|
1126
1173
|
reader.onerror = () => reject(reader.error);
|
|
1127
1174
|
reader.readAsDataURL(blob);
|
|
1128
1175
|
});
|
|
@@ -1213,8 +1260,8 @@ ${attachments.join("\n")}`);
|
|
|
1213
1260
|
async richAnswerText(page) {
|
|
1214
1261
|
const text = await this.lastAssistantText(page);
|
|
1215
1262
|
if (text !== "") return text;
|
|
1216
|
-
const images = await page.evaluate(() => [...document.querySelectorAll("main img")].filter((image) => image.naturalWidth >= 300).map((image) => image.
|
|
1217
|
-
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(",")}` : "";
|
|
1218
1265
|
}
|
|
1219
1266
|
async lastAssistantText(page) {
|
|
1220
1267
|
const messages = page.locator(SELECTORS.assistantMessage);
|
|
@@ -1224,6 +1271,41 @@ ${attachments.join("\n")}`);
|
|
|
1224
1271
|
}
|
|
1225
1272
|
};
|
|
1226
1273
|
|
|
1274
|
+
// ../transport/src/shared.ts
|
|
1275
|
+
import { resolve as resolve2 } from "node:path";
|
|
1276
|
+
var REGISTRY = /* @__PURE__ */ Symbol.for("dsh-pro.transport.shared.v1");
|
|
1277
|
+
function registry() {
|
|
1278
|
+
const holder = globalThis;
|
|
1279
|
+
const existing = holder[REGISTRY];
|
|
1280
|
+
if (existing instanceof Map) return existing;
|
|
1281
|
+
const created = /* @__PURE__ */ new Map();
|
|
1282
|
+
holder[REGISTRY] = created;
|
|
1283
|
+
return created;
|
|
1284
|
+
}
|
|
1285
|
+
function acquireSharedTransport(options, create = () => new ChatGptWebTransport(options)) {
|
|
1286
|
+
const key = resolve2(options.profileDir);
|
|
1287
|
+
const slots = registry();
|
|
1288
|
+
let slot = slots.get(key);
|
|
1289
|
+
if (slot === void 0) {
|
|
1290
|
+
slot = { transport: create(), refs: 0 };
|
|
1291
|
+
slots.set(key, slot);
|
|
1292
|
+
}
|
|
1293
|
+
slot.refs += 1;
|
|
1294
|
+
const target = slot;
|
|
1295
|
+
let released = false;
|
|
1296
|
+
return {
|
|
1297
|
+
transport: target.transport,
|
|
1298
|
+
release: () => {
|
|
1299
|
+
if (released) return;
|
|
1300
|
+
released = true;
|
|
1301
|
+
target.refs -= 1;
|
|
1302
|
+
if (target.refs > 0) return;
|
|
1303
|
+
if (slots.get(key) === target) slots.delete(key);
|
|
1304
|
+
void target.transport.close();
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1227
1309
|
// src/plugin.ts
|
|
1228
1310
|
var Config = z.object({
|
|
1229
1311
|
rounds: z.number().step(1).min(1).max(10).default(3).description("\u6BCF\u4E3B\u9898\u9ED8\u8BA4\u8F6E\u6B21\u4E0A\u9650\uFF081\u201310\uFF09\u3002"),
|
|
@@ -1331,6 +1413,7 @@ var ProResearchService = class {
|
|
|
1331
1413
|
stores = /* @__PURE__ */ new Map();
|
|
1332
1414
|
topicSessions = /* @__PURE__ */ new Map();
|
|
1333
1415
|
transport;
|
|
1416
|
+
shared;
|
|
1334
1417
|
rootFor(cwd) {
|
|
1335
1418
|
return cwd.trim() === "" ? process.cwd() : cwd;
|
|
1336
1419
|
}
|
|
@@ -1354,10 +1437,11 @@ var ProResearchService = class {
|
|
|
1354
1437
|
}
|
|
1355
1438
|
transportFor() {
|
|
1356
1439
|
if (this.transport !== void 0) return this.transport;
|
|
1357
|
-
this.
|
|
1440
|
+
this.shared = acquireSharedTransport({
|
|
1358
1441
|
profileDir: this.config.browser.profileDir,
|
|
1359
1442
|
headless: this.config.browser.headless
|
|
1360
1443
|
});
|
|
1444
|
+
this.transport = this.shared.transport;
|
|
1361
1445
|
return this.transport;
|
|
1362
1446
|
}
|
|
1363
1447
|
judge() {
|
|
@@ -1532,8 +1616,8 @@ ${input.answer.slice(0, 3e4)}`
|
|
|
1532
1616
|
if (entry === void 0) throw new Error(`unknown topic: ${id}`);
|
|
1533
1617
|
const store = this.storeAt(entry.root, entry.mode);
|
|
1534
1618
|
const dir = await store.dirOf(id);
|
|
1535
|
-
const artifactsRoot =
|
|
1536
|
-
const target =
|
|
1619
|
+
const artifactsRoot = resolve3(dir, "artifacts");
|
|
1620
|
+
const target = resolve3(dir, relativePath);
|
|
1537
1621
|
if (target !== artifactsRoot && !target.startsWith(`${artifactsRoot}${sep}`)) {
|
|
1538
1622
|
throw new Error("artifact path escapes the topic");
|
|
1539
1623
|
}
|
|
@@ -1611,7 +1695,7 @@ ${input.answer.slice(0, 3e4)}`
|
|
|
1611
1695
|
withSources(cwd, refs) {
|
|
1612
1696
|
return refs.map((ref) => ({
|
|
1613
1697
|
...ref,
|
|
1614
|
-
source: isAbsolute(ref.path) ? ref.path :
|
|
1698
|
+
source: isAbsolute(ref.path) ? ref.path : resolve3(cwd, ref.path)
|
|
1615
1699
|
}));
|
|
1616
1700
|
}
|
|
1617
1701
|
withDesignCount(brief, designs) {
|
|
@@ -1686,7 +1770,9 @@ ${input.answer.slice(0, 3e4)}`
|
|
|
1686
1770
|
};
|
|
1687
1771
|
}
|
|
1688
1772
|
dispose() {
|
|
1689
|
-
|
|
1773
|
+
this.shared?.release();
|
|
1774
|
+
this.shared = void 0;
|
|
1775
|
+
this.transport = void 0;
|
|
1690
1776
|
}
|
|
1691
1777
|
};
|
|
1692
1778
|
function registerSkill(ctx, spec2) {
|
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",
|