opencode-account-manager 0.4.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/LICENSE +21 -0
- package/README.md +266 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +183 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/accounts.d.ts +19 -0
- package/dist/core/accounts.d.ts.map +1 -0
- package/dist/core/accounts.js +181 -0
- package/dist/core/accounts.js.map +1 -0
- package/dist/core/config-store.d.ts +48 -0
- package/dist/core/config-store.d.ts.map +1 -0
- package/dist/core/config-store.js +206 -0
- package/dist/core/config-store.js.map +1 -0
- package/dist/core/crypto.d.ts +40 -0
- package/dist/core/crypto.d.ts.map +1 -0
- package/dist/core/crypto.js +172 -0
- package/dist/core/crypto.js.map +1 -0
- package/dist/core/importers/amJson.d.ts +17 -0
- package/dist/core/importers/amJson.d.ts.map +1 -0
- package/dist/core/importers/amJson.js +131 -0
- package/dist/core/importers/amJson.js.map +1 -0
- package/dist/core/opencode-config.d.ts +92 -0
- package/dist/core/opencode-config.d.ts.map +1 -0
- package/dist/core/opencode-config.js +148 -0
- package/dist/core/opencode-config.js.map +1 -0
- package/dist/core/paths.d.ts +5 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +38 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/types.d.ts +74 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +30 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/utils.d.ts +5 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +35 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/tui/Dashboard.d.ts +7 -0
- package/dist/tui/Dashboard.d.ts.map +1 -0
- package/dist/tui/Dashboard.js +331 -0
- package/dist/tui/Dashboard.js.map +1 -0
- package/dist/tui/components/AccountList.d.ts +18 -0
- package/dist/tui/components/AccountList.d.ts.map +1 -0
- package/dist/tui/components/AccountList.js +92 -0
- package/dist/tui/components/AccountList.js.map +1 -0
- package/dist/tui/components/Box.d.ts +11 -0
- package/dist/tui/components/Box.d.ts.map +1 -0
- package/dist/tui/components/Box.js +15 -0
- package/dist/tui/components/Box.js.map +1 -0
- package/dist/tui/components/ExportModal.d.ts +10 -0
- package/dist/tui/components/ExportModal.d.ts.map +1 -0
- package/dist/tui/components/ExportModal.js +192 -0
- package/dist/tui/components/ExportModal.js.map +1 -0
- package/dist/tui/components/FileBrowser.d.ts +12 -0
- package/dist/tui/components/FileBrowser.d.ts.map +1 -0
- package/dist/tui/components/FileBrowser.js +349 -0
- package/dist/tui/components/FileBrowser.js.map +1 -0
- package/dist/tui/components/Header.d.ts +8 -0
- package/dist/tui/components/Header.d.ts.map +1 -0
- package/dist/tui/components/Header.js +20 -0
- package/dist/tui/components/Header.js.map +1 -0
- package/dist/tui/components/ImportModal.d.ts +10 -0
- package/dist/tui/components/ImportModal.d.ts.map +1 -0
- package/dist/tui/components/ImportModal.js +215 -0
- package/dist/tui/components/ImportModal.js.map +1 -0
- package/dist/tui/components/McpServerList.d.ts +8 -0
- package/dist/tui/components/McpServerList.d.ts.map +1 -0
- package/dist/tui/components/McpServerList.js +35 -0
- package/dist/tui/components/McpServerList.js.map +1 -0
- package/dist/tui/components/Menu.d.ts +10 -0
- package/dist/tui/components/Menu.d.ts.map +1 -0
- package/dist/tui/components/Menu.js +83 -0
- package/dist/tui/components/Menu.js.map +1 -0
- package/dist/tui/components/PasswordInput.d.ts +12 -0
- package/dist/tui/components/PasswordInput.d.ts.map +1 -0
- package/dist/tui/components/PasswordInput.js +130 -0
- package/dist/tui/components/PasswordInput.js.map +1 -0
- package/dist/tui/components/ProviderList.d.ts +8 -0
- package/dist/tui/components/ProviderList.d.ts.map +1 -0
- package/dist/tui/components/ProviderList.js +37 -0
- package/dist/tui/components/ProviderList.js.map +1 -0
- package/dist/tui/components/SectionBox.d.ts +10 -0
- package/dist/tui/components/SectionBox.d.ts.map +1 -0
- package/dist/tui/components/SectionBox.js +16 -0
- package/dist/tui/components/SectionBox.js.map +1 -0
- package/dist/tui/components/StatsRow.d.ts +13 -0
- package/dist/tui/components/StatsRow.d.ts.map +1 -0
- package/dist/tui/components/StatsRow.js +18 -0
- package/dist/tui/components/StatsRow.js.map +1 -0
- package/dist/tui/components/StatusBadge.d.ts +8 -0
- package/dist/tui/components/StatusBadge.d.ts.map +1 -0
- package/dist/tui/components/StatusBadge.js +30 -0
- package/dist/tui/components/StatusBadge.js.map +1 -0
- package/dist/tui/components/index.d.ts +14 -0
- package/dist/tui/components/index.d.ts.map +1 -0
- package/dist/tui/components/index.js +32 -0
- package/dist/tui/components/index.js.map +1 -0
- package/dist/tui/index.d.ts +5 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +13 -0
- package/dist/tui/index.js.map +1 -0
- package/docs/BLUEPRINT.md +476 -0
- package/docs/ROADMAP.md +74 -0
- package/package.json +38 -0
- package/src/cli.ts +207 -0
- package/src/core/accounts.ts +215 -0
- package/src/core/config-store.ts +212 -0
- package/src/core/crypto.ts +162 -0
- package/src/core/importers/amJson.ts +185 -0
- package/src/core/opencode-config.ts +217 -0
- package/src/core/paths.ts +32 -0
- package/src/core/types.ts +118 -0
- package/src/core/utils.ts +28 -0
- package/src/tui/Dashboard.tsx +431 -0
- package/src/tui/components/AccountList.tsx +155 -0
- package/src/tui/components/Box.tsx +37 -0
- package/src/tui/components/ExportModal.tsx +255 -0
- package/src/tui/components/FileBrowser.tsx +393 -0
- package/src/tui/components/Header.tsx +26 -0
- package/src/tui/components/ImportModal.tsx +288 -0
- package/src/tui/components/McpServerList.tsx +67 -0
- package/src/tui/components/Menu.tsx +103 -0
- package/src/tui/components/PasswordInput.tsx +159 -0
- package/src/tui/components/ProviderList.tsx +61 -0
- package/src/tui/components/SectionBox.tsx +35 -0
- package/src/tui/components/StatsRow.tsx +33 -0
- package/src/tui/components/StatusBadge.tsx +33 -0
- package/src/tui/components/index.ts +13 -0
- package/src/tui/index.tsx +11 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.normalizePluginAccounts = normalizePluginAccounts;
|
|
7
|
+
exports.createEmptyPluginAccountsFile = createEmptyPluginAccountsFile;
|
|
8
|
+
exports.readPluginAccountsFile = readPluginAccountsFile;
|
|
9
|
+
exports.writePluginAccountsFile = writePluginAccountsFile;
|
|
10
|
+
exports.mergeAccount = mergeAccount;
|
|
11
|
+
exports.mergeAccounts = mergeAccounts;
|
|
12
|
+
exports.buildPortableExport = buildPortableExport;
|
|
13
|
+
exports.detectImportFormat = detectImportFormat;
|
|
14
|
+
exports.extractAccountsFromImport = extractAccountsFromImport;
|
|
15
|
+
exports.sanitizeAccountForPublic = sanitizeAccountForPublic;
|
|
16
|
+
exports.summarizeAccounts = summarizeAccounts;
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
const paths_1 = require("./paths");
|
|
20
|
+
const utils_1 = require("./utils");
|
|
21
|
+
function isRecord(value) {
|
|
22
|
+
return typeof value === "object" && value !== null;
|
|
23
|
+
}
|
|
24
|
+
function isAccountCandidate(value) {
|
|
25
|
+
if (!isRecord(value))
|
|
26
|
+
return false;
|
|
27
|
+
if (typeof value.email !== "string")
|
|
28
|
+
return false;
|
|
29
|
+
return value.email.includes("@");
|
|
30
|
+
}
|
|
31
|
+
function normalizeAccount(account) {
|
|
32
|
+
return {
|
|
33
|
+
...account,
|
|
34
|
+
email: account.email.trim(),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function normalizePluginAccounts(data) {
|
|
38
|
+
const accounts = Array.isArray(data.accounts)
|
|
39
|
+
? data.accounts.filter(isAccountCandidate).map(normalizeAccount)
|
|
40
|
+
: [];
|
|
41
|
+
return {
|
|
42
|
+
version: typeof data.version === "number" ? data.version : 3,
|
|
43
|
+
accounts,
|
|
44
|
+
activeIndex: typeof data.activeIndex === "number" ? data.activeIndex : undefined,
|
|
45
|
+
activeIndexByFamily: data.activeIndexByFamily && isRecord(data.activeIndexByFamily)
|
|
46
|
+
? data.activeIndexByFamily
|
|
47
|
+
: undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function createEmptyPluginAccountsFile() {
|
|
51
|
+
return {
|
|
52
|
+
version: 3,
|
|
53
|
+
accounts: [],
|
|
54
|
+
activeIndex: 0,
|
|
55
|
+
activeIndexByFamily: {},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function readPluginAccountsFile(filePath) {
|
|
59
|
+
const resolvedPath = (0, paths_1.getPluginAccountsPath)(filePath);
|
|
60
|
+
if (!fs_1.default.existsSync(resolvedPath)) {
|
|
61
|
+
throw new Error(`Plugin accounts file not found at ${resolvedPath}. ` +
|
|
62
|
+
"Login at least one account first or provide --plugin-path.");
|
|
63
|
+
}
|
|
64
|
+
const data = (0, utils_1.readJsonFile)(resolvedPath);
|
|
65
|
+
return normalizePluginAccounts(data);
|
|
66
|
+
}
|
|
67
|
+
function writePluginAccountsFile(filePath, data) {
|
|
68
|
+
const resolvedPath = (0, paths_1.getPluginAccountsPath)(filePath);
|
|
69
|
+
const normalized = normalizePluginAccounts(data);
|
|
70
|
+
const dir = path_1.default.dirname(resolvedPath);
|
|
71
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
72
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
73
|
+
}
|
|
74
|
+
(0, utils_1.writeJsonFile)(resolvedPath, normalized);
|
|
75
|
+
}
|
|
76
|
+
function mergeRateLimits(existing, incoming) {
|
|
77
|
+
if (!existing && !incoming)
|
|
78
|
+
return undefined;
|
|
79
|
+
return { ...(existing || {}), ...(incoming || {}) };
|
|
80
|
+
}
|
|
81
|
+
function mergeFingerprintHistory(existing, incoming) {
|
|
82
|
+
if (!existing && !incoming)
|
|
83
|
+
return undefined;
|
|
84
|
+
const list = [...(existing || []), ...(incoming || [])];
|
|
85
|
+
return list.length > 0 ? list : undefined;
|
|
86
|
+
}
|
|
87
|
+
function mergeAccount(existing, incoming) {
|
|
88
|
+
return {
|
|
89
|
+
...existing,
|
|
90
|
+
...incoming,
|
|
91
|
+
email: incoming.email || existing.email,
|
|
92
|
+
refreshToken: incoming.refreshToken || existing.refreshToken,
|
|
93
|
+
fingerprint: incoming.fingerprint || existing.fingerprint,
|
|
94
|
+
rateLimitResetTimes: mergeRateLimits(existing.rateLimitResetTimes, incoming.rateLimitResetTimes),
|
|
95
|
+
fingerprintHistory: mergeFingerprintHistory(existing.fingerprintHistory, incoming.fingerprintHistory),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function mergeAccounts(existingFile, incomingAccounts, mode) {
|
|
99
|
+
const base = normalizePluginAccounts(existingFile);
|
|
100
|
+
const incoming = incomingAccounts
|
|
101
|
+
.filter(isAccountCandidate)
|
|
102
|
+
.map(normalizeAccount);
|
|
103
|
+
if (mode === "replace") {
|
|
104
|
+
return {
|
|
105
|
+
version: base.version || 3,
|
|
106
|
+
accounts: incoming,
|
|
107
|
+
activeIndex: 0,
|
|
108
|
+
activeIndexByFamily: {},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const byEmail = new Map();
|
|
112
|
+
for (const account of base.accounts) {
|
|
113
|
+
byEmail.set((0, utils_1.toLowerTrim)(account.email), account);
|
|
114
|
+
}
|
|
115
|
+
for (const account of incoming) {
|
|
116
|
+
const key = (0, utils_1.toLowerTrim)(account.email);
|
|
117
|
+
const existing = byEmail.get(key);
|
|
118
|
+
if (existing) {
|
|
119
|
+
byEmail.set(key, mergeAccount(existing, account));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
byEmail.set(key, account);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
...base,
|
|
127
|
+
accounts: Array.from(byEmail.values()),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function buildPortableExport(accounts) {
|
|
131
|
+
return {
|
|
132
|
+
version: 1,
|
|
133
|
+
exportedAt: Date.now(),
|
|
134
|
+
exportedFrom: "antigravity-sync",
|
|
135
|
+
accounts: accounts.map(normalizeAccount),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function detectImportFormat(data) {
|
|
139
|
+
if (!isRecord(data))
|
|
140
|
+
return "unknown";
|
|
141
|
+
if (data.exportedFrom === "antigravity-sync")
|
|
142
|
+
return "portable";
|
|
143
|
+
if (typeof data.version === "number" && Array.isArray(data.accounts)) {
|
|
144
|
+
return "plugin";
|
|
145
|
+
}
|
|
146
|
+
return "unknown";
|
|
147
|
+
}
|
|
148
|
+
function extractAccountsFromImport(data, format) {
|
|
149
|
+
if (Array.isArray(data)) {
|
|
150
|
+
return data.filter(isAccountCandidate).map(normalizeAccount);
|
|
151
|
+
}
|
|
152
|
+
if (!isRecord(data)) {
|
|
153
|
+
throw new Error("Import data must be an object or an array of accounts.");
|
|
154
|
+
}
|
|
155
|
+
const detected = format || detectImportFormat(data);
|
|
156
|
+
if (detected === "unknown") {
|
|
157
|
+
throw new Error("Unsupported import format. Provide a portable export or plugin file.");
|
|
158
|
+
}
|
|
159
|
+
const accounts = Array.isArray(data.accounts) ? data.accounts : [];
|
|
160
|
+
return accounts.filter(isAccountCandidate).map(normalizeAccount);
|
|
161
|
+
}
|
|
162
|
+
function sanitizeAccountForPublic(account) {
|
|
163
|
+
const { refreshToken, ...rest } = account;
|
|
164
|
+
return rest;
|
|
165
|
+
}
|
|
166
|
+
function summarizeAccounts(accounts) {
|
|
167
|
+
const now = Date.now();
|
|
168
|
+
let limited = 0;
|
|
169
|
+
for (const account of accounts) {
|
|
170
|
+
const resets = account.rateLimitResetTimes || {};
|
|
171
|
+
const isLimited = Object.values(resets).some((value) => value > now);
|
|
172
|
+
if (isLimited)
|
|
173
|
+
limited += 1;
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
total: accounts.length,
|
|
177
|
+
limited,
|
|
178
|
+
available: accounts.length - limited,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=accounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../src/core/accounts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface AppConfig {
|
|
2
|
+
lastExportFolder?: string;
|
|
3
|
+
lastImportFolder?: string;
|
|
4
|
+
defaultExportFormat?: "encrypted" | "plain";
|
|
5
|
+
recentFolders?: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Get the full path to config file
|
|
9
|
+
*/
|
|
10
|
+
export declare function getConfigPath(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Read config file, return empty config if not exists
|
|
13
|
+
*/
|
|
14
|
+
export declare function readConfig(): AppConfig;
|
|
15
|
+
/**
|
|
16
|
+
* Write config file
|
|
17
|
+
*/
|
|
18
|
+
export declare function writeConfig(config: AppConfig): void;
|
|
19
|
+
/**
|
|
20
|
+
* Update last export folder and add to recent folders
|
|
21
|
+
*/
|
|
22
|
+
export declare function updateLastExportFolder(folder: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Update last import folder and add to recent folders
|
|
25
|
+
*/
|
|
26
|
+
export declare function updateLastImportFolder(folder: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Get recent folders list
|
|
29
|
+
*/
|
|
30
|
+
export declare function getRecentFolders(): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Get last export folder or default
|
|
33
|
+
*/
|
|
34
|
+
export declare function getLastExportFolder(): string;
|
|
35
|
+
/**
|
|
36
|
+
* Get last import folder or default
|
|
37
|
+
*/
|
|
38
|
+
export declare function getLastImportFolder(): string;
|
|
39
|
+
export interface QuickLocation {
|
|
40
|
+
label: string;
|
|
41
|
+
path: string;
|
|
42
|
+
exists: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get list of quick locations for file browser
|
|
46
|
+
*/
|
|
47
|
+
export declare function getQuickLocations(): QuickLocation[];
|
|
48
|
+
//# sourceMappingURL=config-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../../src/core/config-store.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAwBD;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAMD;;GAEG;AACH,wBAAgB,UAAU,IAAI,SAAS,CAatC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAWnD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAK3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAK3D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAG3C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAG5C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAG5C;AA2BD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,EAAE,CAmDnD"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getConfigPath = getConfigPath;
|
|
37
|
+
exports.readConfig = readConfig;
|
|
38
|
+
exports.writeConfig = writeConfig;
|
|
39
|
+
exports.updateLastExportFolder = updateLastExportFolder;
|
|
40
|
+
exports.updateLastImportFolder = updateLastImportFolder;
|
|
41
|
+
exports.getRecentFolders = getRecentFolders;
|
|
42
|
+
exports.getLastExportFolder = getLastExportFolder;
|
|
43
|
+
exports.getLastImportFolder = getLastImportFolder;
|
|
44
|
+
exports.getQuickLocations = getQuickLocations;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const os = __importStar(require("os"));
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Constants
|
|
50
|
+
// ============================================================================
|
|
51
|
+
const CONFIG_FILENAME = "ocam-config.json";
|
|
52
|
+
const MAX_RECENT_FOLDERS = 5;
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// Path Functions
|
|
55
|
+
// ============================================================================
|
|
56
|
+
/**
|
|
57
|
+
* Get the config directory path
|
|
58
|
+
*/
|
|
59
|
+
function getConfigDir() {
|
|
60
|
+
if (process.platform === "win32") {
|
|
61
|
+
const appData = process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
|
|
62
|
+
return path.join(appData, "opencode");
|
|
63
|
+
}
|
|
64
|
+
return path.join(os.homedir(), ".config", "opencode");
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get the full path to config file
|
|
68
|
+
*/
|
|
69
|
+
function getConfigPath() {
|
|
70
|
+
return path.join(getConfigDir(), CONFIG_FILENAME);
|
|
71
|
+
}
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// Config Functions
|
|
74
|
+
// ============================================================================
|
|
75
|
+
/**
|
|
76
|
+
* Read config file, return empty config if not exists
|
|
77
|
+
*/
|
|
78
|
+
function readConfig() {
|
|
79
|
+
const configPath = getConfigPath();
|
|
80
|
+
if (!fs.existsSync(configPath)) {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
85
|
+
return JSON.parse(content);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return {};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Write config file
|
|
93
|
+
*/
|
|
94
|
+
function writeConfig(config) {
|
|
95
|
+
const configPath = getConfigPath();
|
|
96
|
+
const configDir = path.dirname(configPath);
|
|
97
|
+
// Ensure directory exists
|
|
98
|
+
if (!fs.existsSync(configDir)) {
|
|
99
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
const content = JSON.stringify(config, null, 2);
|
|
102
|
+
fs.writeFileSync(configPath, content, "utf-8");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Update last export folder and add to recent folders
|
|
106
|
+
*/
|
|
107
|
+
function updateLastExportFolder(folder) {
|
|
108
|
+
const config = readConfig();
|
|
109
|
+
config.lastExportFolder = folder;
|
|
110
|
+
config.recentFolders = addToRecentFolders(config.recentFolders || [], folder);
|
|
111
|
+
writeConfig(config);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Update last import folder and add to recent folders
|
|
115
|
+
*/
|
|
116
|
+
function updateLastImportFolder(folder) {
|
|
117
|
+
const config = readConfig();
|
|
118
|
+
config.lastImportFolder = folder;
|
|
119
|
+
config.recentFolders = addToRecentFolders(config.recentFolders || [], folder);
|
|
120
|
+
writeConfig(config);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get recent folders list
|
|
124
|
+
*/
|
|
125
|
+
function getRecentFolders() {
|
|
126
|
+
const config = readConfig();
|
|
127
|
+
return config.recentFolders || [];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get last export folder or default
|
|
131
|
+
*/
|
|
132
|
+
function getLastExportFolder() {
|
|
133
|
+
const config = readConfig();
|
|
134
|
+
return config.lastExportFolder || process.cwd();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get last import folder or default
|
|
138
|
+
*/
|
|
139
|
+
function getLastImportFolder() {
|
|
140
|
+
const config = readConfig();
|
|
141
|
+
return config.lastImportFolder || process.cwd();
|
|
142
|
+
}
|
|
143
|
+
// ============================================================================
|
|
144
|
+
// Helper Functions
|
|
145
|
+
// ============================================================================
|
|
146
|
+
/**
|
|
147
|
+
* Add folder to recent list, keeping max items and removing duplicates
|
|
148
|
+
*/
|
|
149
|
+
function addToRecentFolders(recent, folder) {
|
|
150
|
+
// Normalize path
|
|
151
|
+
const normalized = path.normalize(folder);
|
|
152
|
+
// Remove if already exists
|
|
153
|
+
const filtered = recent.filter(f => path.normalize(f) !== normalized);
|
|
154
|
+
// Add to front
|
|
155
|
+
filtered.unshift(normalized);
|
|
156
|
+
// Keep only max items
|
|
157
|
+
return filtered.slice(0, MAX_RECENT_FOLDERS);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get list of quick locations for file browser
|
|
161
|
+
*/
|
|
162
|
+
function getQuickLocations() {
|
|
163
|
+
const home = os.homedir();
|
|
164
|
+
const locations = [];
|
|
165
|
+
// Current directory
|
|
166
|
+
locations.push({
|
|
167
|
+
label: "Current Directory",
|
|
168
|
+
path: process.cwd(),
|
|
169
|
+
exists: true,
|
|
170
|
+
});
|
|
171
|
+
// Desktop
|
|
172
|
+
const desktop = path.join(home, "Desktop");
|
|
173
|
+
locations.push({
|
|
174
|
+
label: "Desktop",
|
|
175
|
+
path: desktop,
|
|
176
|
+
exists: fs.existsSync(desktop),
|
|
177
|
+
});
|
|
178
|
+
// Documents
|
|
179
|
+
const documents = path.join(home, "Documents");
|
|
180
|
+
locations.push({
|
|
181
|
+
label: "Documents",
|
|
182
|
+
path: documents,
|
|
183
|
+
exists: fs.existsSync(documents),
|
|
184
|
+
});
|
|
185
|
+
// Downloads
|
|
186
|
+
const downloads = path.join(home, "Downloads");
|
|
187
|
+
locations.push({
|
|
188
|
+
label: "Downloads",
|
|
189
|
+
path: downloads,
|
|
190
|
+
exists: fs.existsSync(downloads),
|
|
191
|
+
});
|
|
192
|
+
// Last export folder (if different from above)
|
|
193
|
+
const config = readConfig();
|
|
194
|
+
if (config.lastExportFolder && fs.existsSync(config.lastExportFolder)) {
|
|
195
|
+
const isAlreadyListed = locations.some(loc => path.normalize(loc.path) === path.normalize(config.lastExportFolder));
|
|
196
|
+
if (!isAlreadyListed) {
|
|
197
|
+
locations.push({
|
|
198
|
+
label: "Recent Export",
|
|
199
|
+
path: config.lastExportFolder,
|
|
200
|
+
exists: true,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return locations.filter(loc => loc.exists);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=config-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/core/config-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface EncryptedData {
|
|
2
|
+
salt: string;
|
|
3
|
+
iv: string;
|
|
4
|
+
authTag: string;
|
|
5
|
+
data: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Generate a random salt for encryption
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateSalt(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Generate a random IV for encryption
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateIV(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Encrypt data object with password using AES-256-GCM
|
|
17
|
+
*
|
|
18
|
+
* @param data - Object to encrypt (will be JSON stringified)
|
|
19
|
+
* @param password - Password for encryption
|
|
20
|
+
* @returns Encrypted data with salt, iv, authTag, and encrypted content
|
|
21
|
+
*/
|
|
22
|
+
export declare function encrypt(data: object, password: string): EncryptedData;
|
|
23
|
+
/**
|
|
24
|
+
* Decrypt data with password using AES-256-GCM
|
|
25
|
+
*
|
|
26
|
+
* @param encrypted - Encrypted data object
|
|
27
|
+
* @param password - Password for decryption
|
|
28
|
+
* @returns Decrypted object
|
|
29
|
+
* @throws Error if password is wrong or data is corrupted
|
|
30
|
+
*/
|
|
31
|
+
export declare function decrypt<T = unknown>(encrypted: EncryptedData, password: string): T;
|
|
32
|
+
/**
|
|
33
|
+
* Verify if a password can decrypt the data
|
|
34
|
+
*
|
|
35
|
+
* @param encrypted - Encrypted data object
|
|
36
|
+
* @param password - Password to verify
|
|
37
|
+
* @returns true if password is correct
|
|
38
|
+
*/
|
|
39
|
+
export declare function verifyPassword(encrypted: EncryptedData, password: string): boolean;
|
|
40
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/core/crypto.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AA4BD;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CA6BrE;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,CA+BlF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOlF"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateSalt = generateSalt;
|
|
37
|
+
exports.generateIV = generateIV;
|
|
38
|
+
exports.encrypt = encrypt;
|
|
39
|
+
exports.decrypt = decrypt;
|
|
40
|
+
exports.verifyPassword = verifyPassword;
|
|
41
|
+
const crypto = __importStar(require("crypto"));
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// Constants
|
|
44
|
+
// ============================================================================
|
|
45
|
+
const ALGORITHM = "aes-256-gcm";
|
|
46
|
+
const KEY_LENGTH = 32; // 256 bits
|
|
47
|
+
const SALT_LENGTH = 32; // 256 bits
|
|
48
|
+
const IV_LENGTH = 12; // 96 bits (recommended for GCM)
|
|
49
|
+
const AUTH_TAG_LENGTH = 16; // 128 bits
|
|
50
|
+
// scrypt parameters (N=16384, r=8, p=1)
|
|
51
|
+
const SCRYPT_N = 16384;
|
|
52
|
+
const SCRYPT_R = 8;
|
|
53
|
+
const SCRYPT_P = 1;
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Helper Functions
|
|
56
|
+
// ============================================================================
|
|
57
|
+
/**
|
|
58
|
+
* Generate random bytes and return as hex string
|
|
59
|
+
*/
|
|
60
|
+
function randomHex(length) {
|
|
61
|
+
return crypto.randomBytes(length).toString("hex");
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Derive encryption key from password using scrypt
|
|
65
|
+
*/
|
|
66
|
+
function deriveKey(password, salt) {
|
|
67
|
+
return crypto.scryptSync(password, salt, KEY_LENGTH, {
|
|
68
|
+
N: SCRYPT_N,
|
|
69
|
+
r: SCRYPT_R,
|
|
70
|
+
p: SCRYPT_P,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// Public Functions
|
|
75
|
+
// ============================================================================
|
|
76
|
+
/**
|
|
77
|
+
* Generate a random salt for encryption
|
|
78
|
+
*/
|
|
79
|
+
function generateSalt() {
|
|
80
|
+
return randomHex(SALT_LENGTH);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Generate a random IV for encryption
|
|
84
|
+
*/
|
|
85
|
+
function generateIV() {
|
|
86
|
+
return randomHex(IV_LENGTH);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Encrypt data object with password using AES-256-GCM
|
|
90
|
+
*
|
|
91
|
+
* @param data - Object to encrypt (will be JSON stringified)
|
|
92
|
+
* @param password - Password for encryption
|
|
93
|
+
* @returns Encrypted data with salt, iv, authTag, and encrypted content
|
|
94
|
+
*/
|
|
95
|
+
function encrypt(data, password) {
|
|
96
|
+
// Generate random salt and IV
|
|
97
|
+
const salt = Buffer.from(generateSalt(), "hex");
|
|
98
|
+
const iv = Buffer.from(generateIV(), "hex");
|
|
99
|
+
// Derive key from password
|
|
100
|
+
const key = deriveKey(password, salt);
|
|
101
|
+
// Create cipher
|
|
102
|
+
const cipher = crypto.createCipheriv(ALGORITHM, key, iv, {
|
|
103
|
+
authTagLength: AUTH_TAG_LENGTH,
|
|
104
|
+
});
|
|
105
|
+
// Encrypt data
|
|
106
|
+
const plaintext = JSON.stringify(data);
|
|
107
|
+
const encrypted = Buffer.concat([
|
|
108
|
+
cipher.update(plaintext, "utf8"),
|
|
109
|
+
cipher.final(),
|
|
110
|
+
]);
|
|
111
|
+
// Get auth tag
|
|
112
|
+
const authTag = cipher.getAuthTag();
|
|
113
|
+
return {
|
|
114
|
+
salt: salt.toString("hex"),
|
|
115
|
+
iv: iv.toString("hex"),
|
|
116
|
+
authTag: authTag.toString("hex"),
|
|
117
|
+
data: encrypted.toString("hex"),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Decrypt data with password using AES-256-GCM
|
|
122
|
+
*
|
|
123
|
+
* @param encrypted - Encrypted data object
|
|
124
|
+
* @param password - Password for decryption
|
|
125
|
+
* @returns Decrypted object
|
|
126
|
+
* @throws Error if password is wrong or data is corrupted
|
|
127
|
+
*/
|
|
128
|
+
function decrypt(encrypted, password) {
|
|
129
|
+
// Convert hex strings to buffers
|
|
130
|
+
const salt = Buffer.from(encrypted.salt, "hex");
|
|
131
|
+
const iv = Buffer.from(encrypted.iv, "hex");
|
|
132
|
+
const authTag = Buffer.from(encrypted.authTag, "hex");
|
|
133
|
+
const data = Buffer.from(encrypted.data, "hex");
|
|
134
|
+
// Derive key from password
|
|
135
|
+
const key = deriveKey(password, salt);
|
|
136
|
+
// Create decipher
|
|
137
|
+
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv, {
|
|
138
|
+
authTagLength: AUTH_TAG_LENGTH,
|
|
139
|
+
});
|
|
140
|
+
// Set auth tag for verification
|
|
141
|
+
decipher.setAuthTag(authTag);
|
|
142
|
+
try {
|
|
143
|
+
// Decrypt data
|
|
144
|
+
const decrypted = Buffer.concat([
|
|
145
|
+
decipher.update(data),
|
|
146
|
+
decipher.final(),
|
|
147
|
+
]);
|
|
148
|
+
// Parse JSON
|
|
149
|
+
return JSON.parse(decrypted.toString("utf8"));
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
// Auth tag verification failed or JSON parse failed
|
|
153
|
+
throw new Error("Invalid password or corrupted file");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Verify if a password can decrypt the data
|
|
158
|
+
*
|
|
159
|
+
* @param encrypted - Encrypted data object
|
|
160
|
+
* @param password - Password to verify
|
|
161
|
+
* @returns true if password is correct
|
|
162
|
+
*/
|
|
163
|
+
function verifyPassword(encrypted, password) {
|
|
164
|
+
try {
|
|
165
|
+
decrypt(encrypted, password);
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=crypto.js.map
|