@kaitranntt/ccs 7.56.0-dev.1 → 7.56.0-dev.3
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 +22 -11
- package/dist/api/services/profile-lifecycle-service.d.ts.map +1 -1
- package/dist/api/services/profile-lifecycle-service.js +10 -10
- package/dist/api/services/profile-lifecycle-service.js.map +1 -1
- package/dist/api/services/profile-writer.d.ts.map +1 -1
- package/dist/api/services/profile-writer.js +33 -36
- package/dist/api/services/profile-writer.js.map +1 -1
- package/dist/auth/profile-registry.d.ts.map +1 -1
- package/dist/auth/profile-registry.js +46 -48
- package/dist/auth/profile-registry.js.map +1 -1
- package/dist/bin/droid-runtime.d.ts +1 -0
- package/dist/bin/droid-runtime.d.ts.map +1 -0
- package/dist/bin/droid-runtime.js +5 -0
- package/dist/bin/droid-runtime.js.map +1 -0
- package/dist/cliproxy/account-manager.d.ts +1 -1
- package/dist/cliproxy/account-manager.d.ts.map +1 -1
- package/dist/cliproxy/account-manager.js +4 -1
- package/dist/cliproxy/account-manager.js.map +1 -1
- package/dist/cliproxy/accounts/index.d.ts +1 -1
- package/dist/cliproxy/accounts/index.d.ts.map +1 -1
- package/dist/cliproxy/accounts/index.js +4 -1
- package/dist/cliproxy/accounts/index.js.map +1 -1
- package/dist/cliproxy/accounts/query.d.ts.map +1 -1
- package/dist/cliproxy/accounts/query.js +4 -6
- package/dist/cliproxy/accounts/query.js.map +1 -1
- package/dist/cliproxy/accounts/registry.d.ts +2 -2
- package/dist/cliproxy/accounts/registry.d.ts.map +1 -1
- package/dist/cliproxy/accounts/registry.js +292 -320
- package/dist/cliproxy/accounts/registry.js.map +1 -1
- package/dist/cliproxy/accounts/token-file-ops.d.ts +16 -1
- package/dist/cliproxy/accounts/token-file-ops.d.ts.map +1 -1
- package/dist/cliproxy/accounts/token-file-ops.js +55 -3
- package/dist/cliproxy/accounts/token-file-ops.js.map +1 -1
- package/dist/cliproxy/ai-providers/config-store.d.ts.map +1 -1
- package/dist/cliproxy/ai-providers/config-store.js +37 -4
- package/dist/cliproxy/ai-providers/config-store.js.map +1 -1
- package/dist/cliproxy/ai-providers/service.d.ts +2 -2
- package/dist/cliproxy/ai-providers/service.d.ts.map +1 -1
- package/dist/cliproxy/ai-providers/service.js +39 -10
- package/dist/cliproxy/ai-providers/service.js.map +1 -1
- package/dist/cliproxy/ai-providers/types.d.ts +2 -0
- package/dist/cliproxy/ai-providers/types.d.ts.map +1 -1
- package/dist/cliproxy/ai-providers/types.js.map +1 -1
- package/dist/cliproxy/auth/oauth-handler.d.ts +1 -0
- package/dist/cliproxy/auth/oauth-handler.d.ts.map +1 -1
- package/dist/cliproxy/auth/oauth-handler.js +31 -69
- package/dist/cliproxy/auth/oauth-handler.js.map +1 -1
- package/dist/cliproxy/auth/oauth-process.d.ts +1 -0
- package/dist/cliproxy/auth/oauth-process.d.ts.map +1 -1
- package/dist/cliproxy/auth/oauth-process.js +5 -5
- package/dist/cliproxy/auth/oauth-process.js.map +1 -1
- package/dist/cliproxy/auth/token-manager.d.ts +1 -1
- package/dist/cliproxy/auth/token-manager.d.ts.map +1 -1
- package/dist/cliproxy/auth/token-manager.js +53 -20
- package/dist/cliproxy/auth/token-manager.js.map +1 -1
- package/dist/cliproxy/auth-token-manager.d.ts.map +1 -1
- package/dist/cliproxy/auth-token-manager.js +47 -50
- package/dist/cliproxy/auth-token-manager.js.map +1 -1
- package/dist/cliproxy/executor/index.js +1 -1
- package/dist/cliproxy/executor/index.js.map +1 -1
- package/dist/cliproxy/services/variant-config-adapter.d.ts.map +1 -1
- package/dist/cliproxy/services/variant-config-adapter.js +43 -39
- package/dist/cliproxy/services/variant-config-adapter.js.map +1 -1
- package/dist/commands/api-command/create-command.d.ts.map +1 -1
- package/dist/commands/api-command/create-command.js +8 -4
- package/dist/commands/api-command/create-command.js.map +1 -1
- package/dist/commands/cliproxy/proxy-lifecycle-subcommand.d.ts +0 -5
- package/dist/commands/cliproxy/proxy-lifecycle-subcommand.d.ts.map +1 -1
- package/dist/commands/cliproxy/proxy-lifecycle-subcommand.js +6 -16
- package/dist/commands/cliproxy/proxy-lifecycle-subcommand.js.map +1 -1
- package/dist/commands/cliproxy/resolve-lifecycle-port.d.ts +6 -0
- package/dist/commands/cliproxy/resolve-lifecycle-port.d.ts.map +1 -0
- package/dist/commands/cliproxy/resolve-lifecycle-port.js +15 -0
- package/dist/commands/cliproxy/resolve-lifecycle-port.js.map +1 -0
- package/dist/commands/cliproxy/variant-subcommand.d.ts.map +1 -1
- package/dist/commands/cliproxy/variant-subcommand.js +12 -6
- package/dist/commands/cliproxy/variant-subcommand.js.map +1 -1
- package/dist/commands/config-auth/disable-command.d.ts.map +1 -1
- package/dist/commands/config-auth/disable-command.js +8 -8
- package/dist/commands/config-auth/disable-command.js.map +1 -1
- package/dist/commands/config-auth/setup-command.d.ts.map +1 -1
- package/dist/commands/config-auth/setup-command.js +9 -11
- package/dist/commands/config-auth/setup-command.js.map +1 -1
- package/dist/commands/copilot-command.js +11 -11
- package/dist/commands/copilot-command.js.map +1 -1
- package/dist/commands/cursor-command.d.ts.map +1 -1
- package/dist/commands/cursor-command.js +11 -11
- package/dist/commands/cursor-command.js.map +1 -1
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +10 -8
- package/dist/commands/help-command.js.map +1 -1
- package/dist/commands/setup-command.d.ts.map +1 -1
- package/dist/commands/setup-command.js +4 -3
- package/dist/commands/setup-command.js.map +1 -1
- package/dist/config/unified-config-loader.d.ts +1 -1
- package/dist/config/unified-config-loader.d.ts.map +1 -1
- package/dist/config/unified-config-loader.js +39 -32
- package/dist/config/unified-config-loader.js.map +1 -1
- package/dist/targets/target-resolver.d.ts +2 -2
- package/dist/targets/target-resolver.d.ts.map +1 -1
- package/dist/targets/target-resolver.js +68 -18
- package/dist/targets/target-resolver.js.map +1 -1
- package/dist/ui/assets/{accounts-CccaoV-N.js → accounts-_HKzUYeW.js} +1 -1
- package/dist/ui/assets/{alert-dialog-D838sIju.js → alert-dialog-7NHGF_Xe.js} +1 -1
- package/dist/ui/assets/api-DOfVbQ1z.js +4 -0
- package/dist/ui/assets/{auth-section-BGCaHAcN.js → auth-section-DqMIwU7c.js} +1 -1
- package/dist/ui/assets/{backups-section-CqZN-2Qq.js → backups-section-D4um8aUY.js} +1 -1
- package/dist/ui/assets/{checkbox-BgLi38k2.js → checkbox-BOeXuNDh.js} +1 -1
- package/dist/ui/assets/{claude-extension-ClHnH_4i.js → claude-extension-CelZ8ku0.js} +1 -1
- package/dist/ui/assets/cliproxy-CzJfXgOZ.js +3 -0
- package/dist/ui/assets/{cliproxy-ai-providers-EhHqrkRr.js → cliproxy-ai-providers-BYWaYXvO.js} +3 -3
- package/dist/ui/assets/{cliproxy-control-panel-lRQBQhPS.js → cliproxy-control-panel-77ZZmJI4.js} +1 -1
- package/dist/ui/assets/{confirm-dialog-t6i94F2B.js → confirm-dialog-Bz3IbucG.js} +1 -1
- package/dist/ui/assets/{copilot-DlSkTZ2q.js → copilot-DzskqpA-.js} +1 -1
- package/dist/ui/assets/{cursor-DJvTEVHh.js → cursor-C8f14wrT.js} +1 -1
- package/dist/ui/assets/{droid-wevxXBVG.js → droid-DR0b5dXu.js} +2 -2
- package/dist/ui/assets/{globalenv-section-De072K_j.js → globalenv-section-O2tusa4k.js} +1 -1
- package/dist/ui/assets/{health-Wv80MRCF.js → health-BPuHhvGU.js} +1 -1
- package/dist/ui/assets/{icons-DMeZET56.js → icons-DR-ORtNe.js} +1 -1
- package/dist/ui/assets/{index-BmB4ckDm.js → index-3azdVT3y.js} +1 -1
- package/dist/ui/assets/{index-BqdBnk5l.js → index-BxTb3XSE.js} +1 -1
- package/dist/ui/assets/{index-C9TiCNLM.js → index-D0r4vaLi.js} +1 -1
- package/dist/ui/assets/index-ZlUC3TcJ.js +47 -0
- package/dist/ui/assets/{index-CxPqnEpn.js → index-eQOk8v6I.js} +1 -1
- package/dist/ui/assets/index-kGiBvBM-.css +1 -0
- package/dist/ui/assets/{proxy-status-widget-DMe8konR.js → proxy-status-widget-CU9RtUUZ.js} +1 -1
- package/dist/ui/assets/{searchable-select-C-dUgzQ_.js → searchable-select-DltMdKve.js} +1 -1
- package/dist/ui/assets/{separator-TnQMGoEt.js → separator-DvmULQuv.js} +1 -1
- package/dist/ui/assets/{shared-Cbcz8ZIu.js → shared-3KjBmAma.js} +1 -1
- package/dist/ui/assets/{switch-Df15Gmz9.js → switch-WfgHsT03.js} +1 -1
- package/dist/ui/assets/{updates-WOEYNHTJ.js → updates-DEb1kb0C.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/web-server/health-service.d.ts.map +1 -1
- package/dist/web-server/health-service.js +2 -3
- package/dist/web-server/health-service.js.map +1 -1
- package/dist/web-server/middleware/auth-middleware.d.ts +2 -0
- package/dist/web-server/middleware/auth-middleware.d.ts.map +1 -1
- package/dist/web-server/middleware/auth-middleware.js +23 -1
- package/dist/web-server/middleware/auth-middleware.js.map +1 -1
- package/dist/web-server/routes/ai-provider-routes.d.ts.map +1 -1
- package/dist/web-server/routes/ai-provider-routes.js +19 -13
- package/dist/web-server/routes/ai-provider-routes.js.map +1 -1
- package/dist/web-server/routes/cliproxy-auth-routes.d.ts +7 -0
- package/dist/web-server/routes/cliproxy-auth-routes.d.ts.map +1 -1
- package/dist/web-server/routes/cliproxy-auth-routes.js +119 -32
- package/dist/web-server/routes/cliproxy-auth-routes.js.map +1 -1
- package/dist/web-server/routes/cliproxy-stats-routes.d.ts.map +1 -1
- package/dist/web-server/routes/cliproxy-stats-routes.js +6 -0
- package/dist/web-server/routes/cliproxy-stats-routes.js.map +1 -1
- package/dist/web-server/routes/cliproxy-sync-routes.d.ts.map +1 -1
- package/dist/web-server/routes/cliproxy-sync-routes.js +6 -11
- package/dist/web-server/routes/cliproxy-sync-routes.js.map +1 -1
- package/dist/web-server/routes/cursor-settings-routes.d.ts.map +1 -1
- package/dist/web-server/routes/cursor-settings-routes.js +36 -33
- package/dist/web-server/routes/cursor-settings-routes.js.map +1 -1
- package/dist/web-server/routes/misc-routes.d.ts.map +1 -1
- package/dist/web-server/routes/misc-routes.js +26 -19
- package/dist/web-server/routes/misc-routes.js.map +1 -1
- package/dist/web-server/routes/proxy-routes.d.ts.map +1 -1
- package/dist/web-server/routes/proxy-routes.js +6 -0
- package/dist/web-server/routes/proxy-routes.js.map +1 -1
- package/dist/web-server/routes/settings-routes.d.ts.map +1 -1
- package/dist/web-server/routes/settings-routes.js +143 -109
- package/dist/web-server/routes/settings-routes.js.map +1 -1
- package/dist/web-server/routes/websearch-routes.d.ts.map +1 -1
- package/dist/web-server/routes/websearch-routes.js +31 -43
- package/dist/web-server/routes/websearch-routes.js.map +1 -1
- package/dist/web-server/shared-routes.d.ts.map +1 -1
- package/dist/web-server/shared-routes.js +6 -0
- package/dist/web-server/shared-routes.js.map +1 -1
- package/package.json +3 -2
- package/scripts/add-shebang.js +33 -20
- package/dist/ui/assets/api-IXigV-A_.js +0 -4
- package/dist/ui/assets/cliproxy-qX23viWV.js +0 -3
- package/dist/ui/assets/index-DRmZP4OP.css +0 -1
- package/dist/ui/assets/index-N_jd9sKU.js +0 -47
|
@@ -30,48 +30,100 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
30
30
|
exports.discoverExistingAccounts = exports.setAccountTier = exports.touchAccount = exports.renameAccount = exports.removeAccount = exports.resumeAccount = exports.pauseAccount = exports.setDefaultAccount = exports.registerAccount = exports.syncRegistryWithTokenFiles = exports.saveAccountsRegistry = exports.loadAccountsRegistry = void 0;
|
|
31
31
|
const fs = __importStar(require("fs"));
|
|
32
32
|
const path = __importStar(require("path"));
|
|
33
|
+
const lockfile = __importStar(require("proper-lockfile"));
|
|
33
34
|
const auth_types_1 = require("../auth/auth-types");
|
|
34
35
|
const config_generator_1 = require("../config-generator");
|
|
35
36
|
const types_1 = require("./types");
|
|
36
37
|
const token_file_ops_1 = require("./token-file-ops");
|
|
37
38
|
/** Default registry structure */
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
function createDefaultRegistry() {
|
|
40
|
+
return {
|
|
41
|
+
version: 1,
|
|
42
|
+
providers: {},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function withAccountsRegistryLock(callback) {
|
|
46
|
+
const lockTarget = (0, config_generator_1.getCliproxyDir)();
|
|
47
|
+
let release;
|
|
48
|
+
if (!fs.existsSync(lockTarget)) {
|
|
49
|
+
fs.mkdirSync(lockTarget, { recursive: true, mode: 0o700 });
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
release = lockfile.lockSync(lockTarget, { stale: 10000 });
|
|
53
|
+
return callback();
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
if (release) {
|
|
57
|
+
try {
|
|
58
|
+
release();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Best-effort release
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function readAccountsRegistryFromDisk() {
|
|
46
67
|
const registryPath = (0, token_file_ops_1.getAccountsRegistryPath)();
|
|
47
68
|
if (!fs.existsSync(registryPath)) {
|
|
48
|
-
return
|
|
69
|
+
return createDefaultRegistry();
|
|
49
70
|
}
|
|
71
|
+
const content = fs.readFileSync(registryPath, 'utf-8');
|
|
72
|
+
let data;
|
|
50
73
|
try {
|
|
51
|
-
|
|
52
|
-
const data = JSON.parse(content);
|
|
53
|
-
return {
|
|
54
|
-
version: data.version || 1,
|
|
55
|
-
providers: data.providers || {},
|
|
56
|
-
};
|
|
74
|
+
data = JSON.parse(content);
|
|
57
75
|
}
|
|
58
|
-
catch {
|
|
59
|
-
|
|
76
|
+
catch (error) {
|
|
77
|
+
throw new Error(`Accounts registry is corrupted: ${error.message}`);
|
|
60
78
|
}
|
|
79
|
+
if (!data || typeof data !== 'object') {
|
|
80
|
+
throw new Error('Accounts registry is corrupted: expected object');
|
|
81
|
+
}
|
|
82
|
+
const parsed = data;
|
|
83
|
+
return {
|
|
84
|
+
version: typeof parsed.version === 'number' ? parsed.version : 1,
|
|
85
|
+
providers: parsed.providers && typeof parsed.providers === 'object'
|
|
86
|
+
? parsed.providers
|
|
87
|
+
: {},
|
|
88
|
+
};
|
|
61
89
|
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Save accounts registry
|
|
65
|
-
*/
|
|
66
|
-
function saveAccountsRegistry(registry) {
|
|
90
|
+
function writeAccountsRegistryToDisk(registry) {
|
|
67
91
|
const registryPath = (0, token_file_ops_1.getAccountsRegistryPath)();
|
|
68
92
|
const dir = path.dirname(registryPath);
|
|
69
93
|
if (!fs.existsSync(dir)) {
|
|
70
94
|
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
71
95
|
}
|
|
72
|
-
|
|
96
|
+
const tempPath = `${registryPath}.tmp.${process.pid}`;
|
|
97
|
+
fs.writeFileSync(tempPath, JSON.stringify(registry, null, 2) + '\n', {
|
|
73
98
|
mode: 0o600,
|
|
74
99
|
});
|
|
100
|
+
fs.renameSync(tempPath, registryPath);
|
|
101
|
+
}
|
|
102
|
+
function mutateAccountsRegistry(mutator) {
|
|
103
|
+
return withAccountsRegistryLock(() => {
|
|
104
|
+
const registry = readAccountsRegistryFromDisk();
|
|
105
|
+
const initialSnapshot = JSON.stringify(registry);
|
|
106
|
+
const result = mutator(registry);
|
|
107
|
+
if (JSON.stringify(registry) !== initialSnapshot) {
|
|
108
|
+
writeAccountsRegistryToDisk(registry);
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Load accounts registry
|
|
115
|
+
*/
|
|
116
|
+
function loadAccountsRegistry() {
|
|
117
|
+
return readAccountsRegistryFromDisk();
|
|
118
|
+
}
|
|
119
|
+
exports.loadAccountsRegistry = loadAccountsRegistry;
|
|
120
|
+
/**
|
|
121
|
+
* Save accounts registry
|
|
122
|
+
*/
|
|
123
|
+
function saveAccountsRegistry(registry) {
|
|
124
|
+
withAccountsRegistryLock(() => {
|
|
125
|
+
writeAccountsRegistryToDisk(registry);
|
|
126
|
+
});
|
|
75
127
|
}
|
|
76
128
|
exports.saveAccountsRegistry = saveAccountsRegistry;
|
|
77
129
|
/**
|
|
@@ -118,99 +170,96 @@ exports.syncRegistryWithTokenFiles = syncRegistryWithTokenFiles;
|
|
|
118
170
|
* Called after successful OAuth to record the account
|
|
119
171
|
*
|
|
120
172
|
* For providers without email (kiro, ghcp):
|
|
121
|
-
* -
|
|
122
|
-
* -
|
|
173
|
+
* - internal accountId is derived from token metadata
|
|
174
|
+
* - nickname is optional metadata
|
|
123
175
|
*
|
|
124
176
|
* For providers with email:
|
|
125
177
|
* - email is used as accountId
|
|
126
178
|
* - nickname is auto-generated from email if not provided
|
|
127
179
|
*/
|
|
128
180
|
function registerAccount(provider, tokenFile, email, nickname, projectId) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
const providerAccounts = registry.providers[provider];
|
|
138
|
-
if (!providerAccounts) {
|
|
139
|
-
throw new Error('Failed to initialize provider accounts');
|
|
140
|
-
}
|
|
141
|
-
// Determine account ID based on provider type
|
|
142
|
-
let accountId;
|
|
143
|
-
let accountNickname;
|
|
144
|
-
if (types_1.PROVIDERS_WITHOUT_EMAIL.includes(provider)) {
|
|
145
|
-
// For kiro/ghcp: nickname is REQUIRED and used as accountId
|
|
146
|
-
if (!nickname || nickname === 'default') {
|
|
147
|
-
throw new Error(`Nickname is required when adding ${provider} accounts. ` +
|
|
148
|
-
`Use --nickname <name> or provide a nickname in the UI.`);
|
|
181
|
+
return mutateAccountsRegistry((registry) => {
|
|
182
|
+
syncRegistryWithTokenFiles(registry);
|
|
183
|
+
if (!registry.providers[provider]) {
|
|
184
|
+
registry.providers[provider] = {
|
|
185
|
+
default: 'default',
|
|
186
|
+
accounts: {},
|
|
187
|
+
};
|
|
149
188
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
throw new Error(validationError);
|
|
189
|
+
const providerAccounts = registry.providers[provider];
|
|
190
|
+
if (!providerAccounts) {
|
|
191
|
+
throw new Error('Failed to initialize provider accounts');
|
|
154
192
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
193
|
+
let accountId;
|
|
194
|
+
let accountNickname;
|
|
195
|
+
if (types_1.PROVIDERS_WITHOUT_EMAIL.includes(provider)) {
|
|
196
|
+
accountId = email
|
|
197
|
+
? (0, token_file_ops_1.extractAccountIdFromTokenFile)(tokenFile, email)
|
|
198
|
+
: (0, token_file_ops_1.deriveNoEmailProviderAccountId)(provider, tokenFile, providerAccounts.accounts);
|
|
199
|
+
const existingAccount = providerAccounts.accounts[accountId];
|
|
200
|
+
if (nickname) {
|
|
201
|
+
const validationError = (0, token_file_ops_1.validateNickname)(nickname);
|
|
202
|
+
if (validationError) {
|
|
203
|
+
throw new Error(validationError);
|
|
204
|
+
}
|
|
205
|
+
const existingAccounts = Object.entries(providerAccounts.accounts).map(([id, account]) => ({
|
|
206
|
+
id,
|
|
207
|
+
nickname: account.nickname,
|
|
208
|
+
}));
|
|
209
|
+
if ((0, token_file_ops_1.hasAccountNameConflict)(existingAccounts, nickname, accountId)) {
|
|
210
|
+
throw new Error(`An account with nickname "${nickname}" already exists for ${provider}. ` +
|
|
211
|
+
`Choose a different nickname.`);
|
|
212
|
+
}
|
|
160
213
|
}
|
|
214
|
+
accountNickname =
|
|
215
|
+
nickname || existingAccount?.nickname || (email ? (0, token_file_ops_1.generateNickname)(email) : accountId);
|
|
161
216
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
nickname: accountNickname,
|
|
195
|
-
tokenFile,
|
|
196
|
-
createdAt: providerAccounts.accounts[accountId].createdAt,
|
|
197
|
-
lastUsedAt: providerAccounts.accounts[accountId].lastUsedAt,
|
|
198
|
-
projectId: providerAccounts.accounts[accountId].projectId,
|
|
199
|
-
};
|
|
217
|
+
else {
|
|
218
|
+
accountId = (0, token_file_ops_1.extractAccountIdFromTokenFile)(tokenFile, email);
|
|
219
|
+
accountNickname = nickname || (0, token_file_ops_1.generateNickname)(email);
|
|
220
|
+
}
|
|
221
|
+
const isFirstAccount = Object.keys(providerAccounts.accounts).length === 0;
|
|
222
|
+
const existingAccount = providerAccounts.accounts[accountId];
|
|
223
|
+
const accountMeta = {
|
|
224
|
+
email,
|
|
225
|
+
nickname: accountNickname,
|
|
226
|
+
tokenFile,
|
|
227
|
+
createdAt: existingAccount?.createdAt || new Date().toISOString(),
|
|
228
|
+
lastUsedAt: new Date().toISOString(),
|
|
229
|
+
};
|
|
230
|
+
if (provider === 'agy' && projectId) {
|
|
231
|
+
accountMeta.projectId = projectId;
|
|
232
|
+
}
|
|
233
|
+
providerAccounts.accounts[accountId] = accountMeta;
|
|
234
|
+
if (isFirstAccount) {
|
|
235
|
+
providerAccounts.default = accountId;
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
id: accountId,
|
|
239
|
+
provider,
|
|
240
|
+
isDefault: accountId === providerAccounts.default,
|
|
241
|
+
email,
|
|
242
|
+
nickname: accountNickname,
|
|
243
|
+
tokenFile,
|
|
244
|
+
createdAt: providerAccounts.accounts[accountId].createdAt,
|
|
245
|
+
lastUsedAt: providerAccounts.accounts[accountId].lastUsedAt,
|
|
246
|
+
projectId: providerAccounts.accounts[accountId].projectId,
|
|
247
|
+
};
|
|
248
|
+
});
|
|
200
249
|
}
|
|
201
250
|
exports.registerAccount = registerAccount;
|
|
202
251
|
/**
|
|
203
252
|
* Set default account for a provider
|
|
204
253
|
*/
|
|
205
254
|
function setDefaultAccount(provider, accountId) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
255
|
+
return mutateAccountsRegistry((registry) => {
|
|
256
|
+
const providerAccounts = registry.providers[provider];
|
|
257
|
+
if (!providerAccounts || !providerAccounts.accounts[accountId]) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
providerAccounts.default = accountId;
|
|
261
|
+
return true;
|
|
262
|
+
});
|
|
214
263
|
}
|
|
215
264
|
exports.setDefaultAccount = setDefaultAccount;
|
|
216
265
|
/**
|
|
@@ -218,22 +267,22 @@ exports.setDefaultAccount = setDefaultAccount;
|
|
|
218
267
|
* Moves token file to paused/ subdir so CLIProxyAPI won't discover it
|
|
219
268
|
*/
|
|
220
269
|
function pauseAccount(provider, accountId) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
270
|
+
return mutateAccountsRegistry((registry) => {
|
|
271
|
+
const providerAccounts = registry.providers[provider];
|
|
272
|
+
if (!providerAccounts?.accounts[accountId]) {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
const accountMeta = providerAccounts.accounts[accountId];
|
|
276
|
+
if (accountMeta.paused) {
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
if (!(0, token_file_ops_1.moveTokenToPaused)(accountMeta.tokenFile)) {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
providerAccounts.accounts[accountId].paused = true;
|
|
283
|
+
providerAccounts.accounts[accountId].pausedAt = new Date().toISOString();
|
|
229
284
|
return true;
|
|
230
|
-
}
|
|
231
|
-
// Move token file to paused directory (if it exists in auth dir)
|
|
232
|
-
(0, token_file_ops_1.moveTokenToPaused)(accountMeta.tokenFile);
|
|
233
|
-
providerAccounts.accounts[accountId].paused = true;
|
|
234
|
-
providerAccounts.accounts[accountId].pausedAt = new Date().toISOString();
|
|
235
|
-
saveAccountsRegistry(registry);
|
|
236
|
-
return true;
|
|
285
|
+
});
|
|
237
286
|
}
|
|
238
287
|
exports.pauseAccount = pauseAccount;
|
|
239
288
|
/**
|
|
@@ -241,45 +290,44 @@ exports.pauseAccount = pauseAccount;
|
|
|
241
290
|
* Moves token file back from paused/ to auth/ so CLIProxyAPI can discover it
|
|
242
291
|
*/
|
|
243
292
|
function resumeAccount(provider, accountId) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
293
|
+
return mutateAccountsRegistry((registry) => {
|
|
294
|
+
const providerAccounts = registry.providers[provider];
|
|
295
|
+
if (!providerAccounts?.accounts[accountId]) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
const accountMeta = providerAccounts.accounts[accountId];
|
|
299
|
+
if (!accountMeta.paused) {
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
if (!(0, token_file_ops_1.moveTokenFromPaused)(accountMeta.tokenFile)) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
providerAccounts.accounts[accountId].paused = false;
|
|
306
|
+
providerAccounts.accounts[accountId].pausedAt = undefined;
|
|
252
307
|
return true;
|
|
253
|
-
}
|
|
254
|
-
// Move token file back from paused directory (if it exists in paused dir)
|
|
255
|
-
(0, token_file_ops_1.moveTokenFromPaused)(accountMeta.tokenFile);
|
|
256
|
-
providerAccounts.accounts[accountId].paused = false;
|
|
257
|
-
providerAccounts.accounts[accountId].pausedAt = undefined;
|
|
258
|
-
saveAccountsRegistry(registry);
|
|
259
|
-
return true;
|
|
308
|
+
});
|
|
260
309
|
}
|
|
261
310
|
exports.resumeAccount = resumeAccount;
|
|
262
311
|
/**
|
|
263
312
|
* Remove an account
|
|
264
313
|
*/
|
|
265
314
|
function removeAccount(provider, accountId) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
return true;
|
|
315
|
+
return mutateAccountsRegistry((registry) => {
|
|
316
|
+
const providerAccounts = registry.providers[provider];
|
|
317
|
+
if (!providerAccounts || !providerAccounts.accounts[accountId]) {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
const tokenFile = providerAccounts.accounts[accountId].tokenFile;
|
|
321
|
+
if (!(0, token_file_ops_1.deleteTokenFile)(tokenFile)) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
delete providerAccounts.accounts[accountId];
|
|
325
|
+
const remainingAccounts = Object.keys(providerAccounts.accounts);
|
|
326
|
+
if (providerAccounts.default === accountId && remainingAccounts.length > 0) {
|
|
327
|
+
providerAccounts.default = remainingAccounts[0];
|
|
328
|
+
}
|
|
329
|
+
return true;
|
|
330
|
+
});
|
|
283
331
|
}
|
|
284
332
|
exports.removeAccount = removeAccount;
|
|
285
333
|
/**
|
|
@@ -290,46 +338,47 @@ function renameAccount(provider, accountId, newNickname) {
|
|
|
290
338
|
if (validationError) {
|
|
291
339
|
throw new Error(validationError);
|
|
292
340
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
341
|
+
return mutateAccountsRegistry((registry) => {
|
|
342
|
+
const providerAccounts = registry.providers[provider];
|
|
343
|
+
if (!providerAccounts?.accounts[accountId]) {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
const existingAccounts = Object.entries(providerAccounts.accounts).map(([id, account]) => ({
|
|
347
|
+
id,
|
|
348
|
+
nickname: account.nickname,
|
|
349
|
+
}));
|
|
350
|
+
if ((0, token_file_ops_1.hasAccountNameConflict)(existingAccounts, newNickname, accountId)) {
|
|
301
351
|
throw new Error(`Nickname "${newNickname}" is already used by another account`);
|
|
302
352
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
return true;
|
|
353
|
+
providerAccounts.accounts[accountId].nickname = newNickname;
|
|
354
|
+
return true;
|
|
355
|
+
});
|
|
307
356
|
}
|
|
308
357
|
exports.renameAccount = renameAccount;
|
|
309
358
|
/**
|
|
310
359
|
* Update last used timestamp for an account
|
|
311
360
|
*/
|
|
312
361
|
function touchAccount(provider, accountId) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
362
|
+
mutateAccountsRegistry((registry) => {
|
|
363
|
+
const providerAccounts = registry.providers[provider];
|
|
364
|
+
if (providerAccounts?.accounts[accountId]) {
|
|
365
|
+
providerAccounts.accounts[accountId].lastUsedAt = new Date().toISOString();
|
|
366
|
+
}
|
|
367
|
+
});
|
|
319
368
|
}
|
|
320
369
|
exports.touchAccount = touchAccount;
|
|
321
370
|
/**
|
|
322
371
|
* Update account tier
|
|
323
372
|
*/
|
|
324
373
|
function setAccountTier(provider, accountId, tier) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
374
|
+
return mutateAccountsRegistry((registry) => {
|
|
375
|
+
const providerAccounts = registry.providers[provider];
|
|
376
|
+
if (!providerAccounts?.accounts[accountId]) {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
providerAccounts.accounts[accountId].tier = tier;
|
|
380
|
+
return true;
|
|
381
|
+
});
|
|
333
382
|
}
|
|
334
383
|
exports.setAccountTier = setAccountTier;
|
|
335
384
|
/**
|
|
@@ -345,166 +394,89 @@ function discoverExistingAccounts() {
|
|
|
345
394
|
if (!fs.existsSync(authDir)) {
|
|
346
395
|
return;
|
|
347
396
|
}
|
|
348
|
-
const registry = loadAccountsRegistry();
|
|
349
397
|
const files = fs.readdirSync(authDir);
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
continue;
|
|
355
|
-
const filePath = path.join(authDir, file);
|
|
356
|
-
try {
|
|
357
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
358
|
-
const data = JSON.parse(content);
|
|
359
|
-
// Skip if no type field
|
|
360
|
-
if (!data.type)
|
|
398
|
+
mutateAccountsRegistry((registry) => {
|
|
399
|
+
syncRegistryWithTokenFiles(registry);
|
|
400
|
+
for (const file of files) {
|
|
401
|
+
if (!file.endsWith('.json'))
|
|
361
402
|
continue;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
403
|
+
const filePath = path.join(authDir, file);
|
|
404
|
+
try {
|
|
405
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
406
|
+
const data = JSON.parse(content);
|
|
407
|
+
if (!data.type)
|
|
408
|
+
continue;
|
|
409
|
+
const typeValue = data.type.toLowerCase();
|
|
410
|
+
let provider;
|
|
411
|
+
for (const [prov, typeValues] of Object.entries(auth_types_1.PROVIDER_TYPE_VALUES)) {
|
|
412
|
+
if (typeValues.includes(typeValue)) {
|
|
413
|
+
provider = prov;
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
370
416
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (!provider) {
|
|
374
|
-
continue;
|
|
375
|
-
}
|
|
376
|
-
// Extract email if available, fallback to filename-based ID
|
|
377
|
-
let email = data.email || undefined;
|
|
378
|
-
// Fallback: extract email from filename (e.g., "kiro-google-user@example.com.json")
|
|
379
|
-
if (!email && file.includes('@')) {
|
|
380
|
-
const match = file.match(/([^-]+@[^.]+\.[^.]+)(?=\.json$)/);
|
|
381
|
-
if (match) {
|
|
382
|
-
email = match[1];
|
|
417
|
+
if (!provider) {
|
|
418
|
+
continue;
|
|
383
419
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
accounts: {},
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
const providerAccounts = registry.providers[provider];
|
|
393
|
-
if (!providerAccounts)
|
|
394
|
-
continue;
|
|
395
|
-
// Skip if token file already registered (under any accountId)
|
|
396
|
-
const existingTokenFiles = Object.values(providerAccounts.accounts).map((a) => a.tokenFile);
|
|
397
|
-
if (existingTokenFiles.includes(file)) {
|
|
398
|
-
// Token file exists - check if we need to update projectId for agy accounts
|
|
399
|
-
const projectIdValue = typeof data.project_id === 'string' && data.project_id.trim()
|
|
400
|
-
? data.project_id.trim()
|
|
401
|
-
: null;
|
|
402
|
-
if (provider === 'agy' && projectIdValue) {
|
|
403
|
-
const existingEntry = Object.entries(providerAccounts.accounts).find(([, meta]) => meta.tokenFile === file);
|
|
404
|
-
// Update if missing or changed
|
|
405
|
-
if (existingEntry && existingEntry[1].projectId !== projectIdValue) {
|
|
406
|
-
existingEntry[1].projectId = projectIdValue;
|
|
407
|
-
discoveredCount++; // Count projectId updates as changes
|
|
420
|
+
let email = data.email || undefined;
|
|
421
|
+
if (!email && file.includes('@')) {
|
|
422
|
+
const match = file.match(/([^-]+@[^.]+\.[^.]+)(?=\.json$)/);
|
|
423
|
+
if (match) {
|
|
424
|
+
email = match[1];
|
|
408
425
|
}
|
|
409
426
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
// For kiro/ghcp without email: extract from filename or generate unique
|
|
416
|
-
// Pattern: kiro-github-ABC123.json -> github-ABC123
|
|
417
|
-
const filenameId = (0, token_file_ops_1.extractAccountIdFromTokenFile)(file, undefined);
|
|
418
|
-
if (filenameId !== 'default') {
|
|
419
|
-
accountId = filenameId;
|
|
427
|
+
if (!registry.providers[provider]) {
|
|
428
|
+
registry.providers[provider] = {
|
|
429
|
+
default: 'default',
|
|
430
|
+
accounts: {},
|
|
431
|
+
};
|
|
420
432
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
433
|
+
const providerAccounts = registry.providers[provider];
|
|
434
|
+
if (!providerAccounts)
|
|
435
|
+
continue;
|
|
436
|
+
const existingTokenFiles = Object.values(providerAccounts.accounts).map((a) => a.tokenFile);
|
|
437
|
+
if (existingTokenFiles.includes(file)) {
|
|
438
|
+
const projectIdValue = typeof data.project_id === 'string' && data.project_id.trim()
|
|
439
|
+
? data.project_id.trim()
|
|
440
|
+
: null;
|
|
441
|
+
if (provider === 'agy' && projectIdValue) {
|
|
442
|
+
const existingEntry = Object.entries(providerAccounts.accounts).find(([, meta]) => meta.tokenFile === file);
|
|
443
|
+
if (existingEntry && existingEntry[1].projectId !== projectIdValue) {
|
|
444
|
+
existingEntry[1].projectId = projectIdValue;
|
|
445
|
+
}
|
|
426
446
|
}
|
|
427
|
-
|
|
447
|
+
continue;
|
|
428
448
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
// Skip if account already registered
|
|
435
|
-
if (providerAccounts.accounts[accountId]) {
|
|
436
|
-
continue;
|
|
437
|
-
}
|
|
438
|
-
// Set as default if first account
|
|
439
|
-
if (Object.keys(providerAccounts.accounts).length === 0) {
|
|
440
|
-
providerAccounts.default = accountId;
|
|
441
|
-
}
|
|
442
|
-
// Get file stats for creation time
|
|
443
|
-
const stats = fs.statSync(filePath);
|
|
444
|
-
// Register account with auto-generated nickname
|
|
445
|
-
// Use mtime as lastUsedAt (when token was last modified = last auth/refresh)
|
|
446
|
-
const lastModified = stats.mtime || stats.birthtime || new Date();
|
|
447
|
-
const accountMeta = {
|
|
448
|
-
email,
|
|
449
|
-
nickname: (0, token_file_ops_1.generateNickname)(email),
|
|
450
|
-
tokenFile: file,
|
|
451
|
-
createdAt: stats.birthtime?.toISOString() || new Date().toISOString(),
|
|
452
|
-
lastUsedAt: lastModified.toISOString(),
|
|
453
|
-
};
|
|
454
|
-
// Read project_id for Antigravity accounts (read-only field from auth token)
|
|
455
|
-
const discoveredProjectId = typeof data.project_id === 'string' && data.project_id.trim()
|
|
456
|
-
? data.project_id.trim()
|
|
457
|
-
: null;
|
|
458
|
-
if (provider === 'agy' && discoveredProjectId) {
|
|
459
|
-
accountMeta.projectId = discoveredProjectId;
|
|
460
|
-
}
|
|
461
|
-
providerAccounts.accounts[accountId] = accountMeta;
|
|
462
|
-
discoveredCount++;
|
|
463
|
-
}
|
|
464
|
-
catch {
|
|
465
|
-
// Skip invalid files
|
|
466
|
-
continue;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
// Only save if at least one account was discovered or updated
|
|
470
|
-
// This prevents creating accounts.json with empty provider sections
|
|
471
|
-
if (discoveredCount === 0) {
|
|
472
|
-
return;
|
|
473
|
-
}
|
|
474
|
-
// Reload-merge pattern: reduce race condition with concurrent OAuth registration
|
|
475
|
-
// Reload fresh registry and merge discovered accounts (fresh registry wins on conflicts)
|
|
476
|
-
const freshRegistry = loadAccountsRegistry();
|
|
477
|
-
for (const [providerName, discovered] of Object.entries(registry.providers)) {
|
|
478
|
-
if (!discovered)
|
|
479
|
-
continue;
|
|
480
|
-
// Skip empty provider sections (no accounts discovered)
|
|
481
|
-
if (Object.keys(discovered.accounts).length === 0)
|
|
482
|
-
continue;
|
|
483
|
-
const prov = providerName;
|
|
484
|
-
if (!freshRegistry.providers[prov]) {
|
|
485
|
-
freshRegistry.providers[prov] = discovered;
|
|
486
|
-
}
|
|
487
|
-
else {
|
|
488
|
-
// Merge accounts, preferring fresh registry's existing entries but updating projectId
|
|
489
|
-
const freshProviderAccounts = freshRegistry.providers[prov];
|
|
490
|
-
if (!freshProviderAccounts)
|
|
491
|
-
continue;
|
|
492
|
-
for (const [id, meta] of Object.entries(discovered.accounts)) {
|
|
493
|
-
if (!freshProviderAccounts.accounts[id]) {
|
|
494
|
-
freshProviderAccounts.accounts[id] = meta;
|
|
495
|
-
// Set default if none exists
|
|
496
|
-
if (!freshProviderAccounts.default || freshProviderAccounts.default === 'default') {
|
|
497
|
-
freshProviderAccounts.default = id;
|
|
498
|
-
}
|
|
449
|
+
const accountId = types_1.PROVIDERS_WITHOUT_EMAIL.includes(provider) && !email
|
|
450
|
+
? (0, token_file_ops_1.deriveNoEmailProviderAccountId)(provider, file, providerAccounts.accounts)
|
|
451
|
+
: (0, token_file_ops_1.extractAccountIdFromTokenFile)(file, email);
|
|
452
|
+
if (providerAccounts.accounts[accountId]) {
|
|
453
|
+
continue;
|
|
499
454
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
freshProviderAccounts.accounts[id].projectId = meta.projectId;
|
|
455
|
+
if (Object.keys(providerAccounts.accounts).length === 0) {
|
|
456
|
+
providerAccounts.default = accountId;
|
|
503
457
|
}
|
|
458
|
+
const stats = fs.statSync(filePath);
|
|
459
|
+
const lastModified = stats.mtime || stats.birthtime || new Date();
|
|
460
|
+
const accountMeta = {
|
|
461
|
+
email,
|
|
462
|
+
nickname: email ? (0, token_file_ops_1.generateNickname)(email) : accountId,
|
|
463
|
+
tokenFile: file,
|
|
464
|
+
createdAt: stats.birthtime?.toISOString() || new Date().toISOString(),
|
|
465
|
+
lastUsedAt: lastModified.toISOString(),
|
|
466
|
+
};
|
|
467
|
+
const discoveredProjectId = typeof data.project_id === 'string' && data.project_id.trim()
|
|
468
|
+
? data.project_id.trim()
|
|
469
|
+
: null;
|
|
470
|
+
if (provider === 'agy' && discoveredProjectId) {
|
|
471
|
+
accountMeta.projectId = discoveredProjectId;
|
|
472
|
+
}
|
|
473
|
+
providerAccounts.accounts[accountId] = accountMeta;
|
|
474
|
+
}
|
|
475
|
+
catch {
|
|
476
|
+
continue;
|
|
504
477
|
}
|
|
505
478
|
}
|
|
506
|
-
}
|
|
507
|
-
saveAccountsRegistry(freshRegistry);
|
|
479
|
+
});
|
|
508
480
|
}
|
|
509
481
|
exports.discoverExistingAccounts = discoverExistingAccounts;
|
|
510
482
|
//# sourceMappingURL=registry.js.map
|