Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
1615 lines (1500 loc) · 135 KB
/
Copy pathindex.html
File metadata and controls
1615 lines (1500 loc) · 135 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="zh-CN" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Universal Web-to-API · 使用手册</title>
<link rel="icon" href="../images/logo.svg" type="image/svg+xml">
<script src="lucide.min.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Noto+Sans+SC:wght@400;500;700;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="progress"></div>
<div class="overlay" id="overlay"></div>
<div class="app">
<!-- ============ 侧边栏 ============ -->
<aside class="sidebar" id="sidebar">
<div class="sb-brand">
<div class="sb-logo"><i data-lucide="globe" style="width:20px;height:20px"></i></div>
<div>
<div class="sb-name">Universal Web-to-API</div>
<div class="sb-sub">docs · v2.9.8</div>
</div>
</div>
<div class="sb-search">
<i data-lucide="search" style="width:15px;height:15px"></i>
<input id="searchInput" type="text" placeholder="搜索文档…" autocomplete="off">
<kbd>/</kbd>
<div class="sb-results" id="searchResults"></div>
</div>
<nav id="nav"><!-- JS 生成 --></nav>
</aside>
<div class="shell">
<!-- ============ 顶栏 ============ -->
<header class="topbar">
<button class="tb-btn" id="menuBtn" aria-label="打开导航"><i data-lucide="menu" style="width:16px;height:16px"></i></button>
<div class="tb-crumb"><span>使用手册</span><i data-lucide="chevron-right" style="width:13px;height:13px"></i><b id="crumbNow">项目概览</b></div>
<div class="tb-right">
<span class="tb-ver">v2.9.8</span>
<button class="tb-btn" id="themeBtn" aria-label="切换主题"><i data-lucide="sun" style="width:15px;height:15px" id="themeIcon"></i></button>
<a class="tb-btn" href="https://github.com/lumingya/universal-web-api" target="_blank" rel="noopener"><i data-lucide="github" style="width:15px;height:15px"></i><span class="hide-sm">GitHub</span></a>
</div>
</header>
<div class="body-wrap">
<main class="content" id="content">
<!-- ============ HERO ============ -->
<div class="hero">
<div class="hero-in">
<div class="hero-eyebrow">
<span class="bdg"><i data-lucide="sparkles" style="width:11px;height:11px"></i> v2.9.8</span>
<span class="bdg g">OpenAI 兼容</span>
<span class="bdg g">本地部署 · 免费开源</span>
</div>
<h1>把任意 AI 聊天网页<br>变成 <span class="grad">OpenAI 标准接口</span></h1>
<p class="lead">Universal Web-to-API 驱动你浏览器中已经登录的 ChatGPT、Gemini、DeepSeek 等对话网页,将其包装为兼容 OpenAI 格式的本地 API,供 SillyTavern、各类客户端与自动化工作流直接调用。</p>
<div class="hero-cta">
<a class="btn btn-pri" href="#quickstart"><i data-lucide="rocket" style="width:16px;height:16px"></i>快速开始</a>
<a class="btn btn-gh" href="http://127.0.0.1:8199/" target="_blank" rel="noopener"><i data-lucide="layout-dashboard" style="width:16px;height:16px"></i>打开控制面板</a>
</div>
</div>
</div>
<!-- ============ 01 项目概览 ============ -->
<section class="doc-section" id="overview">
<div class="sec-kicker"><span class="sec-num">01</span><span class="sec-tag">导览</span></div>
<h2><span class="h-ic"><i data-lucide="compass" style="width:20px;height:20px"></i></span>项目概览<a class="h-anchor" href="#overview"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p class="lead">本项目的核心思路:不再依赖官方 API,而是<strong>自动化你本地的浏览器</strong>——让脚本在你已登录的 AI 网站上输入问题、等待回复、提取结果,再按 OpenAI 的数据格式返回给任何客户端。</p>
<div class="chips">
<span class="chip"><i data-lucide="check" style="width:12px;height:12px"></i>OpenAI / Anthropic 双协议兼容</span>
<span class="chip"><i data-lucide="check" style="width:12px;height:12px"></i>多站点 · 多标签页并发</span>
<span class="chip"><i data-lucide="check" style="width:12px;height:12px"></i>流式输出</span>
<span class="chip"><i data-lucide="check" style="width:12px;height:12px"></i>图片 / 音频 / 视频回传</span>
<span class="chip"><i data-lucide="check" style="width:12px;height:12px"></i>自动化恢复命令</span>
<span class="chip"><i data-lucide="check" style="width:12px;height:12px"></i>函数调用转译</span>
</div>
<p><strong>典型用途:</strong>统一本地接入方式;按站点或标签页组织不同工作流;在长文本场景下通过文件粘贴承载上下文;在调试时观察页面侧与请求侧的执行流程。</p>
<h3>系统架构</h3>
<p>请求从客户端进入后,会依次穿过路由层、调度层与驱动层,再由解析层把网页里的回复翻译回标准格式。理解这条链路,后面的配置章节会好读很多。</p>
<div class="arch">
<div class="a-tier">
<div class="a-node" style="--c:#94a3b8">
<span class="a-lay">USER</span>
<div class="a-tt"><i data-lucide="user" style="width:17px;height:17px"></i>客户端 / 调用方</div>
<div class="a-ds">SillyTavern / Chatbox / 代码集成 / 自动化脚本</div>
</div>
</div>
<div class="a-arrow"><span class="a-cap">OpenAI / Anthropic / Codex 请求</span><span class="ln"></span><i data-lucide="chevron-down" class="tri" style="width:15px;height:15px"></i></div>
<div class="a-tier">
<div class="a-node" style="--c:#f43f5e">
<span class="a-lay">L1</span>
<div class="a-tt"><i data-lucide="network" style="width:17px;height:17px"></i>接口与路由层</div>
<span class="a-path">app/api</span>
<div class="a-ds">解析外部请求,提供标准兼容路由与流式流控</div>
</div>
</div>
<div class="a-split">
<div class="a-arrow"><span class="a-cap">会话分发 / 并发调度</span><span class="ln"></span><i data-lucide="chevron-down" class="tri" style="width:15px;height:15px"></i></div>
<div class="a-arrow"><span class="a-cap">解析函数调用</span><span class="ln"></span><i data-lucide="chevron-down" class="tri" style="width:15px;height:15px"></i></div>
</div>
<div class="a-row">
<div class="a-node" style="--c:#06b6d4">
<span class="a-lay">L2</span>
<div class="a-tt"><i data-lucide="layers" style="width:17px;height:17px"></i>标签页池与生命周期</div>
<span class="a-path">app/core/tab_pool</span>
<div class="a-ds">标签页保活、检测、重连,维护跨请求的会话重用</div>
</div>
<div class="a-node" style="--c:#f59e0b">
<span class="a-lay">L5</span>
<div class="a-tt"><i data-lucide="puzzle" style="width:17px;height:17px"></i>函数调用兼容层</div>
<span class="a-path">app/services/tool_calling</span>
<div class="a-ds">将 tool_calls 转译为提示词,网页端分步执行后合并返回</div>
</div>
</div>
<div class="a-arrow"><span class="a-cap">网页驱动与交互操控</span><span class="ln"></span><i data-lucide="chevron-down" class="tri" style="width:15px;height:15px"></i></div>
<div class="a-tier">
<div class="a-node" style="--c:#3b82f6">
<span class="a-lay">L3</span>
<div class="a-tt"><i data-lucide="cpu" style="width:17px;height:17px"></i>网页自动化执行引擎</div>
<span class="a-path">app/core/workflow</span>
<div class="a-ds">基于 DrissionPage 操控,内置指纹逃逸与低熵仿真操作</div>
</div>
</div>
<div class="a-split">
<div class="a-arrow"><span class="a-cap">注入与响应拦截</span><span class="ln"></span><i data-lucide="chevron-down" class="tri" style="width:15px;height:15px"></i></div>
<div class="a-arrow"><span class="a-cap">拦截指令钩子</span><span class="ln"></span><i data-lucide="chevron-down" class="tri" style="width:15px;height:15px"></i></div>
</div>
<div class="a-row">
<div class="a-node" style="--c:#10b981">
<span class="a-lay">L4</span>
<div class="a-tt"><i data-lucide="eye" style="width:17px;height:17px"></i>流式监控与响应解析</div>
<span class="a-path">app/core/parsers</span>
<div class="a-ds">监听网络事件与 DOM 变化,增量解析并实时流式推送</div>
</div>
<div class="a-node" style="--c:#8b5cf6">
<span class="a-lay">L6</span>
<div class="a-tt"><i data-lucide="terminal" style="width:17px;height:17px"></i>指令引擎与拦截钩子</div>
<span class="a-path">app/services/command_engine</span>
<div class="a-ds">内置指令拦截(附件验证、截屏),防注入与校验</div>
</div>
</div>
<div class="a-base">
<div class="a-base-t"><i data-lucide="shield" style="width:14px;height:14px"></i>底层核心支撑模块</div>
<div class="a-row">
<div class="a-node" style="--c:#ec4899">
<span class="a-lay">L7</span>
<div class="a-tt"><i data-lucide="database" style="width:17px;height:17px"></i>配置与预设中心</div>
<span class="a-path">app/services/config</span>
<div class="a-ds">维护 sites.json 站点规则、环境状态检测,支持热重载</div>
</div>
<div class="a-node" style="--c:#6b7280">
<span class="a-lay">L8</span>
<div class="a-tt"><i data-lucide="wrench" style="width:17px;height:17px"></i>平台工具箱</div>
<span class="a-path">app/utils · app/models</span>
<div class="a-ds">日志存储与脱敏、多模态解析支持、全局数据模型</div>
</div>
</div>
<div class="a-rel">
<span>执行引擎 → 依赖 → 配置中心</span>
<span>指令引擎 → 读写 → 配置中心</span>
<span>流式监控 → 工具包 → 平台工具箱</span>
</div>
</div>
</div>
</section>
<!-- ============ 02 使用预期 ============ -->
<section class="doc-section" id="notes">
<div class="sec-kicker"><span class="sec-num">02</span><span class="sec-tag">导览 · 必读</span></div>
<h2><span class="h-ic"><i data-lucide="megaphone" style="width:20px;height:20px"></i></span>来自作者:使用预期<a class="h-anchor" href="#notes"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>这七条是作者的维护说明,动手前先扫一遍,遇到问题时能省不少排查时间。</p>
<div class="co co-danger">
<i data-lucide="alert-octagon" style="width:18px;height:18px"></i>
<div class="co-bd">
<span class="co-t">1 · 站点突然不能用了?优先检查选择器</span>
<p>网站改版后最易失效的是<strong>选择器</strong>(告诉脚本输入框、发送按钮、结果容器在哪的 CSS 规则)。大多数故障检查选择器即可,而非解析器。标准修法:</p>
<ol>
<li>在受控浏览器里对目标元素右键 →「检查」。</li>
<li>把元素树截图或复制出来发给 AI,让它写出新的选择器。</li>
<li>回控制台粘贴替换,重新测试。</li>
</ol>
<p>如果不是选择器问题,才轮到提取器 / 解析器——那需要拦截网络请求、分析响应结构,难度高得多。</p>
</div>
</div>
<div class="grid2">
<div class="q-card">
<div class="qc-ic"><i data-lucide="heart-handshake" style="width:17px;height:17px"></i></div>
<h5>2 · 各站点的维护覆盖范围</h5>
<p><strong>Gemini、DeepSeek</strong> 是作者日常使用最多、维护最及时的站点。其它站点不保证第一时间跟进,遇到问题更推荐加 QQ 群反馈,通常比 Issue 更快。</p>
</div>
<div class="q-card">
<div class="qc-ic"><i data-lucide="puzzle" style="width:17px;height:17px"></i></div>
<h5>3 · Function Calling 尚不稳定</h5>
<p>它比较依赖模型本身的理解能力,可能存在一定问题。详见「函数调用」章节的预期管理。</p>
</div>
<div class="q-card">
<div class="qc-ic"><i data-lucide="bot" style="width:17px;height:17px"></i></div>
<h5>4 · 遇到问题,优先让 AI 帮你分析</h5>
<p>选择器失效、配置写错、工作流顺序不对——把现象、日志截图、元素树交给 AI,通常比等人工回复快得多。</p>
</div>
<div class="q-card">
<div class="qc-ic"><i data-lucide="bug" style="width:17px;height:17px"></i></div>
<h5>5 · 反馈 Bug 的正确姿势</h5>
<p>说清<strong>做了什么、期望什么、实际看到什么</strong>,附上 DEBUG 级别日志。表述不清时,先让 AI 帮你整理一版再发。</p>
</div>
<div class="q-card">
<div class="qc-ic"><i data-lucide="share-2" style="width:17px;height:17px"></i></div>
<h5>6 · 修好了欢迎分享回来</h5>
<p>不管是更新的选择器还是补好的配置文件,分享给作者或群友都能让整个社区少走弯路。</p>
</div>
<div class="q-card">
<div class="qc-ic"><i data-lucide="target" style="width:17px;height:17px"></i></div>
<h5>7 · 项目的核心场景</h5>
<p>本项目围绕<strong>酒馆 / RP(角色扮演)</strong>场景设计打磨。其它场景能用,但维护上偏向"能用就用,不保证持续深耕"。</p>
</div>
</div>
</section>
<!-- ============ 03 快速开始 ============ -->
<section class="doc-section" id="quickstart" data-reveal>
<div class="sec-kicker"><span class="sec-num">03</span><span class="sec-tag">上手指南</span></div>
<h2><span class="h-ic"><i data-lucide="rocket" style="width:20px;height:20px"></i></span>快速开始<a class="h-anchor" href="#quickstart"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<div class="quickstart-welcome">
<div class="quickstart-welcome-icon"><i data-lucide="hand" style="width:22px;height:22px"></i></div>
<div>
<strong>欢迎使用 Universal Web-to-API</strong>
<p>本项目仅用于体验不同模型的效果,请合理控制使用频率,不要给目标网站带来额外负担。</p>
</div>
</div>
<div class="quickstart-links" aria-label="开始方式">
<a href="#overview">
<span class="quickstart-link-icon"><i data-lucide="book-open" style="width:17px;height:17px"></i></span>
<span><strong>先了解项目基本原理</strong><small>花几分钟了解请求如何流转,以及某些操作为什么必不可少。</small></span>
<i data-lucide="arrow-right" style="width:17px;height:17px"></i>
</a>
<a href="#quickstart-browser">
<span class="quickstart-link-icon"><i data-lucide="zap" style="width:17px;height:17px"></i></span>
<span><strong>我已经了解,直接开始</strong><small>从识别受控浏览器开始,完成第一次连接。</small></span>
<i data-lucide="arrow-down" style="width:17px;height:17px"></i>
</a>
</div>
<h3 id="quickstart-browser">先区分受控浏览器和普通浏览器</h3>
<p>双击运行 <code>start.bat</code> 后,脚本会自动启动一个<strong>受控浏览器</strong>。打开 Windows 任务栏,你应该能看到它已经运行;接下来的登录和站点配置都要在这个浏览器里完成。</p>
<div class="browser-compare">
<div class="browser-kind is-controlled">
<span class="browser-kind-icon"><i data-lucide="scan-eye" style="width:18px;height:18px"></i></span>
<div><strong>受控浏览器</strong><p>由脚本启动并执行网页操作。请在这里打开 AI 站点、登录账号;API 请求执行期间,你可以正常操作或切换标签页查看内容。</p></div>
</div>
<div class="browser-kind">
<span class="browser-kind-icon"><i data-lucide="monitor" style="width:18px;height:18px"></i></span>
<div><strong>普通浏览器</strong><p>你日常使用、正在查看本教程的浏览器,不受脚本控制,也不能代替受控浏览器执行任务。</p></div>
</div>
</div>
<h3 id="quickstart-checklist">首次启动检查清单</h3>
<p>第一次运行时按“进程 → 端口 → 浏览器 → 站点 → API”的顺序确认,任何一步失败都先停在当前层排查,不要直接反复点击发送。</p>
<ol class="steps">
<li><strong>启动脚本没有立即退出。</strong><code>start.bat</code> 窗口应保持打开;若窗口闪退,在项目目录打开 PowerShell 执行 <code>python start.py</code>,保留完整错误信息。</li>
<li><strong>端口可访问。</strong>在普通浏览器打开 <code>http://127.0.0.1:8199/health</code>。返回 JSON 且 HTTP 状态为 <code>200</code> 表示服务和浏览器均已就绪;若为 <code>503</code>,服务还在但受控浏览器未连接。</li>
<li><strong>远程调试端口已监听。</strong>打开 <code>http://127.0.0.1:9222/json/version</code>;能看到 <code>Browser</code> 与 <code>webSocketDebuggerUrl</code> 才表示自动化连接正常。不要把该端口暴露到公网。</li>
<li><strong>标签页池有可用页面。</strong>控制面板 → 标签页池中至少有一个目标站点,状态为“空闲”;新标签页加载完成后等待 2–3 秒再刷新列表。</li>
<li><strong>先做最小请求。</strong>使用 <code>/v1/models</code> 检查路由,再发送一句短文本;确认成功后再启用流式、多模态或函数调用。</li>
</ol>
<div class="co co-warn">
<i data-lucide="stethoscope" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">端口检查失败时的快速判断</span><p><code>8199</code> 无响应通常是服务未启动或端口被占用;<code>/health</code> 返回 <code>503</code> 通常是 Chrome 尚未连上;<code>9222/json/version</code> 无响应则是浏览器启动参数、路径或端口冲突。先看启动窗口中的第一条 <code>[ERROR]</code>,再到「控制台 → 日志」按 <code>RequestID</code> 追踪。</p></div>
</div>
<h3>选择一个已适配的站点</h3>
<p>受控浏览器的基础引导会列出若干已经适配的站点。列表中存在的网站代表已经完成适配,你可以任选一个使用;本教程以 <strong>Gemini</strong> 为例。点击下方卡片复制网址,再粘贴到<strong>受控浏览器</strong>的地址栏中打开。</p>
<div class="site-grid" id="siteGrid"></div>
<div class="co co-info">
<i data-lucide="puzzle" style="width:18px;height:18px"></i>
<div class="co-bd">
<span class="co-t">想适配新的站点?不需要等待项目更新</span>
<p>你可以自行添加新站点,步骤并不复杂。请查看<a href="#addsite">「新增站点 · AI 识别」</a>,其中介绍了自动识别与手动配置两种方法。</p>
</div>
</div>
<h3 id="quickstart-gemini">以 Gemini 为例完成首次配置</h3>
<ol class="steps">
<li><strong>访问 Gemini。</strong>在受控浏览器中打开 <code>https://gemini.google.com/</code>,等待页面完整加载。</li>
<li><strong>登录个人账号。</strong>完成登录并进入真正可以发送消息的对话页面。</li>
<li><strong>整理页面状态。</strong>将页面语言设置为中文,并确保左侧聊天侧边栏处于展开状态;这是脚本稳定识别和操作页面的必要条件。</li>
<li><strong>确认标签页已被接管。</strong>打开「控制面板 → 标签页池」,此时应当能看到刚才打开的 Gemini 页面已经处于标签页池的控制之中。</li>
</ol>
<div class="hero-cta quickstart-actions">
<a class="btn btn-pri" href="http://127.0.0.1:8199/" target="_blank" rel="noopener"><i data-lucide="layout-dashboard" style="width:15px;height:15px"></i>打开控制面板</a>
<a class="btn btn-gh" href="#tabpool"><i data-lucide="layers" style="width:15px;height:15px"></i>了解标签页池</a>
</div>
<h3>连接你的客户端</h3>
<p>标签页进入控制后,选择合适的路由地址,填入任意支持 <strong>OpenAI 兼容接口</strong>的前端即可使用,例如 Chatbox、SillyTavern、Cherry Studio 等。</p>
<div class="quickstart-reference-links">
<a href="#routing-methods"><i data-lucide="route" style="width:16px;height:16px"></i><span>了解不同路由方式的区别</span><i data-lucide="arrow-right" style="width:15px;height:15px"></i></a>
<a href="#api-key-config"><i data-lucide="key-round" style="width:16px;height:16px"></i><span>配置 API 密钥</span><i data-lucide="arrow-right" style="width:15px;height:15px"></i></a>
</div>
<div class="co co-tip">
<i data-lucide="folder-sync" style="width:18px;height:18px"></i>
<div class="co-bd">
<span class="co-t">不想重新收藏网页或逐个登录?</span>
<p>你可以关闭浏览器后,复制一份自己现有的 Chrome 用户配置到项目专用的浏览器配置目录中,以复用书签、历史记录和登录状态。请不要直接使用正在运行的系统默认配置目录,也不要分享包含 Cookie 的配置副本。完整操作步骤与目录示例见<a href="#browser-profile-reuse">「浏览器登录态复用」</a>。</p>
</div>
</div>
</section>
<!-- ============ 04 连接 API ============ -->
<section class="doc-section" id="connect" data-reveal>
<div class="sec-kicker"><span class="sec-num">04</span><span class="sec-tag">上手指南</span></div>
<h2><span class="h-ic"><i data-lucide="plug" style="width:20px;height:20px"></i></span>连接 API<a class="h-anchor" href="#connect"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>本项目提供兼容 <strong>OpenAI 格式</strong> 的接口,绝大多数支持"自定义 OpenAI 端点"的客户端都能直接使用。</p>
<h3 id="routing-methods">选择路由并填写连接信息</h3>
<div class="grid2">
<div class="q-card">
<div class="qc-ic"><i data-lucide="server" style="width:17px;height:17px"></i></div>
<h5>服务提供商 Provider</h5>
<p>选择 <code>OpenAI</code> / <code>OpenAI 兼容</code> / <code>自定义</code>。不同客户端叫法不同,选那个能填写自定义地址的即可。</p>
</div>
<div class="q-card" id="api-key-config">
<div class="qc-ic"><i data-lucide="key-round" style="width:17px;height:17px"></i></div>
<h5>API 密钥</h5>
<p>未启用认证(<code>AUTH_ENABLED=false</code>)时填占位值如 <code>sk-local</code> 即可。启用后必须与 <code>.env</code> 的 <code>AUTH_TOKEN</code> 一致;控制面板密钥 <code>DASHBOARD_AUTH_TOKEN</code> 是另一套,不要提供给 API 使用者。</p>
</div>
</div>
<div class="tw"><table class="tbl">
<thead><tr><th>Base URL 形态</th><th>地址</th><th>适用场景</th></tr></thead>
<tbody>
<tr><td>默认 · 自动分配</td><td><code>http://127.0.0.1:8199/v1</code></td><td>不关心具体站点或标签页时使用</td></tr>
<tr><td>指定站点域名</td><td><code>http://127.0.0.1:8199/url/gemini.google.com/v1</code></td><td>自动匹配该站点的标签页</td></tr>
<tr><td>指定标签页</td><td><code>http://127.0.0.1:8199/tab/1/v1</code></td><td>编号见「标签页池」,适合绑定过预设的标签页</td></tr>
<tr><td>指定完整 URL</td><td><code>http://127.0.0.1:8199/tab-url/{token}/v1</code></td><td>token 从「标签页池」复制,严格匹配当前 URL</td></tr>
<tr><td>站点 + 预设路径</td><td><code>http://127.0.0.1:8199/url/gemini.google.com/pro/v1</code></td><td>同一站点拆多种用途时最推荐,直接作为 Base URL</td></tr>
<tr><td>完整路径补全</td><td>在末尾补上 <code>/chat/completions</code></td><td>部分客户端要求填写完整接口路径</td></tr>
</tbody>
</table></div>
<p><strong>模型名称 (Model)</strong>:建议填写便于客户端保存配置的占位名(如 <code>web-api</code>、<code>gemini-web</code>)。实际响应来源由当前打开的站点与预设决定。</p>
<div class="co co-tip">
<i data-lucide="check-circle-2" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">测试步骤</span><p>把地址、密钥、模型名填好后,<strong>直接发一句正常对话</strong>进行测试。不建议点客户端里的"测试 API"按钮——酒馆(SillyTavern)的测试按钮发送的请求过短,部分站点不会正常响应。</p></div>
</div>
<h3>单次请求指定预设的三种方式</h3>
<p>聊天接口支持直接指定 <code>preset_name</code>,只对<strong>当前这一次请求</strong>生效,不改变站点默认预设。</p>
<div class="cb" data-lang="bash"><div class="cb-top"><span class="cb-dots"><i></i><i></i><i></i></span><span class="cb-lang">bash</span><button class="cb-copy"><i data-lucide="copy" style="width:12px;height:12px"></i><span>复制</span></button></div><pre><code># 方式 A:直接写进路径(最推荐,适合作为 Base URL)
curl "http://127.0.0.1:8199/url/gemini.google.com/pro/v1/chat/completions" ^
-H "Content-Type: application/json" ^
-d "{\"model\":\"any\",\"messages\":[{\"role\":\"user\",\"content\":\"你好\"}]}"
# 方式 B:放到 URL 查询参数
curl "http://127.0.0.1:8199/url/gemini.google.com/v1/chat/completions?preset_name=pro" -d "..."
# 方式 C:放到请求体
{"model":"any","messages":[...],"stream":false,"preset_name":"pro"}</code></pre></div>
<div class="co co-info">
<i data-lucide="info" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">优先级规则</span><p>三处都传了预设时,按 <strong>路径里的预设 > URL 查询参数 > 请求体</strong> 的顺序生效。</p></div>
</div>
<h3>查询参数与调度</h3>
<div class="tw"><table class="tbl">
<thead><tr><th>参数</th><th>示例</th><th>作用</th></tr></thead>
<tbody>
<tr><td><code>selector</code></td><td><code>?selector=round_robin</code></td><td><code>first_idle</code> 优先空闲(默认)/ <code>round_robin</code> 轮询 / <code>random</code> 随机</td></tr>
<tr><td><code>tab_index</code></td><td><code>?tab_index=2</code></td><td>在域名路由下进一步锁定某个固定标签页</td></tr>
<tr><td><code>preset_name</code></td><td><code>?preset_name=pro</code></td><td>本次请求临时覆盖预设</td></tr>
</tbody>
</table></div>
<h3>完整调用示例</h3>
<div class="cb" data-lang="bash"><div class="cb-top"><span class="cb-dots"><i></i><i></i><i></i></span><span class="cb-lang">bash</span><button class="cb-copy"><i data-lucide="copy" style="width:12px;height:12px"></i><span>复制</span></button></div><pre><code># 1. 模型列表(连通性检查)
curl http://127.0.0.1:8199/v1/models
# 2. 默认聊天(自动分配标签页)
curl http://127.0.0.1:8199/v1/chat/completions ^
-H "Content-Type: application/json" ^
-d "{\"model\":\"any\",\"messages\":[{\"role\":\"user\",\"content\":\"你好\"}],\"stream\":false}"
# 3. 按域名路由 + 轮询调度
curl "http://127.0.0.1:8199/url/gemini.google.com/v1/chat/completions?selector=round_robin" -d "..."
# 4. 按域名路由 + 固定标签页
curl "http://127.0.0.1:8199/url/gemini.google.com/v1/chat/completions?tab_index=2" -d "..."
# 5. 域名 + 预设路径
curl http://127.0.0.1:8199/url/gemini.google.com/pro/v1/chat/completions -d "..."
# 6. 精确 URL 路由(token 从标签页池复制)
curl http://127.0.0.1:8199/tab-url/abc123def456/v1/chat/completions -d "..."
# 7. 精确 URL 路由 + 预设路径
curl http://127.0.0.1:8199/tab-url/abc123def456/pro/v1/chat/completions -d "..."</code></pre></div>
<h3 id="api-reference">API 端点速查</h3>
<p>下面是日常集成会用到的公开端点。除 <code>/health</code> 外,服务端点是否要求认证取决于「系统设置」中的开关;启用后统一使用 <code>Authorization: Bearer <AUTH_TOKEN></code>,Anthropic 客户端也可使用 <code>x-api-key</code>。</p>
<div class="tw"><table class="tbl">
<thead><tr><th>方法</th><th>路径</th><th>用途 / 关键字段</th><th>认证</th></tr></thead>
<tbody>
<tr><td><code>GET</code></td><td><code>/health</code></td><td>服务与受控浏览器健康检查;浏览器未连接时返回 <code>503</code></td><td>免认证</td></tr>
<tr><td><code>GET</code></td><td><code>/v1/models</code></td><td>列出当前可路由模型与站点;适合作为连通性探针</td><td>服务认证</td></tr>
<tr><td><code>POST</code></td><td><code>/v1/chat/completions</code></td><td>OpenAI Chat Completions;支持 <code>messages</code>、<code>stream</code>、<code>tools</code></td><td>服务认证</td></tr>
<tr><td><code>POST</code></td><td><code>/v1/responses</code></td><td>OpenAI Responses / Codex 兼容;支持 <code>input</code>、<code>instructions</code>、<code>previous_response_id</code></td><td>服务认证</td></tr>
<tr><td><code>POST</code></td><td><code>/v1/messages</code></td><td>Anthropic Messages / Claude Code 兼容;支持 <code>system</code>、<code>messages</code>、<code>max_tokens</code></td><td>服务认证</td></tr>
<tr><td><code>POST</code></td><td><code>/v1/messages/count_tokens</code></td><td>返回 Anthropic 客户端所需的最小 token 估算结果</td><td>服务认证</td></tr>
<tr><td><code>GET</code></td><td><code>/v1/provider/capabilities</code></td><td>机器可读能力清单、协议开关、模型列表与就绪度</td><td>服务认证</td></tr>
<tr><td><code>GET</code></td><td><code>/v1/provider/status</code></td><td>运行时快照:浏览器、标签页池、请求计数;不返回 Cookie 或令牌</td><td>服务认证</td></tr>
<tr><td><code>GET</code></td><td><code>/docs</code></td><td>FastAPI 交互式 OpenAPI 文档;仅在调试模式开启时提供</td><td>按部署配置</td></tr>
</tbody>
</table></div>
<div class="cb" data-lang="bash"><div class="cb-top"><span class="cb-dots"><i></i><i></i><i></i></span><span class="cb-lang">bash</span><button class="cb-copy"><i data-lucide="copy" style="width:12px;height:12px"></i><span>复制</span></button></div><pre><code># 健康检查(无需令牌)
curl -i http://127.0.0.1:8199/health
# 开启认证后查询能力清单
curl http://127.0.0.1:8199/v1/provider/capabilities ^
-H "Authorization: Bearer YOUR_AUTH_TOKEN"
# Anthropic 客户端也可使用 x-api-key
curl http://127.0.0.1:8199/v1/messages/count_tokens ^
-H "x-api-key: YOUR_AUTH_TOKEN" -H "Content-Type: application/json" ^
-d "{\"model\":\"web-api\",\"messages\":[{\"role\":\"user\",\"content\":\"你好\"}]}"</code></pre></div>
<h3>响应头诊断</h3>
<p>路由类接口会返回诊断响应头,方便确认后端实际采用了哪种分配策略。</p>
<div class="tw"><table class="tbl">
<thead><tr><th>响应头</th><th>含义</th></tr></thead>
<tbody>
<tr><td><code>X-Tab-Selection-Mode</code></td><td>实际选择模式:<code>first_idle</code> / <code>round_robin</code> / <code>random</code> / <code>tab_index</code> / <code>exact_url</code></td></tr>
<tr><td><code>X-Requested-Route-Domain</code></td><td>域名路由请求的目标域名;动态路由尚未选定标签页时也会返回</td></tr>
<tr><td><code>X-Resolved-Tab-Index</code></td><td>已明确解析到固定标签页时返回的编号</td></tr>
<tr><td><code>X-Resolved-Route-Domain</code></td><td>已解析标签页当前所属域名</td></tr>
<tr><td><code>X-Resolved-Exact-Url</code></td><td>精确 URL 路由最终命中的完整 URL</td></tr>
<tr><td><code>X-Resolved-Preset-Name</code></td><td>路径或参数最终命中的预设名称</td></tr>
</tbody>
</table></div>
<div class="co co-info">
<i data-lucide="info" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">动态域名路由说明</span><p>调用 <code>/url/{domain}/...</code> 且未传 <code>tab_index</code> 时,真正的标签页在工作流开始执行时才确定,因此这类响应只会带 <code>X-Requested-Route-Domain</code> 与 <code>X-Tab-Selection-Mode</code>,不会提前伪装成已解析到某个标签页。</p></div>
</div>
<h3>登录状态与上下文上限</h3>
<ul>
<li><strong>推荐登录:</strong>登录你自己的账号,本地接口才能继承当前会话的站点能力与历史上下文。</li>
<li><strong>免登录亦可:</strong>若网站在未登录状态下允许对话,无需登录也能直接通过 API 调用。</li>
</ul>
<div class="co co-warn">
<i data-lucide="alert-triangle" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">上下文长度限制</span><p>受网站输入框单次可容纳字符上限约束,上下文不能太长,否则请求直接失败。长文本场景请开启「文件粘贴」。已测试单次最大发送长度:<strong>ChatGPT 约 200k 字符</strong>;<strong>Gemini 无会员约 30k,Pro 会员目前无明确上限</strong>;<strong>Arena AI 约 120k</strong>。</p></div>
</div>
<h3>开发者协议兼容(实验性)</h3>
<div class="grid2">
<div class="q-card">
<div class="qc-ic"><i data-lucide="terminal" style="width:17px;height:17px"></i></div>
<h5>Claude Code 连通性支持</h5>
<p>内置 Anthropic 风格协议的初步支持:兼容 <code>/v1/messages</code>、<code>/v1/messages/count_tokens</code>、<code>/v1/models</code>;除 <code>Authorization</code> 外亦解析 <code>x-api-key</code>,响应补充 <code>request-id</code> 诊断头。自 2026-05-28 起已完全适配。</p>
</div>
<div class="q-card">
<div class="qc-ic"><i data-lucide="braces" style="width:17px;height:17px"></i></div>
<h5>Codex / Responses API(VSCode)</h5>
<p>暴露实验性 <code>/v1/responses</code> 端点,自动转换并复用 <code>/v1/chat/completions</code> 调度逻辑(支持 <code>input</code>、<code>instructions</code>、<code>tools</code> 载荷);流式模式生成 Codex 规范 SSE 事件,解决工具输出中断问题。</p>
</div>
</div>
<p style="color:var(--tx3);font-size:13.5px">以上协议由于缺乏大规模工具用例覆盖,实际稳定性请按需测试。</p>
</section>
<!-- ============ 05 控制台与监控 ============ -->
<section class="doc-section" id="dashboard" data-reveal>
<div class="sec-kicker"><span class="sec-num">05</span><span class="sec-tag">上手指南</span></div>
<h2><span class="h-ic"><i data-lucide="layout-dashboard" style="width:20px;height:20px"></i></span>控制台与请求监控<a class="h-anchor" href="#dashboard"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>控制台默认运行在 <a href="http://127.0.0.1:8199/" target="_blank" rel="noopener">http://127.0.0.1:8199/</a>。请求队列、运行日志和站点配置都在这里查看与管理。</p>
<div class="mock">
<div class="mock-bar"><i></i><i></i><i></i><span class="mock-url">127.0.0.1:8199</span></div>
<div class="mock-body">
<div class="mock-side"><div class="mi on"></div><div class="mi"></div><div class="mi"></div><div class="mi"></div><div class="mi"></div><div class="mi"></div><div class="mi"></div></div>
<div class="mock-main">
<div class="mock-row">
<div class="mock-kpi"><b>5 站点</b><span>Active Sites</span></div>
<div class="mock-kpi"><b>4 / 8</b><span>Tabs Idle</span></div>
<div class="mock-kpi"><b>99.4%</b><span>Success Rate</span></div>
</div>
<div class="mock-log">
<span class="l-acc">[ROUTE]</span> POST /url/gemini.google.com/v1/chat/completions<br>
<span class="l-acc">[POOL]</span> tab#3 acquired · routing groups match<br>
<span class="l-ok">[STREAM]</span> response finished · 6.8s (DOM Fallback)<br>
<span class="l-acc">[NetworkMonitor]</span> First response timeout 300s reached, falling back to StreamMonitor
</div>
</div>
</div>
</div>
<p class="mock-cap">控制台界面结构示意</p>
<div class="grid3">
<div class="q-card">
<div class="qc-ic"><i data-lucide="panel-left" style="width:17px;height:17px"></i></div>
<h5>中控侧边栏</h5>
<p>显示全局健康度与受控浏览器的连接状态(默认端口 9222),并可切换到首页、站点配置、标签页池、请求监控、命令、日志与设置。</p>
</div>
<div class="q-card">
<div class="qc-ic"><i data-lucide="activity" style="width:17px;height:17px"></i></div>
<h5>请求监控 (Request Monitor)</h5>
<p>显示受控浏览器与后端的内存占用、累计请求量,以及<strong>历史请求明细与执行链追踪</strong>;点击单条记录可查看详情。</p>
</div>
<div class="q-card">
<div class="qc-ic"><i data-lucide="sliders-horizontal" style="width:17px;height:17px"></i></div>
<h5>动态管理</h5>
<p>为不同站点、不同标签页指派预设,配置工作流与拦截规则,或临时覆盖系统参数。</p>
</div>
</div>
<h3>请求异常调试与排查步骤</h3>
<p>请求出问题时,按下面的顺序排查:</p>
<ol class="steps">
<li><strong>查看请求监控列表</strong>:点击失败记录,检查该请求是在哪个阶段失败的——是排队获取标签页时超时(<code>acquire_timeout</code>,默认 60s),还是网络监听等首包响应时超时(<code>first_response_timeout</code>,默认 300s)。</li>
<li><strong>联合日志追踪</strong>:在日志页面中,通过请求的唯一 <code>RequestID</code> 或短追踪哈希,把 <code>[ROUTE]</code>(路由)、<code>[POOL]</code>(标签分配)、<code>[INPUT]</code>(输入)、<code>[STREAM]</code>(输出捕获)与 <code>[NetworkMonitor]</code> 各阶段的日志串起来看,定位卡在哪一步。</li>
<li><strong>隔离问题标签页</strong>:如果某个标签页频繁卡死或变慢,到「标签页池」查看它的锁定状态,用取消按钮中断,或调用调试接口释放。</li>
</ol>
<div class="co co-info">
<i data-lucide="braces" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">系统自愈与调试 API 接口</span>
<ul>
<li><code>GET /api/system/request-history?limit=200</code> — 读取近期请求审计记录(含报错日志摘要)</li>
<li><code>GET /api/system/request-history/{request_id}</code> — 读取单条请求详情(前端详情弹窗同款)</li>
<li><code>POST /api/debug/cancel-current</code> — 取消当前正在处理的阻塞请求,支持指定 <code>tab_id</code></li>
<li><code>POST /api/debug/force-release</code> — 强制清空所有请求锁和标签页锁,重置池状态(最后手段)</li>
</ul>
</div>
</div>
</section>
<!-- ============ 06 选择器配置 ============ -->
<section class="doc-section" id="selectors" data-reveal>
<div class="sec-kicker"><span class="sec-num">06</span><span class="sec-tag">核心配置</span></div>
<h2><span class="h-ic"><i data-lucide="crosshair" style="width:20px;height:20px"></i></span>选择器配置 Selectors<a class="h-anchor" href="#selectors"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>每个站点的每个预设都需要定义一组 CSS 选择器,告诉程序<strong>去哪里输入、点哪里发送、从哪里读回复</strong>。配置完全在控制台的可视化表单中回填,不需要修改任何 JSON 文件。这是所有配置里最关键、也最容易因网站改版而失效的部分。</p>
<h3>先认识 3 个核心字段(在选择器配置面板顶部输入)</h3>
<div class="grid3">
<div class="q-card"><div class="qc-ic"><i data-lucide="text-cursor-input" style="width:17px;height:17px"></i></div><h5>输入框选择器 (input_box)</h5><p>指定聊天输入框(如 <code>textarea</code>)在页面中的位置。<span class="bdg g">必填</span></p></div>
<div class="q-card"><div class="qc-ic"><i data-lucide="send" style="width:17px;height:17px"></i></div><h5>发送按钮选择器 (send_btn)</h5><p>网页上用于发送的按钮。<span class="bdg g">必填</span></p></div>
<div class="q-card"><div class="qc-ic"><i data-lucide="message-square-text" style="width:17px;height:17px"></i></div><h5>AI 回复容器 (result_container)</h5><p>AI 回复文本渲染所在的外层大容器。<span class="bdg g">必填 · 最易出错</span></p></div>
</div>
<p>各字段的常用填写示例:</p>
<div class="tw"><table class="tbl">
<thead><tr><th>界面配置输入框</th><th>常用填入示例(CSS选择器)</th><th>定位技巧说明</th></tr></thead>
<tbody>
<tr><td><strong>输入框选择器 (input_box)</strong></td><td><code>textarea[id='prompt']</code> 或 <code>textarea</code></td><td>优先寻找含有 <code>id</code> 或专属 class 的 textarea 标签。</td></tr>
<tr><td><strong>发送按钮选择器 (send_btn)</strong></td><td><code>button.send-btn</code> 或 <code>button[aria-label="发送消息"]</code></td><td>选择含有发送小飞机图标或带有 Send 文本的 button 元素。</td></tr>
<tr><td><strong>AI 回复容器 (result_container)</strong></td><td><code>.markdown-body</code> 或 <code>div.message-content</code></td><td>务必选择<strong>包裹整条 AI 回复文本的外层容器</strong>。如果选小了,会漏抓格式或发生字符截断。</td></tr>
<tr><td><strong>新建对话按钮 (new_chat_btn)</strong></td><td><code>button.new-chat</code> 或 <code>a[href="/"]</code></td><td>页面左上角或侧栏的新建对话按钮,按需补充。</td></tr>
</tbody>
</table></div>
<div class="co co-info">
<i data-lucide="lightbulb" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">怎么找得更稳</span>
<ul>
<li>在网页中右键点击目标元素(例如输入框) → 检查,查看其 HTML 属性。</li>
<li>优先使用 <code>id</code>、<code>data-testid</code>、<code>aria-label</code> 这类具有明确语义的属性定位;如果 Class 名字是一长串无规则的随机字母数字(动态混淆 Class),先别用它,否则网站一刷新或改版就会失效。</li>
<li>每一项输入完成后,点击右侧的<strong>【测试】</strong>按钮,确认能命中。</li>
</ul>
</div>
</div>
<h3>填写顺序建议</h3>
<ol class="steps">
<li>在受控浏览器中打开目标网站,右键输入框选择“检查元素”,把定位器填入 <code>input_box</code>。</li>
<li>再找到发送按钮,把其定位器填入 <code>send_btn</code>。</li>
<li>在对话框中发一条消息,等 AI 回复完毕后,找到<strong>包裹回复内容的最外层大 DIV</strong>,填入 <code>result_container</code>。</li>
<li>每填一项就点一次该字段右侧的「测试」,确认能命中——切忌全部填完再一起排查。</li>
<li>前三项稳定后,再考虑补充 <code>new_chat_btn</code> 或其他附件上传的选择器。</li>
</ol>
<div class="co co-tip">
<i data-lucide="flask-conical" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">选择器测试工作台</span><p>控制台里的测试按钮已升级为「选择器测试工作台」:点击后不仅能得出是否命中,还会以树形图返回<strong>命中 DOM 详情、系统推荐候选选择器、潜在定位风险</strong>,并支持点击推荐的候选一键回填到配置框中。</p></div>
</div>
</section>
<!-- ============ 07 工作流配置 ============ -->
<section class="doc-section" id="workflow" data-reveal>
<div class="sec-kicker"><span class="sec-num">07</span><span class="sec-tag">核心配置</span></div>
<h2><span class="h-ic"><i data-lucide="workflow" style="width:20px;height:20px"></i></span>工作流与可视化交互调优<a class="h-anchor" href="#workflow"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>工作流定义了一轮 API 交互在受控浏览器中的执行动作顺序(如清除历史、输入提示词、点击发送以及等待流式完成)。最新的工作流支持在控制台进行<strong>完全可视化的拖拽与编辑</strong>,无需编写 JSON 代码。</p>
<h3>可视化节点编辑器</h3>
<p>在站点配置的【请求工作流】区域,所有动作按执行顺序排成一条节点链:</p>
<ul>
<li><strong>添加步骤</strong>:点击“新增步骤”在链末追加动作卡片;也可以套用内置模板,一键生成最短可用工作流。</li>
<li><strong>调整顺序</strong>:按住卡片左侧拖动即可。</li>
<li><strong>删除步骤</strong>:点击卡片右上角的“垃圾桶”图标。</li>
<li><strong>标记必需 / 可选</strong>:每张卡片底部有一个“必需步骤”勾选框——默认勾选表示必需(找不到目标元素就报错);<strong>取消勾选即变为可选</strong>,找不到元素时会自动跳过该步骤。</li>
</ul>
<div class="tw"><table class="tbl">
<thead><tr><th>界面动作节点</th><th>表单可配置属性</th><th>策略含义说明与调优推荐</th></tr></thead>
<tbody>
<tr>
<td><strong>CLICK</strong><br><small>点击元素</small></td>
<td>目标选择器 (Target)<br>验证点击结果 (Verify)<br>失败后自动重试</td>
<td>点击指定按钮(如 <code>new_chat_btn</code>)。勾选“验证点击”后会在点击后二次校验,没生效就自动重试,新建会话时很有用。</td>
</tr>
<tr>
<td><strong>FILL_INPUT</strong><br><small>填充输入</small></td>
<td>目标输入框选择器 (Target)<br>启用稳定等待</td>
<td>把提示词粘贴或键入目标输入框。建议勾选“输入框稳定等待”,避免页面没加载完导致粘贴粘连或失焦。</td>
</tr>
<tr>
<td><strong>WAIT</strong><br><small>延时等待</small></td>
<td>等待秒数 (Value)</td>
<td>暂停指定秒数(如 <code>0.5</code>),用于等待过渡动画或异步请求。</td>
</tr>
<tr>
<td><strong>KEY_PRESS</strong><br><small>按键</small></td>
<td>按键键值 (Target)<br>内置常用组合下拉</td>
<td>模拟键盘按键。发送按钮不可靠或不存在时,可以追加一个 <code>Enter</code> 动作触发发送;支持 <code>Ctrl+Enter</code>、<code>Shift+Enter</code> 等组合键。</td>
</tr>
<tr>
<td><strong>SELECT_MODEL</strong><br><small>选择请求模型</small></td>
<td>模型选择器 (Target)</td>
<td>在支持切换模型的站点上,按请求携带的模型名去页面上点选对应模型项,实现"同站点按模型分流"。</td>
</tr>
<tr>
<td><strong>PAGE_FETCH</strong><br><small>页面直发</small></td>
<td>发送方式(页面直发配置)</td>
<td>使用当前预设的"页面直发"配置直接提交已构造好的 Prompt(绕过逐步点选)。若直发失败且回退模式设为工作流,会继续执行后面的填入 / 按键 / 等待步骤兜底。</td>
</tr>
<tr>
<td><strong>COORD_CLICK</strong><br><small>坐标点击</small></td>
<td>X / Y(viewport 坐标)<br>随机半径</td>
<td>按 viewport CSS 坐标(非屏幕坐标)点击某个位置,可设随机半径抖动。适用于没有稳定选择器、只能靠位置点击的按钮。</td>
</tr>
<tr>
<td><strong>COORD_SCROLL</strong><br><small>模拟滑动</small></td>
<td>起点 / 终点坐标</td>
<td>在指定起终点之间模拟滚动。普通模式直接派发滚轮事件,低熵模式会按站点 stealth 配置走人类化轨迹。</td>
</tr>
<tr>
<td><strong>JS_EXEC</strong><br><small>执行 JavaScript</small></td>
<td>JavaScript 代码</td>
<td>在当前页面上下文执行一段自定义 JS,用于处理特殊弹窗、预处理页面状态等常规节点覆盖不到的场景。</td>
</tr>
<tr>
<td><strong>READONLY_HINT</strong><br><small>只读提示</small></td>
<td>标题 / 正文 / 语气</td>
<td>纯说明卡片,执行时<strong>不会</strong>点击、输入或等待页面,仅用于在工作流里给自己或他人留下备注。</td>
</tr>
<tr>
<td><strong>STREAM_WAIT</strong><br><small>等待输出捕获</small></td>
<td>结果容器选择器 (Target)</td>
<td>等待 AI 的流式响应输出结束,并捕获内容。<strong>常规 UI 工作流必须以它作为最终收尾步骤</strong>(改用 <code>PAGE_FETCH</code> 页面直发的链路除外)。</td>
</tr>
</tbody>
</table></div>
<p style="color:var(--tx3);font-size:13.5px">下拉里的动作以控制面板实际选项为准;本表覆盖当前可选的全部节点类型。</p>
<h3>防风控与开头注入</h3>
<p>在防爬严格的站点(如 GPT、Gemini、Arena)上,频繁发送模式相似的 Prompt 容易触发限频。可在控制面板开启两种扰动手段:</p>
<ul>
<li><strong>开头追加随机占位片段</strong>:发送时在 Prompt 前自动加一段无意义前缀(如 <code>测试号,无实际意义: [随机混淆码]</code>),“开头片段数”与“说明文本”都可自定义,让每条请求内容不完全一致。</li>
<li><strong>提示词内随机字符插入</strong>:从自定义字符集(如 <code>abc123※☆</code>)中随机取一个字符,插入提示词的随机位置。</li>
</ul>
<h3>输入框稳定与自愈等待</h3>
<p>部分网站点击新建对话后会重建输入框节点,导致粘贴时失焦或失败。可在站点配置的【高级功能】中调整:</p>
<ul>
<li><strong>输入框稳定等待</strong>:执行 <code>FILL_INPUT</code> 前,先确认输入框节点连续多次检测保持稳定。</li>
<li><strong>自愈选项</strong>:可勾选“仅在刚点击 <code>new_chat_btn</code> 后启用”或“新建对话后等待 URL 切换”,配合“最长等待秒数”(如 <code>1.5</code> 秒)与“URL 匹配正则”,等页面就绪再填入。</li>
<li><strong>发送内容确认与自愈</strong>:点击 <code>send_btn</code> 后二次确认输入框已清空或明显变短;发现没发出去,就自动重试当前工作流。</li>
</ul>
</section>
<!-- ============ 08 响应检测 ============ -->
<section class="doc-section" id="response" data-reveal>
<div class="sec-kicker"><span class="sec-num">08</span><span class="sec-tag">核心配置</span></div>
<h2><span class="h-ic"><i data-lucide="radio-tower" style="width:20px;height:20px"></i></span>响应检测与自愈重试<a class="h-anchor" href="#response"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>系统需要判定 AI <strong>什么时候开始输出、什么时候算说完</strong>,并从中捕获流式文本。有两种检测模式,支持自动回退。</p>
<div class="tw"><table class="tbl">
<thead><tr><th>检测模式</th><th>流式输出</th><th>工作方式</th></tr></thead>
<tbody>
<tr><td>DOM 模式 <span class="bdg g">通用推荐</span></td><td>✅</td><td>监听网页 DOM 节点的字符变化,不需要了解站点接口,兼容性极高。</td></tr>
<tr><td>网络拦截模式</td><td>✅(需适配)</td><td>直接挂载 CDP 网络监听事件,阻断并获取 XHR/Fetch 数据包,还原代码和公式更精确。<strong>若首次响应超时,会自动向 DOM 模式回退。</strong></td></tr>
</tbody>
</table></div>
<h3>网络监听超时自动回退</h3>
<p>网络拦截模式更精准,但网页改版或解析器报错时可能捕获失败,让请求一直挂着。对应的保护机制:</p>
<ul>
<li><strong>首次响应超时自动回退</strong>:发送后开始计时(<code>first_response_timeout</code>,默认 300s,在流式配置的 <code>network</code> 项下)。超时仍没有流量命中 <code>listen_pattern</code> 规则,就<strong>自动回退到 DOM 模式</strong>(<code>StreamMonitor</code>)继续从页面抓取文本,请求不会因此挂起。</li>
</ul>
<h3>发送确认与重试</h3>
<p>部分站点点击发送后偶发无响应,可在【发送确认与重试】中配置:</p>
<ul>
<li><strong>自动再点一次</strong>:点击 <code>send_btn</code> 后,若观察窗口内(如 <code>1.8</code> 秒)没有出现输入框清空、网络活动或生成状态,就再点一次发送。</li>
<li><strong>重试频次</strong>:最大支持重试 2 次,两次重试间隔支持定制(如 <code>0.6</code> 秒)。</li>
<li><strong>防中断保护</strong>:一旦判定 AI 已开始生成(或发送按钮变成了停止/中断状态),会<strong>立即停止重试</strong>,避免二次点击切断正在生成的回复。</li>
</ul>
<h3>DOM 模式结束判定公式</h3>
<div class="cb" data-lang="text"><div class="cb-top"><span class="cb-dots"><i></i><i></i><i></i></span><span class="cb-lang">稳定判定条件</span><button class="cb-copy"><i data-lucide="copy" style="width:12px;height:12px"></i><span>复制</span></button></div><pre><code>生成结束判定 = (连续稳定次数 ≥ 稳定判定次数) AND (静默时间 > 静默超时阈值)</code></pre></div>
<p>DOM 检查时,内容没有再变化,稳定计数增加,静默时间累加。两个阈值同时达到时,判定本轮回复完成。全局硬超时(DOM 模式默认 <strong>600 秒</strong>,即浏览器常量里的「最大超时」;网络拦截模式则另有各自的首包与硬超时)是本轮监听的物理保底,无论如何都会在到点后强制收尾。</p>
</section>
<!-- ============ 09 预设系统 ============ -->
<section class="doc-section" id="presets" data-reveal>
<div class="sec-kicker"><span class="sec-num">09</span><span class="sec-tag">核心配置</span></div>
<h2><span class="h-ic"><i data-lucide="sliders-horizontal" style="width:20px;height:20px"></i></span>多预设管理系统<a class="h-anchor" href="#presets"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>预设允许你为<strong>同一个站点创建多套独立的配置方案</strong>,并分配给不同标签页。每个预设包含独立的选择器、工作流、流式配置、多模态提取、文件粘贴等全套配置,互不影响。</p>
<div class="tw"><table class="tbl">
<thead><tr><th>标签页编号</th><th>绑定的预设名称</th><th>实际配置差异与工作场景</th></tr></thead>
<tbody>
<tr><td>标签页 #1</td><td><strong>主预设 (默认)</strong></td><td>常规工作流(新建会话)、开启大文本文件粘贴。适用于大段长文本翻译。</td></tr>
<tr><td>标签页 #2</td><td><strong>快速识图</strong></td><td>简化工作流(不重置会话)、开启多模态图片提取、设置较短的响应超时。适用于识图。</td></tr>
<tr><td>标签页 #3</td><td><strong>网络拦截调试</strong></td><td>开启网络拦截模式、绑定专用解析器。适用于代码块与公式的精确截获。</td></tr>
</tbody>
</table></div>
<h3>预设操作</h3>
<p>都在【站点配置】面板里完成:</p>
<ol class="steps">
<li><strong>切换与新建</strong>:在页面顶部的“当前预设”下拉框选择要修改的预设,或点击<strong>【+ 新建预设】</strong>输入新名字。新预设会复制当前预设的全部参数,之后各自独立调整。</li>
<li><strong>管理与设为默认</strong>:点击下拉框旁的“管理预设”可以改名或删除。点击<strong>【⭐ 设为默认】</strong>后,该预设作为 API 请求的保底配置。</li>
<li><strong>绑定到标签页</strong>:切换到【标签页】选项卡,每一行代表一个正在运行的标签页,在“预设”列的下拉菜单里选中预设名即可绑定。</li>
<li><strong>单次请求临时覆盖</strong>:不想改绑定时,在请求 URL 上加参数(如 <code>/v1/chat/completions?preset_name=快速识图</code>),只对这一次请求生效。</li>
</ol>
<div class="co co-info">
<i data-lucide="info" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">自动持久化</span><p>面板上的新建、修改、删除都会自动保存到 <code>config/sites.json</code>,<strong>不需要手动编辑 JSON</strong>。</p></div>
</div>
<h3>对话复用与新建会话控制</h3>
<ul>
<li><strong>对话复用窗口(秒):</strong>大于 <code>0</code> 时,同一标签页在窗口期内收到的后续请求会直接复用当前会话续聊;设为 <code>0</code>(默认)表示关闭复用,每次请求都可能触发工作流开头的"新建会话"逻辑。</li>
<li><strong>强制新建对话:</strong>开启后即使配置了大窗口也忽略复用,<strong>每次都强制新开会话</strong>——特别适合测试无历史干扰的独立 Prompt 流程。</li>
</ul>
<div class="co co-warn">
<i data-lucide="alert-triangle" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">删除不可撤销</span><p>删除预设无法恢复,且每个站点至少需要保留一个预设——只剩一个时删除按钮会被禁用。</p></div>
</div>
</section>
<!-- ============ 10 标签页池 ============ -->
<section class="doc-section" id="tabpool" data-reveal>
<div class="sec-kicker"><span class="sec-num">10</span><span class="sec-tag">核心配置</span></div>
<h2><span class="h-ic"><i data-lucide="layers" style="width:20px;height:20px"></i></span>标签页池与会话隔离<a class="h-anchor" href="#tabpool"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>标签页池(Tab Pool)负责把并行的 API 请求排队、分发到合适的标签页,实现单浏览器多会话并行。</p>
<h3>核心生命周期与超时参数</h3>
<div class="tw"><table class="tbl">
<thead><tr><th>配置参数</th><th>默认值</th><th>说明</th></tr></thead>
<tbody>
<tr><td><code>max_tabs</code></td><td><code>5</code></td><td>允许开启的最大标签页数量上限。超出限制后,新请求必须排队等待。</td></tr>
<tr><td><code>min_tabs</code></td><td><code>1</code></td><td>保留在内存中的最小标签页数量,防止频繁开启/关闭页面。</td></tr>
<tr><td><code>idle_timeout</code></td><td><code>300</code> 秒</td><td>标签页空闲超时阈值。超过该时间没有任何 API 请求时,标签页会自动关闭释放内存。</td></tr>
<tr><td><code>acquire_timeout</code></td><td><code>60</code> 秒</td><td>API 请求排队获取空闲标签页的最长等待时间。超时则返回 429 或 504 错误。</td></tr>
<tr><td><code>stuck_timeout</code></td><td><code>180</code> 秒</td><td>页面交互卡死超时时间。由于 DOM 监听死锁或站点假死超过该时间,强制回收标签页。</td></tr>
</tbody>
</table></div>
<h3>独立 Cookie 标签页</h3>
<p>对 <code>arena.ai</code> 这类需要隔离 Cookie 的站点(避免多标签页共用同一登录会话),【高级功能】中提供:</p>
<ul>
<li><strong>独立 Cookie 标签页</strong>:开启后,该预设创建的标签页在独立的匿名会话容器中运行,各标签页的 Cookie、Local Storage 彼此隔离。</li>
<li><strong>自动接管手动新标签页</strong>:人工新建或弹出的标签页会被脚本接管,关闭原页面并转为独立的受控窗口。</li>
</ul>
<h3>域名路由分组 (Route Groups)</h3>
<p>用于多账号、多业务线的隔离。可以为不同请求定义专属的标签页路由组(在配置文件或标签面板管理):</p>
<ul>
<li><strong>工作逻辑</strong>:为指定域名(如 <code>chat.deepseek.com</code>)绑定一组专用标签页,或按传入的 URL token 指定独立会话。不同路由组互不干扰,可实现<strong>多账号轮询分流</strong>。</li>
<li><strong>分配策略 (allocation_mode)</strong>:支持 <code>first_idle</code>(最先空闲)、<code>round_robin</code>(同组轮询分摊)与 <code>random</code>(随机选择,防轨迹侦测)三种分发逻辑。</li>
<li><strong>错误标签页保留 (preserve_error_tabs)</strong>:勾选后,标签页发生严重错误或被风控拦截时<strong>不会被关闭</strong>,控制台亮起报警,方便进入受控浏览器人工处理。</li>
</ul>
<h3>常用路由方式一览</h3>
<div class="tw"><table class="tbl">
<thead><tr><th>方式</th><th>接口 URL 格式</th><th>工作说明</th></tr></thead>
<tbody>
<tr><td>自动分发</td><td><code>/v1/chat/completions</code></td><td>系统根据全局分配模式挑空闲页面。</td></tr>
<tr><td>域名指定</td><td><code>/url/gemini.google.com/v1/chat/completions</code></td><td>只分发到 gemini.google.com 的可用标签页。</td></tr>
<tr><td>标签指定</td><td><code>/tab/3/v1/chat/completions</code></td><td>只通过编号 #3 的标签页发送请求。</td></tr>
<tr><td>URL 短哈希</td><td><code>/tab-url/{token}/v1/chat/completions</code></td><td>路由到该 token 对应会话 URL 的标签页,严格匹配。</td></tr>
</tbody>
</table></div>
</section>
<!-- ============ 11 多模态提取 ============ -->
<section class="doc-section" id="multimodal" data-reveal>
<div class="sec-kicker"><span class="sec-num">11</span><span class="sec-tag">高级能力</span></div>
<h2><span class="h-ic"><i data-lucide="image" style="width:20px;height:20px"></i></span>多模态提取与媒体配置<a class="h-anchor" href="#multimodal"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>【多模态提取】面板管理如何从网页中提取<strong>图片、音频、视频</strong>,并转换成客户端可直接使用的本地链接或 Markdown 图片标签。全部在面板里配置,不需要改 JSON。</p>
<h3>1. 基础开关与提取范围</h3>
<ul>
<li><strong>启用多模态提取(开关)</strong>:全局总开关。勾选后,系统才会在对话完成时去扫描网页里的图片/视频。</li>
<li><strong>提取策略模式(下拉框)</strong>:
<ul>
<li><code>提取所有 (all)</code> — 网页上生成的全部图片或媒体文件一并打包返回。</li>
<li><code>仅首个 (first)</code> — 仅提取网页回答中出现的第一张图片,适合标准的单图输出场景。</li>
</ul>
</li>
<li><strong>媒体文件大小限制(数字输入框)</strong>:单位为 MB(默认 <code>10</code>)。超过此大小的媒体文件将被忽略,防止超大视频/无用底图占满服务器带宽。</li>
<li><strong>下载二进制资源 (Download Blobs)</strong>:开启后,自动下载网页里的二进制 Blob 媒体并转换为持久本地链接,防止因浏览器页面关闭导致临时链接失效。</li>
</ul>
<h3>2. 子模态参数配置(图片 / 音频 / 视频卡片)</h3>
<p>可分别为每种媒体开启提取,并配置对应的<strong>运行策略</strong>与<strong>等待时长</strong>:</p>
<div class="tw"><table class="tbl">
<thead><tr><th>界面配置项</th><th>可用运行策略(下拉菜单)</th><th>策略含义说明与推荐场景</th></tr></thead>
<tbody>
<tr>
<td><strong>启用状态 (Enabled)</strong><br><small>勾选框</small></td>
<td>无</td>
<td>控制是否启用当前类别(图片/音频/视频)的提取。</td>
</tr>
<tr>
<td><strong>运行策略 (Run Policy)</strong><br><small>下拉框</small></td>
<td>
① 仅普通扫描<br><code>(generic_only)</code><br>
② 按信号等待 <span class="bdg g">推荐</span><br><code>(on_signal)</code><br>
③ 有朗读按钮才探测<br><code>(probe_if_trigger_found)</code><br>
④ 始终等待<br><code>(always_probe)</code>
</td>
<td>
<ul>
<li><code>generic_only</code>:只快速扫一眼现有 DOM,不触发任何长等待或录音(如 Gemini 直连返回)。</li>
<li><code>on_signal</code>:当检测到正在生成的占位提示或正在上传的文件信号时才进行长等待,效率最高。</li>
<li><code>probe_if_trigger_found</code>:【音频专用】先侦测页面是否有可点的朗读/听书按钮,有才进入捕获流程。</li>
<li><code>always_probe</code>:强制每次对话完都硬等媒体加载,仅在确定每轮必出媒体时开启。</li>
</ul>
</td>
</tr>
<tr>
<td><strong>快速探测时间 (秒)</strong><br><small>数字框 (默认 1.0)</small></td>
<td>无</td>
<td>发送完消息后,先用很短的时间(如 1 秒)扫描有没有媒体生成信号;没有就直接结束,避免白等。</td>
</tr>
<tr>
<td><strong>最终等待时间 (秒)</strong><br><small>数字框</small></td>
<td>无</td>
<td>确认有生成信号后,给媒体加载与下载预留的最长时间(图片可填 45,视频可填 90)。超时仍没加载完则报错返回。</td>
</tr>
</tbody>
</table></div>
<h3>3. 提取源定位(DOM 选择器配置)</h3>
<p>【元素选择器】用来告诉脚本媒体在页面的哪个位置,避免误抓广告或头像:</p>
<ul>
<li><strong>媒体选择器 (Selector)</strong>:指示媒体标签。例如图片填 <code>img</code>,视频填 <code>video, video source</code>。</li>
<li><strong>容器选择器 (Container Selector)</strong>:<strong>非常重要</strong>,用来圈定提取范围(如 <code>.result-content</code>)。系统<strong>只抓取该容器内的媒体</strong>,从而避开顶栏、侧边栏的无关图片。</li>
</ul>
<h3>4. 页面朗读音频捕获(TTS 语音录制)</h3>
<p>除了抓取网页里已有的 <code>audio</code> 节点外,如果想录制 AI 的“在线朗读”发音,可以展开并配置【朗读捕获】表单:</p>
<ul>
<li><strong>启用朗读录制 (audio_capture_enabled)</strong>:勾选后,系统会在文本输出完成后,去寻找并自动点击网页中的“朗读”或“发声”按钮来捕获音频。</li>
<li><strong>朗读按钮选择器 (audio_trigger_selector)</strong>:填入发音按钮的精确定位器。</li>
<li><strong>按钮文本兜底 (audio_trigger_labels)</strong>:当选择器不稳定时,可通过文字(如 <code>"朗读", "发音", "收听"</code>)匹配按钮。</li>
<li><strong>网络音频直抓 (url_patterns)</strong>:设置过滤关键词(如 <code>tts</code>、<code>voice</code>)后,播放时若有匹配的网络音频流,会优先直抓合成,失败时降级为页面内录音兜底。</li>
</ul>
<div class="co co-tip">
<i data-lucide="check-circle-2" style="width:18px;height:18px"></i>
<div class="co-bd"><span class="co-t">返回格式</span><p>图片以 Markdown 标签 <code></code> 返回;音频、视频以链接 <code>[audio_0](/download_images/xxx.mp3)</code> 返回,SillyTavern 等客户端可以直接显示和播放。</p></div>
</div>
</section>
<!-- ============ 12 文件粘贴 ============ -->
<section class="doc-section" id="filepaste" data-reveal>
<div class="sec-kicker"><span class="sec-num">12</span><span class="sec-tag">高级能力</span></div>
<h2><span class="h-ic"><i data-lucide="paperclip" style="width:20px;height:20px"></i></span>文件与附件发送判定<a class="h-anchor" href="#filepaste"><i data-lucide="link" style="width:16px;height:16px"></i></a></h2>
<p>当 Prompt 超过网站输入框的长度限制时,系统会自动把它写入临时文件,通过网页的附件上传通道发给 AI,以此承载超长上下文。</p>
<h3>文件粘贴配置</h3>
<p>在站点配置的【文件粘贴模式】板块配置:</p>
<div class="tw"><table class="tbl">
<thead><tr><th>界面配置表单项</th><th>建议值/示例</th><th>作用说明与推荐场景</th></tr></thead>
<tbody>
<tr>
<td><strong>启用状态开关</strong></td>
<td>开启 / 关闭</td>
<td>控制是否启用大文本自动转化为文件上传的拦截机制。</td>
</tr>
<tr>
<td><strong>阈值 (字符数)</strong></td>
<td><code>40000</code></td>
<td>当输入的消息字符数超过该值时,自动拦截普通文本发送,转化为附件上传通道。建议设为目标网站输入框物理字数上限的 70% 左右。</td>
</tr>
<tr>
<td><strong>临时文件类型</strong><br><small>下拉菜单</small></td>
<td>
① <code>TXT</code><br>
② <code>PDF</code><br>
③ <code>ERROR</code>
</td>
<td>
<ul>
<li><code>TXT</code>:生成临时 <code>.txt</code> 纯文本文件并上传。最常用、速度快。</li>
<li><code>PDF</code>:生成临时 <code>.pdf</code> 文档并上传。在某些对 PDF 拥有深度阅读优化或只支持文档上传的 AI 平台上(如 Claude、Gemini 等),选择 PDF 格式常能获得更好的段落级格式保持。</li>
<li><code>ERROR</code>:不做转换上传,<strong>直接向 API 调用方抛出错误响应</strong>。适合需要对长提示词强制限额的场景。</li>
</ul>
</td>
</tr>
<tr>
<td><strong>引导文本</strong></td>
<td><code>上传的文件内容即为上下文,请据此回复</code></td>
<td>文件上传成功后,系统在聊天输入框里自动灌入并发送的指令文本,用来引导 AI 优先去阅读和分析刚刚上传的附件。</td>
</tr>
<tr>
<td><strong>上传信号超时 (秒)</strong></td>
<td><code>2.5</code> 秒</td>
<td>触发附件上传动作后,等待网页端成功弹出“上传中”或“挂载就绪”预览芯片的最长侦测等待时间。</td>
</tr>
<tr>
<td><strong>上传后稳定等待 (秒)</strong></td>
<td><code>0</code> 秒</td>
<td>识别到附件就绪后,额外静止等待多少秒再点击发送(针对网络卡顿或需要文件二次解析的网站)。</td>
</tr>
<tr>
<td><strong>上传完成后重新定位输入框</strong></td>
<td>勾选</td>
<td>部分网站(如 Claude)在上传完文件后,原输入框会强制失焦。勾选后系统会在发送前自动重新定位并聚焦输入框,防止发送失败。</td>
</tr>
<tr>
<td><strong>上传后专用输入框 selector</strong></td>
<td><code>.composer textarea</code></td>
<td>配合重新定位功能,指定上传完毕后重新聚焦哪一个输入框元素定位器(选填)。</td>
</tr>
</tbody>
</table></div>
<h3>附件发送判定</h3>
<p>发送带附件的消息时(文件粘贴或图片粘贴),系统会观察预览就绪、发送按钮置灰、进入生成态等信号,确认附件真的发出去了:</p>
<div class="tw"><table class="tbl">
<thead><tr><th>界面配置项</th><th>设置推荐</th><th>作用说明</th></tr></thead>
<tbody>
<tr>
<td><strong>敏感度 (Sensitivity)</strong></td>
<td><code>高</code> / <code>中</code> / <code>低</code></td>
<td>敏感度越高,对附件预览挂载/消失的检测越严格,判断上传状态也越早。</td>
</tr>
<tr>
<td><strong>最大重试次数</strong></td>
<td><code>2</code> 次</td>
<td>检测到发送失败或附件未挂上时的最大自动重发次数。</td>
</tr>
<tr>
<td><strong>重试间隔</strong></td>
<td><code>0.6</code> 秒</td>
<td>发生重试发送动作时的两次点击间隔时间。</td>
</tr>
<tr>
<td><strong>最小冷却窗</strong></td>
<td><code>1.5</code> 秒</td>
<td>点击发送按钮到允许下一次发送的物理保护时间窗口,防止过度高频点击将页面判定卡死。</td>
</tr>
<tr>
<td><strong>重试前短探测</strong></td>
<td><code>0.12</code> 秒</td>
<td>重试点击前,先做一次快速 DOM 探测的等待时间。</td>
</tr>
<tr>
<td><strong>自动重试动作</strong></td>
<td><code>点击发送按钮</code> / <code>按键发送</code></td>
<td>重发时的驱动模式:支持点击网页 Send 按钮或模拟发送按键。</td>
</tr>
<tr>
<td><strong>重试按键 (retry_key)</strong></td>
<td><code>Enter</code> / 自定义组合</td>
<td>按键重试时的物理按键组合(支持 Enter、Ctrl+Enter 或 Shift+Enter)。</td>
</tr>
</tbody>
</table></div>
<h3>高级附件规则</h3>
<p>【高级附件规则】里还有几个开关:</p>
<ul>
<li><strong>发送前必须看到附件已挂上页面</strong>:上传预览渲染出来后才允许点发送,避免文件没挂上就把消息发出去。</li>
<li><strong>没有观察到上传启动前,不允许判定 ready</strong>:防止网络卡顿造成脚本还未来得及触发上传就直接判为就绪发送。</li>