@afffun/codexbot 1.0.94 → 1.0.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/entrypoint.mjs +1 -0
- package/src/install_seed_service.mjs +50 -5
package/package.json
CHANGED
package/src/entrypoint.mjs
CHANGED
|
@@ -36,6 +36,7 @@ function renderUsage() {
|
|
|
36
36
|
' --openai-api-key <key>',
|
|
37
37
|
' --license-key <key>',
|
|
38
38
|
' install will auto-claim and activate when a license key is provided.',
|
|
39
|
+
' on an existing install, current connector/API key/license settings are preserved unless explicit replacement flags are provided.',
|
|
39
40
|
' --license-file </path/to/license.json>',
|
|
40
41
|
' --license-public-key-file </path/to/license-public.pem>',
|
|
41
42
|
' --license-server-public-key-file </path/to/license-server-public.pem>',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
|
+
import fsSync from 'node:fs';
|
|
2
3
|
import os from 'node:os';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import {
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
promptUntilValid,
|
|
10
11
|
trim,
|
|
11
12
|
} from './input_contract_service.mjs';
|
|
13
|
+
import { resolveInstalledControlLayout } from './installed_layout_service.mjs';
|
|
12
14
|
|
|
13
15
|
async function promptForConnectorChoice(prompter, logger) {
|
|
14
16
|
return promptUntilValid(prompter, {
|
|
@@ -218,12 +220,32 @@ function renderEnvFile(values = {}) {
|
|
|
218
220
|
|
|
219
221
|
export function createNpmDistributionInstallSeedService(deps = {}) {
|
|
220
222
|
const fsPromises = deps.fsPromises || fs;
|
|
223
|
+
const fsSyncModule = deps.fsSyncModule || fsSync;
|
|
221
224
|
const osModule = deps.osModule || os;
|
|
222
225
|
const pathModule = deps.pathModule || path;
|
|
223
226
|
const processImpl = deps.processImpl || process;
|
|
224
227
|
const logger = deps.logger || console;
|
|
225
228
|
const nowIso = deps.nowIso || (() => new Date().toISOString());
|
|
226
229
|
const promptFactory = deps.promptFactory || createPrompter;
|
|
230
|
+
const resolveInstalledLayout = deps.resolveInstalledLayout || resolveInstalledControlLayout;
|
|
231
|
+
|
|
232
|
+
function detectExistingInstall() {
|
|
233
|
+
try {
|
|
234
|
+
const layout = resolveInstalledLayout({
|
|
235
|
+
fsSync: fsSyncModule,
|
|
236
|
+
pathModule,
|
|
237
|
+
env: processImpl.env,
|
|
238
|
+
});
|
|
239
|
+
const hasControlEnv = Boolean(layout.controlEnvFile) && fsSyncModule.existsSync(layout.controlEnvFile);
|
|
240
|
+
const hasAppDir = Boolean(layout.appDir) && fsSyncModule.existsSync(layout.appDir);
|
|
241
|
+
if (!hasControlEnv && !hasAppDir) {
|
|
242
|
+
return { installed: false, layout };
|
|
243
|
+
}
|
|
244
|
+
return { installed: true, layout };
|
|
245
|
+
} catch {
|
|
246
|
+
return { installed: false, layout: null };
|
|
247
|
+
}
|
|
248
|
+
}
|
|
227
249
|
|
|
228
250
|
async function prepareInstallSeed(options = {}) {
|
|
229
251
|
const explicitSeedFiles = Boolean(
|
|
@@ -243,6 +265,8 @@ export function createNpmDistributionInstallSeedService(deps = {}) {
|
|
|
243
265
|
};
|
|
244
266
|
|
|
245
267
|
try {
|
|
268
|
+
const installState = detectExistingInstall();
|
|
269
|
+
const existingInstall = Boolean(installState.installed);
|
|
246
270
|
const result = {
|
|
247
271
|
seedEnvFile: trim(options.seedEnvFile),
|
|
248
272
|
seedConnectorsStateFile: trim(options.seedConnectorsStateFile),
|
|
@@ -257,6 +281,7 @@ export function createNpmDistributionInstallSeedService(deps = {}) {
|
|
|
257
281
|
connectorSeeded: false,
|
|
258
282
|
openAiSeeded: false,
|
|
259
283
|
licenseDeferred: false,
|
|
284
|
+
existingInstall,
|
|
260
285
|
},
|
|
261
286
|
cleanup,
|
|
262
287
|
};
|
|
@@ -290,13 +315,22 @@ export function createNpmDistributionInstallSeedService(deps = {}) {
|
|
|
290
315
|
if (!connector && hasExplicitConnectorArgs) {
|
|
291
316
|
connector = trim(options.wecomBotId || options.wecomSecret || options.wecomTencentDocsApiKey) ? 'wecom' : 'telegram';
|
|
292
317
|
}
|
|
293
|
-
|
|
318
|
+
const preserveExistingConnector = existingInstall && !hasExplicitConnectorArgs;
|
|
319
|
+
if (preserveExistingConnector) {
|
|
320
|
+
logger.log('==> Existing install detected; keeping current connector settings');
|
|
321
|
+
} else if (!connector && !nonInteractive) {
|
|
294
322
|
logger.log('==> Remote control channel setup');
|
|
295
323
|
connector = await promptForConnectorChoice(prompter, logger);
|
|
296
324
|
}
|
|
297
325
|
if (!connector) connector = 'skip';
|
|
298
326
|
|
|
299
|
-
const
|
|
327
|
+
const preserveExistingOpenAi = existingInstall && !trim(options.openAiApiKey);
|
|
328
|
+
if (preserveExistingOpenAi) {
|
|
329
|
+
logger.log('==> Existing install detected; keeping current OpenAI API key setting');
|
|
330
|
+
}
|
|
331
|
+
const openAiApiKey = preserveExistingOpenAi
|
|
332
|
+
? ''
|
|
333
|
+
: trim(options.openAiApiKey || (!nonInteractive ? await prompter.ask('OPENAI_API_KEY (optional, blank to skip): ') : ''));
|
|
300
334
|
if (openAiApiKey) {
|
|
301
335
|
const envFile = pathModule.join(tempDir, 'seed.env');
|
|
302
336
|
await fsPromises.writeFile(envFile, renderEnvFile({ OPENAI_API_KEY: openAiApiKey }), 'utf8');
|
|
@@ -304,7 +338,9 @@ export function createNpmDistributionInstallSeedService(deps = {}) {
|
|
|
304
338
|
result.summary.openAiSeeded = true;
|
|
305
339
|
}
|
|
306
340
|
|
|
307
|
-
if (
|
|
341
|
+
if (preserveExistingConnector) {
|
|
342
|
+
result.summary.connector = 'preserve';
|
|
343
|
+
} else if (connector === 'telegram') {
|
|
308
344
|
const telegramBotToken = trim(options.telegramBotToken || (
|
|
309
345
|
!nonInteractive
|
|
310
346
|
? await promptUntilValid(prompter, {
|
|
@@ -388,13 +424,22 @@ export function createNpmDistributionInstallSeedService(deps = {}) {
|
|
|
388
424
|
let licenseFile = trim(options.licenseFile);
|
|
389
425
|
let licensePublicKeyFile = trim(options.licensePublicKeyFile);
|
|
390
426
|
let licenseServerPublicKeyFile = trim(options.licenseServerPublicKeyFile);
|
|
427
|
+
const hasExplicitLicenseInputs = Boolean(
|
|
428
|
+
licenseKey
|
|
429
|
+
|| licenseFile
|
|
430
|
+
|| licensePublicKeyFile
|
|
431
|
+
|| licenseServerPublicKeyFile,
|
|
432
|
+
);
|
|
391
433
|
if (licenseKey && (licenseFile || licensePublicKeyFile || licenseServerPublicKeyFile)) {
|
|
392
434
|
throw new Error('license key cannot be combined with direct license file inputs');
|
|
393
435
|
}
|
|
394
|
-
|
|
436
|
+
const preserveExistingLicense = existingInstall && !hasExplicitLicenseInputs;
|
|
437
|
+
if (preserveExistingLicense) {
|
|
438
|
+
logger.log('==> Existing install detected; keeping current license state');
|
|
439
|
+
} else if (!licenseKey && !licenseFile && !licensePublicKeyFile && !licenseServerPublicKeyFile && !nonInteractive) {
|
|
395
440
|
licenseKey = trim(await prompter.ask('License key (optional, blank to skip and activate later): '));
|
|
396
441
|
}
|
|
397
|
-
if (!licenseKey && !licenseFile && !licensePublicKeyFile && !licenseServerPublicKeyFile) {
|
|
442
|
+
if (!preserveExistingLicense && !licenseKey && !licenseFile && !licensePublicKeyFile && !licenseServerPublicKeyFile) {
|
|
398
443
|
result.deferLicenseActivation = true;
|
|
399
444
|
}
|
|
400
445
|
|