vcorp-chrome 2.2.0 → 2.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/extension/cloud.js +16 -7
- package/extension/manifest.json +1 -1
- package/extension/panel.js +4 -2
- package/package.json +1 -1
- package/src/lib/native-install.js +10 -2
package/extension/cloud.js
CHANGED
|
@@ -668,6 +668,7 @@ const updateTask = (jobId, fn) => serial(async () => {
|
|
|
668
668
|
const HOST = 'ai.vcorp.desktop';
|
|
669
669
|
const DESK = 'cloudDesktop'; // storage.local:启用桌面能力时宿主报的设备
|
|
670
670
|
const DESK_PENDING = 'cloudDesktopPending'; // 为补上 nativeMessaging 绑定而重载,重载后接着启用
|
|
671
|
+
const DESK_ERR = 'cloudDesktopError'; // 上次启用失败的原因,给侧栏看。重载后的那次启用没人接它抛的错
|
|
671
672
|
const DESK_SNAPS = 4; // 每个任务记几份快照的户口。户口按 ref 存名字,大应用一份上百 KB
|
|
672
673
|
|
|
673
674
|
const deskInfo = async () => (await chrome.storage.local.get(DESK))[DESK] || null;
|
|
@@ -717,6 +718,7 @@ async function desktopChild() {
|
|
|
717
718
|
}
|
|
718
719
|
|
|
719
720
|
async function enableDesktop() {
|
|
721
|
+
await chrome.storage.local.remove(DESK_ERR);
|
|
720
722
|
// 运行时才授予的 nativeMessaging,Chrome 不给已经在跑的 service worker 补上绑定,重载后才有
|
|
721
723
|
if (!chrome.runtime.sendNativeMessage) {
|
|
722
724
|
if (!(await chrome.permissions.contains({ permissions: ['nativeMessaging'] }))) {
|
|
@@ -727,9 +729,16 @@ async function enableDesktop() {
|
|
|
727
729
|
chrome.runtime.reload();
|
|
728
730
|
return;
|
|
729
731
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
732
|
+
let device;
|
|
733
|
+
let r;
|
|
734
|
+
try {
|
|
735
|
+
r = await hostCall({ op: 'hello' });
|
|
736
|
+
device = cleanDevice(r.device);
|
|
737
|
+
if (!device || device.kind !== 'desktop') throw err('DEVICE_OFFLINE', '桌面宿主报上来的设备不对');
|
|
738
|
+
} catch (e) {
|
|
739
|
+
await chrome.storage.local.set({ [DESK_ERR]: (e.message || String(e)).replace('请用户在终端', '请在终端') });
|
|
740
|
+
throw e;
|
|
741
|
+
}
|
|
733
742
|
await chrome.storage.local.set({ [DESK]: { device, ready: !!r.ready, at: Date.now() } });
|
|
734
743
|
await log({ ev: 'desktop_on', msg: device.id });
|
|
735
744
|
// 重连一次,服务器在 hello 里看到这台设备
|
|
@@ -737,7 +746,7 @@ async function enableDesktop() {
|
|
|
737
746
|
}
|
|
738
747
|
|
|
739
748
|
async function disableDesktop() {
|
|
740
|
-
await chrome.storage.local.remove(DESK);
|
|
749
|
+
await chrome.storage.local.remove([DESK, DESK_ERR]);
|
|
741
750
|
await log({ ev: 'desktop_off' });
|
|
742
751
|
disconnect(); retryDelay = 0; void connect();
|
|
743
752
|
}
|
|
@@ -1156,8 +1165,8 @@ async function uploadMedia(p, tid, sid, label) {
|
|
|
1156
1165
|
const fromPanel = (sender) => !sender.tab && typeof sender.url === 'string' && sender.url.startsWith(chrome.runtime.getURL(''));
|
|
1157
1166
|
|
|
1158
1167
|
async function panelState() {
|
|
1159
|
-
const [cfg, { [STATUS]: status }, { [CLAIM]: claimed }, tasks, { [LOG]: list = [] }] = await Promise.all([
|
|
1160
|
-
getCfg(), chrome.storage.session.get(STATUS), chrome.storage.session.get(CLAIM), getTasks(), chrome.storage.local.get(LOG),
|
|
1168
|
+
const [cfg, { [STATUS]: status }, { [CLAIM]: claimed }, tasks, { [LOG]: list = [], [DESK_ERR]: deskErr }] = await Promise.all([
|
|
1169
|
+
getCfg(), chrome.storage.session.get(STATUS), chrome.storage.session.get(CLAIM), getTasks(), chrome.storage.local.get([LOG, DESK_ERR]),
|
|
1161
1170
|
]);
|
|
1162
1171
|
return {
|
|
1163
1172
|
cfg: cfg && { origin: cfg.origin, account: cfg.account, sites: allowOf(cfg), auto: cfg.auto, autoConfirm: !!cfg.autoConfirm, paused: cfg.paused, pairedAt: cfg.pairedAt },
|
|
@@ -1165,7 +1174,7 @@ async function panelState() {
|
|
|
1165
1174
|
claim: claimed && claimed.expiresAt > Date.now() ? { origin: claimed.origin, account: claimed.account } : null,
|
|
1166
1175
|
tasks: Object.values(tasks).sort((a, b) => b.lastAt - a.lastAt).map(({ desk: _desk, ...t }) => t),
|
|
1167
1176
|
folders: await folders.listFolders().catch(() => []),
|
|
1168
|
-
desktop: await deskInfo().then((d) => (d && chrome.runtime.sendNativeMessage ? d : null)),
|
|
1177
|
+
desktop: await deskInfo().then((d) => (d && chrome.runtime.sendNativeMessage ? d : deskErr ? { error: deskErr } : null)),
|
|
1169
1178
|
log: list.slice(-40).reverse(),
|
|
1170
1179
|
defaultOrigin: policy.DEFAULT_ORIGIN,
|
|
1171
1180
|
};
|
package/extension/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "vcorp-chrome",
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.1",
|
|
5
5
|
"description": "让 AI agent 操控你已登录的 Chrome。基于花叔的 huashu-chrome(MIT)修改。",
|
|
6
6
|
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq6xRqEwG4yTuHRG1Zah3j//T3B72XnazyZ+9fOCa5P4bBLPmNBN7YAGL5WnjtPVJefXT9r2Ol0qvNztayDG3dMjK6AZoWccgKa5rhxcvWgFUjanXtmBBQ0qgYwNhuEJSkdinLLtyUg6YmK7Mn72NWpfa/NfqNHdK5AHslvvtJ50iQAYmabl2Nd3vOJ9DxtLBt8a2DfoGPWizgEB3+gkqm2PB8LywwwoiGKd7acr1wZEWmWK9/s0YWdzIstjlvk5AO5XFn6EtEzW8tAAOwBka9239pcyj0kEogWctHLJn7p9VFru38r+I1USyGn6u9XQ68n9edWddxBYokETCqEMT9QIDAQAB",
|
|
7
7
|
"minimum_chrome_version": "116",
|
package/extension/panel.js
CHANGED
|
@@ -442,7 +442,9 @@ $('deskOn').onclick = async () => {
|
|
|
442
442
|
const granted = await chrome.permissions.request({ permissions: ['nativeMessaging'] }).catch(() => false);
|
|
443
443
|
if (!granted) { $('deskState').textContent = '没有拿到权限,桌面能力保持关闭'; return; }
|
|
444
444
|
$('deskState').textContent = '启用中…第一次启用要重载扩展,侧栏若关掉了,重新打开即可';
|
|
445
|
-
await cloudCall('desktopEnable');
|
|
445
|
+
const r = await cloudCall('desktopEnable');
|
|
446
|
+
// 失败原因写在桌面这一栏,不要留着「启用中…」,也不用在顶上再报一遍
|
|
447
|
+
if (r && !r.ok && r.error) { $('deskState').textContent = r.error; $('cloudErr').hidden = true; }
|
|
446
448
|
};
|
|
447
449
|
$('deskOff').onclick = async () => {
|
|
448
450
|
await cloudCall('desktopDisable');
|
|
@@ -453,7 +455,7 @@ $('deskOff').onclick = async () => {
|
|
|
453
455
|
|
|
454
456
|
chrome.storage.onChanged.addListener((changes, area) => {
|
|
455
457
|
const keys0 = Object.keys(changes);
|
|
456
|
-
if (keys0.some((k) => ['cloud', 'cloudTasks', 'cloudLog', 'cloudStatus', 'cloudClaim', 'folderTick', 'cloudDesktop'].includes(k))) void cloudCall('state');
|
|
458
|
+
if (keys0.some((k) => ['cloud', 'cloudTasks', 'cloudLog', 'cloudStatus', 'cloudClaim', 'folderTick', 'cloudDesktop', 'cloudDesktopError'].includes(k))) void cloudCall('state');
|
|
457
459
|
if (area !== 'session') return;
|
|
458
460
|
const keys = Object.keys(changes);
|
|
459
461
|
if (keys.includes(`panel:${tabId}`) || keys.includes('liveSids')) renderPage();
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Chrome 找宿主靠一份清单:Windows 在注册表 HKCU 下登记清单路径,macOS / Linux 把清单放进
|
|
4
4
|
// 浏览器约定的目录。清单的 path 指向一个启动脚本,脚本用装它时的那个 node 跑 native-host/host.js。
|
|
5
|
-
// allowed_origins
|
|
5
|
+
// allowed_origins 只写本扩展:开发者模式加载的 id 由 manifest.json 里的 key 算出来,再加上商店版的 id。
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import os from 'node:os';
|
|
8
8
|
import path from 'node:path';
|
|
@@ -28,6 +28,14 @@ function ourExtensionId() {
|
|
|
28
28
|
return extensionId(mf.key);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// 商店版的 id 是商店分配的:打商店包时 manifest.key 被剥掉(scripts/pack-extension.mjs),算不出来,只能写死
|
|
32
|
+
export const STORE_EXTENSION_ID = 'migojdmaegllchbambngejkclndannnf';
|
|
33
|
+
|
|
34
|
+
// 清单放行的来源:开发者模式加载的(id 由 key 算出)和商店装的,两种都是本扩展
|
|
35
|
+
export function allowedOrigins(id = ourExtensionId()) {
|
|
36
|
+
return [...new Set([id, STORE_EXTENSION_ID])].map((x) => `chrome-extension://${x}/`);
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
const REG_KEYS = [
|
|
32
40
|
`HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${HOST_NAME}`,
|
|
33
41
|
`HKCU\\Software\\Microsoft\\Edge\\NativeMessagingHosts\\${HOST_NAME}`,
|
|
@@ -57,7 +65,7 @@ export function install() {
|
|
|
57
65
|
description: 'vcorp-chrome desktop host',
|
|
58
66
|
path: launcher,
|
|
59
67
|
type: 'stdio',
|
|
60
|
-
allowed_origins:
|
|
68
|
+
allowed_origins: allowedOrigins(id),
|
|
61
69
|
}, null, 2));
|
|
62
70
|
const placed = [];
|
|
63
71
|
if (win) {
|