dsh-subagent-agy 0.0.0-stage → 0.2.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/README.md +401 -3
- package/cordis.patch.yml +15 -0
- package/icon.svg +1 -0
- package/lib/classify.js +40 -0
- package/lib/client.js +397 -0
- package/lib/gemini-web.js +400 -0
- package/lib/index.js +183 -0
- package/lib/parallel.js +226 -0
- package/lib/run.js +314 -0
- package/lib/types/index.d.ts +71 -0
- package/lib/wire.js +178 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +81 -6
- package/scripts/gemini_research/browser.py +35 -0
- package/scripts/gemini_research/init_login.py +91 -0
- package/scripts/gemini_research/run_research.py +312 -0
package/lib/client.js
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-subagent-agy —— Gemini 网页 Deep Research 侧边栏面板(浏览器端)。
|
|
3
|
+
*
|
|
4
|
+
* 客户端是 DSH 的 lazy-CJS 包:只注册工厂,模块体副作用在首次物化时执行。
|
|
5
|
+
* 面板注册到 root 作用域的 `main` keyed slot,并在 `sidebar.panellist`
|
|
6
|
+
* 注册同名 entry;点击侧边栏的「Gemini 调研」即可打开。
|
|
7
|
+
*
|
|
8
|
+
* 所有耗时操作都走主机侧 /api/dsh-gemini-research/* 桥接,浏览器端不直接
|
|
9
|
+
* 启动进程,也不接触登录态。
|
|
10
|
+
*/
|
|
11
|
+
window.__ModuleLoader__.load({
|
|
12
|
+
id: 'dsh-subagent-agy',
|
|
13
|
+
factory: function (require) {
|
|
14
|
+
var module = { exports: {} };
|
|
15
|
+
var exports = module.exports;
|
|
16
|
+
var react = require('react');
|
|
17
|
+
|
|
18
|
+
var h = react.createElement;
|
|
19
|
+
var useState = react.useState;
|
|
20
|
+
var useEffect = react.useEffect;
|
|
21
|
+
var useRef = react.useRef;
|
|
22
|
+
|
|
23
|
+
var PANEL_ID = 'gemini-research';
|
|
24
|
+
var API = '/api/dsh-gemini-research';
|
|
25
|
+
var STYLE_ID = 'dsh-gemini-research-styles';
|
|
26
|
+
|
|
27
|
+
var CSS = [
|
|
28
|
+
'.dgr-page{box-sizing:border-box;width:100%;max-width:920px;margin:0 auto;padding:28px 28px 48px;color:var(--dsw-alias-label-primary,inherit);font:inherit}',
|
|
29
|
+
'.dgr-head{display:flex;align-items:flex-start;gap:12px;margin-bottom:18px}',
|
|
30
|
+
'.dgr-headText{flex:1;min-width:0}',
|
|
31
|
+
'.dgr-title{font-size:20px;line-height:28px;font-weight:650;margin:0}',
|
|
32
|
+
'.dgr-sub{margin-top:4px;font-size:12.5px;line-height:20px;color:var(--dsw-alias-label-secondary,inherit);opacity:.8}',
|
|
33
|
+
'.dgr-badge{flex:none;display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;font-size:12px;line-height:18px;background:var(--dsw-alias-fill-secondary,rgba(127,127,127,.12));color:var(--dsw-alias-label-secondary,inherit)}',
|
|
34
|
+
'.dgr-dot{width:7px;height:7px;border-radius:50%;background:#8a8f99}',
|
|
35
|
+
'.dgr-dot.ok{background:#22a06b}.dgr-dot.run{background:#4c8dff}.dgr-dot.bad{background:#e5484d}',
|
|
36
|
+
'.dgr-card{border:1px solid var(--dsw-alias-border-l2,rgba(127,127,127,.22));border-radius:14px;background:var(--dsw-alias-bg-layer-2,transparent);padding:16px;margin-bottom:14px}',
|
|
37
|
+
'.dgr-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}',
|
|
38
|
+
'.dgr-col{display:flex;flex-direction:column;gap:10px}',
|
|
39
|
+
'.dgr-label{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary,inherit);opacity:.8}',
|
|
40
|
+
'.dgr-input{box-sizing:border-box;width:100%;min-height:92px;resize:vertical;padding:10px 12px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2,rgba(127,127,127,.3));background:var(--dsw-alias-bg-layer-1,transparent);color:inherit;font:inherit;font-size:13.5px;line-height:21px;outline:none}',
|
|
41
|
+
'.dgr-input:focus{border-color:#4c8dff}',
|
|
42
|
+
'.dgr-btn{appearance:none;min-height:34px;padding:0 14px;border-radius:9px;border:1px solid var(--dsw-alias-border-l2,rgba(127,127,127,.35));background:var(--dsw-alias-fill-elevated,rgba(127,127,127,.08));color:inherit;font:inherit;font-size:13px;cursor:pointer}',
|
|
43
|
+
'.dgr-btn:hover:not(:disabled){background:var(--dsw-alias-fill-secondary,rgba(127,127,127,.16))}',
|
|
44
|
+
'.dgr-btn:disabled{opacity:.5;cursor:default}',
|
|
45
|
+
'.dgr-btn.primary{border-color:#4c8dff;background:#4c8dff;color:#fff}',
|
|
46
|
+
'.dgr-btn.danger{border-color:#e5484d;color:#e5484d;background:transparent}',
|
|
47
|
+
'.dgr-status{display:flex;gap:16px;flex-wrap:wrap;font-size:12.5px;line-height:20px}',
|
|
48
|
+
'.dgr-kv{display:flex;gap:6px;align-items:baseline}.dgr-kv b{font-weight:600}',
|
|
49
|
+
'.dgr-note{font-size:12px;line-height:19px;color:var(--dsw-alias-label-secondary,inherit);opacity:.82}',
|
|
50
|
+
'.dgr-warn{border:1px solid rgba(220,140,0,.45);background:rgba(220,140,0,.08);border-radius:10px;padding:10px 12px;font-size:12.5px;line-height:20px}',
|
|
51
|
+
'.dgr-report{white-space:pre-wrap;overflow-wrap:anywhere;font-size:13px;line-height:22px;max-height:60vh;overflow:auto;padding:14px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2,rgba(127,127,127,.25));background:var(--dsw-alias-bg-layer-1,rgba(127,127,127,.04))}',
|
|
52
|
+
'.dgr-log{white-space:pre-wrap;overflow-wrap:anywhere;font-family:var(--dsw-font-mono,ui-monospace,monospace);font-size:11px;line-height:17px;max-height:180px;overflow:auto;opacity:.7}',
|
|
53
|
+
'.dgr-empty{padding:26px 0;text-align:center;font-size:13px;color:var(--dsw-alias-label-secondary,inherit);opacity:.72}',
|
|
54
|
+
'.dgr-icon{display:block}',
|
|
55
|
+
'@media (max-width:700px){.dgr-page{padding:20px 16px 40px}}',
|
|
56
|
+
].join('');
|
|
57
|
+
|
|
58
|
+
function ensureStyles() {
|
|
59
|
+
if (typeof document === 'undefined' || !document.head) return;
|
|
60
|
+
if (document.querySelector('style[data-plugin-css="' + STYLE_ID + '"]') !== null) return;
|
|
61
|
+
var tag = document.createElement('style');
|
|
62
|
+
tag.dataset.plugin = 'dsh-subagent-agy';
|
|
63
|
+
tag.dataset.pluginCss = STYLE_ID;
|
|
64
|
+
tag.textContent = CSS;
|
|
65
|
+
document.head.appendChild(tag);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getJson(path) {
|
|
69
|
+
return fetch(API + path, { method: 'GET', headers: { accept: 'application/json' } }).then(function (res) {
|
|
70
|
+
return res.json().then(function (body) {
|
|
71
|
+
if (!res.ok) throw new Error((body && (body.message || body.code)) || ('HTTP ' + res.status));
|
|
72
|
+
return body;
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function postJson(path, body) {
|
|
78
|
+
return fetch(API + path, {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: { 'content-type': 'application/json', accept: 'application/json' },
|
|
81
|
+
body: JSON.stringify(body || {}),
|
|
82
|
+
}).then(function (res) {
|
|
83
|
+
return res.json().then(function (payload) {
|
|
84
|
+
if (!res.ok) throw new Error((payload && (payload.message || payload.code)) || ('HTTP ' + res.status));
|
|
85
|
+
return payload;
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function fmtTime(value) {
|
|
91
|
+
if (!value) return '—';
|
|
92
|
+
try {
|
|
93
|
+
var date = new Date(value);
|
|
94
|
+
if (Number.isNaN(date.getTime())) return '—';
|
|
95
|
+
return date.toLocaleString();
|
|
96
|
+
} catch (error) {
|
|
97
|
+
return '—';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function elapsed(job) {
|
|
102
|
+
if (!job || !job.startedAt) return '—';
|
|
103
|
+
var end = job.endedAt ? new Date(job.endedAt).getTime() : Date.now();
|
|
104
|
+
var start = new Date(job.startedAt).getTime();
|
|
105
|
+
if (!Number.isFinite(start) || !Number.isFinite(end)) return '—';
|
|
106
|
+
var seconds = Math.max(0, Math.round((end - start) / 1000));
|
|
107
|
+
var minutes = Math.floor(seconds / 60);
|
|
108
|
+
return minutes > 0 ? minutes + ' 分 ' + (seconds % 60) + ' 秒' : seconds + ' 秒';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
var STATUS_TEXT = {
|
|
112
|
+
queued: '排队中',
|
|
113
|
+
running: '调研中',
|
|
114
|
+
done: '已完成',
|
|
115
|
+
error: '失败',
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
function statusTone(job) {
|
|
119
|
+
if (!job) return '';
|
|
120
|
+
if (job.status === 'done') return 'ok';
|
|
121
|
+
if (job.status === 'running' || job.status === 'queued') return 'run';
|
|
122
|
+
if (job.status === 'error') return 'bad';
|
|
123
|
+
return '';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function GeminiIcon(props) {
|
|
127
|
+
var size = props && typeof props.size === 'number' ? props.size : 18;
|
|
128
|
+
return h(
|
|
129
|
+
'svg',
|
|
130
|
+
{
|
|
131
|
+
className: 'dgr-icon',
|
|
132
|
+
width: size,
|
|
133
|
+
height: size,
|
|
134
|
+
viewBox: '0 0 24 24',
|
|
135
|
+
fill: 'none',
|
|
136
|
+
'aria-hidden': 'true',
|
|
137
|
+
},
|
|
138
|
+
h('path', {
|
|
139
|
+
d: 'M12 2.6l1.9 5.9 5.9 1.9-5.9 1.9L12 18.2l-1.9-5.9L4.2 10.4l5.9-1.9L12 2.6z',
|
|
140
|
+
fill: 'currentColor',
|
|
141
|
+
opacity: '0.92',
|
|
142
|
+
}),
|
|
143
|
+
h('path', { d: 'M19 15.2l.9 2.7 2.7.9-2.7.9-.9 2.7-.9-2.7-2.7-.9 2.7-.9.9-2.7z', fill: 'currentColor', opacity: '0.55' })
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function GeminiResearchPanel() {
|
|
148
|
+
var topicState = useState('');
|
|
149
|
+
var statusState = useState(null);
|
|
150
|
+
var jobState = useState(null);
|
|
151
|
+
var errorState = useState('');
|
|
152
|
+
var noticeState = useState('');
|
|
153
|
+
var busyState = useState(false);
|
|
154
|
+
|
|
155
|
+
var topic = topicState[0];
|
|
156
|
+
var setTopic = topicState[1];
|
|
157
|
+
var status = statusState[0];
|
|
158
|
+
var setStatus = statusState[1];
|
|
159
|
+
var job = jobState[0];
|
|
160
|
+
var setJob = jobState[1];
|
|
161
|
+
var error = errorState[0];
|
|
162
|
+
var setError = errorState[1];
|
|
163
|
+
var notice = noticeState[0];
|
|
164
|
+
var setNotice = noticeState[1];
|
|
165
|
+
var busy = busyState[0];
|
|
166
|
+
var setBusy = busyState[1];
|
|
167
|
+
var jobIdRef = useRef(null);
|
|
168
|
+
|
|
169
|
+
function refresh() {
|
|
170
|
+
return getJson('/status')
|
|
171
|
+
.then(function (data) {
|
|
172
|
+
setStatus(data);
|
|
173
|
+
if (data && data.job) {
|
|
174
|
+
jobIdRef.current = data.job.id;
|
|
175
|
+
setJob(function (previous) {
|
|
176
|
+
if (previous && previous.id === data.job.id) {
|
|
177
|
+
return Object.assign({}, data.job, { result: previous.result, logTail: previous.logTail });
|
|
178
|
+
}
|
|
179
|
+
return data.job;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return data;
|
|
183
|
+
})
|
|
184
|
+
.catch(function (err) {
|
|
185
|
+
setError(String(err && err.message ? err.message : err));
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function refreshJob() {
|
|
190
|
+
var id = jobIdRef.current;
|
|
191
|
+
if (!id) return Promise.resolve(null);
|
|
192
|
+
return getJson('/job?id=' + encodeURIComponent(id))
|
|
193
|
+
.then(function (data) {
|
|
194
|
+
if (data && data.job) setJob(data.job);
|
|
195
|
+
return data && data.job;
|
|
196
|
+
})
|
|
197
|
+
.catch(function () {
|
|
198
|
+
return null;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
useEffect(function () {
|
|
203
|
+
refresh();
|
|
204
|
+
var timer = setInterval(function () {
|
|
205
|
+
refreshJob().then(function (current) {
|
|
206
|
+
if (current && (current.status === 'done' || current.status === 'error')) {
|
|
207
|
+
clearInterval(timer);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
getJson('/status').then(setStatus).catch(function () {});
|
|
211
|
+
}, 2500);
|
|
212
|
+
return function () {
|
|
213
|
+
clearInterval(timer);
|
|
214
|
+
};
|
|
215
|
+
}, []);
|
|
216
|
+
|
|
217
|
+
function startResearch() {
|
|
218
|
+
var text = topic.trim();
|
|
219
|
+
if (text.length === 0) {
|
|
220
|
+
setError('先写调研主题');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
setError('');
|
|
224
|
+
setNotice('');
|
|
225
|
+
setBusy(true);
|
|
226
|
+
postJson('/run', { topic: text })
|
|
227
|
+
.then(function (data) {
|
|
228
|
+
jobIdRef.current = data.jobId;
|
|
229
|
+
setNotice('已提交,任务会自动排队执行。');
|
|
230
|
+
return refreshJob();
|
|
231
|
+
})
|
|
232
|
+
.catch(function (err) {
|
|
233
|
+
setError(String(err && err.message ? err.message : err));
|
|
234
|
+
})
|
|
235
|
+
.finally(function () {
|
|
236
|
+
setBusy(false);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function initLogin() {
|
|
241
|
+
setError('');
|
|
242
|
+
setNotice('');
|
|
243
|
+
setBusy(true);
|
|
244
|
+
postJson('/login/init', {})
|
|
245
|
+
.then(function () {
|
|
246
|
+
setNotice('已打开登录窗口:请在弹出的系统默认浏览器里登录 Google 账号,登录完成后窗口会自动关闭。');
|
|
247
|
+
return refresh();
|
|
248
|
+
})
|
|
249
|
+
.catch(function (err) {
|
|
250
|
+
setError(String(err && err.message ? err.message : err));
|
|
251
|
+
})
|
|
252
|
+
.finally(function () {
|
|
253
|
+
setBusy(false);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function copyReport() {
|
|
258
|
+
var text = job && job.result ? job.result : '';
|
|
259
|
+
if (!text) return;
|
|
260
|
+
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
|
|
261
|
+
navigator.clipboard.writeText(text).then(function () {
|
|
262
|
+
setNotice('报告已复制到剪贴板');
|
|
263
|
+
}).catch(function () {
|
|
264
|
+
setError('复制失败,请手动选择报告文本');
|
|
265
|
+
});
|
|
266
|
+
} else {
|
|
267
|
+
setError('当前环境不支持剪贴板');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
var running = !!(job && (job.status === 'running' || job.status === 'queued'));
|
|
272
|
+
var loginKnown = status && status.loginReady === true;
|
|
273
|
+
|
|
274
|
+
return h(
|
|
275
|
+
'div',
|
|
276
|
+
{ className: 'dgr-page' },
|
|
277
|
+
h(
|
|
278
|
+
'div',
|
|
279
|
+
{ className: 'dgr-head' },
|
|
280
|
+
h('div', { className: 'dgr-headText' },
|
|
281
|
+
h('h1', { className: 'dgr-title' }, 'Gemini 网页调研'),
|
|
282
|
+
h('div', { className: 'dgr-sub' }, '用 Google AI Pro 网页端的 Deep Research 做多步调研,结果回到这里;单次通常 5–10 分钟。')
|
|
283
|
+
),
|
|
284
|
+
h('span', { className: 'dgr-badge' },
|
|
285
|
+
h('span', { className: 'dgr-dot ' + (loginKnown ? 'ok' : '') }),
|
|
286
|
+
loginKnown ? '登录态已保存' : '待初始化登录'
|
|
287
|
+
)
|
|
288
|
+
),
|
|
289
|
+
|
|
290
|
+
status === null
|
|
291
|
+
? h('div', { className: 'dgr-empty' }, '正在读取服务状态…')
|
|
292
|
+
: h(
|
|
293
|
+
'div',
|
|
294
|
+
{ className: 'dgr-card' },
|
|
295
|
+
h('div', { className: 'dgr-status' },
|
|
296
|
+
h('span', { className: 'dgr-kv' }, h('b', null, '运行状态'), running ? '调研中' : '空闲'),
|
|
297
|
+
h('span', { className: 'dgr-kv' }, h('b', null, '登录进程'), status.loginRunning ? '运行中' : '未运行'),
|
|
298
|
+
h('span', { className: 'dgr-kv' }, h('b', null, '登录态'), status.loginReady ? '已就绪' : '未就绪'),
|
|
299
|
+
h('span', { className: 'dgr-kv' }, h('b', null, 'Profile'), status.profileExists ? '已创建' : '未创建')
|
|
300
|
+
),
|
|
301
|
+
!loginKnown
|
|
302
|
+
? h('div', { className: 'dgr-warn', style: { marginTop: '12px' } },
|
|
303
|
+
'还没有可用的 Gemini 登录态。先点「初始化登录」,在弹出的系统默认浏览器里完成 Google 登录;登录态会保存在本机 profile 里。'
|
|
304
|
+
)
|
|
305
|
+
: null
|
|
306
|
+
),
|
|
307
|
+
|
|
308
|
+
h(
|
|
309
|
+
'div',
|
|
310
|
+
{ className: 'dgr-card dgr-col' },
|
|
311
|
+
h('div', { className: 'dgr-label' }, '调研主题'),
|
|
312
|
+
h('textarea', {
|
|
313
|
+
className: 'dgr-input',
|
|
314
|
+
placeholder: '例如:调研 2026 年 GT3 组别对 e-Fuel 的技术规范与引入时间表,要求列出关键数据、多方观点与来源链接',
|
|
315
|
+
value: topic,
|
|
316
|
+
onChange: function (event) { setTopic(event.target.value); },
|
|
317
|
+
disabled: running,
|
|
318
|
+
}),
|
|
319
|
+
h('div', { className: 'dgr-row' },
|
|
320
|
+
h('button', { className: 'dgr-btn primary', type: 'button', onClick: startResearch, disabled: busy || running }, running ? '调研进行中…' : '开始 Deep Research'),
|
|
321
|
+
h('button', { className: 'dgr-btn', type: 'button', onClick: initLogin, disabled: busy }, '初始化登录'),
|
|
322
|
+
h('button', { className: 'dgr-btn', type: 'button', onClick: refresh, disabled: busy }, '刷新状态')
|
|
323
|
+
),
|
|
324
|
+
h('div', { className: 'dgr-note' }, '额度提示:Google AI Pro 的 Deep Research 约为每天 20 次;同一时间只跑一个任务(浏览器 profile 单实例锁)。')
|
|
325
|
+
),
|
|
326
|
+
|
|
327
|
+
error ? h('div', { className: 'dgr-warn', style: { marginBottom: '14px' } }, error) : null,
|
|
328
|
+
notice ? h('div', { className: 'dgr-note', style: { marginBottom: '14px' } }, notice) : null,
|
|
329
|
+
|
|
330
|
+
job
|
|
331
|
+
? h(
|
|
332
|
+
'div',
|
|
333
|
+
{ className: 'dgr-card' },
|
|
334
|
+
h('div', { className: 'dgr-status', style: { marginBottom: '10px' } },
|
|
335
|
+
h('span', { className: 'dgr-kv' }, h('b', null, '任务'), job.id ? job.id.slice(0, 8) : '—'),
|
|
336
|
+
h('span', { className: 'dgr-kv' }, h('b', null, '状态'), STATUS_TEXT[job.status] || job.status),
|
|
337
|
+
h('span', { className: 'dgr-kv' }, h('b', null, '耗时'), elapsed(job)),
|
|
338
|
+
h('span', { className: 'dgr-kv' }, h('b', null, '创建'), fmtTime(job.createdAt))
|
|
339
|
+
),
|
|
340
|
+
job.topic ? h('div', { className: 'dgr-note', style: { marginBottom: '10px' } }, '主题:' + job.topic) : null,
|
|
341
|
+
job.status === 'done' && job.result
|
|
342
|
+
? h('div', { className: 'dgr-col' },
|
|
343
|
+
h('div', { className: 'dgr-row' },
|
|
344
|
+
h('div', { className: 'dgr-label', style: { flex: '1' } }, '调研报告'),
|
|
345
|
+
h('button', { className: 'dgr-btn', type: 'button', onClick: copyReport }, '复制报告')
|
|
346
|
+
),
|
|
347
|
+
h('pre', { className: 'dgr-report' }, job.result)
|
|
348
|
+
)
|
|
349
|
+
: null,
|
|
350
|
+
job.status === 'error'
|
|
351
|
+
? h('div', { className: 'dgr-warn' }, '调研失败:' + (job.error || '未知错误'))
|
|
352
|
+
: null,
|
|
353
|
+
job.logTail
|
|
354
|
+
? h('details', { style: { marginTop: '10px' } },
|
|
355
|
+
h('summary', { className: 'dgr-label' }, '运行日志'),
|
|
356
|
+
h('pre', { className: 'dgr-log' }, job.logTail)
|
|
357
|
+
)
|
|
358
|
+
: null
|
|
359
|
+
)
|
|
360
|
+
: h('div', { className: 'dgr-empty' }, '还没有任务。填好主题后点「开始 Deep Research」。')
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
var inject = ['slots'];
|
|
365
|
+
|
|
366
|
+
function apply(ctx) {
|
|
367
|
+
ensureStyles();
|
|
368
|
+
var disposers = [];
|
|
369
|
+
if (ctx && ctx.slots && typeof ctx.slots.inject === 'function') {
|
|
370
|
+
disposers.push(
|
|
371
|
+
ctx.slots.inject('main', function () {
|
|
372
|
+
return ctx.slots.register({ name: 'main', key: PANEL_ID }, GeminiResearchPanel);
|
|
373
|
+
})
|
|
374
|
+
);
|
|
375
|
+
disposers.push(
|
|
376
|
+
ctx.slots.inject('sidebar.panellist', function () {
|
|
377
|
+
return ctx.slots.register(
|
|
378
|
+
{ name: 'sidebar.panellist', id: PANEL_ID, order: 30, label: function () { return 'Gemini 调研'; } },
|
|
379
|
+
GeminiIcon
|
|
380
|
+
);
|
|
381
|
+
})
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
return function () {
|
|
385
|
+
for (var i = 0; i < disposers.length; i += 1) {
|
|
386
|
+
try { disposers[i](); } catch (error) { /* ignore */ }
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
exports.apply = apply;
|
|
392
|
+
exports.inject = inject;
|
|
393
|
+
exports.__panel = GeminiResearchPanel;
|
|
394
|
+
exports.__icon = GeminiIcon;
|
|
395
|
+
return module.exports;
|
|
396
|
+
},
|
|
397
|
+
});
|