opencode-account-manager 0.4.1 → 0.4.2
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/dist/cli.js +1 -1
- package/dist/core/importers/amExport.d.ts +42 -0
- package/dist/core/importers/amExport.d.ts.map +1 -0
- package/dist/core/importers/amExport.js +154 -0
- package/dist/core/importers/amExport.js.map +1 -0
- package/dist/core/types.d.ts +13 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +15 -0
- package/dist/core/types.js.map +1 -1
- package/dist/tui/components/ImportModal.d.ts.map +1 -1
- package/dist/tui/components/ImportModal.js +41 -4
- package/dist/tui/components/ImportModal.js.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/core/importers/amExport.ts +177 -0
- package/src/core/types.ts +40 -0
- package/src/tui/components/ImportModal.tsx +50 -4
package/dist/cli.js
CHANGED
|
@@ -35,7 +35,7 @@ const program = new commander_1.Command();
|
|
|
35
35
|
program
|
|
36
36
|
.name("ocam")
|
|
37
37
|
.description("OpenCode Account Manager - TUI dashboard and CLI for managing accounts")
|
|
38
|
-
.version("0.4.
|
|
38
|
+
.version("0.4.2");
|
|
39
39
|
// Default command - show dashboard
|
|
40
40
|
program
|
|
41
41
|
.command("dashboard", { isDefault: true })
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import accounts from Antigravity Manager EXPORTED files
|
|
3
|
+
*
|
|
4
|
+
* AM Export Format (from app export button):
|
|
5
|
+
* [
|
|
6
|
+
* { "email": "xxx@gmail.com", "refresh_token": "1//..." },
|
|
7
|
+
* ...
|
|
8
|
+
* ]
|
|
9
|
+
*
|
|
10
|
+
* This is different from AM folder structure (accounts.json + accounts/*.json)
|
|
11
|
+
*/
|
|
12
|
+
import { Account } from "../types";
|
|
13
|
+
/**
|
|
14
|
+
* Single entry in AM export file
|
|
15
|
+
*/
|
|
16
|
+
export interface AMExportEntry {
|
|
17
|
+
email: string;
|
|
18
|
+
refresh_token: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Type guard to check if data is an AM export file (array of entries)
|
|
22
|
+
*/
|
|
23
|
+
export declare function isAMExportFile(data: unknown): data is AMExportEntry[];
|
|
24
|
+
export interface ImportFromAMExportResult {
|
|
25
|
+
accounts: Account[];
|
|
26
|
+
skipped: string[];
|
|
27
|
+
errors: string[];
|
|
28
|
+
source: "am-export";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Import accounts from AM export file content
|
|
32
|
+
*/
|
|
33
|
+
export declare function importFromAMExportContent(entries: AMExportEntry[]): ImportFromAMExportResult;
|
|
34
|
+
/**
|
|
35
|
+
* Import accounts from AM export file path
|
|
36
|
+
*/
|
|
37
|
+
export declare function importFromAMExportFile(filePath: string): ImportFromAMExportResult;
|
|
38
|
+
/**
|
|
39
|
+
* Check if a file is an AM export file (by reading and checking format)
|
|
40
|
+
*/
|
|
41
|
+
export declare function isAMExportFilePath(filePath: string): boolean;
|
|
42
|
+
//# sourceMappingURL=amExport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amExport.d.ts","sourceRoot":"","sources":["../../../src/core/importers/amExport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,aAAa,EAAE,CAYrE;AA0CD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,wBAAwB,CAmC5F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,wBAAwB,CA+BjF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAU5D"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Import accounts from Antigravity Manager EXPORTED files
|
|
4
|
+
*
|
|
5
|
+
* AM Export Format (from app export button):
|
|
6
|
+
* [
|
|
7
|
+
* { "email": "xxx@gmail.com", "refresh_token": "1//..." },
|
|
8
|
+
* ...
|
|
9
|
+
* ]
|
|
10
|
+
*
|
|
11
|
+
* This is different from AM folder structure (accounts.json + accounts/*.json)
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.isAMExportFile = isAMExportFile;
|
|
18
|
+
exports.importFromAMExportContent = importFromAMExportContent;
|
|
19
|
+
exports.importFromAMExportFile = importFromAMExportFile;
|
|
20
|
+
exports.isAMExportFilePath = isAMExportFilePath;
|
|
21
|
+
const fs_1 = __importDefault(require("fs"));
|
|
22
|
+
/**
|
|
23
|
+
* Type guard to check if data is an AM export file (array of entries)
|
|
24
|
+
*/
|
|
25
|
+
function isAMExportFile(data) {
|
|
26
|
+
if (!Array.isArray(data))
|
|
27
|
+
return false;
|
|
28
|
+
if (data.length === 0)
|
|
29
|
+
return true; // Empty array is valid
|
|
30
|
+
// Check first few entries to be sure
|
|
31
|
+
const sample = data.slice(0, 3);
|
|
32
|
+
return sample.every(item => typeof item === "object" &&
|
|
33
|
+
item !== null &&
|
|
34
|
+
typeof item.email === "string" &&
|
|
35
|
+
typeof item.refresh_token === "string");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Generate a new fingerprint for imported accounts
|
|
39
|
+
*/
|
|
40
|
+
function generateFingerprint() {
|
|
41
|
+
const randomHex = (len) => {
|
|
42
|
+
let result = "";
|
|
43
|
+
for (let i = 0; i < len; i++) {
|
|
44
|
+
result += Math.floor(Math.random() * 16).toString(16);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
const platforms = ["win32/x64", "win32/arm64", "darwin/x64", "darwin/arm64"];
|
|
49
|
+
const ides = ["ANDROID_STUDIO", "INTELLIJ", "IDE_UNSPECIFIED"];
|
|
50
|
+
const clients = [
|
|
51
|
+
"google-cloud-sdk android-studio/2024.1",
|
|
52
|
+
"google-cloud-sdk intellij/2024.1",
|
|
53
|
+
"google-cloud-sdk vscode/1.87.0",
|
|
54
|
+
];
|
|
55
|
+
const platform = platforms[Math.floor(Math.random() * platforms.length)];
|
|
56
|
+
return {
|
|
57
|
+
deviceId: crypto.randomUUID(),
|
|
58
|
+
sessionToken: randomHex(32),
|
|
59
|
+
userAgent: `antigravity/1.15.8 ${platform}`,
|
|
60
|
+
apiClient: clients[Math.floor(Math.random() * clients.length)],
|
|
61
|
+
clientMetadata: {
|
|
62
|
+
ideType: ides[Math.floor(Math.random() * ides.length)],
|
|
63
|
+
platform: platform.startsWith("darwin") ? "MACOS" : "WINDOWS",
|
|
64
|
+
pluginType: "GEMINI",
|
|
65
|
+
osVersion: platform.startsWith("darwin") ? "14.2.1" : "10.0.19042",
|
|
66
|
+
arch: platform.split("/")[1],
|
|
67
|
+
sqmId: `{${crypto.randomUUID().toUpperCase()}}`,
|
|
68
|
+
},
|
|
69
|
+
quotaUser: `device-${randomHex(16)}`,
|
|
70
|
+
createdAt: Date.now(),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Import accounts from AM export file content
|
|
75
|
+
*/
|
|
76
|
+
function importFromAMExportContent(entries) {
|
|
77
|
+
const result = {
|
|
78
|
+
accounts: [],
|
|
79
|
+
skipped: [],
|
|
80
|
+
errors: [],
|
|
81
|
+
source: "am-export",
|
|
82
|
+
};
|
|
83
|
+
for (const entry of entries) {
|
|
84
|
+
// Validate email
|
|
85
|
+
if (!entry.email || !entry.email.includes("@")) {
|
|
86
|
+
result.skipped.push(`Invalid email: ${entry.email || "(empty)"}`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// Validate refresh_token
|
|
90
|
+
if (!entry.refresh_token || !entry.refresh_token.startsWith("1//")) {
|
|
91
|
+
result.skipped.push(`${entry.email} (invalid or missing refresh_token)`);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
// Convert to Plugin account format
|
|
95
|
+
const account = {
|
|
96
|
+
email: entry.email.trim(),
|
|
97
|
+
refreshToken: entry.refresh_token,
|
|
98
|
+
addedAt: Date.now(),
|
|
99
|
+
lastUsed: Date.now(),
|
|
100
|
+
fingerprint: generateFingerprint(),
|
|
101
|
+
enabled: true,
|
|
102
|
+
};
|
|
103
|
+
result.accounts.push(account);
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Import accounts from AM export file path
|
|
109
|
+
*/
|
|
110
|
+
function importFromAMExportFile(filePath) {
|
|
111
|
+
const result = {
|
|
112
|
+
accounts: [],
|
|
113
|
+
skipped: [],
|
|
114
|
+
errors: [],
|
|
115
|
+
source: "am-export",
|
|
116
|
+
};
|
|
117
|
+
// Check if file exists
|
|
118
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
119
|
+
result.errors.push(`File not found: ${filePath}`);
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
// Read and parse file
|
|
123
|
+
let data;
|
|
124
|
+
try {
|
|
125
|
+
const content = fs_1.default.readFileSync(filePath, "utf-8");
|
|
126
|
+
data = JSON.parse(content);
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
result.errors.push(`Failed to parse file: ${err}`);
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
// Validate format
|
|
133
|
+
if (!isAMExportFile(data)) {
|
|
134
|
+
result.errors.push("Invalid AM export format. Expected array of {email, refresh_token}");
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
return importFromAMExportContent(data);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check if a file is an AM export file (by reading and checking format)
|
|
141
|
+
*/
|
|
142
|
+
function isAMExportFilePath(filePath) {
|
|
143
|
+
if (!fs_1.default.existsSync(filePath))
|
|
144
|
+
return false;
|
|
145
|
+
try {
|
|
146
|
+
const content = fs_1.default.readFileSync(filePath, "utf-8");
|
|
147
|
+
const data = JSON.parse(content);
|
|
148
|
+
return isAMExportFile(data);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=amExport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amExport.js","sourceRoot":"","sources":["../../../src/core/importers/amExport.ts"],"names":[],"mappings":"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"}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -71,4 +71,17 @@ export interface ImportResult {
|
|
|
71
71
|
overwrittenCount: number;
|
|
72
72
|
error?: string;
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Single entry in AM export file (from app export button)
|
|
76
|
+
* Format: [{ "email": "...", "refresh_token": "..." }, ...]
|
|
77
|
+
*/
|
|
78
|
+
export interface AMExportEntry {
|
|
79
|
+
email: string;
|
|
80
|
+
refresh_token: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Type guard to check if data is an AM export file
|
|
84
|
+
*/
|
|
85
|
+
export declare function isAMExportFile(data: unknown): data is AMExportEntry[];
|
|
86
|
+
export type ImportFileType = "encrypted" | "portable" | "am-export" | "plugin-native" | "unknown";
|
|
74
87
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/core/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,kBAAkB,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,0BAA0B,GAAG,kBAAkB,CAAC;IAC9D,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAMD,MAAM,WAAW,mBAAmB;IAElC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,aAAa,CAAC;IAGzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAGhB,IAAI,EAAE,MAAM,CAAC;IAGb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,0BAA0B,CAAC;CAC1C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,mBAAmB,CAWhF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,kBAAkB,CAQ9E;AAMD,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,kBAAkB,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,0BAA0B,GAAG,kBAAkB,CAAC;IAC9D,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAMD,MAAM,WAAW,mBAAmB;IAElC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,aAAa,CAAC;IAGzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAGhB,IAAI,EAAE,MAAM,CAAC;IAGb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,0BAA0B,CAAC;CAC1C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,mBAAmB,CAWhF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,kBAAkB,CAQ9E;AAMD,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,aAAa,EAAE,CAWrE;AAMD,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,UAAU,GACV,WAAW,GACX,eAAe,GACf,SAAS,CAAC"}
|
package/dist/core/types.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isEncryptedExportFile = isEncryptedExportFile;
|
|
4
4
|
exports.isPortableExportFile = isPortableExportFile;
|
|
5
|
+
exports.isAMExportFile = isAMExportFile;
|
|
5
6
|
/**
|
|
6
7
|
* Type guard to check if data is an encrypted export file
|
|
7
8
|
*/
|
|
@@ -27,4 +28,18 @@ function isPortableExportFile(data) {
|
|
|
27
28
|
typeof obj.exportedAt === "number" &&
|
|
28
29
|
Array.isArray(obj.accounts));
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Type guard to check if data is an AM export file
|
|
33
|
+
*/
|
|
34
|
+
function isAMExportFile(data) {
|
|
35
|
+
if (!Array.isArray(data))
|
|
36
|
+
return false;
|
|
37
|
+
if (data.length === 0)
|
|
38
|
+
return true;
|
|
39
|
+
const sample = data.slice(0, 3);
|
|
40
|
+
return sample.every(item => typeof item === "object" &&
|
|
41
|
+
item !== null &&
|
|
42
|
+
typeof item.email === "string" &&
|
|
43
|
+
typeof item.refresh_token === "string");
|
|
44
|
+
}
|
|
30
45
|
//# sourceMappingURL=types.js.map
|
package/dist/core/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":";;AAwEA,sDAWC;AAKD,oDAQC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":";;AAwEA,sDAWC;AAKD,oDAQC;AAuCD,wCAWC;AA7ED;;GAEG;AACH,SAAgB,qBAAqB,CAAC,IAAa;IACjD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,GAAG,GAAG,IAA+B,CAAC;IAC5C,OAAO,CACL,GAAG,CAAC,MAAM,KAAK,WAAW;QAC1B,GAAG,CAAC,SAAS,KAAK,aAAa;QAC/B,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;QAC5B,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;QAC1B,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAC/B,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAC7B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAAC,IAAa;IAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,GAAG,GAAG,IAA+B,CAAC;IAC5C,OAAO,CACL,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAC/B,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;QAClC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAC5B,CAAC;AACJ,CAAC;AAoCD;;GAEG;AACH,SAAgB,cAAc,CAAC,IAAa;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CACzB,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACb,OAAQ,IAAgC,CAAC,KAAK,KAAK,QAAQ;QAC3D,OAAQ,IAAgC,CAAC,aAAa,KAAK,QAAQ,CACpE,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImportModal.d.ts","sourceRoot":"","sources":["../../../src/tui/components/ImportModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAMxC,OAAO,EACL,OAAO,
|
|
1
|
+
{"version":3,"file":"ImportModal.d.ts","sourceRoot":"","sources":["../../../src/tui/components/ImportModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAMxC,OAAO,EACL,OAAO,EAOR,MAAM,kBAAkB,CAAC;AAM1B,UAAU,gBAAgB;IACxB,gBAAgB,EAAE,OAAO,EAAE,CAAC;IAC5B,UAAU,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,KAAK,IAAI,CAAC;IACtF,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAWD,wBAAgB,WAAW,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,gBAAgB,qBA0SvF"}
|
|
@@ -43,10 +43,12 @@ const types_1 = require("../../core/types");
|
|
|
43
43
|
const crypto_1 = require("../../core/crypto");
|
|
44
44
|
const utils_1 = require("../../core/utils");
|
|
45
45
|
const config_store_1 = require("../../core/config-store");
|
|
46
|
+
const amExport_1 = require("../../core/importers/amExport");
|
|
46
47
|
function ImportModal({ existingAccounts, onComplete, onCancel }) {
|
|
47
48
|
const [step, setStep] = (0, react_1.useState)("file");
|
|
48
49
|
const [selectedFile, setSelectedFile] = (0, react_1.useState)("");
|
|
49
50
|
const [isEncrypted, setIsEncrypted] = (0, react_1.useState)(false);
|
|
51
|
+
const [detectedFormat, setDetectedFormat] = (0, react_1.useState)("unknown");
|
|
50
52
|
const [importedAccounts, setImportedAccounts] = (0, react_1.useState)([]);
|
|
51
53
|
const [previewItems, setPreviewItems] = (0, react_1.useState)([]);
|
|
52
54
|
const [error, setError] = (0, react_1.useState)("");
|
|
@@ -62,20 +64,31 @@ function ImportModal({ existingAccounts, onComplete, onCancel }) {
|
|
|
62
64
|
try {
|
|
63
65
|
const data = (0, utils_1.readJsonFile)(filePath);
|
|
64
66
|
if ((0, types_1.isEncryptedExportFile)(data)) {
|
|
67
|
+
// Encrypted .ocam file
|
|
65
68
|
setIsEncrypted(true);
|
|
69
|
+
setDetectedFormat("encrypted");
|
|
66
70
|
setStep("password");
|
|
67
71
|
}
|
|
72
|
+
else if ((0, types_1.isAMExportFile)(data)) {
|
|
73
|
+
// Antigravity Manager export format: [{ email, refresh_token }]
|
|
74
|
+
setIsEncrypted(false);
|
|
75
|
+
setDetectedFormat("am-export");
|
|
76
|
+
processAMExport(data);
|
|
77
|
+
}
|
|
68
78
|
else if ((0, types_1.isPortableExportFile)(data)) {
|
|
79
|
+
// opencode-account-manager plain export
|
|
69
80
|
setIsEncrypted(false);
|
|
81
|
+
setDetectedFormat("portable");
|
|
70
82
|
processAccounts(data.accounts);
|
|
71
83
|
}
|
|
72
|
-
else if (Array.isArray(data)) {
|
|
73
|
-
// Raw array of accounts
|
|
84
|
+
else if (Array.isArray(data) && data.length > 0 && data[0].email) {
|
|
85
|
+
// Raw array of accounts (legacy format)
|
|
74
86
|
setIsEncrypted(false);
|
|
87
|
+
setDetectedFormat("raw-array");
|
|
75
88
|
processAccounts(data);
|
|
76
89
|
}
|
|
77
90
|
else {
|
|
78
|
-
throw new Error("Unknown file format");
|
|
91
|
+
throw new Error("Unknown file format. Expected: encrypted, AM export, or portable format.");
|
|
79
92
|
}
|
|
80
93
|
}
|
|
81
94
|
catch (err) {
|
|
@@ -83,6 +96,28 @@ function ImportModal({ existingAccounts, onComplete, onCancel }) {
|
|
|
83
96
|
setStep("error");
|
|
84
97
|
}
|
|
85
98
|
};
|
|
99
|
+
// Process Antigravity Manager export format
|
|
100
|
+
const processAMExport = (entries) => {
|
|
101
|
+
const result = (0, amExport_1.importFromAMExportContent)(entries);
|
|
102
|
+
if (result.errors.length > 0) {
|
|
103
|
+
setError(result.errors.join("; "));
|
|
104
|
+
setStep("error");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (result.accounts.length === 0) {
|
|
108
|
+
setError(`No valid accounts found. Skipped: ${result.skipped.join(", ") || "none"}`);
|
|
109
|
+
setStep("error");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
setImportedAccounts(result.accounts);
|
|
113
|
+
// Build preview
|
|
114
|
+
const preview = result.accounts.map(acc => ({
|
|
115
|
+
email: acc.email,
|
|
116
|
+
exists: existsInCurrent(acc.email),
|
|
117
|
+
}));
|
|
118
|
+
setPreviewItems(preview);
|
|
119
|
+
setStep("preview");
|
|
120
|
+
};
|
|
86
121
|
// Handle password for encrypted files
|
|
87
122
|
const handlePasswordSubmit = (password) => {
|
|
88
123
|
try {
|
|
@@ -163,7 +198,9 @@ function ImportModal({ existingAccounts, onComplete, onCancel }) {
|
|
|
163
198
|
" accounts in",
|
|
164
199
|
" ",
|
|
165
200
|
react_1.default.createElement(ink_1.Text, { color: "cyan" }, path.basename(selectedFile)),
|
|
166
|
-
|
|
201
|
+
detectedFormat === "encrypted" && react_1.default.createElement(ink_1.Text, { color: "green" }, " (encrypted)"),
|
|
202
|
+
detectedFormat === "am-export" && react_1.default.createElement(ink_1.Text, { color: "magenta" }, " (AM export)"),
|
|
203
|
+
detectedFormat === "portable" && react_1.default.createElement(ink_1.Text, { color: "blue" }, " (portable)"))),
|
|
167
204
|
react_1.default.createElement(ink_1.Box, { flexDirection: "column" },
|
|
168
205
|
previewItems.slice(0, 8).map((item, index) => (react_1.default.createElement(ink_1.Box, { key: item.email },
|
|
169
206
|
react_1.default.createElement(ink_1.Text, null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImportModal.js","sourceRoot":"","sources":["../../../src/tui/components/ImportModal.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"ImportModal.js","sourceRoot":"","sources":["../../../src/tui/components/ImportModal.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import accounts from Antigravity Manager EXPORTED files
|
|
3
|
+
*
|
|
4
|
+
* AM Export Format (from app export button):
|
|
5
|
+
* [
|
|
6
|
+
* { "email": "xxx@gmail.com", "refresh_token": "1//..." },
|
|
7
|
+
* ...
|
|
8
|
+
* ]
|
|
9
|
+
*
|
|
10
|
+
* This is different from AM folder structure (accounts.json + accounts/*.json)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
import { Account } from "../types";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Single entry in AM export file
|
|
18
|
+
*/
|
|
19
|
+
export interface AMExportEntry {
|
|
20
|
+
email: string;
|
|
21
|
+
refresh_token: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Type guard to check if data is an AM export file (array of entries)
|
|
26
|
+
*/
|
|
27
|
+
export function isAMExportFile(data: unknown): data is AMExportEntry[] {
|
|
28
|
+
if (!Array.isArray(data)) return false;
|
|
29
|
+
if (data.length === 0) return true; // Empty array is valid
|
|
30
|
+
|
|
31
|
+
// Check first few entries to be sure
|
|
32
|
+
const sample = data.slice(0, 3);
|
|
33
|
+
return sample.every(item =>
|
|
34
|
+
typeof item === "object" &&
|
|
35
|
+
item !== null &&
|
|
36
|
+
typeof (item as Record<string, unknown>).email === "string" &&
|
|
37
|
+
typeof (item as Record<string, unknown>).refresh_token === "string"
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Generate a new fingerprint for imported accounts
|
|
43
|
+
*/
|
|
44
|
+
function generateFingerprint() {
|
|
45
|
+
const randomHex = (len: number) => {
|
|
46
|
+
let result = "";
|
|
47
|
+
for (let i = 0; i < len; i++) {
|
|
48
|
+
result += Math.floor(Math.random() * 16).toString(16);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const platforms = ["win32/x64", "win32/arm64", "darwin/x64", "darwin/arm64"];
|
|
54
|
+
const ides = ["ANDROID_STUDIO", "INTELLIJ", "IDE_UNSPECIFIED"];
|
|
55
|
+
const clients = [
|
|
56
|
+
"google-cloud-sdk android-studio/2024.1",
|
|
57
|
+
"google-cloud-sdk intellij/2024.1",
|
|
58
|
+
"google-cloud-sdk vscode/1.87.0",
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const platform = platforms[Math.floor(Math.random() * platforms.length)];
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
deviceId: crypto.randomUUID(),
|
|
65
|
+
sessionToken: randomHex(32),
|
|
66
|
+
userAgent: `antigravity/1.15.8 ${platform}`,
|
|
67
|
+
apiClient: clients[Math.floor(Math.random() * clients.length)],
|
|
68
|
+
clientMetadata: {
|
|
69
|
+
ideType: ides[Math.floor(Math.random() * ides.length)],
|
|
70
|
+
platform: platform.startsWith("darwin") ? "MACOS" : "WINDOWS",
|
|
71
|
+
pluginType: "GEMINI",
|
|
72
|
+
osVersion: platform.startsWith("darwin") ? "14.2.1" : "10.0.19042",
|
|
73
|
+
arch: platform.split("/")[1],
|
|
74
|
+
sqmId: `{${crypto.randomUUID().toUpperCase()}}`,
|
|
75
|
+
},
|
|
76
|
+
quotaUser: `device-${randomHex(16)}`,
|
|
77
|
+
createdAt: Date.now(),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface ImportFromAMExportResult {
|
|
82
|
+
accounts: Account[];
|
|
83
|
+
skipped: string[];
|
|
84
|
+
errors: string[];
|
|
85
|
+
source: "am-export";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Import accounts from AM export file content
|
|
90
|
+
*/
|
|
91
|
+
export function importFromAMExportContent(entries: AMExportEntry[]): ImportFromAMExportResult {
|
|
92
|
+
const result: ImportFromAMExportResult = {
|
|
93
|
+
accounts: [],
|
|
94
|
+
skipped: [],
|
|
95
|
+
errors: [],
|
|
96
|
+
source: "am-export",
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
for (const entry of entries) {
|
|
100
|
+
// Validate email
|
|
101
|
+
if (!entry.email || !entry.email.includes("@")) {
|
|
102
|
+
result.skipped.push(`Invalid email: ${entry.email || "(empty)"}`);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Validate refresh_token
|
|
107
|
+
if (!entry.refresh_token || !entry.refresh_token.startsWith("1//")) {
|
|
108
|
+
result.skipped.push(`${entry.email} (invalid or missing refresh_token)`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Convert to Plugin account format
|
|
113
|
+
const account: Account = {
|
|
114
|
+
email: entry.email.trim(),
|
|
115
|
+
refreshToken: entry.refresh_token,
|
|
116
|
+
addedAt: Date.now(),
|
|
117
|
+
lastUsed: Date.now(),
|
|
118
|
+
fingerprint: generateFingerprint(),
|
|
119
|
+
enabled: true,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
result.accounts.push(account);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Import accounts from AM export file path
|
|
130
|
+
*/
|
|
131
|
+
export function importFromAMExportFile(filePath: string): ImportFromAMExportResult {
|
|
132
|
+
const result: ImportFromAMExportResult = {
|
|
133
|
+
accounts: [],
|
|
134
|
+
skipped: [],
|
|
135
|
+
errors: [],
|
|
136
|
+
source: "am-export",
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// Check if file exists
|
|
140
|
+
if (!fs.existsSync(filePath)) {
|
|
141
|
+
result.errors.push(`File not found: ${filePath}`);
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Read and parse file
|
|
146
|
+
let data: unknown;
|
|
147
|
+
try {
|
|
148
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
149
|
+
data = JSON.parse(content);
|
|
150
|
+
} catch (err) {
|
|
151
|
+
result.errors.push(`Failed to parse file: ${err}`);
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Validate format
|
|
156
|
+
if (!isAMExportFile(data)) {
|
|
157
|
+
result.errors.push("Invalid AM export format. Expected array of {email, refresh_token}");
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return importFromAMExportContent(data);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Check if a file is an AM export file (by reading and checking format)
|
|
166
|
+
*/
|
|
167
|
+
export function isAMExportFilePath(filePath: string): boolean {
|
|
168
|
+
if (!fs.existsSync(filePath)) return false;
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
172
|
+
const data = JSON.parse(content);
|
|
173
|
+
return isAMExportFile(data);
|
|
174
|
+
} catch {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
package/src/core/types.ts
CHANGED
|
@@ -116,3 +116,43 @@ export interface ImportResult {
|
|
|
116
116
|
overwrittenCount: number;
|
|
117
117
|
error?: string;
|
|
118
118
|
}
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Antigravity Manager Export Types
|
|
122
|
+
// ============================================================================
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Single entry in AM export file (from app export button)
|
|
126
|
+
* Format: [{ "email": "...", "refresh_token": "..." }, ...]
|
|
127
|
+
*/
|
|
128
|
+
export interface AMExportEntry {
|
|
129
|
+
email: string;
|
|
130
|
+
refresh_token: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Type guard to check if data is an AM export file
|
|
135
|
+
*/
|
|
136
|
+
export function isAMExportFile(data: unknown): data is AMExportEntry[] {
|
|
137
|
+
if (!Array.isArray(data)) return false;
|
|
138
|
+
if (data.length === 0) return true;
|
|
139
|
+
|
|
140
|
+
const sample = data.slice(0, 3);
|
|
141
|
+
return sample.every(item =>
|
|
142
|
+
typeof item === "object" &&
|
|
143
|
+
item !== null &&
|
|
144
|
+
typeof (item as Record<string, unknown>).email === "string" &&
|
|
145
|
+
typeof (item as Record<string, unknown>).refresh_token === "string"
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ============================================================================
|
|
150
|
+
// Import Source Detection
|
|
151
|
+
// ============================================================================
|
|
152
|
+
|
|
153
|
+
export type ImportFileType =
|
|
154
|
+
| "encrypted" // .ocam encrypted file
|
|
155
|
+
| "portable" // opencode-account-manager plain export
|
|
156
|
+
| "am-export" // Antigravity Manager app export
|
|
157
|
+
| "plugin-native" // antigravity-accounts.json format
|
|
158
|
+
| "unknown";
|
|
@@ -10,10 +10,13 @@ import {
|
|
|
10
10
|
PortableExportFile,
|
|
11
11
|
isEncryptedExportFile,
|
|
12
12
|
isPortableExportFile,
|
|
13
|
+
isAMExportFile,
|
|
14
|
+
ImportFileType,
|
|
13
15
|
} from "../../core/types";
|
|
14
16
|
import { decrypt } from "../../core/crypto";
|
|
15
17
|
import { readJsonFile } from "../../core/utils";
|
|
16
18
|
import { updateLastImportFolder, getLastImportFolder } from "../../core/config-store";
|
|
19
|
+
import { importFromAMExportContent, AMExportEntry } from "../../core/importers/amExport";
|
|
17
20
|
|
|
18
21
|
interface ImportModalProps {
|
|
19
22
|
existingAccounts: Account[];
|
|
@@ -28,10 +31,13 @@ interface ImportPreviewItem {
|
|
|
28
31
|
exists: boolean;
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
type DetectedFormat = "encrypted" | "portable" | "am-export" | "raw-array" | "unknown";
|
|
35
|
+
|
|
31
36
|
export function ImportModal({ existingAccounts, onComplete, onCancel }: ImportModalProps) {
|
|
32
37
|
const [step, setStep] = useState<ImportStep>("file");
|
|
33
38
|
const [selectedFile, setSelectedFile] = useState<string>("");
|
|
34
39
|
const [isEncrypted, setIsEncrypted] = useState<boolean>(false);
|
|
40
|
+
const [detectedFormat, setDetectedFormat] = useState<DetectedFormat>("unknown");
|
|
35
41
|
const [importedAccounts, setImportedAccounts] = useState<Account[]>([]);
|
|
36
42
|
const [previewItems, setPreviewItems] = useState<ImportPreviewItem[]>([]);
|
|
37
43
|
const [error, setError] = useState<string>("");
|
|
@@ -53,17 +59,27 @@ export function ImportModal({ existingAccounts, onComplete, onCancel }: ImportMo
|
|
|
53
59
|
const data = readJsonFile(filePath);
|
|
54
60
|
|
|
55
61
|
if (isEncryptedExportFile(data)) {
|
|
62
|
+
// Encrypted .ocam file
|
|
56
63
|
setIsEncrypted(true);
|
|
64
|
+
setDetectedFormat("encrypted");
|
|
57
65
|
setStep("password");
|
|
66
|
+
} else if (isAMExportFile(data)) {
|
|
67
|
+
// Antigravity Manager export format: [{ email, refresh_token }]
|
|
68
|
+
setIsEncrypted(false);
|
|
69
|
+
setDetectedFormat("am-export");
|
|
70
|
+
processAMExport(data);
|
|
58
71
|
} else if (isPortableExportFile(data)) {
|
|
72
|
+
// opencode-account-manager plain export
|
|
59
73
|
setIsEncrypted(false);
|
|
74
|
+
setDetectedFormat("portable");
|
|
60
75
|
processAccounts(data.accounts);
|
|
61
|
-
} else if (Array.isArray(data)) {
|
|
62
|
-
// Raw array of accounts
|
|
76
|
+
} else if (Array.isArray(data) && data.length > 0 && data[0].email) {
|
|
77
|
+
// Raw array of accounts (legacy format)
|
|
63
78
|
setIsEncrypted(false);
|
|
79
|
+
setDetectedFormat("raw-array");
|
|
64
80
|
processAccounts(data);
|
|
65
81
|
} else {
|
|
66
|
-
throw new Error("Unknown file format");
|
|
82
|
+
throw new Error("Unknown file format. Expected: encrypted, AM export, or portable format.");
|
|
67
83
|
}
|
|
68
84
|
} catch (err) {
|
|
69
85
|
setError(err instanceof Error ? err.message : "Failed to read file");
|
|
@@ -71,6 +87,34 @@ export function ImportModal({ existingAccounts, onComplete, onCancel }: ImportMo
|
|
|
71
87
|
}
|
|
72
88
|
};
|
|
73
89
|
|
|
90
|
+
// Process Antigravity Manager export format
|
|
91
|
+
const processAMExport = (entries: AMExportEntry[]) => {
|
|
92
|
+
const result = importFromAMExportContent(entries);
|
|
93
|
+
|
|
94
|
+
if (result.errors.length > 0) {
|
|
95
|
+
setError(result.errors.join("; "));
|
|
96
|
+
setStep("error");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (result.accounts.length === 0) {
|
|
101
|
+
setError(`No valid accounts found. Skipped: ${result.skipped.join(", ") || "none"}`);
|
|
102
|
+
setStep("error");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
setImportedAccounts(result.accounts);
|
|
107
|
+
|
|
108
|
+
// Build preview
|
|
109
|
+
const preview: ImportPreviewItem[] = result.accounts.map(acc => ({
|
|
110
|
+
email: acc.email,
|
|
111
|
+
exists: existsInCurrent(acc.email),
|
|
112
|
+
}));
|
|
113
|
+
|
|
114
|
+
setPreviewItems(preview);
|
|
115
|
+
setStep("preview");
|
|
116
|
+
};
|
|
117
|
+
|
|
74
118
|
// Handle password for encrypted files
|
|
75
119
|
const handlePasswordSubmit = (password: string) => {
|
|
76
120
|
try {
|
|
@@ -192,7 +236,9 @@ export function ImportModal({ existingAccounts, onComplete, onCancel }: ImportMo
|
|
|
192
236
|
<Text>
|
|
193
237
|
Found {importedAccounts.length} accounts in{" "}
|
|
194
238
|
<Text color="cyan">{path.basename(selectedFile)}</Text>
|
|
195
|
-
{
|
|
239
|
+
{detectedFormat === "encrypted" && <Text color="green"> (encrypted)</Text>}
|
|
240
|
+
{detectedFormat === "am-export" && <Text color="magenta"> (AM export)</Text>}
|
|
241
|
+
{detectedFormat === "portable" && <Text color="blue"> (portable)</Text>}
|
|
196
242
|
</Text>
|
|
197
243
|
</Box>
|
|
198
244
|
|