cicy-desktop 2.1.36 → 2.1.37
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/package.json +1 -1
- package/src/tools/chrome-tools.js +44 -16
package/package.json
CHANGED
|
@@ -59,7 +59,11 @@ function writePrivateChromeConfig(nextConfig) {
|
|
|
59
59
|
if (!fs.existsSync(dir)) {
|
|
60
60
|
fs.mkdirSync(dir, { recursive: true });
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
// chrome.json now holds per-account passwords + TOTP secrets — keep it
|
|
63
|
+
// owner-only (0600). mode on writeFileSync only applies on create, so chmod
|
|
64
|
+
// explicitly to also tighten a pre-existing world/group-readable file.
|
|
65
|
+
fs.writeFileSync(PRIVATE_CHROME_JSON, JSON.stringify(nextConfig || {}, null, 2), { mode: 0o600 });
|
|
66
|
+
try { fs.chmodSync(PRIVATE_CHROME_JSON, 0o600); } catch {}
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
function listPrivateChromeEntries({ includeHidden = false } = {}) {
|
|
@@ -97,14 +101,19 @@ function normalizePrivateChromeEntry(profileKey, accountIdx, entry) {
|
|
|
97
101
|
const port = typeof safeEntry.port === "number" ? safeEntry.port : null;
|
|
98
102
|
const proxyUrl = normalizePrivateProxy(safeEntry.proxy);
|
|
99
103
|
const platform = safeEntry.platform && typeof safeEntry.platform === "object" ? safeEntry.platform : {};
|
|
100
|
-
// Free-text note + a service→
|
|
101
|
-
//
|
|
102
|
-
//
|
|
104
|
+
// Free-text note + a service→credentials map for `list profile with <svc>` —
|
|
105
|
+
// written via chrome_set_profile_meta. Each value is {account,password,totp}.
|
|
106
|
+
// Legacy normalization: array → {}; a bare string value → {account:<string>}.
|
|
103
107
|
const note = typeof safeEntry.note === "string" ? safeEntry.note : "";
|
|
104
|
-
const
|
|
108
|
+
const rawAccounts =
|
|
105
109
|
safeEntry.accounts && typeof safeEntry.accounts === "object" && !Array.isArray(safeEntry.accounts)
|
|
106
110
|
? safeEntry.accounts
|
|
107
111
|
: {};
|
|
112
|
+
const accounts = {};
|
|
113
|
+
for (const [svc, val] of Object.entries(rawAccounts)) {
|
|
114
|
+
if (typeof val === "string") accounts[svc] = { account: val };
|
|
115
|
+
else if (val && typeof val === "object" && !Array.isArray(val)) accounts[svc] = val;
|
|
116
|
+
}
|
|
108
117
|
|
|
109
118
|
return {
|
|
110
119
|
profileKey,
|
|
@@ -666,14 +675,24 @@ function registerChromeTools(registerTool) {
|
|
|
666
675
|
|
|
667
676
|
registerTool(
|
|
668
677
|
"chrome_set_profile_meta",
|
|
669
|
-
"设置 ~/cicy-ai/db/chrome.json 中指定 accountIdx 的 note(备注)/ accounts
|
|
678
|
+
"设置 ~/cicy-ai/db/chrome.json 中指定 accountIdx 的 note(备注)/ accounts(服务→{account,password,totp} map,用于 list profile with <svc> + 自动 2FA)",
|
|
670
679
|
z.object({
|
|
671
680
|
accountIdx: z.number().describe("账户索引"),
|
|
672
681
|
note: z.string().optional().describe("自由文本备注;省略则不动"),
|
|
673
682
|
accounts: z
|
|
674
|
-
.record(
|
|
683
|
+
.record(
|
|
684
|
+
z
|
|
685
|
+
.object({
|
|
686
|
+
account: z.string().optional(),
|
|
687
|
+
password: z.string().optional(),
|
|
688
|
+
totp: z.string().optional(),
|
|
689
|
+
})
|
|
690
|
+
.partial()
|
|
691
|
+
)
|
|
675
692
|
.optional()
|
|
676
|
-
.describe(
|
|
693
|
+
.describe(
|
|
694
|
+
"服务→{account,password,totp} map,如 {github:{account:'octocat',password:'..',totp:'BASE32'}};字段级合并,字段空值删该字段,svc 清空则删该服务;省略则整体不动"
|
|
695
|
+
),
|
|
677
696
|
}),
|
|
678
697
|
async ({ accountIdx, note, accounts } = {}) => {
|
|
679
698
|
const data = readPrivateChromeConfig();
|
|
@@ -683,18 +702,27 @@ function registerChromeTools(registerTool) {
|
|
|
683
702
|
}
|
|
684
703
|
const patch = { ...data[key], ...(note !== undefined ? { note: String(note) } : {}) };
|
|
685
704
|
if (accounts !== undefined) {
|
|
686
|
-
//
|
|
687
|
-
|
|
705
|
+
// Field-level merge into the existing service→credentials map.
|
|
706
|
+
// Empty field value deletes that field; a service with no fields left
|
|
707
|
+
// is removed entirely. Legacy string value normalizes to {account}.
|
|
708
|
+
const base =
|
|
688
709
|
data[key].accounts && typeof data[key].accounts === "object" && !Array.isArray(data[key].accounts)
|
|
689
710
|
? data[key].accounts
|
|
690
711
|
: {};
|
|
691
|
-
const next = { ...
|
|
692
|
-
for (const [
|
|
693
|
-
const svc = String(
|
|
694
|
-
const val = String(v ?? "").trim();
|
|
712
|
+
const next = { ...base };
|
|
713
|
+
for (const [rawSvc, fieldPatch] of Object.entries(accounts)) {
|
|
714
|
+
const svc = String(rawSvc).trim().toLowerCase();
|
|
695
715
|
if (!svc) continue;
|
|
696
|
-
|
|
697
|
-
|
|
716
|
+
let cur = next[svc];
|
|
717
|
+
if (typeof cur === "string") cur = { account: cur }; // 1.3.0 compat
|
|
718
|
+
cur = cur && typeof cur === "object" && !Array.isArray(cur) ? { ...cur } : {};
|
|
719
|
+
for (const [f, v] of Object.entries(fieldPatch || {})) {
|
|
720
|
+
const val = String(v ?? "").trim();
|
|
721
|
+
if (val === "") delete cur[f];
|
|
722
|
+
else cur[f] = val;
|
|
723
|
+
}
|
|
724
|
+
if (Object.keys(cur).length === 0) delete next[svc];
|
|
725
|
+
else next[svc] = cur;
|
|
698
726
|
}
|
|
699
727
|
patch.accounts = next;
|
|
700
728
|
}
|