vcorp-chrome 1.4.1 → 1.6.0
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 +547 -547
- package/docs//344/272/221/347/253/257/345/217/221/345/270/203.md +32 -31
- package/docs//345/215/217/350/256/256.md +16 -1
- package/extension/background.js +2 -0
- package/extension/cloud-policy.js +390 -426
- package/extension/cloud.js +972 -1013
- package/extension/manifest.json +38 -38
- package/extension/mark.js +16 -1
- package/extension/panel.html +210 -204
- package/extension/panel.js +427 -428
- package/extension/welcome.html +99 -99
- package/package.json +44 -44
package/extension/manifest.json
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"manifest_version": 3,
|
|
3
|
-
"name": "vcorp-chrome",
|
|
4
|
-
"version": "1.
|
|
5
|
-
"description": "让 AI agent 操控你已登录的 Chrome。基于花叔的 huashu-chrome(MIT)修改。",
|
|
6
|
-
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq6xRqEwG4yTuHRG1Zah3j//T3B72XnazyZ+9fOCa5P4bBLPmNBN7YAGL5WnjtPVJefXT9r2Ol0qvNztayDG3dMjK6AZoWccgKa5rhxcvWgFUjanXtmBBQ0qgYwNhuEJSkdinLLtyUg6YmK7Mn72NWpfa/NfqNHdK5AHslvvtJ50iQAYmabl2Nd3vOJ9DxtLBt8a2DfoGPWizgEB3+gkqm2PB8LywwwoiGKd7acr1wZEWmWK9/s0YWdzIstjlvk5AO5XFn6EtEzW8tAAOwBka9239pcyj0kEogWctHLJn7p9VFru38r+I1USyGn6u9XQ68n9edWddxBYokETCqEMT9QIDAQAB",
|
|
7
|
-
"minimum_chrome_version": "116",
|
|
8
|
-
"background": {
|
|
9
|
-
"service_worker": "background.js",
|
|
10
|
-
"type": "module"
|
|
11
|
-
},
|
|
12
|
-
"action": {
|
|
13
|
-
"default_title": "vcorp-chrome"
|
|
14
|
-
},
|
|
15
|
-
"permissions": [
|
|
16
|
-
"tabs",
|
|
17
|
-
"tabGroups",
|
|
18
|
-
"scripting",
|
|
19
|
-
"storage",
|
|
20
|
-
"alarms",
|
|
21
|
-
"offscreen",
|
|
22
|
-
"downloads",
|
|
23
|
-
"sidePanel",
|
|
24
|
-
"notifications",
|
|
25
|
-
"debugger"
|
|
26
|
-
],
|
|
27
|
-
"host_permissions": [
|
|
28
|
-
"<all_urls>"
|
|
29
|
-
],
|
|
30
|
-
"icons": {
|
|
31
|
-
"16": "icons/icon16.png",
|
|
32
|
-
"48": "icons/icon48.png",
|
|
33
|
-
"128": "icons/icon128.png"
|
|
34
|
-
},
|
|
35
|
-
"side_panel": {
|
|
36
|
-
"default_path": "panel.html"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 3,
|
|
3
|
+
"name": "vcorp-chrome",
|
|
4
|
+
"version": "1.6.0",
|
|
5
|
+
"description": "让 AI agent 操控你已登录的 Chrome。基于花叔的 huashu-chrome(MIT)修改。",
|
|
6
|
+
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq6xRqEwG4yTuHRG1Zah3j//T3B72XnazyZ+9fOCa5P4bBLPmNBN7YAGL5WnjtPVJefXT9r2Ol0qvNztayDG3dMjK6AZoWccgKa5rhxcvWgFUjanXtmBBQ0qgYwNhuEJSkdinLLtyUg6YmK7Mn72NWpfa/NfqNHdK5AHslvvtJ50iQAYmabl2Nd3vOJ9DxtLBt8a2DfoGPWizgEB3+gkqm2PB8LywwwoiGKd7acr1wZEWmWK9/s0YWdzIstjlvk5AO5XFn6EtEzW8tAAOwBka9239pcyj0kEogWctHLJn7p9VFru38r+I1USyGn6u9XQ68n9edWddxBYokETCqEMT9QIDAQAB",
|
|
7
|
+
"minimum_chrome_version": "116",
|
|
8
|
+
"background": {
|
|
9
|
+
"service_worker": "background.js",
|
|
10
|
+
"type": "module"
|
|
11
|
+
},
|
|
12
|
+
"action": {
|
|
13
|
+
"default_title": "vcorp-chrome"
|
|
14
|
+
},
|
|
15
|
+
"permissions": [
|
|
16
|
+
"tabs",
|
|
17
|
+
"tabGroups",
|
|
18
|
+
"scripting",
|
|
19
|
+
"storage",
|
|
20
|
+
"alarms",
|
|
21
|
+
"offscreen",
|
|
22
|
+
"downloads",
|
|
23
|
+
"sidePanel",
|
|
24
|
+
"notifications",
|
|
25
|
+
"debugger"
|
|
26
|
+
],
|
|
27
|
+
"host_permissions": [
|
|
28
|
+
"<all_urls>"
|
|
29
|
+
],
|
|
30
|
+
"icons": {
|
|
31
|
+
"16": "icons/icon16.png",
|
|
32
|
+
"48": "icons/icon48.png",
|
|
33
|
+
"128": "icons/icon128.png"
|
|
34
|
+
},
|
|
35
|
+
"side_panel": {
|
|
36
|
+
"default_path": "panel.html"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/extension/mark.js
CHANGED
|
@@ -213,6 +213,9 @@
|
|
|
213
213
|
.ask .ok:hover { background: #ea580c; }
|
|
214
214
|
.ask .no { background: #fff; color: #666; border-color: #e2e2e2; }
|
|
215
215
|
.ask .no:hover { background: #f6f6f6; }
|
|
216
|
+
.ask.confirm { width: 420px; }
|
|
217
|
+
.ask .all { background: #fff; color: #9a3412; border-color: #fed7aa; font-size: 12px; padding: 7px 10px; }
|
|
218
|
+
.ask .all:hover { background: #fff7ed; }
|
|
216
219
|
/* 支付确认:同一个浮条换一身红。这类打断一年遇不上几次,
|
|
217
220
|
必须一眼就和「帮我解个验证码」区分开——看错了是要花钱的。 */
|
|
218
221
|
.ask.danger .head { background: linear-gradient(135deg,#fef2f2,#fee2e2); }
|
|
@@ -228,6 +231,8 @@
|
|
|
228
231
|
.ask .note { background: #2a2a2c; border-color: #3a3a3c; color: #f2f2f2; }
|
|
229
232
|
.ask .no { background: #2a2a2c; color: #ccc; border-color: #3a3a3c; }
|
|
230
233
|
.ask .no:hover { background: #333; }
|
|
234
|
+
.ask .all { background: #2a2a2c; color: #fdba74; border-color: #7c2d12; }
|
|
235
|
+
.ask .all:hover { background: #3b2a1a; }
|
|
231
236
|
.ask.danger .head { background: linear-gradient(135deg,#3f1d1d,#2a1414); }
|
|
232
237
|
.ask .what { background: #2a2a2c; }
|
|
233
238
|
.ask .amount { color: #f87171; }
|
|
@@ -546,11 +551,12 @@
|
|
|
546
551
|
let askOutcome = null; // 已结算的结果,等 background 来取
|
|
547
552
|
let askTimer = null;
|
|
548
553
|
|
|
549
|
-
function closeAsk(result, note) {
|
|
554
|
+
function closeAsk(result, note, extra) {
|
|
550
555
|
if (askEl) { askEl.remove(); askEl = null; }
|
|
551
556
|
if (askTimer) { clearInterval(askTimer); askTimer = null; }
|
|
552
557
|
askSettle = null;
|
|
553
558
|
askOutcome = { outcome: result, note: note || '' };
|
|
559
|
+
if (extra?.always) askOutcome.always = true;
|
|
554
560
|
maybeTeardown();
|
|
555
561
|
}
|
|
556
562
|
|
|
@@ -578,6 +584,7 @@
|
|
|
578
584
|
askEl.querySelector('.t').textContent = msg.title || `${chrome.runtime.getManifest().name} 需要你搭把手`;
|
|
579
585
|
askEl.querySelector('.p').textContent = msg.prompt || '';
|
|
580
586
|
if (msg.danger) askEl.classList.add('danger');
|
|
587
|
+
if (msg.offerAlways && !msg.danger) askEl.classList.add('confirm');
|
|
581
588
|
if (msg.okText) askEl.querySelector('.ok').textContent = msg.okText;
|
|
582
589
|
if (msg.noText) askEl.querySelector('.no').textContent = msg.noText;
|
|
583
590
|
// 「点哪个按钮、在哪个站、多少钱」单独拎出来,不混在正文里。
|
|
@@ -609,6 +616,14 @@
|
|
|
609
616
|
|
|
610
617
|
askEl.querySelector('.ok').addEventListener('click', () => closeAsk('continued', noteEl?.value));
|
|
611
618
|
askEl.querySelector('.no').addEventListener('click', () => closeAsk('cancelled', noteEl?.value));
|
|
619
|
+
// 文案写死在扩展里,不接 agent 传来的字。支付确认不给这个按钮。
|
|
620
|
+
if (msg.offerAlways && !msg.danger) {
|
|
621
|
+
const always = document.createElement('button');
|
|
622
|
+
always.className = 'all';
|
|
623
|
+
always.textContent = '本任务内都同意';
|
|
624
|
+
askEl.querySelector('.ok').before(always);
|
|
625
|
+
always.addEventListener('click', () => closeAsk('continued', noteEl?.value, { always: true }));
|
|
626
|
+
}
|
|
612
627
|
|
|
613
628
|
// 挂在 own 之外:会话区重画时不触碰 ask(输入框的焦点经不起挪动)
|
|
614
629
|
wrap.querySelector('.dock').appendChild(askEl);
|
package/extension/panel.html
CHANGED
|
@@ -1,204 +1,210 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<meta charset="utf-8" />
|
|
4
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
5
|
-
<title>vcorp-chrome</title>
|
|
6
|
-
<style>
|
|
7
|
-
:root {
|
|
8
|
-
color-scheme: light dark;
|
|
9
|
-
--bg: #fafaf9; --card: #ffffff; --ink: #1c1917; --mute: #78716c; --line: rgba(0,0,0,.07);
|
|
10
|
-
--soft: rgba(0,0,0,.04); --ok: #16a34a; --warn: #d97706; --bad: #dc2626; --accent: #2563eb;
|
|
11
|
-
}
|
|
12
|
-
@media (prefers-color-scheme: dark) {
|
|
13
|
-
:root { --bg: #161616; --card: #1f1f1f; --ink: #f2f2f2; --mute: #a1a1aa; --line: rgba(255,255,255,.08);
|
|
14
|
-
--soft: rgba(255,255,255,.05); --ok: #22c55e; --warn: #f59e0b; --bad: #f87171; --accent: #60a5fa; }
|
|
15
|
-
}
|
|
16
|
-
* { box-sizing: border-box; }
|
|
17
|
-
[hidden] { display: none !important; }
|
|
18
|
-
body { margin: 0; background: var(--bg); color: var(--ink);
|
|
19
|
-
font: 13px/1.6 -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif; }
|
|
20
|
-
header { display: flex; align-items: center; gap: 10px; padding: 14px 16px 10px; }
|
|
21
|
-
header img { width: 30px; height: 30px; border-radius: 50%; }
|
|
22
|
-
header .t { font-weight: 600; font-size: 14px; }
|
|
23
|
-
header .v { color: var(--mute); font-size: 11px; margin-left: 4px; font-weight: 400; }
|
|
24
|
-
.pill { margin-left: auto; display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--mute);
|
|
25
|
-
padding: 3px 9px; border-radius: 999px; background: var(--soft); }
|
|
26
|
-
.dot { width: 8px; height: 8px; border-radius: 50%; background: #a8a29e; flex: none; }
|
|
27
|
-
.dot.ok { background: var(--ok); } .dot.warn { background: var(--warn); } .dot.bad { background: var(--bad); }
|
|
28
|
-
main { padding: 0 12px 20px; display: flex; flex-direction: column; gap: 12px; }
|
|
29
|
-
section { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
|
|
30
|
-
h2 { margin: 0 0 8px; font-size: 11px; letter-spacing: .8px; color: var(--mute); font-weight: 500; }
|
|
31
|
-
.empty { color: var(--mute); font-size: 12.5px; }
|
|
32
|
-
.owner { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
|
33
|
-
.owner .sw { width: 10px; height: 10px; border-radius: 50%; flex: none; }
|
|
34
|
-
.owner .who { font-weight: 600; }
|
|
35
|
-
.owner .code { color: var(--mute); font-size: 11px; font-variant-numeric: tabular-nums; }
|
|
36
|
-
.blk { margin-top: 10px; }
|
|
37
|
-
.lab { font-size: 10.5px; letter-spacing: .6px; color: var(--mute); margin-bottom: 2px; }
|
|
38
|
-
/* agent 说的话带引用边,扩展观察到的事实平铺——前者可能源自被注入的页面 */
|
|
39
|
-
.intent { border-left: 2px solid var(--c, #888); padding-left: 8px; }
|
|
40
|
-
.ago { color: var(--mute); font-size: 10.5px; margin-left: 6px; font-variant-numeric: tabular-nums; }
|
|
41
|
-
.now { display: flex; align-items: center; gap: 7px; font-weight: 500; }
|
|
42
|
-
.pulse { width: 7px; height: 7px; border-radius: 50%; animation: pulse 1.4s ease-in-out infinite; flex: none; }
|
|
43
|
-
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
|
|
44
|
-
.tl { display: flex; flex-direction: column; gap: 3px; max-height: 260px; overflow-y: auto; }
|
|
45
|
-
.tl .row { display: flex; gap: 10px; font-size: 12px; color: var(--mute); }
|
|
46
|
-
.tl .row:first-child { color: var(--ink); }
|
|
47
|
-
.tl .row .ago { flex: none; width: 46px; text-align: right; margin: 0; }
|
|
48
|
-
.sess { display: flex; flex-direction: column; gap: 2px; }
|
|
49
|
-
.sess button { all: unset; display: flex; align-items: center; gap: 8px; padding: 6px 8px; margin: 0 -8px;
|
|
50
|
-
border-radius: 8px; cursor: pointer; font-size: 12.5px; }
|
|
51
|
-
.sess button:hover { background: var(--soft); }
|
|
52
|
-
.sess button[disabled] { cursor: default; }
|
|
53
|
-
.sess button[disabled]:hover { background: none; }
|
|
54
|
-
.sess .who { font-weight: 600; flex: none; }
|
|
55
|
-
.sess .page { color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
56
|
-
.light { display: flex; align-items: flex-start; gap: 9px; padding: 6px 0; }
|
|
57
|
-
.light .dot { margin-top: 6px; }
|
|
58
|
-
.light .name { font-weight: 500; }
|
|
59
|
-
.light .sub { color: var(--mute); font-size: 12px; }
|
|
60
|
-
.cmd { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
|
|
61
|
-
code { font: 11.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; background: var(--soft);
|
|
62
|
-
padding: 4px 7px; border-radius: 6px; word-break: break-all; flex: 1; }
|
|
63
|
-
button.btn { font: inherit; font-size: 12px; border: 0; border-radius: 7px; padding: 5px 10px; cursor: pointer;
|
|
64
|
-
background: var(--accent); color: #fff; flex: none; }
|
|
65
|
-
button.btn.ghost { background: var(--soft); color: var(--ink); }
|
|
66
|
-
button.btn:disabled { opacity: .45; cursor: default; }
|
|
67
|
-
.sw-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; }
|
|
68
|
-
.sw-row .txt { flex: 1; }
|
|
69
|
-
.sw-row .sub { color: var(--mute); font-size: 11.5px; }
|
|
70
|
-
.toggle { appearance: none; width: 34px; height: 20px; border-radius: 10px; background: #d6d3d1; position: relative;
|
|
71
|
-
cursor: pointer; flex: none; transition: background .15s; margin: 0; }
|
|
72
|
-
.toggle::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
|
|
73
|
-
background: #fff; transition: transform .15s; box-shadow: 0 1px 2px rgba(0,0,0,.2); }
|
|
74
|
-
.toggle:checked { background: var(--ok); }
|
|
75
|
-
.toggle:checked::after { transform: translateX(14px); }
|
|
76
|
-
footer { color: var(--mute); font-size: 11.5px; padding: 0 16px 18px; }
|
|
77
|
-
/* 云端发布 */
|
|
78
|
-
.field { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
|
|
79
|
-
.field input[type=text] { font: inherit; padding: 6px 8px; border-radius: 7px; border: 1px solid var(--line);
|
|
80
|
-
background: var(--bg); color: var(--ink); }
|
|
81
|
-
.field input.code { font: 15px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 2px; text-transform: uppercase; }
|
|
82
|
-
.row { display: flex; gap: 6px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
|
|
83
|
-
.msg { font-size: 12px; margin-top: 6px; }
|
|
84
|
-
.msg.bad { color: var(--bad); }
|
|
85
|
-
.confirm { border: 1px solid var(--warn); border-radius: 9px; padding: 9px 10px; margin-top: 8px; }
|
|
86
|
-
.confirm b { word-break: break-all; }
|
|
87
|
-
.
|
|
88
|
-
.
|
|
89
|
-
.
|
|
90
|
-
.
|
|
91
|
-
.task
|
|
92
|
-
.task.
|
|
93
|
-
.
|
|
94
|
-
.
|
|
95
|
-
.log
|
|
96
|
-
.log
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
a
|
|
101
|
-
a.guide
|
|
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
|
-
<div class="
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
<div
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
<div class="
|
|
157
|
-
|
|
158
|
-
<div class="
|
|
159
|
-
<div id="
|
|
160
|
-
<
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
<div id="
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
<
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
</
|
|
200
|
-
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
</
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<meta charset="utf-8" />
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
5
|
+
<title>vcorp-chrome</title>
|
|
6
|
+
<style>
|
|
7
|
+
:root {
|
|
8
|
+
color-scheme: light dark;
|
|
9
|
+
--bg: #fafaf9; --card: #ffffff; --ink: #1c1917; --mute: #78716c; --line: rgba(0,0,0,.07);
|
|
10
|
+
--soft: rgba(0,0,0,.04); --ok: #16a34a; --warn: #d97706; --bad: #dc2626; --accent: #2563eb;
|
|
11
|
+
}
|
|
12
|
+
@media (prefers-color-scheme: dark) {
|
|
13
|
+
:root { --bg: #161616; --card: #1f1f1f; --ink: #f2f2f2; --mute: #a1a1aa; --line: rgba(255,255,255,.08);
|
|
14
|
+
--soft: rgba(255,255,255,.05); --ok: #22c55e; --warn: #f59e0b; --bad: #f87171; --accent: #60a5fa; }
|
|
15
|
+
}
|
|
16
|
+
* { box-sizing: border-box; }
|
|
17
|
+
[hidden] { display: none !important; }
|
|
18
|
+
body { margin: 0; background: var(--bg); color: var(--ink);
|
|
19
|
+
font: 13px/1.6 -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif; }
|
|
20
|
+
header { display: flex; align-items: center; gap: 10px; padding: 14px 16px 10px; }
|
|
21
|
+
header img { width: 30px; height: 30px; border-radius: 50%; }
|
|
22
|
+
header .t { font-weight: 600; font-size: 14px; }
|
|
23
|
+
header .v { color: var(--mute); font-size: 11px; margin-left: 4px; font-weight: 400; }
|
|
24
|
+
.pill { margin-left: auto; display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--mute);
|
|
25
|
+
padding: 3px 9px; border-radius: 999px; background: var(--soft); }
|
|
26
|
+
.dot { width: 8px; height: 8px; border-radius: 50%; background: #a8a29e; flex: none; }
|
|
27
|
+
.dot.ok { background: var(--ok); } .dot.warn { background: var(--warn); } .dot.bad { background: var(--bad); }
|
|
28
|
+
main { padding: 0 12px 20px; display: flex; flex-direction: column; gap: 12px; }
|
|
29
|
+
section { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
|
|
30
|
+
h2 { margin: 0 0 8px; font-size: 11px; letter-spacing: .8px; color: var(--mute); font-weight: 500; }
|
|
31
|
+
.empty { color: var(--mute); font-size: 12.5px; }
|
|
32
|
+
.owner { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
|
33
|
+
.owner .sw { width: 10px; height: 10px; border-radius: 50%; flex: none; }
|
|
34
|
+
.owner .who { font-weight: 600; }
|
|
35
|
+
.owner .code { color: var(--mute); font-size: 11px; font-variant-numeric: tabular-nums; }
|
|
36
|
+
.blk { margin-top: 10px; }
|
|
37
|
+
.lab { font-size: 10.5px; letter-spacing: .6px; color: var(--mute); margin-bottom: 2px; }
|
|
38
|
+
/* agent 说的话带引用边,扩展观察到的事实平铺——前者可能源自被注入的页面 */
|
|
39
|
+
.intent { border-left: 2px solid var(--c, #888); padding-left: 8px; }
|
|
40
|
+
.ago { color: var(--mute); font-size: 10.5px; margin-left: 6px; font-variant-numeric: tabular-nums; }
|
|
41
|
+
.now { display: flex; align-items: center; gap: 7px; font-weight: 500; }
|
|
42
|
+
.pulse { width: 7px; height: 7px; border-radius: 50%; animation: pulse 1.4s ease-in-out infinite; flex: none; }
|
|
43
|
+
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
|
|
44
|
+
.tl { display: flex; flex-direction: column; gap: 3px; max-height: 260px; overflow-y: auto; }
|
|
45
|
+
.tl .row { display: flex; gap: 10px; font-size: 12px; color: var(--mute); }
|
|
46
|
+
.tl .row:first-child { color: var(--ink); }
|
|
47
|
+
.tl .row .ago { flex: none; width: 46px; text-align: right; margin: 0; }
|
|
48
|
+
.sess { display: flex; flex-direction: column; gap: 2px; }
|
|
49
|
+
.sess button { all: unset; display: flex; align-items: center; gap: 8px; padding: 6px 8px; margin: 0 -8px;
|
|
50
|
+
border-radius: 8px; cursor: pointer; font-size: 12.5px; }
|
|
51
|
+
.sess button:hover { background: var(--soft); }
|
|
52
|
+
.sess button[disabled] { cursor: default; }
|
|
53
|
+
.sess button[disabled]:hover { background: none; }
|
|
54
|
+
.sess .who { font-weight: 600; flex: none; }
|
|
55
|
+
.sess .page { color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
56
|
+
.light { display: flex; align-items: flex-start; gap: 9px; padding: 6px 0; }
|
|
57
|
+
.light .dot { margin-top: 6px; }
|
|
58
|
+
.light .name { font-weight: 500; }
|
|
59
|
+
.light .sub { color: var(--mute); font-size: 12px; }
|
|
60
|
+
.cmd { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
|
|
61
|
+
code { font: 11.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; background: var(--soft);
|
|
62
|
+
padding: 4px 7px; border-radius: 6px; word-break: break-all; flex: 1; }
|
|
63
|
+
button.btn { font: inherit; font-size: 12px; border: 0; border-radius: 7px; padding: 5px 10px; cursor: pointer;
|
|
64
|
+
background: var(--accent); color: #fff; flex: none; }
|
|
65
|
+
button.btn.ghost { background: var(--soft); color: var(--ink); }
|
|
66
|
+
button.btn:disabled { opacity: .45; cursor: default; }
|
|
67
|
+
.sw-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; }
|
|
68
|
+
.sw-row .txt { flex: 1; }
|
|
69
|
+
.sw-row .sub { color: var(--mute); font-size: 11.5px; }
|
|
70
|
+
.toggle { appearance: none; width: 34px; height: 20px; border-radius: 10px; background: #d6d3d1; position: relative;
|
|
71
|
+
cursor: pointer; flex: none; transition: background .15s; margin: 0; }
|
|
72
|
+
.toggle::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
|
|
73
|
+
background: #fff; transition: transform .15s; box-shadow: 0 1px 2px rgba(0,0,0,.2); }
|
|
74
|
+
.toggle:checked { background: var(--ok); }
|
|
75
|
+
.toggle:checked::after { transform: translateX(14px); }
|
|
76
|
+
footer { color: var(--mute); font-size: 11.5px; padding: 0 16px 18px; }
|
|
77
|
+
/* 云端发布 */
|
|
78
|
+
.field { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
|
|
79
|
+
.field input[type=text] { font: inherit; padding: 6px 8px; border-radius: 7px; border: 1px solid var(--line);
|
|
80
|
+
background: var(--bg); color: var(--ink); }
|
|
81
|
+
.field input.code { font: 15px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 2px; text-transform: uppercase; }
|
|
82
|
+
.row { display: flex; gap: 6px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
|
|
83
|
+
.msg { font-size: 12px; margin-top: 6px; }
|
|
84
|
+
.msg.bad { color: var(--bad); }
|
|
85
|
+
.confirm { border: 1px solid var(--warn); border-radius: 9px; padding: 9px 10px; margin-top: 8px; }
|
|
86
|
+
.confirm b { word-break: break-all; }
|
|
87
|
+
.sites { display: flex; flex-direction: column; margin-top: 4px; }
|
|
88
|
+
.sites .site { display: flex; gap: 8px; align-items: center; font-size: 12.5px; padding: 2px 0; }
|
|
89
|
+
.sites .host { flex: 1; word-break: break-all; }
|
|
90
|
+
.sites .btn { padding: 2px 8px; }
|
|
91
|
+
.task { border-top: 1px solid var(--line); padding: 8px 0 2px; margin-top: 6px; }
|
|
92
|
+
.task .t { font-weight: 500; word-break: break-all; }
|
|
93
|
+
.task .sub, .muted { color: var(--mute); font-size: 11.5px; }
|
|
94
|
+
.task.pending { border-left: 3px solid var(--warn); padding-left: 8px; }
|
|
95
|
+
.log { max-height: 220px; overflow-y: auto; font-size: 11.5px; color: var(--mute); margin-top: 6px; }
|
|
96
|
+
.log div { display: flex; gap: 8px; }
|
|
97
|
+
.log .ago { flex: none; width: 46px; text-align: right; margin: 0; }
|
|
98
|
+
.log .no { color: var(--bad); }
|
|
99
|
+
details summary { cursor: pointer; color: var(--mute); font-size: 12px; margin-top: 8px; }
|
|
100
|
+
a { color: var(--accent); }
|
|
101
|
+
a.guide { display: flex; text-decoration: none; color: inherit; cursor: pointer; border-radius: 8px; margin: 0 -6px; padding-left: 6px; padding-right: 6px; }
|
|
102
|
+
a.guide:hover { background: var(--soft); }
|
|
103
|
+
a.guide .go { color: var(--accent); font-size: 12px; flex: none; }
|
|
104
|
+
</style>
|
|
105
|
+
|
|
106
|
+
<header>
|
|
107
|
+
<img src="icons/icon128.png" alt="" />
|
|
108
|
+
<div class="t">vcorp-chrome<span class="v" id="ver"></span></div>
|
|
109
|
+
<div class="pill"><span class="dot" id="pilldot"></span><span id="pilltxt">检查中…</span></div>
|
|
110
|
+
</header>
|
|
111
|
+
|
|
112
|
+
<main>
|
|
113
|
+
<section>
|
|
114
|
+
<h2>这一页</h2>
|
|
115
|
+
<div id="page"><div class="empty">读取中…</div></div>
|
|
116
|
+
</section>
|
|
117
|
+
|
|
118
|
+
<section>
|
|
119
|
+
<h2>所有在线的 agent</h2>
|
|
120
|
+
<div class="sess" id="sess"></div>
|
|
121
|
+
</section>
|
|
122
|
+
|
|
123
|
+
<section>
|
|
124
|
+
<h2>连接</h2>
|
|
125
|
+
<div id="lights"></div>
|
|
126
|
+
<div class="cmd" id="reconnRow" hidden><button class="btn" id="reconn">重连</button>
|
|
127
|
+
<span class="sub" style="color:var(--mute);font-size:12px">插件没消失,断的只是到终端的连接</span></div>
|
|
128
|
+
</section>
|
|
129
|
+
|
|
130
|
+
<section id="cloud">
|
|
131
|
+
<h2>云端发布</h2>
|
|
132
|
+
<!-- 没配对 -->
|
|
133
|
+
<div id="cloudPair" hidden>
|
|
134
|
+
<div class="muted">让 maker.vcorp.ai 在这个浏览器里替你发布作品、查资料、办事——用的是你已经登录好的账号,
|
|
135
|
+
网站的 cookie 不会离开这台电脑。到网页上「浏览器扩展」里拿一个配对码填在这里。</div>
|
|
136
|
+
<div class="field">
|
|
137
|
+
<input type="text" class="code" id="pairCode" maxlength="9" placeholder="ABCD-EFGH" autocomplete="off" spellcheck="false" />
|
|
138
|
+
</div>
|
|
139
|
+
<details>
|
|
140
|
+
<summary>服务器地址</summary>
|
|
141
|
+
<div class="field"><input type="text" id="pairOrigin" spellcheck="false" /></div>
|
|
142
|
+
<div class="muted">只有自建了服务才需要改。</div>
|
|
143
|
+
</details>
|
|
144
|
+
<div class="row"><button class="btn" id="pairGo">下一步</button></div>
|
|
145
|
+
</div>
|
|
146
|
+
<!-- 配对第一步完成,等用户确认账号 -->
|
|
147
|
+
<div id="cloudClaim" hidden>
|
|
148
|
+
<div class="confirm">
|
|
149
|
+
<div>要把这个浏览器交给 <b id="claimOrigin"></b> 上的账号 <b id="claimAccount"></b> 吗?</div>
|
|
150
|
+
<div class="muted" style="margin-top:4px">确认后,这个账号可以申请在你允许的网站上替你操作,每个任务都要你点头。配对码如果是别人发给你的,点取消。</div>
|
|
151
|
+
<div class="row"><button class="btn" id="claimYes">确认连接</button><button class="btn ghost" id="claimNo">取消</button></div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
<!-- 已配对 -->
|
|
155
|
+
<div id="cloudOn" hidden>
|
|
156
|
+
<div class="light"><span class="dot" id="cloudDot"></span>
|
|
157
|
+
<div><div class="name" id="cloudName"></div><div class="sub" id="cloudSub"></div></div></div>
|
|
158
|
+
<div class="lab" style="margin-top:6px">允许它使用的网站</div>
|
|
159
|
+
<div class="sites" id="cloudSites"></div>
|
|
160
|
+
<div class="muted" style="margin-top:4px">任务申请网站、你点了允许,就记在这里(含子域)。不在这里、也没在任务里批准的网站,它连页面都打不开。</div>
|
|
161
|
+
<div id="cloudTasks"></div>
|
|
162
|
+
<label class="sw-row">
|
|
163
|
+
<span class="txt">自动允许新任务<div class="sub">不再逐个弹窗确认。只在你信任这个账号时打开:新任务,以及它一开始就要去的网站,会直接放行。任务开始之后再加的网站,还有本地文件夹,仍然要你逐个点头</div></span>
|
|
164
|
+
<input type="checkbox" class="toggle" id="cloudAuto" />
|
|
165
|
+
</label>
|
|
166
|
+
<label class="sw-row">
|
|
167
|
+
<span class="txt">对外动作不再逐条确认<div class="sub">发消息、投递、发帖之前不再问你。扫码、验证码仍然要你本人来。付款一律不做</div></span>
|
|
168
|
+
<input type="checkbox" class="toggle" id="cloudAutoConfirm" />
|
|
169
|
+
</label>
|
|
170
|
+
<label class="sw-row">
|
|
171
|
+
<span class="txt">暂停<div class="sub">立刻断开,云端的命令一条都不接,直到你再打开</div></span>
|
|
172
|
+
<input type="checkbox" class="toggle" id="cloudPause" />
|
|
173
|
+
</label>
|
|
174
|
+
<details>
|
|
175
|
+
<summary>操作记录</summary>
|
|
176
|
+
<div class="log" id="cloudLog"></div>
|
|
177
|
+
</details>
|
|
178
|
+
<div class="row"><button class="btn ghost" id="cloudReconn">重连</button><button class="btn ghost" id="cloudUnpair">断开并忘记这个服务器</button></div>
|
|
179
|
+
</div>
|
|
180
|
+
<div class="msg bad" id="cloudErr" hidden></div>
|
|
181
|
+
</section>
|
|
182
|
+
|
|
183
|
+
<section>
|
|
184
|
+
<h2>本地文件夹</h2>
|
|
185
|
+
<div class="muted">挂载之后,配对的网站可以申请读取里面的文档(Markdown、文本、PDF、Word、CSV、JSON、HTML)。只读,不会改你的文件。每次真正读取之前还会再问你一次。浏览器重启后如果这里显示需要恢复,点「恢复访问」。</div>
|
|
186
|
+
<div id="folderList"></div>
|
|
187
|
+
<div class="row"><button class="btn" id="folderAdd" type="button">添加文件夹</button></div>
|
|
188
|
+
</section>
|
|
189
|
+
|
|
190
|
+
<section>
|
|
191
|
+
<h2>设置</h2>
|
|
192
|
+
<a class="sw-row guide" id="guide" href="welcome.html">
|
|
193
|
+
<span class="txt">开始使用<div class="sub">配对码、接上本机 agent、第一句怎么说</div></span>
|
|
194
|
+
<span class="go">打开</span>
|
|
195
|
+
</a>
|
|
196
|
+
<label class="sw-row">
|
|
197
|
+
<span class="txt">高保真模式<div class="sub">需要时用浏览器级真实输入,应付严格的站点和富文本编辑器;用完自动断开</div></span>
|
|
198
|
+
<input type="checkbox" class="toggle" id="l2" />
|
|
199
|
+
</label>
|
|
200
|
+
<label class="sw-row">
|
|
201
|
+
<span class="txt">页面标记<div class="sub">被操作的页面带彩色描边、光标和小头像;录屏演示时可以关掉</div></span>
|
|
202
|
+
<input type="checkbox" class="toggle" id="mark" />
|
|
203
|
+
</label>
|
|
204
|
+
</section>
|
|
205
|
+
</main>
|
|
206
|
+
|
|
207
|
+
<footer>连不上时在终端跑 <code style="padding:1px 5px">npx vcorp-chrome doctor</code>,它会告诉你卡在哪一步。</footer>
|
|
208
|
+
|
|
209
|
+
<script type="module" src="panel.js"></script>
|
|
210
|
+
</html>
|