laysoai 0.1.1 → 0.1.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 +14 -0
- package/dist/index.js +375 -53
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -39,6 +39,14 @@ Non-interactive setup:
|
|
|
39
39
|
laysoai init --key sk-layso-xxx --targets claude,codex,gemini --yes
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
Optional Codex default model:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
laysoai init --key sk-layso-xxx --targets codex --codex-model your-model-name
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If `--codex-model` is omitted, `laysoai` does not write `model` and Codex keeps its own default model behavior.
|
|
49
|
+
|
|
42
50
|
Supported targets:
|
|
43
51
|
|
|
44
52
|
```text
|
|
@@ -140,6 +148,12 @@ wire_api = "responses"
|
|
|
140
148
|
experimental_bearer_token = "your-key"
|
|
141
149
|
```
|
|
142
150
|
|
|
151
|
+
By default, `laysoai` does not write Codex `model`. If a model is provided with `--codex-model`, it writes:
|
|
152
|
+
|
|
153
|
+
```toml
|
|
154
|
+
model = "your-model-name"
|
|
155
|
+
```
|
|
156
|
+
|
|
143
157
|
### Gemini CLI
|
|
144
158
|
|
|
145
159
|
Writes:
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { checkbox, confirm, password } from "@inquirer/prompts";
|
|
4
|
+
import { checkbox, confirm, input as textInput, password, select } from "@inquirer/prompts";
|
|
5
5
|
import chalk2 from "chalk";
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
import ora from "ora";
|
|
8
8
|
|
|
9
9
|
// src/constants.ts
|
|
10
10
|
var PACKAGE_NAME = "laysoai";
|
|
11
|
-
var PACKAGE_VERSION = "0.1.
|
|
11
|
+
var PACKAGE_VERSION = "0.1.3";
|
|
12
12
|
var LAYSOAI_BASE_URL = "https://laysoai.com";
|
|
13
13
|
var LAYSOAI_HOME_DIR = ".laysoai";
|
|
14
14
|
var TARGETS = ["claude", "codex", "gemini"];
|
|
@@ -319,6 +319,25 @@ var codexAdapter = {
|
|
|
319
319
|
"model_providers.laysoai.wire_api": "responses",
|
|
320
320
|
"model_providers.laysoai.experimental_bearer_token": input.apiKey
|
|
321
321
|
};
|
|
322
|
+
const changes = [
|
|
323
|
+
{ key: "model_provider", action: config.model_provider === desired.model_provider ? "skip" : "update" },
|
|
324
|
+
{ key: "model_providers.laysoai.name", action: laysoai.name === desired["model_providers.laysoai.name"] ? "skip" : keyAction(laysoai, "name") },
|
|
325
|
+
{ key: "model_providers.laysoai.base_url", action: laysoai.base_url === desired["model_providers.laysoai.base_url"] ? "skip" : keyAction(laysoai, "base_url") },
|
|
326
|
+
{ key: "model_providers.laysoai.wire_api", action: laysoai.wire_api === desired["model_providers.laysoai.wire_api"] ? "skip" : keyAction(laysoai, "wire_api") },
|
|
327
|
+
{
|
|
328
|
+
key: "model_providers.laysoai.experimental_bearer_token",
|
|
329
|
+
action: laysoai.experimental_bearer_token === input.apiKey ? "skip" : keyAction(laysoai, "experimental_bearer_token")
|
|
330
|
+
}
|
|
331
|
+
];
|
|
332
|
+
if (input.codexModel) {
|
|
333
|
+
changes.push({ key: "model", action: config.model === input.codexModel ? "skip" : keyAction(config, "model") });
|
|
334
|
+
}
|
|
335
|
+
if (isInvalidServiceTier(config.service_tier)) {
|
|
336
|
+
changes.push({ key: "service_tier", action: "update" });
|
|
337
|
+
}
|
|
338
|
+
if (isInvalidServiceTier(laysoai.service_tier)) {
|
|
339
|
+
changes.push({ key: "model_providers.laysoai.service_tier", action: "update" });
|
|
340
|
+
}
|
|
322
341
|
return {
|
|
323
342
|
target: this.id,
|
|
324
343
|
name: this.name,
|
|
@@ -326,16 +345,7 @@ var codexAdapter = {
|
|
|
326
345
|
backupPath: null,
|
|
327
346
|
beforeSummary: before.summary,
|
|
328
347
|
afterSummary: "\u5199\u5165 Codex LaysoAI provider \u5E76\u8BBE\u4E3A\u9ED8\u8BA4 provider",
|
|
329
|
-
changes
|
|
330
|
-
{ key: "model_provider", action: config.model_provider === desired.model_provider ? "skip" : "update" },
|
|
331
|
-
{ key: "model_providers.laysoai.name", action: laysoai.name === desired["model_providers.laysoai.name"] ? "skip" : keyAction(laysoai, "name") },
|
|
332
|
-
{ key: "model_providers.laysoai.base_url", action: laysoai.base_url === desired["model_providers.laysoai.base_url"] ? "skip" : keyAction(laysoai, "base_url") },
|
|
333
|
-
{ key: "model_providers.laysoai.wire_api", action: laysoai.wire_api === desired["model_providers.laysoai.wire_api"] ? "skip" : keyAction(laysoai, "wire_api") },
|
|
334
|
-
{
|
|
335
|
-
key: "model_providers.laysoai.experimental_bearer_token",
|
|
336
|
-
action: laysoai.experimental_bearer_token === input.apiKey ? "skip" : keyAction(laysoai, "experimental_bearer_token")
|
|
337
|
-
}
|
|
338
|
-
]
|
|
348
|
+
changes
|
|
339
349
|
};
|
|
340
350
|
},
|
|
341
351
|
async apply(input) {
|
|
@@ -345,16 +355,22 @@ var codexAdapter = {
|
|
|
345
355
|
try {
|
|
346
356
|
const config = await readToml(configPath);
|
|
347
357
|
const providers = asRecord2(config.model_providers);
|
|
358
|
+
const laysoaiProvider = {
|
|
359
|
+
...asRecord2(providers.laysoai),
|
|
360
|
+
name: "LaysoAI",
|
|
361
|
+
base_url: LAYSOAI_BASE_URL,
|
|
362
|
+
wire_api: "responses",
|
|
363
|
+
experimental_bearer_token: input.apiKey
|
|
364
|
+
};
|
|
365
|
+
removeInvalidServiceTier(config);
|
|
366
|
+
removeInvalidServiceTier(laysoaiProvider);
|
|
348
367
|
config.model_provider = "laysoai";
|
|
368
|
+
if (input.codexModel) {
|
|
369
|
+
config.model = input.codexModel;
|
|
370
|
+
}
|
|
349
371
|
config.model_providers = {
|
|
350
372
|
...providers,
|
|
351
|
-
laysoai:
|
|
352
|
-
...asRecord2(providers.laysoai),
|
|
353
|
-
name: "LaysoAI",
|
|
354
|
-
base_url: LAYSOAI_BASE_URL,
|
|
355
|
-
wire_api: "responses",
|
|
356
|
-
experimental_bearer_token: input.apiKey
|
|
357
|
-
}
|
|
373
|
+
laysoai: laysoaiProvider
|
|
358
374
|
};
|
|
359
375
|
await writeText(configPath, TOML.stringify(config));
|
|
360
376
|
} catch (error) {
|
|
@@ -398,6 +414,14 @@ function asRecord2(value) {
|
|
|
398
414
|
function keyAction(record, key) {
|
|
399
415
|
return key in record ? "update" : "add";
|
|
400
416
|
}
|
|
417
|
+
function isInvalidServiceTier(value) {
|
|
418
|
+
return typeof value === "string" && value !== "fast" && value !== "flex";
|
|
419
|
+
}
|
|
420
|
+
function removeInvalidServiceTier(record) {
|
|
421
|
+
if (isInvalidServiceTier(record.service_tier)) {
|
|
422
|
+
delete record.service_tier;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
401
425
|
|
|
402
426
|
// src/core/env-file.ts
|
|
403
427
|
function upsertEnvValues(content, values) {
|
|
@@ -615,7 +639,7 @@ function normalizeVersion(version) {
|
|
|
615
639
|
async function runCli(argv = process.argv) {
|
|
616
640
|
const program = new Command();
|
|
617
641
|
program.name(PACKAGE_NAME).description("Configure Claude Code, Codex, and Gemini to use LaysoAI.").version(PACKAGE_VERSION);
|
|
618
|
-
program.command("init", { isDefault: true }).description("Configure selected AI CLI tools with your LaysoAI key.").option("-k, --key <key>", "LaysoAI API key").option("-t, --targets <targets>", "Target CLIs: claude,codex,gemini,all").option("-y, --yes", "Skip confirmation").option("--dry-run", "Show changes without writing files").option("--force", "Write config even if the selected CLI command is not installed").action(async (options) => {
|
|
642
|
+
program.command("init", { isDefault: true }).description("Configure selected AI CLI tools with your LaysoAI key.").option("-k, --key <key>", "LaysoAI API key").option("-t, --targets <targets>", "Target CLIs: claude,codex,gemini,all").option("-y, --yes", "Skip confirmation").option("--dry-run", "Show changes without writing files").option("--force", "Write config even if the selected CLI command is not installed").option("--language <language>", "Language: zh-CN,en,fr,ru,ja,vi").option("--codex-model <model>", "Optional default model for Codex CLI. Omit to keep Codex default behavior.").action(async (options) => {
|
|
619
643
|
await initCommand(options);
|
|
620
644
|
});
|
|
621
645
|
program.command("config").description("Show detected LaysoAI CLI configuration.").action(async () => {
|
|
@@ -643,76 +667,86 @@ async function notifyIfUpdateAvailable() {
|
|
|
643
667
|
logger.warn(`\u53D1\u73B0\u65B0\u7248 ${PACKAGE_NAME}@${latestVersion}\uFF0C\u5F53\u524D\u7248\u672C ${PACKAGE_VERSION}\u3002\u5EFA\u8BAE\u8FD0\u884C: npm install -g ${PACKAGE_NAME}@latest`);
|
|
644
668
|
}
|
|
645
669
|
async function initCommand(options) {
|
|
646
|
-
const
|
|
647
|
-
const
|
|
670
|
+
const language = await resolveLanguage(options);
|
|
671
|
+
const messages = MESSAGES[language];
|
|
672
|
+
const targets = options.targets ? parseTargets(options.targets, messages) : await promptTargets(messages);
|
|
673
|
+
const apiKey = options.key?.trim() || await password({ message: messages.apiKeyPrompt, mask: "*" });
|
|
648
674
|
if (!apiKey.trim()) {
|
|
649
|
-
throw new Error(
|
|
675
|
+
throw new Error(messages.emptyApiKey);
|
|
650
676
|
}
|
|
677
|
+
const codexModel = await resolveCodexModel(targets, options, messages);
|
|
651
678
|
const input = {
|
|
652
679
|
apiKey: apiKey.trim(),
|
|
653
680
|
targets,
|
|
654
681
|
yes: Boolean(options.yes),
|
|
655
682
|
dryRun: Boolean(options.dryRun),
|
|
656
|
-
force: Boolean(options.force)
|
|
683
|
+
force: Boolean(options.force),
|
|
684
|
+
codexModel
|
|
657
685
|
};
|
|
658
|
-
logger.info(
|
|
686
|
+
logger.info(`${messages.requestUrl}: ${LAYSOAI_BASE_URL}`);
|
|
659
687
|
logger.info(`LaysoAI Key: ${maskSecret(input.apiKey)}`);
|
|
660
688
|
const selectedAdapters = getAdapters(targets);
|
|
661
|
-
const preflight = await printPreflight(selectedAdapters);
|
|
689
|
+
const preflight = await printPreflight(selectedAdapters, messages);
|
|
662
690
|
const missing = preflight.filter((result) => !result.installed);
|
|
663
691
|
if (missing.length > 0 && !input.force) {
|
|
664
692
|
logger.plain("");
|
|
665
|
-
logger.warn(
|
|
693
|
+
logger.warn(messages.missingCliStop);
|
|
666
694
|
for (const result of missing) {
|
|
667
695
|
logger.plain(`- ${result.name}: ${installCommandFor(result.target)}`);
|
|
668
696
|
}
|
|
669
697
|
logger.plain("");
|
|
670
|
-
logger.plain(
|
|
698
|
+
logger.plain(messages.forceHint);
|
|
671
699
|
return;
|
|
672
700
|
}
|
|
673
701
|
const plans = [];
|
|
674
702
|
for (const adapter of selectedAdapters) {
|
|
675
703
|
plans.push(await adapter.plan(input));
|
|
676
704
|
}
|
|
677
|
-
printPlans(plans);
|
|
705
|
+
printPlans(plans, messages);
|
|
678
706
|
if (input.dryRun) {
|
|
679
|
-
logger.warn(
|
|
707
|
+
logger.warn(messages.dryRun);
|
|
680
708
|
return;
|
|
681
709
|
}
|
|
682
710
|
if (!input.yes) {
|
|
683
711
|
const approved = await confirm({
|
|
684
|
-
message:
|
|
712
|
+
message: messages.confirmWrite,
|
|
685
713
|
default: true
|
|
686
714
|
});
|
|
687
715
|
if (!approved) {
|
|
688
|
-
logger.warn(
|
|
716
|
+
logger.warn(messages.cancelled);
|
|
689
717
|
return;
|
|
690
718
|
}
|
|
691
719
|
}
|
|
692
720
|
for (const adapter of selectedAdapters) {
|
|
693
|
-
const spinner = ora(
|
|
721
|
+
const spinner = ora(`${messages.configuring} ${adapter.name}...`).start();
|
|
694
722
|
try {
|
|
695
723
|
const plan = await adapter.apply(input);
|
|
696
|
-
spinner.succeed(`${adapter.name}
|
|
724
|
+
spinner.succeed(`${adapter.name} ${messages.configComplete}: ${plan.configPath}`);
|
|
697
725
|
if (plan.backupPath) {
|
|
698
726
|
logger.plain(chalk2.dim(` backup: ${plan.backupPath}`));
|
|
699
727
|
}
|
|
700
728
|
} catch (error) {
|
|
701
|
-
spinner.fail(`${adapter.name}
|
|
729
|
+
spinner.fail(`${adapter.name} ${messages.configFailed}`);
|
|
702
730
|
throw error;
|
|
703
731
|
}
|
|
704
732
|
}
|
|
705
|
-
logger.success(
|
|
733
|
+
logger.success(messages.setupComplete);
|
|
706
734
|
logger.plain("");
|
|
707
|
-
logger.plain(
|
|
735
|
+
logger.plain(`${messages.verifyCommands}:`);
|
|
708
736
|
for (const adapter of selectedAdapters) {
|
|
709
737
|
logger.plain(`- ${adapter.name}: ${adapter.verifyHint().join(" / ")}`);
|
|
710
738
|
}
|
|
739
|
+
logger.plain("");
|
|
740
|
+
logger.plain(`${messages.usageIntro}:`);
|
|
741
|
+
for (const adapter of selectedAdapters) {
|
|
742
|
+
logger.plain(`- ${adapter.name}: ${adapter.command}`);
|
|
743
|
+
}
|
|
744
|
+
logger.success(messages.enjoy);
|
|
711
745
|
}
|
|
712
|
-
async function printPreflight(selectedAdapters) {
|
|
746
|
+
async function printPreflight(selectedAdapters, messages) {
|
|
713
747
|
const results = [];
|
|
714
748
|
logger.plain("");
|
|
715
|
-
logger.plain(
|
|
749
|
+
logger.plain(`${messages.envCheck}:`);
|
|
716
750
|
for (const adapter of selectedAdapters) {
|
|
717
751
|
const [detected, current] = await Promise.all([adapter.detect(), adapter.inspect()]);
|
|
718
752
|
results.push({
|
|
@@ -721,10 +755,10 @@ async function printPreflight(selectedAdapters) {
|
|
|
721
755
|
installed: detected.installed
|
|
722
756
|
});
|
|
723
757
|
logger.plain(`- ${adapter.name}`);
|
|
724
|
-
logger.plain(` CLI: ${detected.installed ? chalk2.green(
|
|
725
|
-
logger.plain(`
|
|
726
|
-
logger.plain(`
|
|
727
|
-
logger.plain(` LaysoAI: ${current.configured ? chalk2.green(
|
|
758
|
+
logger.plain(` CLI: ${detected.installed ? chalk2.green(messages.installed) : chalk2.yellow(messages.notFound)} (${detected.command})`);
|
|
759
|
+
logger.plain(` ${messages.configFile}: ${current.exists ? chalk2.green(messages.exists) : chalk2.yellow(messages.notExists)}`);
|
|
760
|
+
logger.plain(` ${messages.path}: ${current.configPath}`);
|
|
761
|
+
logger.plain(` LaysoAI: ${current.configured ? chalk2.green(messages.configured) : chalk2.yellow(messages.notConfigured)}`);
|
|
728
762
|
}
|
|
729
763
|
return results;
|
|
730
764
|
}
|
|
@@ -748,7 +782,7 @@ async function doctorCommand() {
|
|
|
748
782
|
}
|
|
749
783
|
}
|
|
750
784
|
async function resetCommand(options) {
|
|
751
|
-
const targets = options.targets ? parseTargets(options.targets) : await promptTargets();
|
|
785
|
+
const targets = options.targets ? parseTargets(options.targets) : await promptTargets(MESSAGES.en);
|
|
752
786
|
const entries = [];
|
|
753
787
|
for (const target of targets) {
|
|
754
788
|
const entry = await latestEntryFor(target);
|
|
@@ -780,21 +814,21 @@ async function resetCommand(options) {
|
|
|
780
814
|
logger.success(`${adapters[entry.target].name} \u5DF2\u6062\u590D\u3002`);
|
|
781
815
|
}
|
|
782
816
|
}
|
|
783
|
-
function printPlans(plans) {
|
|
817
|
+
function printPlans(plans, messages) {
|
|
784
818
|
logger.plain("");
|
|
785
|
-
logger.plain(
|
|
819
|
+
logger.plain(`${messages.changePlan}:`);
|
|
786
820
|
for (const plan of plans) {
|
|
787
821
|
logger.plain(`- ${plan.name}`);
|
|
788
822
|
logger.plain(` path: ${plan.configPath}`);
|
|
789
|
-
logger.plain(` before: ${plan.beforeSummary}`);
|
|
790
|
-
logger.plain(` after: ${plan.afterSummary}`);
|
|
823
|
+
logger.plain(` ${messages.before}: ${plan.beforeSummary}`);
|
|
824
|
+
logger.plain(` ${messages.after}: ${plan.afterSummary}`);
|
|
791
825
|
for (const change of plan.changes) {
|
|
792
826
|
logger.plain(` ${change.action.padEnd(6)} ${change.key}`);
|
|
793
827
|
}
|
|
794
828
|
}
|
|
795
829
|
logger.plain("");
|
|
796
830
|
}
|
|
797
|
-
function parseTargets(value) {
|
|
831
|
+
function parseTargets(value, messages = MESSAGES.en) {
|
|
798
832
|
const rawTargets = value.split(",").map((target) => target.trim().toLowerCase()).filter(Boolean);
|
|
799
833
|
if (rawTargets.includes("all")) {
|
|
800
834
|
return [...TARGETS];
|
|
@@ -807,17 +841,17 @@ function parseTargets(value) {
|
|
|
807
841
|
});
|
|
808
842
|
const invalid = normalized.filter((target) => !TARGETS.includes(target));
|
|
809
843
|
if (invalid.length > 0) {
|
|
810
|
-
throw new Error(
|
|
844
|
+
throw new Error(`${messages.invalidTargets}: ${invalid.join(", ")}. ${messages.availableTargets}: claude,codex,gemini,all`);
|
|
811
845
|
}
|
|
812
846
|
const unique = Array.from(new Set(normalized));
|
|
813
847
|
if (unique.length === 0) {
|
|
814
|
-
throw new Error(
|
|
848
|
+
throw new Error(messages.chooseAtLeastOneTarget);
|
|
815
849
|
}
|
|
816
850
|
return unique;
|
|
817
851
|
}
|
|
818
|
-
async function promptTargets() {
|
|
852
|
+
async function promptTargets(messages) {
|
|
819
853
|
const selected = await checkbox({
|
|
820
|
-
message:
|
|
854
|
+
message: messages.targetPrompt,
|
|
821
855
|
choices: [
|
|
822
856
|
{ name: "Claude Code", value: "claude" },
|
|
823
857
|
{ name: "Codex CLI", value: "codex" },
|
|
@@ -827,6 +861,33 @@ async function promptTargets() {
|
|
|
827
861
|
});
|
|
828
862
|
return selected;
|
|
829
863
|
}
|
|
864
|
+
async function resolveCodexModel(targets, options, messages) {
|
|
865
|
+
if (!targets.includes("codex")) {
|
|
866
|
+
return void 0;
|
|
867
|
+
}
|
|
868
|
+
const optionModel = normalizeOptionalCodexModel(options.codexModel);
|
|
869
|
+
if (optionModel !== null) {
|
|
870
|
+
return optionModel;
|
|
871
|
+
}
|
|
872
|
+
if (options.yes) {
|
|
873
|
+
return void 0;
|
|
874
|
+
}
|
|
875
|
+
const model = await textInput({
|
|
876
|
+
message: messages.codexModelPrompt,
|
|
877
|
+
default: ""
|
|
878
|
+
});
|
|
879
|
+
return normalizeOptionalCodexModel(model) ?? void 0;
|
|
880
|
+
}
|
|
881
|
+
function normalizeOptionalCodexModel(model) {
|
|
882
|
+
if (model === void 0) {
|
|
883
|
+
return null;
|
|
884
|
+
}
|
|
885
|
+
const trimmed = model.trim();
|
|
886
|
+
if (!trimmed || ["none", "skip", "default"].includes(trimmed.toLowerCase())) {
|
|
887
|
+
return void 0;
|
|
888
|
+
}
|
|
889
|
+
return trimmed;
|
|
890
|
+
}
|
|
830
891
|
function installCommandFor(target) {
|
|
831
892
|
switch (target) {
|
|
832
893
|
case "claude":
|
|
@@ -837,6 +898,267 @@ function installCommandFor(target) {
|
|
|
837
898
|
return "npm install -g @google/gemini-cli";
|
|
838
899
|
}
|
|
839
900
|
}
|
|
901
|
+
var LANGUAGE_CHOICES = [
|
|
902
|
+
{ name: "\u7B80\u4F53\u4E2D\u6587", value: "zh-CN" },
|
|
903
|
+
{ name: "English", value: "en" },
|
|
904
|
+
{ name: "Fran\xE7ais", value: "fr" },
|
|
905
|
+
{ name: "\u0420\u0443\u0441\u0441\u043A\u0438\u0439", value: "ru" },
|
|
906
|
+
{ name: "\u65E5\u672C\u8A9E", value: "ja" },
|
|
907
|
+
{ name: "Ti\u1EBFng Vi\u1EC7t", value: "vi" }
|
|
908
|
+
];
|
|
909
|
+
var MESSAGES = {
|
|
910
|
+
"zh-CN": {
|
|
911
|
+
languagePrompt: "\u8BF7\u9009\u62E9\u8BED\u8A00:",
|
|
912
|
+
targetPrompt: "\u8BF7\u9009\u62E9\u9700\u8981\u914D\u7F6E\u7684\u5DE5\u5177:",
|
|
913
|
+
apiKeyPrompt: "\u8BF7\u8F93\u5165 LaysoAI API Key:",
|
|
914
|
+
codexModelPrompt: "Codex \u9ED8\u8BA4\u6A21\u578B\uFF0C\u53EF\u9009\uFF0C\u56DE\u8F66\u8DF3\u8FC7:",
|
|
915
|
+
emptyApiKey: "LaysoAI API Key \u4E0D\u80FD\u4E3A\u7A7A\u3002",
|
|
916
|
+
requestUrl: "LaysoAI \u8BF7\u6C42\u5730\u5740",
|
|
917
|
+
envCheck: "\u73AF\u5883\u68C0\u67E5",
|
|
918
|
+
installed: "\u5DF2\u5B89\u88C5",
|
|
919
|
+
notFound: "\u672A\u68C0\u6D4B\u5230",
|
|
920
|
+
configFile: "\u914D\u7F6E\u6587\u4EF6",
|
|
921
|
+
exists: "\u5B58\u5728",
|
|
922
|
+
notExists: "\u4E0D\u5B58\u5728",
|
|
923
|
+
path: "\u8DEF\u5F84",
|
|
924
|
+
configured: "\u5DF2\u914D\u7F6E",
|
|
925
|
+
notConfigured: "\u672A\u914D\u7F6E",
|
|
926
|
+
missingCliStop: "\u68C0\u6D4B\u5230\u76EE\u6807 CLI \u672A\u5B89\u88C5\uFF0C\u5DF2\u505C\u6B62\u5199\u5165\u914D\u7F6E\u3002\u8BF7\u5148\u5B89\u88C5\u5BF9\u5E94 CLI \u540E\u518D\u8FD0\u884C laysoai\u3002",
|
|
927
|
+
forceHint: "\u5982\u679C\u4F60\u786E\u8BA4\u8981\u5148\u5199\u914D\u7F6E\uFF0C\u53EF\u4EE5\u8FFD\u52A0 --force\u3002",
|
|
928
|
+
changePlan: "\u5C06\u6267\u884C\u4EE5\u4E0B\u914D\u7F6E\u4FEE\u6539",
|
|
929
|
+
before: "before",
|
|
930
|
+
after: "after",
|
|
931
|
+
dryRun: "dry-run \u6A21\u5F0F\u672A\u5199\u5165\u4EFB\u4F55\u6587\u4EF6\u3002",
|
|
932
|
+
confirmWrite: "\u786E\u8BA4\u76F4\u63A5\u4FEE\u6539\u4EE5\u4E0A\u672C\u673A CLI \u914D\u7F6E\u6587\u4EF6\u5417\uFF1F",
|
|
933
|
+
cancelled: "\u5DF2\u53D6\u6D88\u914D\u7F6E\u3002",
|
|
934
|
+
configuring: "\u6B63\u5728\u914D\u7F6E",
|
|
935
|
+
configComplete: "\u914D\u7F6E\u5B8C\u6210",
|
|
936
|
+
configFailed: "\u914D\u7F6E\u5931\u8D25",
|
|
937
|
+
setupComplete: "LaysoAI \u81EA\u52A8\u914D\u7F6E\u5B8C\u6210\u3002",
|
|
938
|
+
verifyCommands: "\u9A8C\u8BC1\u547D\u4EE4",
|
|
939
|
+
usageIntro: "\u63A5\u4E0B\u6765\u53EF\u4EE5\u8FD9\u6837\u4F7F\u7528",
|
|
940
|
+
enjoy: "\u795D\u4F60\u4F7F\u7528 LaysoAI API \u6109\u5FEB\uFF01",
|
|
941
|
+
invalidTargets: "\u4E0D\u652F\u6301\u7684 targets",
|
|
942
|
+
availableTargets: "\u53EF\u7528\u503C",
|
|
943
|
+
chooseAtLeastOneTarget: "\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A target\u3002"
|
|
944
|
+
},
|
|
945
|
+
en: {
|
|
946
|
+
languagePrompt: "Select language:",
|
|
947
|
+
targetPrompt: "Select tools to configure:",
|
|
948
|
+
apiKeyPrompt: "Enter LaysoAI API Key:",
|
|
949
|
+
codexModelPrompt: "Codex default model, optional. Press Enter to skip:",
|
|
950
|
+
emptyApiKey: "LaysoAI API Key cannot be empty.",
|
|
951
|
+
requestUrl: "LaysoAI request URL",
|
|
952
|
+
envCheck: "Environment check",
|
|
953
|
+
installed: "installed",
|
|
954
|
+
notFound: "not found",
|
|
955
|
+
configFile: "config file",
|
|
956
|
+
exists: "exists",
|
|
957
|
+
notExists: "missing",
|
|
958
|
+
path: "path",
|
|
959
|
+
configured: "configured",
|
|
960
|
+
notConfigured: "not configured",
|
|
961
|
+
missingCliStop: "Selected CLI command is not installed. Config write stopped. Install the CLI first, then run laysoai again.",
|
|
962
|
+
forceHint: "To write config before installing the CLI, add --force.",
|
|
963
|
+
changePlan: "Planned changes",
|
|
964
|
+
before: "before",
|
|
965
|
+
after: "after",
|
|
966
|
+
dryRun: "dry-run mode did not write any files.",
|
|
967
|
+
confirmWrite: "Modify the local CLI config files above?",
|
|
968
|
+
cancelled: "Setup cancelled.",
|
|
969
|
+
configuring: "Configuring",
|
|
970
|
+
configComplete: "configured",
|
|
971
|
+
configFailed: "failed",
|
|
972
|
+
setupComplete: "LaysoAI setup completed.",
|
|
973
|
+
verifyCommands: "Verification commands",
|
|
974
|
+
usageIntro: "Use it next with",
|
|
975
|
+
enjoy: "Enjoy using LaysoAI API!",
|
|
976
|
+
invalidTargets: "Unsupported targets",
|
|
977
|
+
availableTargets: "Available values",
|
|
978
|
+
chooseAtLeastOneTarget: "Select at least one target."
|
|
979
|
+
},
|
|
980
|
+
fr: {
|
|
981
|
+
languagePrompt: "Choisissez la langue:",
|
|
982
|
+
targetPrompt: "Choisissez les outils a configurer:",
|
|
983
|
+
apiKeyPrompt: "Saisissez la cle API LaysoAI:",
|
|
984
|
+
codexModelPrompt: "Modele Codex par defaut, facultatif. Entree pour ignorer:",
|
|
985
|
+
emptyApiKey: "La cle API LaysoAI ne peut pas etre vide.",
|
|
986
|
+
requestUrl: "URL de requete LaysoAI",
|
|
987
|
+
envCheck: "Verification de l environnement",
|
|
988
|
+
installed: "installe",
|
|
989
|
+
notFound: "introuvable",
|
|
990
|
+
configFile: "fichier de configuration",
|
|
991
|
+
exists: "existe",
|
|
992
|
+
notExists: "manquant",
|
|
993
|
+
path: "chemin",
|
|
994
|
+
configured: "configure",
|
|
995
|
+
notConfigured: "non configure",
|
|
996
|
+
missingCliStop: "La CLI selectionnee n est pas installee. L ecriture de configuration est arretee. Installez d abord la CLI.",
|
|
997
|
+
forceHint: "Pour ecrire la configuration avant installation, ajoutez --force.",
|
|
998
|
+
changePlan: "Modifications prevues",
|
|
999
|
+
before: "avant",
|
|
1000
|
+
after: "apres",
|
|
1001
|
+
dryRun: "Le mode dry-run n a ecrit aucun fichier.",
|
|
1002
|
+
confirmWrite: "Modifier les fichiers de configuration CLI locaux ci-dessus ?",
|
|
1003
|
+
cancelled: "Configuration annulee.",
|
|
1004
|
+
configuring: "Configuration de",
|
|
1005
|
+
configComplete: "configure",
|
|
1006
|
+
configFailed: "echec",
|
|
1007
|
+
setupComplete: "Configuration LaysoAI terminee.",
|
|
1008
|
+
verifyCommands: "Commandes de verification",
|
|
1009
|
+
usageIntro: "Utilisez ensuite",
|
|
1010
|
+
enjoy: "Bonne utilisation de LaysoAI API !",
|
|
1011
|
+
invalidTargets: "Targets non pris en charge",
|
|
1012
|
+
availableTargets: "Valeurs disponibles",
|
|
1013
|
+
chooseAtLeastOneTarget: "Selectionnez au moins un target."
|
|
1014
|
+
},
|
|
1015
|
+
ru: {
|
|
1016
|
+
languagePrompt: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u044F\u0437\u044B\u043A:",
|
|
1017
|
+
targetPrompt: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B \u0434\u043B\u044F \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438:",
|
|
1018
|
+
apiKeyPrompt: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 API Key LaysoAI:",
|
|
1019
|
+
codexModelPrompt: "\u041C\u043E\u0434\u0435\u043B\u044C Codex \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E, \u043D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E. Enter \u0447\u0442\u043E\u0431\u044B \u043F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u044C:",
|
|
1020
|
+
emptyApiKey: "API Key LaysoAI \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u044B\u043C.",
|
|
1021
|
+
requestUrl: "URL \u0437\u0430\u043F\u0440\u043E\u0441\u0430 LaysoAI",
|
|
1022
|
+
envCheck: "\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u044F",
|
|
1023
|
+
installed: "\u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E",
|
|
1024
|
+
notFound: "\u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E",
|
|
1025
|
+
configFile: "\u0444\u0430\u0439\u043B \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438",
|
|
1026
|
+
exists: "\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442",
|
|
1027
|
+
notExists: "\u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442",
|
|
1028
|
+
path: "\u043F\u0443\u0442\u044C",
|
|
1029
|
+
configured: "\u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043D\u043E",
|
|
1030
|
+
notConfigured: "\u043D\u0435 \u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043D\u043E",
|
|
1031
|
+
missingCliStop: "\u0412\u044B\u0431\u0440\u0430\u043D\u043D\u0430\u044F CLI \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0430. \u0417\u0430\u043F\u0438\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0430. \u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 CLI.",
|
|
1032
|
+
forceHint: "\u0427\u0442\u043E\u0431\u044B \u0437\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044E \u0434\u043E \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 CLI, \u0434\u043E\u0431\u0430\u0432\u044C\u0442\u0435 --force.",
|
|
1033
|
+
changePlan: "\u041F\u043B\u0430\u043D\u0438\u0440\u0443\u0435\u043C\u044B\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F",
|
|
1034
|
+
before: "\u0434\u043E",
|
|
1035
|
+
after: "\u043F\u043E\u0441\u043B\u0435",
|
|
1036
|
+
dryRun: "dry-run \u043D\u0435 \u0437\u0430\u043F\u0438\u0441\u0430\u043B \u0444\u0430\u0439\u043B\u044B.",
|
|
1037
|
+
confirmWrite: "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u044B\u0435 \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u044B\u0435 \u0444\u0430\u0439\u043B\u044B \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 CLI?",
|
|
1038
|
+
cancelled: "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043E\u0442\u043C\u0435\u043D\u0435\u043D\u0430.",
|
|
1039
|
+
configuring: "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430",
|
|
1040
|
+
configComplete: "\u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043D\u043E",
|
|
1041
|
+
configFailed: "\u043E\u0448\u0438\u0431\u043A\u0430",
|
|
1042
|
+
setupComplete: "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 LaysoAI \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430.",
|
|
1043
|
+
verifyCommands: "\u041A\u043E\u043C\u0430\u043D\u0434\u044B \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438",
|
|
1044
|
+
usageIntro: "\u0414\u0430\u043B\u0435\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435",
|
|
1045
|
+
enjoy: "\u041F\u0440\u0438\u044F\u0442\u043D\u043E\u0433\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F LaysoAI API!",
|
|
1046
|
+
invalidTargets: "\u041D\u0435\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043C\u044B\u0435 targets",
|
|
1047
|
+
availableTargets: "\u0414\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F",
|
|
1048
|
+
chooseAtLeastOneTarget: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D target."
|
|
1049
|
+
},
|
|
1050
|
+
ja: {
|
|
1051
|
+
languagePrompt: "\u8A00\u8A9E\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044:",
|
|
1052
|
+
targetPrompt: "\u8A2D\u5B9A\u3059\u308B\u30C4\u30FC\u30EB\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044:",
|
|
1053
|
+
apiKeyPrompt: "LaysoAI API Key \u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044:",
|
|
1054
|
+
codexModelPrompt: "Codex \u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30E2\u30C7\u30EB\u3001\u7701\u7565\u53EF\u3002Enter \u3067\u30B9\u30AD\u30C3\u30D7:",
|
|
1055
|
+
emptyApiKey: "LaysoAI API Key \u306F\u7A7A\u306B\u3067\u304D\u307E\u305B\u3093\u3002",
|
|
1056
|
+
requestUrl: "LaysoAI \u30EA\u30AF\u30A8\u30B9\u30C8 URL",
|
|
1057
|
+
envCheck: "\u74B0\u5883\u30C1\u30A7\u30C3\u30AF",
|
|
1058
|
+
installed: "\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u6E08\u307F",
|
|
1059
|
+
notFound: "\u672A\u691C\u51FA",
|
|
1060
|
+
configFile: "\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB",
|
|
1061
|
+
exists: "\u5B58\u5728",
|
|
1062
|
+
notExists: "\u5B58\u5728\u3057\u306A\u3044",
|
|
1063
|
+
path: "\u30D1\u30B9",
|
|
1064
|
+
configured: "\u8A2D\u5B9A\u6E08\u307F",
|
|
1065
|
+
notConfigured: "\u672A\u8A2D\u5B9A",
|
|
1066
|
+
missingCliStop: "\u9078\u629E\u3057\u305F CLI \u304C\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u8A2D\u5B9A\u306E\u66F8\u304D\u8FBC\u307F\u3092\u505C\u6B62\u3057\u307E\u3057\u305F\u3002\u5148\u306B CLI \u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
1067
|
+
forceHint: "CLI \u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u524D\u306B\u8A2D\u5B9A\u3092\u66F8\u304D\u8FBC\u3080\u5834\u5408\u306F --force \u3092\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
1068
|
+
changePlan: "\u5909\u66F4\u4E88\u5B9A",
|
|
1069
|
+
before: "before",
|
|
1070
|
+
after: "after",
|
|
1071
|
+
dryRun: "dry-run \u30E2\u30FC\u30C9\u3067\u306F\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u8FBC\u307F\u307E\u305B\u3093\u3067\u3057\u305F\u3002",
|
|
1072
|
+
confirmWrite: "\u4E0A\u8A18\u306E\u30ED\u30FC\u30AB\u30EB CLI \u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u3092\u5909\u66F4\u3057\u307E\u3059\u304B\uFF1F",
|
|
1073
|
+
cancelled: "\u8A2D\u5B9A\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F\u3002",
|
|
1074
|
+
configuring: "\u8A2D\u5B9A\u4E2D",
|
|
1075
|
+
configComplete: "\u8A2D\u5B9A\u5B8C\u4E86",
|
|
1076
|
+
configFailed: "\u8A2D\u5B9A\u5931\u6557",
|
|
1077
|
+
setupComplete: "LaysoAI \u306E\u81EA\u52D5\u8A2D\u5B9A\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\u3002",
|
|
1078
|
+
verifyCommands: "\u78BA\u8A8D\u30B3\u30DE\u30F3\u30C9",
|
|
1079
|
+
usageIntro: "\u6B21\u306E\u30B3\u30DE\u30F3\u30C9\u3067\u4F7F\u7528\u3067\u304D\u307E\u3059",
|
|
1080
|
+
enjoy: "LaysoAI API \u3092\u5FEB\u9069\u306B\u3054\u5229\u7528\u304F\u3060\u3055\u3044\uFF01",
|
|
1081
|
+
invalidTargets: "\u672A\u5BFE\u5FDC\u306E targets",
|
|
1082
|
+
availableTargets: "\u5229\u7528\u53EF\u80FD\u306A\u5024",
|
|
1083
|
+
chooseAtLeastOneTarget: "\u5C11\u306A\u304F\u3068\u3082 1 \u3064\u306E target \u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
1084
|
+
},
|
|
1085
|
+
vi: {
|
|
1086
|
+
languagePrompt: "Chon ngon ngu:",
|
|
1087
|
+
targetPrompt: "Chon cong cu can cau hinh:",
|
|
1088
|
+
apiKeyPrompt: "Nhap LaysoAI API Key:",
|
|
1089
|
+
codexModelPrompt: "Model mac dinh cho Codex, tuy chon. Nhan Enter de bo qua:",
|
|
1090
|
+
emptyApiKey: "LaysoAI API Key khong duoc de trong.",
|
|
1091
|
+
requestUrl: "URL yeu cau LaysoAI",
|
|
1092
|
+
envCheck: "Kiem tra moi truong",
|
|
1093
|
+
installed: "da cai dat",
|
|
1094
|
+
notFound: "khong tim thay",
|
|
1095
|
+
configFile: "tep cau hinh",
|
|
1096
|
+
exists: "ton tai",
|
|
1097
|
+
notExists: "khong ton tai",
|
|
1098
|
+
path: "duong dan",
|
|
1099
|
+
configured: "da cau hinh",
|
|
1100
|
+
notConfigured: "chua cau hinh",
|
|
1101
|
+
missingCliStop: "CLI da chon chua duoc cai dat. Da dung ghi cau hinh. Hay cai dat CLI truoc.",
|
|
1102
|
+
forceHint: "Neu muon ghi cau hinh truoc khi cai CLI, them --force.",
|
|
1103
|
+
changePlan: "Thay doi du kien",
|
|
1104
|
+
before: "truoc",
|
|
1105
|
+
after: "sau",
|
|
1106
|
+
dryRun: "Che do dry-run khong ghi tep nao.",
|
|
1107
|
+
confirmWrite: "Sua cac tep cau hinh CLI cuc bo o tren?",
|
|
1108
|
+
cancelled: "Da huy cau hinh.",
|
|
1109
|
+
configuring: "Dang cau hinh",
|
|
1110
|
+
configComplete: "da cau hinh",
|
|
1111
|
+
configFailed: "that bai",
|
|
1112
|
+
setupComplete: "Cau hinh LaysoAI hoan tat.",
|
|
1113
|
+
verifyCommands: "Lenh xac minh",
|
|
1114
|
+
usageIntro: "Tiep theo co the dung",
|
|
1115
|
+
enjoy: "Chuc ban su dung LaysoAI API vui ve!",
|
|
1116
|
+
invalidTargets: "Targets khong duoc ho tro",
|
|
1117
|
+
availableTargets: "Gia tri kha dung",
|
|
1118
|
+
chooseAtLeastOneTarget: "Chon it nhat mot target."
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
async function resolveLanguage(options) {
|
|
1122
|
+
const parsed = normalizeLanguage(options.language);
|
|
1123
|
+
if (parsed) {
|
|
1124
|
+
return parsed;
|
|
1125
|
+
}
|
|
1126
|
+
logger.success("Welcome to LaysoAI API!");
|
|
1127
|
+
const shouldPrompt = !options.yes || !options.key || !options.targets;
|
|
1128
|
+
if (!shouldPrompt) {
|
|
1129
|
+
return "en";
|
|
1130
|
+
}
|
|
1131
|
+
return select({
|
|
1132
|
+
message: MESSAGES.en.languagePrompt,
|
|
1133
|
+
choices: LANGUAGE_CHOICES,
|
|
1134
|
+
default: "en"
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
function normalizeLanguage(language) {
|
|
1138
|
+
if (!language) {
|
|
1139
|
+
return null;
|
|
1140
|
+
}
|
|
1141
|
+
const normalized = language.trim().toLowerCase();
|
|
1142
|
+
if (normalized === "zh" || normalized === "zh-cn" || normalized === "cn" || normalized === "chinese") {
|
|
1143
|
+
return "zh-CN";
|
|
1144
|
+
}
|
|
1145
|
+
if (normalized === "en" || normalized === "english") {
|
|
1146
|
+
return "en";
|
|
1147
|
+
}
|
|
1148
|
+
if (normalized === "fr" || normalized === "francais" || normalized === "fran\xE7ais" || normalized === "french") {
|
|
1149
|
+
return "fr";
|
|
1150
|
+
}
|
|
1151
|
+
if (normalized === "ru" || normalized === "russian") {
|
|
1152
|
+
return "ru";
|
|
1153
|
+
}
|
|
1154
|
+
if (normalized === "ja" || normalized === "jp" || normalized === "japanese") {
|
|
1155
|
+
return "ja";
|
|
1156
|
+
}
|
|
1157
|
+
if (normalized === "vi" || normalized === "vn" || normalized === "vietnamese") {
|
|
1158
|
+
return "vi";
|
|
1159
|
+
}
|
|
1160
|
+
return null;
|
|
1161
|
+
}
|
|
840
1162
|
|
|
841
1163
|
// src/index.ts
|
|
842
1164
|
void runCli();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/constants.ts","../src/adapters/claude.ts","../src/core/backup.ts","../src/core/fs.ts","../src/core/paths.ts","../src/core/commands.ts","../src/core/manifest.ts","../src/core/mask.ts","../src/adapters/codex.ts","../src/core/env-file.ts","../src/adapters/gemini.ts","../src/adapters/index.ts","../src/core/logger.ts","../src/core/update-check.ts","../src/index.ts"],"sourcesContent":["import { checkbox, confirm, password } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport ora from 'ora';\nimport { LAYSOAI_BASE_URL, PACKAGE_NAME, PACKAGE_VERSION, TARGETS, TargetId } from './constants.js';\nimport { adapters, getAdapters } from './adapters/index.js';\nimport { SetupInput } from './adapters/types.js';\nimport { logger } from './core/logger.js';\nimport { maskSecret } from './core/mask.js';\nimport { latestEntryFor, restoreEntry } from './core/manifest.js';\nimport { checkForUpdate } from './core/update-check.js';\n\ntype InitOptions = {\n key?: string;\n targets?: string;\n yes?: boolean;\n dryRun?: boolean;\n force?: boolean;\n};\n\ntype TargetOptions = {\n targets?: string;\n yes?: boolean;\n};\n\nexport async function runCli(argv = process.argv): Promise<void> {\n const program = new Command();\n\n program\n .name(PACKAGE_NAME)\n .description('Configure Claude Code, Codex, and Gemini to use LaysoAI.')\n .version(PACKAGE_VERSION);\n\n program\n .command('init', { isDefault: true })\n .description('Configure selected AI CLI tools with your LaysoAI key.')\n .option('-k, --key <key>', 'LaysoAI API key')\n .option('-t, --targets <targets>', 'Target CLIs: claude,codex,gemini,all')\n .option('-y, --yes', 'Skip confirmation')\n .option('--dry-run', 'Show changes without writing files')\n .option('--force', 'Write config even if the selected CLI command is not installed')\n .action(async (options: InitOptions) => {\n await initCommand(options);\n });\n\n program\n .command('config')\n .description('Show detected LaysoAI CLI configuration.')\n .action(async () => {\n await configCommand();\n });\n\n program\n .command('doctor')\n .description('Check CLI installation and LaysoAI configuration status.')\n .action(async () => {\n await doctorCommand();\n });\n\n program\n .command('reset')\n .description('Restore the latest backup generated by laysoai.')\n .option('-t, --targets <targets>', 'Target CLIs: claude,codex,gemini,all')\n .option('-y, --yes', 'Skip confirmation')\n .action(async (options: TargetOptions) => {\n await resetCommand(options);\n });\n\n try {\n await notifyIfUpdateAvailable();\n await program.parseAsync(argv);\n } catch (error) {\n logger.error((error as Error).message);\n process.exitCode = 1;\n }\n}\n\nasync function notifyIfUpdateAvailable(): Promise<void> {\n const latestVersion = await checkForUpdate(PACKAGE_VERSION);\n if (!latestVersion) {\n return;\n }\n\n logger.warn(`发现新版 ${PACKAGE_NAME}@${latestVersion},当前版本 ${PACKAGE_VERSION}。建议运行: npm install -g ${PACKAGE_NAME}@latest`);\n}\n\nasync function initCommand(options: InitOptions): Promise<void> {\n const targets = options.targets ? parseTargets(options.targets) : await promptTargets();\n const apiKey = options.key?.trim() || (await password({ message: '请输入 LaysoAI API Key:', mask: '*' }));\n\n if (!apiKey.trim()) {\n throw new Error('LaysoAI API Key 不能为空。');\n }\n\n const input: SetupInput = {\n apiKey: apiKey.trim(),\n targets,\n yes: Boolean(options.yes),\n dryRun: Boolean(options.dryRun),\n force: Boolean(options.force)\n };\n\n logger.info(`LaysoAI 请求地址: ${LAYSOAI_BASE_URL}`);\n logger.info(`LaysoAI Key: ${maskSecret(input.apiKey)}`);\n\n const selectedAdapters = getAdapters(targets);\n const preflight = await printPreflight(selectedAdapters);\n const missing = preflight.filter((result) => !result.installed);\n if (missing.length > 0 && !input.force) {\n logger.plain('');\n logger.warn('检测到目标 CLI 未安装,已停止写入配置。请先安装对应 CLI 后再运行 laysoai。');\n for (const result of missing) {\n logger.plain(`- ${result.name}: ${installCommandFor(result.target)}`);\n }\n logger.plain('');\n logger.plain('如果你确认要先写配置,可以追加 --force。');\n return;\n }\n\n const plans = [];\n for (const adapter of selectedAdapters) {\n plans.push(await adapter.plan(input));\n }\n\n printPlans(plans);\n\n if (input.dryRun) {\n logger.warn('dry-run 模式未写入任何文件。');\n return;\n }\n\n if (!input.yes) {\n const approved = await confirm({\n message: '确认直接修改以上本机 CLI 配置文件吗?',\n default: true\n });\n if (!approved) {\n logger.warn('已取消配置。');\n return;\n }\n }\n\n for (const adapter of selectedAdapters) {\n const spinner = ora(`正在配置 ${adapter.name}...`).start();\n try {\n const plan = await adapter.apply(input);\n spinner.succeed(`${adapter.name} 配置完成: ${plan.configPath}`);\n if (plan.backupPath) {\n logger.plain(chalk.dim(` backup: ${plan.backupPath}`));\n }\n } catch (error) {\n spinner.fail(`${adapter.name} 配置失败`);\n throw error;\n }\n }\n\n logger.success('LaysoAI 自动配置完成。');\n logger.plain('');\n logger.plain('验证命令:');\n for (const adapter of selectedAdapters) {\n logger.plain(`- ${adapter.name}: ${adapter.verifyHint().join(' / ')}`);\n }\n}\n\ntype PreflightResult = {\n target: TargetId;\n name: string;\n installed: boolean;\n};\n\nasync function printPreflight(selectedAdapters: ReturnType<typeof getAdapters>): Promise<PreflightResult[]> {\n const results: PreflightResult[] = [];\n logger.plain('');\n logger.plain('环境检查:');\n for (const adapter of selectedAdapters) {\n const [detected, current] = await Promise.all([adapter.detect(), adapter.inspect()]);\n results.push({\n target: adapter.id,\n name: adapter.name,\n installed: detected.installed\n });\n logger.plain(`- ${adapter.name}`);\n logger.plain(` CLI: ${detected.installed ? chalk.green('已安装') : chalk.yellow('未检测到')} (${detected.command})`);\n logger.plain(` 配置文件: ${current.exists ? chalk.green('存在') : chalk.yellow('不存在')}`);\n logger.plain(` 路径: ${current.configPath}`);\n logger.plain(` LaysoAI: ${current.configured ? chalk.green('已配置') : chalk.yellow('未配置')}`);\n }\n return results;\n}\n\nasync function configCommand(): Promise<void> {\n for (const adapter of Object.values(adapters)) {\n const current = await adapter.inspect();\n const state = current.configured ? chalk.green('configured') : chalk.yellow('not configured');\n logger.plain(`${current.name}: ${state}`);\n logger.plain(` path: ${current.configPath}`);\n logger.plain(` ${current.summary}`);\n }\n}\n\nasync function doctorCommand(): Promise<void> {\n logger.info(`LaysoAI 请求地址: ${LAYSOAI_BASE_URL}`);\n for (const adapter of Object.values(adapters)) {\n const [detected, current] = await Promise.all([adapter.detect(), adapter.inspect()]);\n logger.plain(`${adapter.name}:`);\n logger.plain(` command: ${detected.installed ? chalk.green('found') : chalk.yellow('not found')} (${detected.command})`);\n logger.plain(` config: ${current.configured ? chalk.green('configured') : chalk.yellow('not configured')}`);\n logger.plain(` path: ${current.configPath}`);\n }\n}\n\nasync function resetCommand(options: TargetOptions): Promise<void> {\n const targets = options.targets ? parseTargets(options.targets) : await promptTargets();\n\n const entries = [];\n for (const target of targets) {\n const entry = await latestEntryFor(target);\n if (entry) {\n entries.push(entry);\n } else {\n logger.warn(`${adapters[target].name}: 没有找到 laysoai 备份记录。`);\n }\n }\n\n if (entries.length === 0) {\n return;\n }\n\n logger.warn('将恢复以下配置:');\n for (const entry of entries) {\n logger.plain(`- ${adapters[entry.target].name}: ${entry.configPath}`);\n }\n\n if (!options.yes) {\n const approved = await confirm({\n message: '确认恢复最近一次备份吗?',\n default: false\n });\n if (!approved) {\n logger.warn('已取消恢复。');\n return;\n }\n }\n\n for (const entry of entries) {\n await restoreEntry(entry);\n logger.success(`${adapters[entry.target].name} 已恢复。`);\n }\n}\n\nfunction printPlans(plans: Awaited<ReturnType<typeof adapters.claude.plan>>[]): void {\n logger.plain('');\n logger.plain('将执行以下配置修改:');\n for (const plan of plans) {\n logger.plain(`- ${plan.name}`);\n logger.plain(` path: ${plan.configPath}`);\n logger.plain(` before: ${plan.beforeSummary}`);\n logger.plain(` after: ${plan.afterSummary}`);\n for (const change of plan.changes) {\n logger.plain(` ${change.action.padEnd(6)} ${change.key}`);\n }\n }\n logger.plain('');\n}\n\nfunction parseTargets(value: string): TargetId[] {\n const rawTargets = value\n .split(',')\n .map((target) => target.trim().toLowerCase())\n .filter(Boolean);\n\n if (rawTargets.includes('all')) {\n return [...TARGETS];\n }\n\n const normalized = rawTargets.map((target) => {\n if (target === 'claude-code') {\n return 'claude';\n }\n return target;\n });\n\n const invalid = normalized.filter((target) => !TARGETS.includes(target as TargetId));\n if (invalid.length > 0) {\n throw new Error(`不支持的 targets: ${invalid.join(', ')}。可用值: claude,codex,gemini,all`);\n }\n\n const unique = Array.from(new Set(normalized)) as TargetId[];\n if (unique.length === 0) {\n throw new Error('请至少选择一个 target。');\n }\n return unique;\n}\n\nasync function promptTargets(): Promise<TargetId[]> {\n const selected = await checkbox<TargetId>({\n message: '请选择需要配置的工具:',\n choices: [\n { name: 'Claude Code', value: 'claude' },\n { name: 'Codex CLI', value: 'codex' },\n { name: 'Gemini CLI', value: 'gemini' }\n ],\n required: true\n });\n\n return selected;\n}\n\nfunction installCommandFor(target: TargetId): string {\n switch (target) {\n case 'claude':\n return 'npm install -g @anthropic-ai/claude-code';\n case 'codex':\n return 'npm install -g @openai/codex';\n case 'gemini':\n return 'npm install -g @google/gemini-cli';\n }\n}\n","export const PACKAGE_NAME = 'laysoai';\nexport const PACKAGE_VERSION = '0.1.1';\nexport const LAYSOAI_BASE_URL = 'https://laysoai.com';\nexport const LAYSOAI_HOME_DIR = '.laysoai';\n\nexport const TARGETS = ['claude', 'codex', 'gemini'] as const;\nexport type TargetId = (typeof TARGETS)[number];\n","import path from 'node:path';\nimport { LAYSOAI_BASE_URL } from '../constants.js';\nimport { backupConfig } from '../core/backup.js';\nimport { commandExists } from '../core/commands.js';\nimport { readJsonObject, writeJsonObject, pathExists } from '../core/fs.js';\nimport { addManifestEntry } from '../core/manifest.js';\nimport { hasValue } from '../core/mask.js';\nimport { homePath } from '../core/paths.js';\nimport { CliAdapter, ConfigChangePlan, CurrentConfig, DetectResult, SetupInput } from './types.js';\n\nconst ENV_VALUES = (apiKey: string) => ({\n ANTHROPIC_BASE_URL: LAYSOAI_BASE_URL,\n ANTHROPIC_AUTH_TOKEN: apiKey,\n ANTHROPIC_API_KEY: apiKey\n});\n\nexport const claudeAdapter: CliAdapter = {\n id: 'claude',\n name: 'Claude Code',\n command: 'claude',\n\n configPath() {\n return homePath('.claude', 'settings.json');\n },\n\n async detect(): Promise<DetectResult> {\n return { command: this.command, installed: await commandExists(this.command) };\n },\n\n async inspect(): Promise<CurrentConfig> {\n const configPath = this.configPath();\n const exists = await pathExists(configPath);\n if (!exists) {\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured: false,\n summary: '配置文件不存在'\n };\n }\n\n const config = await readJsonObject(configPath);\n const env = asRecord(config.env);\n const configured = env.ANTHROPIC_BASE_URL === LAYSOAI_BASE_URL && (hasValue(env.ANTHROPIC_AUTH_TOKEN) || hasValue(env.ANTHROPIC_API_KEY));\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured,\n summary: configured ? '已配置 LaysoAI env' : '未检测到完整 LaysoAI env'\n };\n },\n\n async plan(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const before = await this.inspect();\n const config = await safeReadJson(configPath);\n const env = asRecord(config.env);\n const desired = ENV_VALUES(input.apiKey);\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n backupPath: null,\n beforeSummary: before.summary,\n afterSummary: '写入 ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_API_KEY',\n changes: Object.entries(desired).map(([key, value]) => ({\n key,\n action: env[key] === value ? 'skip' : key in env ? 'update' : 'add'\n }))\n };\n },\n\n async apply(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const plan = await this.plan(input);\n const backup = await backupConfig(this.id, configPath);\n\n try {\n const config = await safeReadJson(configPath);\n const env = asRecord(config.env);\n config.env = {\n ...env,\n ...ENV_VALUES(input.apiKey)\n };\n await writeJsonObject(configPath, config);\n } catch (error) {\n if (backup.existed && backup.backupPath) {\n const original = await import('node:fs/promises');\n await original.copyFile(backup.backupPath, configPath);\n }\n throw error;\n }\n\n await addManifestEntry({\n id: backup.id,\n date: new Date().toISOString(),\n target: this.id,\n configPath,\n backupPath: backup.backupPath,\n existed: backup.existed\n });\n\n return { ...plan, backupPath: backup.backupPath };\n },\n\n verifyHint() {\n return ['claude --version', 'claude'];\n }\n};\n\nasync function safeReadJson(configPath: string): Promise<Record<string, unknown>> {\n try {\n return await readJsonObject(configPath);\n } catch (error) {\n throw new Error(`无法读取 Claude Code 配置 ${path.basename(configPath)}:${(error as Error).message}`);\n }\n}\n\nfunction asRecord(value: unknown): Record<string, string> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n return value as Record<string, string>;\n}\n","import path from 'node:path';\nimport { TargetId } from '../constants.js';\nimport { copyFileIfExists } from './fs.js';\nimport { laysoaiPath, timestampId } from './paths.js';\n\nexport type BackupResult = {\n id: string;\n backupPath: string | null;\n existed: boolean;\n};\n\nexport async function backupConfig(target: TargetId, configPath: string): Promise<BackupResult> {\n const id = timestampId();\n const backupPath = laysoaiPath('backups', target, id, path.basename(configPath));\n const existed = await copyFileIfExists(configPath, backupPath);\n\n return {\n id,\n backupPath: existed ? backupPath : null,\n existed\n };\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport async function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\nexport async function readText(filePath: string): Promise<string | null> {\n if (!(await pathExists(filePath))) {\n return null;\n }\n return fs.readFile(filePath, 'utf8');\n}\n\nexport async function writeText(filePath: string, content: string): Promise<void> {\n await ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content, 'utf8');\n}\n\nexport async function readJsonObject(filePath: string): Promise<Record<string, unknown>> {\n const content = await readText(filePath);\n if (!content || !content.trim()) {\n return {};\n }\n const parsed = JSON.parse(content) as unknown;\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`${filePath} must contain a JSON object.`);\n }\n return parsed as Record<string, unknown>;\n}\n\nexport async function writeJsonObject(filePath: string, value: Record<string, unknown>): Promise<void> {\n await writeText(filePath, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nexport async function copyFileIfExists(source: string, destination: string): Promise<boolean> {\n if (!(await pathExists(source))) {\n return false;\n }\n await ensureDir(path.dirname(destination));\n await fs.copyFile(source, destination);\n return true;\n}\n\nexport async function removeFileIfExists(filePath: string): Promise<void> {\n if (await pathExists(filePath)) {\n await fs.rm(filePath, { force: true });\n }\n}\n","import os from 'node:os';\nimport path from 'node:path';\nimport { LAYSOAI_HOME_DIR } from '../constants.js';\n\nexport function homePath(...parts: string[]): string {\n return path.join(os.homedir(), ...parts);\n}\n\nexport function laysoaiPath(...parts: string[]): string {\n return homePath(LAYSOAI_HOME_DIR, ...parts);\n}\n\nexport function timestampId(date = new Date()): string {\n return date.toISOString().replace(/[:.]/g, '-');\n}\n","import { spawn } from 'node:child_process';\nimport process from 'node:process';\n\nexport async function commandExists(command: string): Promise<boolean> {\n const checker = process.platform === 'win32' ? 'where' : 'command';\n const args = process.platform === 'win32' ? [command] : ['-v', command];\n\n return new Promise((resolve) => {\n const child = spawn(checker, args, {\n stdio: 'ignore',\n shell: process.platform !== 'win32'\n });\n\n child.on('error', () => resolve(false));\n child.on('close', (code) => resolve(code === 0));\n });\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { TargetId } from '../constants.js';\nimport { ensureDir, pathExists, readText, writeText } from './fs.js';\nimport { laysoaiPath } from './paths.js';\n\nexport type ManifestEntry = {\n id: string;\n date: string;\n target: TargetId;\n configPath: string;\n backupPath: string | null;\n existed: boolean;\n};\n\ntype Manifest = {\n version: 1;\n entries: ManifestEntry[];\n};\n\nconst MANIFEST_PATH = laysoaiPath('manifest.json');\n\nasync function readManifest(): Promise<Manifest> {\n const content = await readText(MANIFEST_PATH);\n if (!content) {\n return { version: 1, entries: [] };\n }\n const parsed = JSON.parse(content) as Manifest;\n return {\n version: 1,\n entries: Array.isArray(parsed.entries) ? parsed.entries : []\n };\n}\n\nasync function writeManifest(manifest: Manifest): Promise<void> {\n await ensureDir(path.dirname(MANIFEST_PATH));\n await writeText(MANIFEST_PATH, `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n\nexport async function addManifestEntry(entry: ManifestEntry): Promise<void> {\n const manifest = await readManifest();\n manifest.entries.push(entry);\n await writeManifest(manifest);\n}\n\nexport async function latestEntryFor(target: TargetId): Promise<ManifestEntry | null> {\n const manifest = await readManifest();\n const matches = manifest.entries.filter((entry) => entry.target === target);\n return matches.at(-1) ?? null;\n}\n\nexport async function restoreEntry(entry: ManifestEntry): Promise<void> {\n if (entry.existed && entry.backupPath) {\n if (!(await pathExists(entry.backupPath))) {\n throw new Error(`Backup file not found: ${entry.backupPath}`);\n }\n await ensureDir(path.dirname(entry.configPath));\n await fs.copyFile(entry.backupPath, entry.configPath);\n return;\n }\n\n await fs.rm(entry.configPath, { force: true });\n}\n","export function maskSecret(secret: string): string {\n if (secret.length <= 8) {\n return '*'.repeat(secret.length);\n }\n return `${secret.slice(0, 4)}...${secret.slice(-4)}`;\n}\n\nexport function hasValue(value: unknown): boolean {\n return typeof value === 'string' && value.trim().length > 0;\n}\n","import * as TOML from 'smol-toml';\nimport { LAYSOAI_BASE_URL } from '../constants.js';\nimport { backupConfig } from '../core/backup.js';\nimport { commandExists } from '../core/commands.js';\nimport { pathExists, readText, writeText } from '../core/fs.js';\nimport { addManifestEntry } from '../core/manifest.js';\nimport { homePath } from '../core/paths.js';\nimport { CliAdapter, ConfigChangePlan, CurrentConfig, DetectResult, SetupInput } from './types.js';\n\ntype TomlObject = Record<string, unknown>;\n\nexport const codexAdapter: CliAdapter = {\n id: 'codex',\n name: 'Codex CLI',\n command: 'codex',\n\n configPath() {\n return homePath('.codex', 'config.toml');\n },\n\n async detect(): Promise<DetectResult> {\n return { command: this.command, installed: await commandExists(this.command) };\n },\n\n async inspect(): Promise<CurrentConfig> {\n const configPath = this.configPath();\n const exists = await pathExists(configPath);\n if (!exists) {\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured: false,\n summary: '配置文件不存在'\n };\n }\n\n const config = await readToml(configPath);\n const providers = asRecord(config.model_providers);\n const laysoai = asRecord(providers.laysoai);\n const configured = config.model_provider === 'laysoai' && laysoai.base_url === LAYSOAI_BASE_URL;\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured,\n summary: configured ? '已配置 LaysoAI provider' : '未检测到 LaysoAI provider'\n };\n },\n\n async plan(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const before = await this.inspect();\n const config = await readToml(configPath);\n const providers = asRecord(config.model_providers);\n const laysoai = asRecord(providers.laysoai);\n\n const desired = {\n model_provider: 'laysoai',\n 'model_providers.laysoai.name': 'LaysoAI',\n 'model_providers.laysoai.base_url': LAYSOAI_BASE_URL,\n 'model_providers.laysoai.wire_api': 'responses',\n 'model_providers.laysoai.experimental_bearer_token': input.apiKey\n };\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n backupPath: null,\n beforeSummary: before.summary,\n afterSummary: '写入 Codex LaysoAI provider 并设为默认 provider',\n changes: [\n { key: 'model_provider', action: config.model_provider === desired.model_provider ? 'skip' : 'update' },\n { key: 'model_providers.laysoai.name', action: laysoai.name === desired['model_providers.laysoai.name'] ? 'skip' : keyAction(laysoai, 'name') },\n { key: 'model_providers.laysoai.base_url', action: laysoai.base_url === desired['model_providers.laysoai.base_url'] ? 'skip' : keyAction(laysoai, 'base_url') },\n { key: 'model_providers.laysoai.wire_api', action: laysoai.wire_api === desired['model_providers.laysoai.wire_api'] ? 'skip' : keyAction(laysoai, 'wire_api') },\n {\n key: 'model_providers.laysoai.experimental_bearer_token',\n action: laysoai.experimental_bearer_token === input.apiKey ? 'skip' : keyAction(laysoai, 'experimental_bearer_token')\n }\n ]\n };\n },\n\n async apply(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const plan = await this.plan(input);\n const backup = await backupConfig(this.id, configPath);\n\n try {\n const config = await readToml(configPath);\n const providers = asRecord(config.model_providers);\n config.model_provider = 'laysoai';\n config.model_providers = {\n ...providers,\n laysoai: {\n ...asRecord(providers.laysoai),\n name: 'LaysoAI',\n base_url: LAYSOAI_BASE_URL,\n wire_api: 'responses',\n experimental_bearer_token: input.apiKey\n }\n };\n await writeText(configPath, TOML.stringify(config));\n } catch (error) {\n if (backup.existed && backup.backupPath) {\n const fs = await import('node:fs/promises');\n await fs.copyFile(backup.backupPath, configPath);\n }\n throw error;\n }\n\n await addManifestEntry({\n id: backup.id,\n date: new Date().toISOString(),\n target: this.id,\n configPath,\n backupPath: backup.backupPath,\n existed: backup.existed\n });\n\n return { ...plan, backupPath: backup.backupPath };\n },\n\n verifyHint() {\n return ['codex --version', 'codex'];\n }\n};\n\nasync function readToml(configPath: string): Promise<TomlObject> {\n const content = await readText(configPath);\n if (!content?.trim()) {\n return {};\n }\n const parsed = TOML.parse(content);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`${configPath} must contain a TOML object.`);\n }\n return parsed as TomlObject;\n}\n\nfunction asRecord(value: unknown): TomlObject {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n return value as TomlObject;\n}\n\nfunction keyAction(record: TomlObject, key: string): 'add' | 'update' {\n return key in record ? 'update' : 'add';\n}\n","export function upsertEnvValues(content: string, values: Record<string, string>): string {\n const lines = content ? content.split(/\\r?\\n/) : [];\n const seen = new Set<string>();\n const nextLines = lines.map((line) => {\n const match = line.match(/^\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*=/);\n if (!match) {\n return line;\n }\n\n const key = match[1];\n if (!(key in values)) {\n return line;\n }\n\n seen.add(key);\n return `${key}=${quoteEnv(values[key])}`;\n });\n\n for (const [key, value] of Object.entries(values)) {\n if (!seen.has(key)) {\n nextLines.push(`${key}=${quoteEnv(value)}`);\n }\n }\n\n return `${nextLines.filter((line, index) => line.length > 0 || index < nextLines.length - 1).join('\\n')}\\n`;\n}\n\nfunction quoteEnv(value: string): string {\n return JSON.stringify(value);\n}\n","import { LAYSOAI_BASE_URL } from '../constants.js';\nimport { backupConfig } from '../core/backup.js';\nimport { commandExists } from '../core/commands.js';\nimport { upsertEnvValues } from '../core/env-file.js';\nimport { pathExists, readText, writeText } from '../core/fs.js';\nimport { addManifestEntry } from '../core/manifest.js';\nimport { homePath } from '../core/paths.js';\nimport { CliAdapter, ConfigChangePlan, CurrentConfig, DetectResult, SetupInput } from './types.js';\n\nconst ENV_VALUES = (apiKey: string) => ({\n GEMINI_API_KEY: apiKey,\n GOOGLE_GEMINI_BASE_URL: LAYSOAI_BASE_URL\n});\n\nexport const geminiAdapter: CliAdapter = {\n id: 'gemini',\n name: 'Gemini CLI',\n command: 'gemini',\n\n configPath() {\n return homePath('.gemini', '.env');\n },\n\n async detect(): Promise<DetectResult> {\n return { command: this.command, installed: await commandExists(this.command) };\n },\n\n async inspect(): Promise<CurrentConfig> {\n const configPath = this.configPath();\n const exists = await pathExists(configPath);\n if (!exists) {\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured: false,\n summary: '配置文件不存在'\n };\n }\n\n const content = (await readText(configPath)) ?? '';\n const configured = hasEnvLine(content, 'GEMINI_API_KEY') && hasEnvLine(content, 'GOOGLE_GEMINI_BASE_URL', LAYSOAI_BASE_URL);\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured,\n summary: configured ? '已配置 LaysoAI env' : '未检测到完整 LaysoAI env'\n };\n },\n\n async plan(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const before = await this.inspect();\n const content = (await readText(configPath)) ?? '';\n const desired = ENV_VALUES(input.apiKey);\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n backupPath: null,\n beforeSummary: before.summary,\n afterSummary: '写入 GEMINI_API_KEY、GOOGLE_GEMINI_BASE_URL',\n changes: Object.entries(desired).map(([key, value]) => ({\n key,\n action: hasEnvLine(content, key, value) ? 'skip' : hasEnvLine(content, key) ? 'update' : 'add'\n }))\n };\n },\n\n async apply(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const plan = await this.plan(input);\n const backup = await backupConfig(this.id, configPath);\n\n try {\n const content = (await readText(configPath)) ?? '';\n await writeText(configPath, upsertEnvValues(content, ENV_VALUES(input.apiKey)));\n } catch (error) {\n if (backup.existed && backup.backupPath) {\n const fs = await import('node:fs/promises');\n await fs.copyFile(backup.backupPath, configPath);\n }\n throw error;\n }\n\n await addManifestEntry({\n id: backup.id,\n date: new Date().toISOString(),\n target: this.id,\n configPath,\n backupPath: backup.backupPath,\n existed: backup.existed\n });\n\n return { ...plan, backupPath: backup.backupPath };\n },\n\n verifyHint() {\n return ['gemini --version', 'gemini'];\n }\n};\n\nfunction hasEnvLine(content: string, key: string, value?: string): boolean {\n const matcher = new RegExp(`^\\\\s*${escapeRegExp(key)}\\\\s*=\\\\s*(.*)\\\\s*$`, 'm');\n const match = content.match(matcher);\n if (!match) {\n return false;\n }\n if (value === undefined) {\n return true;\n }\n return unquote(match[1].trim()) === value;\n}\n\nfunction unquote(value: string): string {\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n return value.slice(1, -1);\n }\n return value;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import { TargetId } from '../constants.js';\nimport { claudeAdapter } from './claude.js';\nimport { codexAdapter } from './codex.js';\nimport { geminiAdapter } from './gemini.js';\nimport { CliAdapter } from './types.js';\n\nexport const adapters: Record<TargetId, CliAdapter> = {\n claude: claudeAdapter,\n codex: codexAdapter,\n gemini: geminiAdapter\n};\n\nexport function getAdapters(targets: TargetId[]): CliAdapter[] {\n return targets.map((target) => adapters[target]);\n}\n","import chalk from 'chalk';\n\nexport const logger = {\n info(message: string): void {\n console.log(chalk.cyan(message));\n },\n success(message: string): void {\n console.log(chalk.green(message));\n },\n warn(message: string): void {\n console.log(chalk.yellow(message));\n },\n error(message: string): void {\n console.error(chalk.red(message));\n },\n plain(message: string): void {\n console.log(message);\n }\n};\n","import { PACKAGE_NAME } from '../constants.js';\n\ntype RegistryLatest = {\n version?: string;\n};\n\nexport async function checkForUpdate(currentVersion: string): Promise<string | null> {\n if (process.env.LAYSOAI_SKIP_UPDATE_CHECK === '1') {\n return null;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 1500);\n\n try {\n const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {\n signal: controller.signal,\n headers: {\n accept: 'application/json',\n 'user-agent': `${PACKAGE_NAME}/${currentVersion}`\n }\n });\n\n if (!response.ok) {\n return null;\n }\n\n const latest = (await response.json()) as RegistryLatest;\n if (latest.version && compareVersions(latest.version, currentVersion) > 0) {\n return latest.version;\n }\n return null;\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport function compareVersions(left: string, right: string): number {\n const leftParts = normalizeVersion(left);\n const rightParts = normalizeVersion(right);\n\n for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index += 1) {\n const leftPart = leftParts[index] ?? 0;\n const rightPart = rightParts[index] ?? 0;\n if (leftPart > rightPart) {\n return 1;\n }\n if (leftPart < rightPart) {\n return -1;\n }\n }\n\n return 0;\n}\n\nfunction normalizeVersion(version: string): number[] {\n return version\n .replace(/^v/, '')\n .split(/[.-]/)\n .map((part) => Number.parseInt(part, 10))\n .map((part) => (Number.isFinite(part) ? part : 0));\n}\n","#!/usr/bin/env node\nimport { runCli } from './cli.js';\n\nvoid runCli();\n"],"mappings":";;;AAAA,SAAS,UAAU,SAAS,gBAAgB;AAC5C,OAAOA,YAAW;AAClB,SAAS,eAAe;AACxB,OAAO,SAAS;;;ACHT,IAAM,eAAe;AACrB,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAEzB,IAAM,UAAU,CAAC,UAAU,SAAS,QAAQ;;;ACLnD,OAAOC,WAAU;;;ACAjB,OAAOC,WAAU;;;ACAjB,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAsB,WAAW,UAAoC;AACnE,MAAI;AACF,UAAM,GAAG,OAAO,QAAQ;AACxB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,UAAU,SAAgC;AAC9D,QAAM,GAAG,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAC7C;AAEA,eAAsB,SAAS,UAA0C;AACvE,MAAI,CAAE,MAAM,WAAW,QAAQ,GAAI;AACjC,WAAO;AAAA,EACT;AACA,SAAO,GAAG,SAAS,UAAU,MAAM;AACrC;AAEA,eAAsB,UAAU,UAAkB,SAAgC;AAChF,QAAM,UAAU,KAAK,QAAQ,QAAQ,CAAC;AACtC,QAAM,GAAG,UAAU,UAAU,SAAS,MAAM;AAC9C;AAEA,eAAsB,eAAe,UAAoD;AACvF,QAAM,UAAU,MAAM,SAAS,QAAQ;AACvC,MAAI,CAAC,WAAW,CAAC,QAAQ,KAAK,GAAG;AAC/B,WAAO,CAAC;AAAA,EACV;AACA,QAAM,SAAS,KAAK,MAAM,OAAO;AACjC,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,UAAM,IAAI,MAAM,GAAG,QAAQ,8BAA8B;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,eAAsB,gBAAgB,UAAkB,OAA+C;AACrG,QAAM,UAAU,UAAU,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,CAAI;AACjE;AAEA,eAAsB,iBAAiB,QAAgB,aAAuC;AAC5F,MAAI,CAAE,MAAM,WAAW,MAAM,GAAI;AAC/B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,KAAK,QAAQ,WAAW,CAAC;AACzC,QAAM,GAAG,SAAS,QAAQ,WAAW;AACrC,SAAO;AACT;;;ACnDA,OAAO,QAAQ;AACf,OAAOC,WAAU;AAGV,SAAS,YAAY,OAAyB;AACnD,SAAOC,MAAK,KAAK,GAAG,QAAQ,GAAG,GAAG,KAAK;AACzC;AAEO,SAAS,eAAe,OAAyB;AACtD,SAAO,SAAS,kBAAkB,GAAG,KAAK;AAC5C;AAEO,SAAS,YAAY,OAAO,oBAAI,KAAK,GAAW;AACrD,SAAO,KAAK,YAAY,EAAE,QAAQ,SAAS,GAAG;AAChD;;;AFHA,eAAsB,aAAa,QAAkB,YAA2C;AAC9F,QAAM,KAAK,YAAY;AACvB,QAAM,aAAa,YAAY,WAAW,QAAQ,IAAIC,MAAK,SAAS,UAAU,CAAC;AAC/E,QAAM,UAAU,MAAM,iBAAiB,YAAY,UAAU;AAE7D,SAAO;AAAA,IACL;AAAA,IACA,YAAY,UAAU,aAAa;AAAA,IACnC;AAAA,EACF;AACF;;;AGrBA,SAAS,aAAa;AACtB,OAAOC,cAAa;AAEpB,eAAsB,cAAc,SAAmC;AACrE,QAAM,UAAUA,SAAQ,aAAa,UAAU,UAAU;AACzD,QAAM,OAAOA,SAAQ,aAAa,UAAU,CAAC,OAAO,IAAI,CAAC,MAAM,OAAO;AAEtE,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQ,MAAM,SAAS,MAAM;AAAA,MACjC,OAAO;AAAA,MACP,OAAOA,SAAQ,aAAa;AAAA,IAC9B,CAAC;AAED,UAAM,GAAG,SAAS,MAAM,QAAQ,KAAK,CAAC;AACtC,UAAM,GAAG,SAAS,CAAC,SAAS,QAAQ,SAAS,CAAC,CAAC;AAAA,EACjD,CAAC;AACH;;;AChBA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAmBjB,IAAM,gBAAgB,YAAY,eAAe;AAEjD,eAAe,eAAkC;AAC/C,QAAM,UAAU,MAAM,SAAS,aAAa;AAC5C,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,SAAS,GAAG,SAAS,CAAC,EAAE;AAAA,EACnC;AACA,QAAM,SAAS,KAAK,MAAM,OAAO;AACjC,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC;AAAA,EAC7D;AACF;AAEA,eAAe,cAAc,UAAmC;AAC9D,QAAM,UAAUC,MAAK,QAAQ,aAAa,CAAC;AAC3C,QAAM,UAAU,eAAe,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,CAAI;AACzE;AAEA,eAAsB,iBAAiB,OAAqC;AAC1E,QAAM,WAAW,MAAM,aAAa;AACpC,WAAS,QAAQ,KAAK,KAAK;AAC3B,QAAM,cAAc,QAAQ;AAC9B;AAEA,eAAsB,eAAe,QAAiD;AACpF,QAAM,WAAW,MAAM,aAAa;AACpC,QAAM,UAAU,SAAS,QAAQ,OAAO,CAAC,UAAU,MAAM,WAAW,MAAM;AAC1E,SAAO,QAAQ,GAAG,EAAE,KAAK;AAC3B;AAEA,eAAsB,aAAa,OAAqC;AACtE,MAAI,MAAM,WAAW,MAAM,YAAY;AACrC,QAAI,CAAE,MAAM,WAAW,MAAM,UAAU,GAAI;AACzC,YAAM,IAAI,MAAM,0BAA0B,MAAM,UAAU,EAAE;AAAA,IAC9D;AACA,UAAM,UAAUA,MAAK,QAAQ,MAAM,UAAU,CAAC;AAC9C,UAAMC,IAAG,SAAS,MAAM,YAAY,MAAM,UAAU;AACpD;AAAA,EACF;AAEA,QAAMA,IAAG,GAAG,MAAM,YAAY,EAAE,OAAO,KAAK,CAAC;AAC/C;;;AC9DO,SAAS,WAAW,QAAwB;AACjD,MAAI,OAAO,UAAU,GAAG;AACtB,WAAO,IAAI,OAAO,OAAO,MAAM;AAAA,EACjC;AACA,SAAO,GAAG,OAAO,MAAM,GAAG,CAAC,CAAC,MAAM,OAAO,MAAM,EAAE,CAAC;AACpD;AAEO,SAAS,SAAS,OAAyB;AAChD,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS;AAC5D;;;ANCA,IAAM,aAAa,CAAC,YAAoB;AAAA,EACtC,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,mBAAmB;AACrB;AAEO,IAAM,gBAA4B;AAAA,EACvC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EAET,aAAa;AACX,WAAO,SAAS,WAAW,eAAe;AAAA,EAC5C;AAAA,EAEA,MAAM,SAAgC;AACpC,WAAO,EAAE,SAAS,KAAK,SAAS,WAAW,MAAM,cAAc,KAAK,OAAO,EAAE;AAAA,EAC/E;AAAA,EAEA,MAAM,UAAkC;AACtC,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,eAAe,UAAU;AAC9C,UAAM,MAAM,SAAS,OAAO,GAAG;AAC/B,UAAM,aAAa,IAAI,uBAAuB,qBAAqB,SAAS,IAAI,oBAAoB,KAAK,SAAS,IAAI,iBAAiB;AAEvI,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,aAAa,mCAAoB;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAA8C;AACvD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,UAAM,SAAS,MAAM,aAAa,UAAU;AAC5C,UAAM,MAAM,SAAS,OAAO,GAAG;AAC/B,UAAM,UAAU,WAAW,MAAM,MAAM;AAEvC,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA,YAAY;AAAA,MACZ,eAAe,OAAO;AAAA,MACtB,cAAc;AAAA,MACd,SAAS,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,QACtD;AAAA,QACA,QAAQ,IAAI,GAAG,MAAM,QAAQ,SAAS,OAAO,MAAM,WAAW;AAAA,MAChE,EAAE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,OAA8C;AACxD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,OAAO,MAAM,KAAK,KAAK,KAAK;AAClC,UAAM,SAAS,MAAM,aAAa,KAAK,IAAI,UAAU;AAErD,QAAI;AACF,YAAM,SAAS,MAAM,aAAa,UAAU;AAC5C,YAAM,MAAM,SAAS,OAAO,GAAG;AAC/B,aAAO,MAAM;AAAA,QACX,GAAG;AAAA,QACH,GAAG,WAAW,MAAM,MAAM;AAAA,MAC5B;AACA,YAAM,gBAAgB,YAAY,MAAM;AAAA,IAC1C,SAAS,OAAO;AACd,UAAI,OAAO,WAAW,OAAO,YAAY;AACvC,cAAM,WAAW,MAAM,OAAO,aAAkB;AAChD,cAAM,SAAS,SAAS,OAAO,YAAY,UAAU;AAAA,MACvD;AACA,YAAM;AAAA,IACR;AAEA,UAAM,iBAAiB;AAAA,MACrB,IAAI,OAAO;AAAA,MACX,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7B,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,WAAO,EAAE,GAAG,MAAM,YAAY,OAAO,WAAW;AAAA,EAClD;AAAA,EAEA,aAAa;AACX,WAAO,CAAC,oBAAoB,QAAQ;AAAA,EACtC;AACF;AAEA,eAAe,aAAa,YAAsD;AAChF,MAAI;AACF,WAAO,MAAM,eAAe,UAAU;AAAA,EACxC,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,qDAAuBC,MAAK,SAAS,UAAU,CAAC,SAAK,MAAgB,OAAO,EAAE;AAAA,EAChG;AACF;AAEA,SAAS,SAAS,OAAwC;AACxD,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,WAAO,CAAC;AAAA,EACV;AACA,SAAO;AACT;;;AOjIA,YAAY,UAAU;AAWf,IAAM,eAA2B;AAAA,EACtC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EAET,aAAa;AACX,WAAO,SAAS,UAAU,aAAa;AAAA,EACzC;AAAA,EAEA,MAAM,SAAgC;AACpC,WAAO,EAAE,SAAS,KAAK,SAAS,WAAW,MAAM,cAAc,KAAK,OAAO,EAAE;AAAA,EAC/E;AAAA,EAEA,MAAM,UAAkC;AACtC,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,SAAS,UAAU;AACxC,UAAM,YAAYC,UAAS,OAAO,eAAe;AACjD,UAAM,UAAUA,UAAS,UAAU,OAAO;AAC1C,UAAM,aAAa,OAAO,mBAAmB,aAAa,QAAQ,aAAa;AAE/E,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,aAAa,wCAAyB;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAA8C;AACvD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,UAAM,SAAS,MAAM,SAAS,UAAU;AACxC,UAAM,YAAYA,UAAS,OAAO,eAAe;AACjD,UAAM,UAAUA,UAAS,UAAU,OAAO;AAE1C,UAAM,UAAU;AAAA,MACd,gBAAgB;AAAA,MAChB,gCAAgC;AAAA,MAChC,oCAAoC;AAAA,MACpC,oCAAoC;AAAA,MACpC,qDAAqD,MAAM;AAAA,IAC7D;AAEA,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA,YAAY;AAAA,MACZ,eAAe,OAAO;AAAA,MACtB,cAAc;AAAA,MACd,SAAS;AAAA,QACP,EAAE,KAAK,kBAAkB,QAAQ,OAAO,mBAAmB,QAAQ,iBAAiB,SAAS,SAAS;AAAA,QACtG,EAAE,KAAK,gCAAgC,QAAQ,QAAQ,SAAS,QAAQ,8BAA8B,IAAI,SAAS,UAAU,SAAS,MAAM,EAAE;AAAA,QAC9I,EAAE,KAAK,oCAAoC,QAAQ,QAAQ,aAAa,QAAQ,kCAAkC,IAAI,SAAS,UAAU,SAAS,UAAU,EAAE;AAAA,QAC9J,EAAE,KAAK,oCAAoC,QAAQ,QAAQ,aAAa,QAAQ,kCAAkC,IAAI,SAAS,UAAU,SAAS,UAAU,EAAE;AAAA,QAC9J;AAAA,UACE,KAAK;AAAA,UACL,QAAQ,QAAQ,8BAA8B,MAAM,SAAS,SAAS,UAAU,SAAS,2BAA2B;AAAA,QACtH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,OAA8C;AACxD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,OAAO,MAAM,KAAK,KAAK,KAAK;AAClC,UAAM,SAAS,MAAM,aAAa,KAAK,IAAI,UAAU;AAErD,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,UAAU;AACxC,YAAM,YAAYA,UAAS,OAAO,eAAe;AACjD,aAAO,iBAAiB;AACxB,aAAO,kBAAkB;AAAA,QACvB,GAAG;AAAA,QACH,SAAS;AAAA,UACP,GAAGA,UAAS,UAAU,OAAO;AAAA,UAC7B,MAAM;AAAA,UACN,UAAU;AAAA,UACV,UAAU;AAAA,UACV,2BAA2B,MAAM;AAAA,QACnC;AAAA,MACF;AACA,YAAM,UAAU,YAAiB,eAAU,MAAM,CAAC;AAAA,IACpD,SAAS,OAAO;AACd,UAAI,OAAO,WAAW,OAAO,YAAY;AACvC,cAAMC,MAAK,MAAM,OAAO,aAAkB;AAC1C,cAAMA,IAAG,SAAS,OAAO,YAAY,UAAU;AAAA,MACjD;AACA,YAAM;AAAA,IACR;AAEA,UAAM,iBAAiB;AAAA,MACrB,IAAI,OAAO;AAAA,MACX,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7B,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,WAAO,EAAE,GAAG,MAAM,YAAY,OAAO,WAAW;AAAA,EAClD;AAAA,EAEA,aAAa;AACX,WAAO,CAAC,mBAAmB,OAAO;AAAA,EACpC;AACF;AAEA,eAAe,SAAS,YAAyC;AAC/D,QAAM,UAAU,MAAM,SAAS,UAAU;AACzC,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,CAAC;AAAA,EACV;AACA,QAAM,SAAc,WAAM,OAAO;AACjC,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,UAAM,IAAI,MAAM,GAAG,UAAU,8BAA8B;AAAA,EAC7D;AACA,SAAO;AACT;AAEA,SAASD,UAAS,OAA4B;AAC5C,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,WAAO,CAAC;AAAA,EACV;AACA,SAAO;AACT;AAEA,SAAS,UAAU,QAAoB,KAA+B;AACpE,SAAO,OAAO,SAAS,WAAW;AACpC;;;AC1JO,SAAS,gBAAgB,SAAiB,QAAwC;AACvF,QAAM,QAAQ,UAAU,QAAQ,MAAM,OAAO,IAAI,CAAC;AAClD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,YAAY,MAAM,IAAI,CAAC,SAAS;AACpC,UAAM,QAAQ,KAAK,MAAM,kCAAkC;AAC3D,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,MAAM,CAAC;AACnB,QAAI,EAAE,OAAO,SAAS;AACpB,aAAO;AAAA,IACT;AAEA,SAAK,IAAI,GAAG;AACZ,WAAO,GAAG,GAAG,IAAI,SAAS,OAAO,GAAG,CAAC,CAAC;AAAA,EACxC,CAAC;AAED,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,gBAAU,KAAK,GAAG,GAAG,IAAI,SAAS,KAAK,CAAC,EAAE;AAAA,IAC5C;AAAA,EACF;AAEA,SAAO,GAAG,UAAU,OAAO,CAAC,MAAM,UAAU,KAAK,SAAS,KAAK,QAAQ,UAAU,SAAS,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA;AACzG;AAEA,SAAS,SAAS,OAAuB;AACvC,SAAO,KAAK,UAAU,KAAK;AAC7B;;;ACpBA,IAAME,cAAa,CAAC,YAAoB;AAAA,EACtC,gBAAgB;AAAA,EAChB,wBAAwB;AAC1B;AAEO,IAAM,gBAA4B;AAAA,EACvC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EAET,aAAa;AACX,WAAO,SAAS,WAAW,MAAM;AAAA,EACnC;AAAA,EAEA,MAAM,SAAgC;AACpC,WAAO,EAAE,SAAS,KAAK,SAAS,WAAW,MAAM,cAAc,KAAK,OAAO,EAAE;AAAA,EAC/E;AAAA,EAEA,MAAM,UAAkC;AACtC,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,UAAW,MAAM,SAAS,UAAU,KAAM;AAChD,UAAM,aAAa,WAAW,SAAS,gBAAgB,KAAK,WAAW,SAAS,0BAA0B,gBAAgB;AAE1H,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,aAAa,mCAAoB;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAA8C;AACvD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,UAAM,UAAW,MAAM,SAAS,UAAU,KAAM;AAChD,UAAM,UAAUA,YAAW,MAAM,MAAM;AAEvC,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA,YAAY;AAAA,MACZ,eAAe,OAAO;AAAA,MACtB,cAAc;AAAA,MACd,SAAS,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,QACtD;AAAA,QACA,QAAQ,WAAW,SAAS,KAAK,KAAK,IAAI,SAAS,WAAW,SAAS,GAAG,IAAI,WAAW;AAAA,MAC3F,EAAE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,OAA8C;AACxD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,OAAO,MAAM,KAAK,KAAK,KAAK;AAClC,UAAM,SAAS,MAAM,aAAa,KAAK,IAAI,UAAU;AAErD,QAAI;AACF,YAAM,UAAW,MAAM,SAAS,UAAU,KAAM;AAChD,YAAM,UAAU,YAAY,gBAAgB,SAASA,YAAW,MAAM,MAAM,CAAC,CAAC;AAAA,IAChF,SAAS,OAAO;AACd,UAAI,OAAO,WAAW,OAAO,YAAY;AACvC,cAAMC,MAAK,MAAM,OAAO,aAAkB;AAC1C,cAAMA,IAAG,SAAS,OAAO,YAAY,UAAU;AAAA,MACjD;AACA,YAAM;AAAA,IACR;AAEA,UAAM,iBAAiB;AAAA,MACrB,IAAI,OAAO;AAAA,MACX,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7B,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,WAAO,EAAE,GAAG,MAAM,YAAY,OAAO,WAAW;AAAA,EAClD;AAAA,EAEA,aAAa;AACX,WAAO,CAAC,oBAAoB,QAAQ;AAAA,EACtC;AACF;AAEA,SAAS,WAAW,SAAiB,KAAa,OAAyB;AACzE,QAAM,UAAU,IAAI,OAAO,QAAQ,aAAa,GAAG,CAAC,sBAAsB,GAAG;AAC7E,QAAM,QAAQ,QAAQ,MAAM,OAAO;AACnC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM;AACtC;AAEA,SAAS,QAAQ,OAAuB;AACtC,MAAK,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAAO,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAAI;AACpG,WAAO,MAAM,MAAM,GAAG,EAAE;AAAA,EAC1B;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;;;AC1HO,IAAM,WAAyC;AAAA,EACpD,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACV;AAEO,SAAS,YAAY,SAAmC;AAC7D,SAAO,QAAQ,IAAI,CAAC,WAAW,SAAS,MAAM,CAAC;AACjD;;;ACdA,OAAO,WAAW;AAEX,IAAM,SAAS;AAAA,EACpB,KAAK,SAAuB;AAC1B,YAAQ,IAAI,MAAM,KAAK,OAAO,CAAC;AAAA,EACjC;AAAA,EACA,QAAQ,SAAuB;AAC7B,YAAQ,IAAI,MAAM,MAAM,OAAO,CAAC;AAAA,EAClC;AAAA,EACA,KAAK,SAAuB;AAC1B,YAAQ,IAAI,MAAM,OAAO,OAAO,CAAC;AAAA,EACnC;AAAA,EACA,MAAM,SAAuB;AAC3B,YAAQ,MAAM,MAAM,IAAI,OAAO,CAAC;AAAA,EAClC;AAAA,EACA,MAAM,SAAuB;AAC3B,YAAQ,IAAI,OAAO;AAAA,EACrB;AACF;;;ACZA,eAAsB,eAAe,gBAAgD;AACnF,MAAI,QAAQ,IAAI,8BAA8B,KAAK;AACjD,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,IAAI;AAEzD,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,8BAA8B,YAAY,WAAW;AAAA,MAChF,QAAQ,WAAW;AAAA,MACnB,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,cAAc,GAAG,YAAY,IAAI,cAAc;AAAA,MACjD;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,IACT;AAEA,UAAM,SAAU,MAAM,SAAS,KAAK;AACpC,QAAI,OAAO,WAAW,gBAAgB,OAAO,SAAS,cAAc,IAAI,GAAG;AACzE,aAAO,OAAO;AAAA,IAChB;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAEO,SAAS,gBAAgB,MAAc,OAAuB;AACnE,QAAM,YAAY,iBAAiB,IAAI;AACvC,QAAM,aAAa,iBAAiB,KAAK;AAEzC,WAAS,QAAQ,GAAG,QAAQ,KAAK,IAAI,UAAU,QAAQ,WAAW,MAAM,GAAG,SAAS,GAAG;AACrF,UAAM,WAAW,UAAU,KAAK,KAAK;AACrC,UAAM,YAAY,WAAW,KAAK,KAAK;AACvC,QAAI,WAAW,WAAW;AACxB,aAAO;AAAA,IACT;AACA,QAAI,WAAW,WAAW;AACxB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,SAA2B;AACnD,SAAO,QACJ,QAAQ,MAAM,EAAE,EAChB,MAAM,MAAM,EACZ,IAAI,CAAC,SAAS,OAAO,SAAS,MAAM,EAAE,CAAC,EACvC,IAAI,CAAC,SAAU,OAAO,SAAS,IAAI,IAAI,OAAO,CAAE;AACrD;;;AdtCA,eAAsB,OAAO,OAAO,QAAQ,MAAqB;AAC/D,QAAM,UAAU,IAAI,QAAQ;AAE5B,UACG,KAAK,YAAY,EACjB,YAAY,0DAA0D,EACtE,QAAQ,eAAe;AAE1B,UACG,QAAQ,QAAQ,EAAE,WAAW,KAAK,CAAC,EACnC,YAAY,wDAAwD,EACpE,OAAO,mBAAmB,iBAAiB,EAC3C,OAAO,2BAA2B,sCAAsC,EACxE,OAAO,aAAa,mBAAmB,EACvC,OAAO,aAAa,oCAAoC,EACxD,OAAO,WAAW,gEAAgE,EAClF,OAAO,OAAO,YAAyB;AACtC,UAAM,YAAY,OAAO;AAAA,EAC3B,CAAC;AAEH,UACG,QAAQ,QAAQ,EAChB,YAAY,0CAA0C,EACtD,OAAO,YAAY;AAClB,UAAM,cAAc;AAAA,EACtB,CAAC;AAEH,UACG,QAAQ,QAAQ,EAChB,YAAY,0DAA0D,EACtE,OAAO,YAAY;AAClB,UAAM,cAAc;AAAA,EACtB,CAAC;AAEH,UACG,QAAQ,OAAO,EACf,YAAY,iDAAiD,EAC7D,OAAO,2BAA2B,sCAAsC,EACxE,OAAO,aAAa,mBAAmB,EACvC,OAAO,OAAO,YAA2B;AACxC,UAAM,aAAa,OAAO;AAAA,EAC5B,CAAC;AAEH,MAAI;AACF,UAAM,wBAAwB;AAC9B,UAAM,QAAQ,WAAW,IAAI;AAAA,EAC/B,SAAS,OAAO;AACd,WAAO,MAAO,MAAgB,OAAO;AACrC,YAAQ,WAAW;AAAA,EACrB;AACF;AAEA,eAAe,0BAAyC;AACtD,QAAM,gBAAgB,MAAM,eAAe,eAAe;AAC1D,MAAI,CAAC,eAAe;AAClB;AAAA,EACF;AAEA,SAAO,KAAK,4BAAQ,YAAY,IAAI,aAAa,kCAAS,eAAe,kDAAyB,YAAY,SAAS;AACzH;AAEA,eAAe,YAAY,SAAqC;AAC9D,QAAM,UAAU,QAAQ,UAAU,aAAa,QAAQ,OAAO,IAAI,MAAM,cAAc;AACtF,QAAM,SAAS,QAAQ,KAAK,KAAK,KAAM,MAAM,SAAS,EAAE,SAAS,uCAAwB,MAAM,IAAI,CAAC;AAEpG,MAAI,CAAC,OAAO,KAAK,GAAG;AAClB,UAAM,IAAI,MAAM,gDAAuB;AAAA,EACzC;AAEA,QAAM,QAAoB;AAAA,IACxB,QAAQ,OAAO,KAAK;AAAA,IACpB;AAAA,IACA,KAAK,QAAQ,QAAQ,GAAG;AAAA,IACxB,QAAQ,QAAQ,QAAQ,MAAM;AAAA,IAC9B,OAAO,QAAQ,QAAQ,KAAK;AAAA,EAC9B;AAEA,SAAO,KAAK,qCAAiB,gBAAgB,EAAE;AAC/C,SAAO,KAAK,gBAAgB,WAAW,MAAM,MAAM,CAAC,EAAE;AAEtD,QAAM,mBAAmB,YAAY,OAAO;AAC5C,QAAM,YAAY,MAAM,eAAe,gBAAgB;AACvD,QAAM,UAAU,UAAU,OAAO,CAAC,WAAW,CAAC,OAAO,SAAS;AAC9D,MAAI,QAAQ,SAAS,KAAK,CAAC,MAAM,OAAO;AACtC,WAAO,MAAM,EAAE;AACf,WAAO,KAAK,4LAAgD;AAC5D,eAAW,UAAU,SAAS;AAC5B,aAAO,MAAM,KAAK,OAAO,IAAI,KAAK,kBAAkB,OAAO,MAAM,CAAC,EAAE;AAAA,IACtE;AACA,WAAO,MAAM,EAAE;AACf,WAAO,MAAM,0GAA0B;AACvC;AAAA,EACF;AAEA,QAAM,QAAQ,CAAC;AACf,aAAW,WAAW,kBAAkB;AACtC,UAAM,KAAK,MAAM,QAAQ,KAAK,KAAK,CAAC;AAAA,EACtC;AAEA,aAAW,KAAK;AAEhB,MAAI,MAAM,QAAQ;AAChB,WAAO,KAAK,sEAAoB;AAChC;AAAA,EACF;AAEA,MAAI,CAAC,MAAM,KAAK;AACd,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAU;AACb,aAAO,KAAK,sCAAQ;AACpB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,WAAW,kBAAkB;AACtC,UAAM,UAAU,IAAI,4BAAQ,QAAQ,IAAI,KAAK,EAAE,MAAM;AACrD,QAAI;AACF,YAAM,OAAO,MAAM,QAAQ,MAAM,KAAK;AACtC,cAAQ,QAAQ,GAAG,QAAQ,IAAI,8BAAU,KAAK,UAAU,EAAE;AAC1D,UAAI,KAAK,YAAY;AACnB,eAAO,MAAMC,OAAM,IAAI,aAAa,KAAK,UAAU,EAAE,CAAC;AAAA,MACxD;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,GAAG,QAAQ,IAAI,2BAAO;AACnC,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO,QAAQ,oDAAiB;AAChC,SAAO,MAAM,EAAE;AACf,SAAO,MAAM,2BAAO;AACpB,aAAW,WAAW,kBAAkB;AACtC,WAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,QAAQ,WAAW,EAAE,KAAK,KAAK,CAAC,EAAE;AAAA,EACvE;AACF;AAQA,eAAe,eAAe,kBAA8E;AAC1G,QAAM,UAA6B,CAAC;AACpC,SAAO,MAAM,EAAE;AACf,SAAO,MAAM,2BAAO;AACpB,aAAW,WAAW,kBAAkB;AACtC,UAAM,CAAC,UAAU,OAAO,IAAI,MAAM,QAAQ,IAAI,CAAC,QAAQ,OAAO,GAAG,QAAQ,QAAQ,CAAC,CAAC;AACnF,YAAQ,KAAK;AAAA,MACX,QAAQ,QAAQ;AAAA,MAChB,MAAM,QAAQ;AAAA,MACd,WAAW,SAAS;AAAA,IACtB,CAAC;AACD,WAAO,MAAM,KAAK,QAAQ,IAAI,EAAE;AAChC,WAAO,MAAM,UAAU,SAAS,YAAYA,OAAM,MAAM,oBAAK,IAAIA,OAAM,OAAO,0BAAM,CAAC,KAAK,SAAS,OAAO,GAAG;AAC7G,WAAO,MAAM,+BAAW,QAAQ,SAASA,OAAM,MAAM,cAAI,IAAIA,OAAM,OAAO,oBAAK,CAAC,EAAE;AAClF,WAAO,MAAM,mBAAS,QAAQ,UAAU,EAAE;AAC1C,WAAO,MAAM,cAAc,QAAQ,aAAaA,OAAM,MAAM,oBAAK,IAAIA,OAAM,OAAO,oBAAK,CAAC,EAAE;AAAA,EAC5F;AACA,SAAO;AACT;AAEA,eAAe,gBAA+B;AAC5C,aAAW,WAAW,OAAO,OAAO,QAAQ,GAAG;AAC7C,UAAM,UAAU,MAAM,QAAQ,QAAQ;AACtC,UAAM,QAAQ,QAAQ,aAAaA,OAAM,MAAM,YAAY,IAAIA,OAAM,OAAO,gBAAgB;AAC5F,WAAO,MAAM,GAAG,QAAQ,IAAI,KAAK,KAAK,EAAE;AACxC,WAAO,MAAM,WAAW,QAAQ,UAAU,EAAE;AAC5C,WAAO,MAAM,KAAK,QAAQ,OAAO,EAAE;AAAA,EACrC;AACF;AAEA,eAAe,gBAA+B;AAC5C,SAAO,KAAK,qCAAiB,gBAAgB,EAAE;AAC/C,aAAW,WAAW,OAAO,OAAO,QAAQ,GAAG;AAC7C,UAAM,CAAC,UAAU,OAAO,IAAI,MAAM,QAAQ,IAAI,CAAC,QAAQ,OAAO,GAAG,QAAQ,QAAQ,CAAC,CAAC;AACnF,WAAO,MAAM,GAAG,QAAQ,IAAI,GAAG;AAC/B,WAAO,MAAM,cAAc,SAAS,YAAYA,OAAM,MAAM,OAAO,IAAIA,OAAM,OAAO,WAAW,CAAC,KAAK,SAAS,OAAO,GAAG;AACxH,WAAO,MAAM,aAAa,QAAQ,aAAaA,OAAM,MAAM,YAAY,IAAIA,OAAM,OAAO,gBAAgB,CAAC,EAAE;AAC3G,WAAO,MAAM,WAAW,QAAQ,UAAU,EAAE;AAAA,EAC9C;AACF;AAEA,eAAe,aAAa,SAAuC;AACjE,QAAM,UAAU,QAAQ,UAAU,aAAa,QAAQ,OAAO,IAAI,MAAM,cAAc;AAEtF,QAAM,UAAU,CAAC;AACjB,aAAW,UAAU,SAAS;AAC5B,UAAM,QAAQ,MAAM,eAAe,MAAM;AACzC,QAAI,OAAO;AACT,cAAQ,KAAK,KAAK;AAAA,IACpB,OAAO;AACL,aAAO,KAAK,GAAG,SAAS,MAAM,EAAE,IAAI,mEAAsB;AAAA,IAC5D;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB;AAAA,EACF;AAEA,SAAO,KAAK,6CAAU;AACtB,aAAW,SAAS,SAAS;AAC3B,WAAO,MAAM,KAAK,SAAS,MAAM,MAAM,EAAE,IAAI,KAAK,MAAM,UAAU,EAAE;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,KAAK;AAChB,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAU;AACb,aAAO,KAAK,sCAAQ;AACpB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,SAAS,SAAS;AAC3B,UAAM,aAAa,KAAK;AACxB,WAAO,QAAQ,GAAG,SAAS,MAAM,MAAM,EAAE,IAAI,2BAAO;AAAA,EACtD;AACF;AAEA,SAAS,WAAW,OAAiE;AACnF,SAAO,MAAM,EAAE;AACf,SAAO,MAAM,yDAAY;AACzB,aAAW,QAAQ,OAAO;AACxB,WAAO,MAAM,KAAK,KAAK,IAAI,EAAE;AAC7B,WAAO,MAAM,WAAW,KAAK,UAAU,EAAE;AACzC,WAAO,MAAM,aAAa,KAAK,aAAa,EAAE;AAC9C,WAAO,MAAM,YAAY,KAAK,YAAY,EAAE;AAC5C,eAAW,UAAU,KAAK,SAAS;AACjC,aAAO,MAAM,KAAK,OAAO,OAAO,OAAO,CAAC,CAAC,IAAI,OAAO,GAAG,EAAE;AAAA,IAC3D;AAAA,EACF;AACA,SAAO,MAAM,EAAE;AACjB;AAEA,SAAS,aAAa,OAA2B;AAC/C,QAAM,aAAa,MAChB,MAAM,GAAG,EACT,IAAI,CAAC,WAAW,OAAO,KAAK,EAAE,YAAY,CAAC,EAC3C,OAAO,OAAO;AAEjB,MAAI,WAAW,SAAS,KAAK,GAAG;AAC9B,WAAO,CAAC,GAAG,OAAO;AAAA,EACpB;AAEA,QAAM,aAAa,WAAW,IAAI,CAAC,WAAW;AAC5C,QAAI,WAAW,eAAe;AAC5B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,UAAU,WAAW,OAAO,CAAC,WAAW,CAAC,QAAQ,SAAS,MAAkB,CAAC;AACnF,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,IAAI,MAAM,qCAAiB,QAAQ,KAAK,IAAI,CAAC,mDAA+B;AAAA,EACpF;AAEA,QAAM,SAAS,MAAM,KAAK,IAAI,IAAI,UAAU,CAAC;AAC7C,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,IAAI,MAAM,yDAAiB;AAAA,EACnC;AACA,SAAO;AACT;AAEA,eAAe,gBAAqC;AAClD,QAAM,WAAW,MAAM,SAAmB;AAAA,IACxC,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,MAAM,eAAe,OAAO,SAAS;AAAA,MACvC,EAAE,MAAM,aAAa,OAAO,QAAQ;AAAA,MACpC,EAAE,MAAM,cAAc,OAAO,SAAS;AAAA,IACxC;AAAA,IACA,UAAU;AAAA,EACZ,CAAC;AAED,SAAO;AACT;AAEA,SAAS,kBAAkB,QAA0B;AACnD,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;;;Ae1TA,KAAK,OAAO;","names":["chalk","path","path","path","path","path","process","fs","path","path","fs","path","asRecord","fs","ENV_VALUES","fs","chalk"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/constants.ts","../src/adapters/claude.ts","../src/core/backup.ts","../src/core/fs.ts","../src/core/paths.ts","../src/core/commands.ts","../src/core/manifest.ts","../src/core/mask.ts","../src/adapters/codex.ts","../src/core/env-file.ts","../src/adapters/gemini.ts","../src/adapters/index.ts","../src/core/logger.ts","../src/core/update-check.ts","../src/index.ts"],"sourcesContent":["import { checkbox, confirm, input as textInput, password, select } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport ora from 'ora';\nimport { LAYSOAI_BASE_URL, PACKAGE_NAME, PACKAGE_VERSION, TARGETS, TargetId } from './constants.js';\nimport { adapters, getAdapters } from './adapters/index.js';\nimport { SetupInput } from './adapters/types.js';\nimport { logger } from './core/logger.js';\nimport { maskSecret } from './core/mask.js';\nimport { latestEntryFor, restoreEntry } from './core/manifest.js';\nimport { checkForUpdate } from './core/update-check.js';\n\ntype InitOptions = {\n key?: string;\n targets?: string;\n yes?: boolean;\n dryRun?: boolean;\n force?: boolean;\n language?: string;\n codexModel?: string;\n};\n\ntype TargetOptions = {\n targets?: string;\n yes?: boolean;\n};\n\nexport async function runCli(argv = process.argv): Promise<void> {\n const program = new Command();\n\n program\n .name(PACKAGE_NAME)\n .description('Configure Claude Code, Codex, and Gemini to use LaysoAI.')\n .version(PACKAGE_VERSION);\n\n program\n .command('init', { isDefault: true })\n .description('Configure selected AI CLI tools with your LaysoAI key.')\n .option('-k, --key <key>', 'LaysoAI API key')\n .option('-t, --targets <targets>', 'Target CLIs: claude,codex,gemini,all')\n .option('-y, --yes', 'Skip confirmation')\n .option('--dry-run', 'Show changes without writing files')\n .option('--force', 'Write config even if the selected CLI command is not installed')\n .option('--language <language>', 'Language: zh-CN,en,fr,ru,ja,vi')\n .option('--codex-model <model>', 'Optional default model for Codex CLI. Omit to keep Codex default behavior.')\n .action(async (options: InitOptions) => {\n await initCommand(options);\n });\n\n program\n .command('config')\n .description('Show detected LaysoAI CLI configuration.')\n .action(async () => {\n await configCommand();\n });\n\n program\n .command('doctor')\n .description('Check CLI installation and LaysoAI configuration status.')\n .action(async () => {\n await doctorCommand();\n });\n\n program\n .command('reset')\n .description('Restore the latest backup generated by laysoai.')\n .option('-t, --targets <targets>', 'Target CLIs: claude,codex,gemini,all')\n .option('-y, --yes', 'Skip confirmation')\n .action(async (options: TargetOptions) => {\n await resetCommand(options);\n });\n\n try {\n await notifyIfUpdateAvailable();\n await program.parseAsync(argv);\n } catch (error) {\n logger.error((error as Error).message);\n process.exitCode = 1;\n }\n}\n\nasync function notifyIfUpdateAvailable(): Promise<void> {\n const latestVersion = await checkForUpdate(PACKAGE_VERSION);\n if (!latestVersion) {\n return;\n }\n\n logger.warn(`发现新版 ${PACKAGE_NAME}@${latestVersion},当前版本 ${PACKAGE_VERSION}。建议运行: npm install -g ${PACKAGE_NAME}@latest`);\n}\n\nasync function initCommand(options: InitOptions): Promise<void> {\n const language = await resolveLanguage(options);\n const messages = MESSAGES[language];\n const targets = options.targets ? parseTargets(options.targets, messages) : await promptTargets(messages);\n const apiKey = options.key?.trim() || (await password({ message: messages.apiKeyPrompt, mask: '*' }));\n\n if (!apiKey.trim()) {\n throw new Error(messages.emptyApiKey);\n }\n const codexModel = await resolveCodexModel(targets, options, messages);\n\n const input: SetupInput = {\n apiKey: apiKey.trim(),\n targets,\n yes: Boolean(options.yes),\n dryRun: Boolean(options.dryRun),\n force: Boolean(options.force),\n codexModel\n };\n\n logger.info(`${messages.requestUrl}: ${LAYSOAI_BASE_URL}`);\n logger.info(`LaysoAI Key: ${maskSecret(input.apiKey)}`);\n\n const selectedAdapters = getAdapters(targets);\n const preflight = await printPreflight(selectedAdapters, messages);\n const missing = preflight.filter((result) => !result.installed);\n if (missing.length > 0 && !input.force) {\n logger.plain('');\n logger.warn(messages.missingCliStop);\n for (const result of missing) {\n logger.plain(`- ${result.name}: ${installCommandFor(result.target)}`);\n }\n logger.plain('');\n logger.plain(messages.forceHint);\n return;\n }\n\n const plans = [];\n for (const adapter of selectedAdapters) {\n plans.push(await adapter.plan(input));\n }\n\n printPlans(plans, messages);\n\n if (input.dryRun) {\n logger.warn(messages.dryRun);\n return;\n }\n\n if (!input.yes) {\n const approved = await confirm({\n message: messages.confirmWrite,\n default: true\n });\n if (!approved) {\n logger.warn(messages.cancelled);\n return;\n }\n }\n\n for (const adapter of selectedAdapters) {\n const spinner = ora(`${messages.configuring} ${adapter.name}...`).start();\n try {\n const plan = await adapter.apply(input);\n spinner.succeed(`${adapter.name} ${messages.configComplete}: ${plan.configPath}`);\n if (plan.backupPath) {\n logger.plain(chalk.dim(` backup: ${plan.backupPath}`));\n }\n } catch (error) {\n spinner.fail(`${adapter.name} ${messages.configFailed}`);\n throw error;\n }\n }\n\n logger.success(messages.setupComplete);\n logger.plain('');\n logger.plain(`${messages.verifyCommands}:`);\n for (const adapter of selectedAdapters) {\n logger.plain(`- ${adapter.name}: ${adapter.verifyHint().join(' / ')}`);\n }\n logger.plain('');\n logger.plain(`${messages.usageIntro}:`);\n for (const adapter of selectedAdapters) {\n logger.plain(`- ${adapter.name}: ${adapter.command}`);\n }\n logger.success(messages.enjoy);\n}\n\ntype PreflightResult = {\n target: TargetId;\n name: string;\n installed: boolean;\n};\n\nasync function printPreflight(selectedAdapters: ReturnType<typeof getAdapters>, messages: UiMessages): Promise<PreflightResult[]> {\n const results: PreflightResult[] = [];\n logger.plain('');\n logger.plain(`${messages.envCheck}:`);\n for (const adapter of selectedAdapters) {\n const [detected, current] = await Promise.all([adapter.detect(), adapter.inspect()]);\n results.push({\n target: adapter.id,\n name: adapter.name,\n installed: detected.installed\n });\n logger.plain(`- ${adapter.name}`);\n logger.plain(` CLI: ${detected.installed ? chalk.green(messages.installed) : chalk.yellow(messages.notFound)} (${detected.command})`);\n logger.plain(` ${messages.configFile}: ${current.exists ? chalk.green(messages.exists) : chalk.yellow(messages.notExists)}`);\n logger.plain(` ${messages.path}: ${current.configPath}`);\n logger.plain(` LaysoAI: ${current.configured ? chalk.green(messages.configured) : chalk.yellow(messages.notConfigured)}`);\n }\n return results;\n}\n\nasync function configCommand(): Promise<void> {\n for (const adapter of Object.values(adapters)) {\n const current = await adapter.inspect();\n const state = current.configured ? chalk.green('configured') : chalk.yellow('not configured');\n logger.plain(`${current.name}: ${state}`);\n logger.plain(` path: ${current.configPath}`);\n logger.plain(` ${current.summary}`);\n }\n}\n\nasync function doctorCommand(): Promise<void> {\n logger.info(`LaysoAI 请求地址: ${LAYSOAI_BASE_URL}`);\n for (const adapter of Object.values(adapters)) {\n const [detected, current] = await Promise.all([adapter.detect(), adapter.inspect()]);\n logger.plain(`${adapter.name}:`);\n logger.plain(` command: ${detected.installed ? chalk.green('found') : chalk.yellow('not found')} (${detected.command})`);\n logger.plain(` config: ${current.configured ? chalk.green('configured') : chalk.yellow('not configured')}`);\n logger.plain(` path: ${current.configPath}`);\n }\n}\n\nasync function resetCommand(options: TargetOptions): Promise<void> {\n const targets = options.targets ? parseTargets(options.targets) : await promptTargets(MESSAGES.en);\n\n const entries = [];\n for (const target of targets) {\n const entry = await latestEntryFor(target);\n if (entry) {\n entries.push(entry);\n } else {\n logger.warn(`${adapters[target].name}: 没有找到 laysoai 备份记录。`);\n }\n }\n\n if (entries.length === 0) {\n return;\n }\n\n logger.warn('将恢复以下配置:');\n for (const entry of entries) {\n logger.plain(`- ${adapters[entry.target].name}: ${entry.configPath}`);\n }\n\n if (!options.yes) {\n const approved = await confirm({\n message: '确认恢复最近一次备份吗?',\n default: false\n });\n if (!approved) {\n logger.warn('已取消恢复。');\n return;\n }\n }\n\n for (const entry of entries) {\n await restoreEntry(entry);\n logger.success(`${adapters[entry.target].name} 已恢复。`);\n }\n}\n\nfunction printPlans(plans: Awaited<ReturnType<typeof adapters.claude.plan>>[], messages: UiMessages): void {\n logger.plain('');\n logger.plain(`${messages.changePlan}:`);\n for (const plan of plans) {\n logger.plain(`- ${plan.name}`);\n logger.plain(` path: ${plan.configPath}`);\n logger.plain(` ${messages.before}: ${plan.beforeSummary}`);\n logger.plain(` ${messages.after}: ${plan.afterSummary}`);\n for (const change of plan.changes) {\n logger.plain(` ${change.action.padEnd(6)} ${change.key}`);\n }\n }\n logger.plain('');\n}\n\nfunction parseTargets(value: string, messages = MESSAGES.en): TargetId[] {\n const rawTargets = value\n .split(',')\n .map((target) => target.trim().toLowerCase())\n .filter(Boolean);\n\n if (rawTargets.includes('all')) {\n return [...TARGETS];\n }\n\n const normalized = rawTargets.map((target) => {\n if (target === 'claude-code') {\n return 'claude';\n }\n return target;\n });\n\n const invalid = normalized.filter((target) => !TARGETS.includes(target as TargetId));\n if (invalid.length > 0) {\n throw new Error(`${messages.invalidTargets}: ${invalid.join(', ')}. ${messages.availableTargets}: claude,codex,gemini,all`);\n }\n\n const unique = Array.from(new Set(normalized)) as TargetId[];\n if (unique.length === 0) {\n throw new Error(messages.chooseAtLeastOneTarget);\n }\n return unique;\n}\n\nasync function promptTargets(messages: UiMessages): Promise<TargetId[]> {\n const selected = await checkbox<TargetId>({\n message: messages.targetPrompt,\n choices: [\n { name: 'Claude Code', value: 'claude' },\n { name: 'Codex CLI', value: 'codex' },\n { name: 'Gemini CLI', value: 'gemini' }\n ],\n required: true\n });\n\n return selected;\n}\n\nasync function resolveCodexModel(targets: TargetId[], options: InitOptions, messages: UiMessages): Promise<string | undefined> {\n if (!targets.includes('codex')) {\n return undefined;\n }\n\n const optionModel = normalizeOptionalCodexModel(options.codexModel);\n if (optionModel !== null) {\n return optionModel;\n }\n\n if (options.yes) {\n return undefined;\n }\n\n const model = await textInput({\n message: messages.codexModelPrompt,\n default: ''\n });\n return normalizeOptionalCodexModel(model) ?? undefined;\n}\n\nfunction normalizeOptionalCodexModel(model?: string): string | undefined | null {\n if (model === undefined) {\n return null;\n }\n const trimmed = model.trim();\n if (!trimmed || ['none', 'skip', 'default'].includes(trimmed.toLowerCase())) {\n return undefined;\n }\n return trimmed;\n}\n\nfunction installCommandFor(target: TargetId): string {\n switch (target) {\n case 'claude':\n return 'npm install -g @anthropic-ai/claude-code';\n case 'codex':\n return 'npm install -g @openai/codex';\n case 'gemini':\n return 'npm install -g @google/gemini-cli';\n }\n}\n\ntype LanguageCode = 'zh-CN' | 'en' | 'fr' | 'ru' | 'ja' | 'vi';\n\ntype UiMessages = {\n languagePrompt: string;\n targetPrompt: string;\n apiKeyPrompt: string;\n codexModelPrompt: string;\n emptyApiKey: string;\n requestUrl: string;\n envCheck: string;\n installed: string;\n notFound: string;\n configFile: string;\n exists: string;\n notExists: string;\n path: string;\n configured: string;\n notConfigured: string;\n missingCliStop: string;\n forceHint: string;\n changePlan: string;\n before: string;\n after: string;\n dryRun: string;\n confirmWrite: string;\n cancelled: string;\n configuring: string;\n configComplete: string;\n configFailed: string;\n setupComplete: string;\n verifyCommands: string;\n usageIntro: string;\n enjoy: string;\n invalidTargets: string;\n availableTargets: string;\n chooseAtLeastOneTarget: string;\n};\n\nconst LANGUAGE_CHOICES: Array<{ name: string; value: LanguageCode }> = [\n { name: '简体中文', value: 'zh-CN' },\n { name: 'English', value: 'en' },\n { name: 'Français', value: 'fr' },\n { name: 'Русский', value: 'ru' },\n { name: '日本語', value: 'ja' },\n { name: 'Tiếng Việt', value: 'vi' }\n];\n\nconst MESSAGES: Record<LanguageCode, UiMessages> = {\n 'zh-CN': {\n languagePrompt: '请选择语言:',\n targetPrompt: '请选择需要配置的工具:',\n apiKeyPrompt: '请输入 LaysoAI API Key:',\n codexModelPrompt: 'Codex 默认模型,可选,回车跳过:',\n emptyApiKey: 'LaysoAI API Key 不能为空。',\n requestUrl: 'LaysoAI 请求地址',\n envCheck: '环境检查',\n installed: '已安装',\n notFound: '未检测到',\n configFile: '配置文件',\n exists: '存在',\n notExists: '不存在',\n path: '路径',\n configured: '已配置',\n notConfigured: '未配置',\n missingCliStop: '检测到目标 CLI 未安装,已停止写入配置。请先安装对应 CLI 后再运行 laysoai。',\n forceHint: '如果你确认要先写配置,可以追加 --force。',\n changePlan: '将执行以下配置修改',\n before: 'before',\n after: 'after',\n dryRun: 'dry-run 模式未写入任何文件。',\n confirmWrite: '确认直接修改以上本机 CLI 配置文件吗?',\n cancelled: '已取消配置。',\n configuring: '正在配置',\n configComplete: '配置完成',\n configFailed: '配置失败',\n setupComplete: 'LaysoAI 自动配置完成。',\n verifyCommands: '验证命令',\n usageIntro: '接下来可以这样使用',\n enjoy: '祝你使用 LaysoAI API 愉快!',\n invalidTargets: '不支持的 targets',\n availableTargets: '可用值',\n chooseAtLeastOneTarget: '请至少选择一个 target。'\n },\n en: {\n languagePrompt: 'Select language:',\n targetPrompt: 'Select tools to configure:',\n apiKeyPrompt: 'Enter LaysoAI API Key:',\n codexModelPrompt: 'Codex default model, optional. Press Enter to skip:',\n emptyApiKey: 'LaysoAI API Key cannot be empty.',\n requestUrl: 'LaysoAI request URL',\n envCheck: 'Environment check',\n installed: 'installed',\n notFound: 'not found',\n configFile: 'config file',\n exists: 'exists',\n notExists: 'missing',\n path: 'path',\n configured: 'configured',\n notConfigured: 'not configured',\n missingCliStop: 'Selected CLI command is not installed. Config write stopped. Install the CLI first, then run laysoai again.',\n forceHint: 'To write config before installing the CLI, add --force.',\n changePlan: 'Planned changes',\n before: 'before',\n after: 'after',\n dryRun: 'dry-run mode did not write any files.',\n confirmWrite: 'Modify the local CLI config files above?',\n cancelled: 'Setup cancelled.',\n configuring: 'Configuring',\n configComplete: 'configured',\n configFailed: 'failed',\n setupComplete: 'LaysoAI setup completed.',\n verifyCommands: 'Verification commands',\n usageIntro: 'Use it next with',\n enjoy: 'Enjoy using LaysoAI API!',\n invalidTargets: 'Unsupported targets',\n availableTargets: 'Available values',\n chooseAtLeastOneTarget: 'Select at least one target.'\n },\n fr: {\n languagePrompt: 'Choisissez la langue:',\n targetPrompt: 'Choisissez les outils a configurer:',\n apiKeyPrompt: 'Saisissez la cle API LaysoAI:',\n codexModelPrompt: 'Modele Codex par defaut, facultatif. Entree pour ignorer:',\n emptyApiKey: 'La cle API LaysoAI ne peut pas etre vide.',\n requestUrl: 'URL de requete LaysoAI',\n envCheck: 'Verification de l environnement',\n installed: 'installe',\n notFound: 'introuvable',\n configFile: 'fichier de configuration',\n exists: 'existe',\n notExists: 'manquant',\n path: 'chemin',\n configured: 'configure',\n notConfigured: 'non configure',\n missingCliStop: 'La CLI selectionnee n est pas installee. L ecriture de configuration est arretee. Installez d abord la CLI.',\n forceHint: 'Pour ecrire la configuration avant installation, ajoutez --force.',\n changePlan: 'Modifications prevues',\n before: 'avant',\n after: 'apres',\n dryRun: 'Le mode dry-run n a ecrit aucun fichier.',\n confirmWrite: 'Modifier les fichiers de configuration CLI locaux ci-dessus ?',\n cancelled: 'Configuration annulee.',\n configuring: 'Configuration de',\n configComplete: 'configure',\n configFailed: 'echec',\n setupComplete: 'Configuration LaysoAI terminee.',\n verifyCommands: 'Commandes de verification',\n usageIntro: 'Utilisez ensuite',\n enjoy: 'Bonne utilisation de LaysoAI API !',\n invalidTargets: 'Targets non pris en charge',\n availableTargets: 'Valeurs disponibles',\n chooseAtLeastOneTarget: 'Selectionnez au moins un target.'\n },\n ru: {\n languagePrompt: 'Выберите язык:',\n targetPrompt: 'Выберите инструменты для настройки:',\n apiKeyPrompt: 'Введите API Key LaysoAI:',\n codexModelPrompt: 'Модель Codex по умолчанию, необязательно. Enter чтобы пропустить:',\n emptyApiKey: 'API Key LaysoAI не может быть пустым.',\n requestUrl: 'URL запроса LaysoAI',\n envCheck: 'Проверка окружения',\n installed: 'установлено',\n notFound: 'не найдено',\n configFile: 'файл конфигурации',\n exists: 'существует',\n notExists: 'отсутствует',\n path: 'путь',\n configured: 'настроено',\n notConfigured: 'не настроено',\n missingCliStop: 'Выбранная CLI не установлена. Запись конфигурации остановлена. Сначала установите CLI.',\n forceHint: 'Чтобы записать конфигурацию до установки CLI, добавьте --force.',\n changePlan: 'Планируемые изменения',\n before: 'до',\n after: 'после',\n dryRun: 'dry-run не записал файлы.',\n confirmWrite: 'Изменить указанные локальные файлы конфигурации CLI?',\n cancelled: 'Настройка отменена.',\n configuring: 'Настройка',\n configComplete: 'настроено',\n configFailed: 'ошибка',\n setupComplete: 'Настройка LaysoAI завершена.',\n verifyCommands: 'Команды проверки',\n usageIntro: 'Далее используйте',\n enjoy: 'Приятного использования LaysoAI API!',\n invalidTargets: 'Неподдерживаемые targets',\n availableTargets: 'Доступные значения',\n chooseAtLeastOneTarget: 'Выберите хотя бы один target.'\n },\n ja: {\n languagePrompt: '言語を選択してください:',\n targetPrompt: '設定するツールを選択してください:',\n apiKeyPrompt: 'LaysoAI API Key を入力してください:',\n codexModelPrompt: 'Codex のデフォルトモデル、省略可。Enter でスキップ:',\n emptyApiKey: 'LaysoAI API Key は空にできません。',\n requestUrl: 'LaysoAI リクエスト URL',\n envCheck: '環境チェック',\n installed: 'インストール済み',\n notFound: '未検出',\n configFile: '設定ファイル',\n exists: '存在',\n notExists: '存在しない',\n path: 'パス',\n configured: '設定済み',\n notConfigured: '未設定',\n missingCliStop: '選択した CLI がインストールされていません。設定の書き込みを停止しました。先に CLI をインストールしてください。',\n forceHint: 'CLI のインストール前に設定を書き込む場合は --force を追加してください。',\n changePlan: '変更予定',\n before: 'before',\n after: 'after',\n dryRun: 'dry-run モードではファイルを書き込みませんでした。',\n confirmWrite: '上記のローカル CLI 設定ファイルを変更しますか?',\n cancelled: '設定をキャンセルしました。',\n configuring: '設定中',\n configComplete: '設定完了',\n configFailed: '設定失敗',\n setupComplete: 'LaysoAI の自動設定が完了しました。',\n verifyCommands: '確認コマンド',\n usageIntro: '次のコマンドで使用できます',\n enjoy: 'LaysoAI API を快適にご利用ください!',\n invalidTargets: '未対応の targets',\n availableTargets: '利用可能な値',\n chooseAtLeastOneTarget: '少なくとも 1 つの target を選択してください。'\n },\n vi: {\n languagePrompt: 'Chon ngon ngu:',\n targetPrompt: 'Chon cong cu can cau hinh:',\n apiKeyPrompt: 'Nhap LaysoAI API Key:',\n codexModelPrompt: 'Model mac dinh cho Codex, tuy chon. Nhan Enter de bo qua:',\n emptyApiKey: 'LaysoAI API Key khong duoc de trong.',\n requestUrl: 'URL yeu cau LaysoAI',\n envCheck: 'Kiem tra moi truong',\n installed: 'da cai dat',\n notFound: 'khong tim thay',\n configFile: 'tep cau hinh',\n exists: 'ton tai',\n notExists: 'khong ton tai',\n path: 'duong dan',\n configured: 'da cau hinh',\n notConfigured: 'chua cau hinh',\n missingCliStop: 'CLI da chon chua duoc cai dat. Da dung ghi cau hinh. Hay cai dat CLI truoc.',\n forceHint: 'Neu muon ghi cau hinh truoc khi cai CLI, them --force.',\n changePlan: 'Thay doi du kien',\n before: 'truoc',\n after: 'sau',\n dryRun: 'Che do dry-run khong ghi tep nao.',\n confirmWrite: 'Sua cac tep cau hinh CLI cuc bo o tren?',\n cancelled: 'Da huy cau hinh.',\n configuring: 'Dang cau hinh',\n configComplete: 'da cau hinh',\n configFailed: 'that bai',\n setupComplete: 'Cau hinh LaysoAI hoan tat.',\n verifyCommands: 'Lenh xac minh',\n usageIntro: 'Tiep theo co the dung',\n enjoy: 'Chuc ban su dung LaysoAI API vui ve!',\n invalidTargets: 'Targets khong duoc ho tro',\n availableTargets: 'Gia tri kha dung',\n chooseAtLeastOneTarget: 'Chon it nhat mot target.'\n }\n};\n\nasync function resolveLanguage(options: InitOptions): Promise<LanguageCode> {\n const parsed = normalizeLanguage(options.language);\n if (parsed) {\n return parsed;\n }\n\n logger.success('Welcome to LaysoAI API!');\n\n const shouldPrompt = !options.yes || !options.key || !options.targets;\n if (!shouldPrompt) {\n return 'en';\n }\n\n return select<LanguageCode>({\n message: MESSAGES.en.languagePrompt,\n choices: LANGUAGE_CHOICES,\n default: 'en'\n });\n}\n\nfunction normalizeLanguage(language?: string): LanguageCode | null {\n if (!language) {\n return null;\n }\n const normalized = language.trim().toLowerCase();\n if (normalized === 'zh' || normalized === 'zh-cn' || normalized === 'cn' || normalized === 'chinese') {\n return 'zh-CN';\n }\n if (normalized === 'en' || normalized === 'english') {\n return 'en';\n }\n if (normalized === 'fr' || normalized === 'francais' || normalized === 'français' || normalized === 'french') {\n return 'fr';\n }\n if (normalized === 'ru' || normalized === 'russian') {\n return 'ru';\n }\n if (normalized === 'ja' || normalized === 'jp' || normalized === 'japanese') {\n return 'ja';\n }\n if (normalized === 'vi' || normalized === 'vn' || normalized === 'vietnamese') {\n return 'vi';\n }\n return null;\n}\n","export const PACKAGE_NAME = 'laysoai';\nexport const PACKAGE_VERSION = '0.1.3';\nexport const LAYSOAI_BASE_URL = 'https://laysoai.com';\nexport const LAYSOAI_HOME_DIR = '.laysoai';\n\nexport const TARGETS = ['claude', 'codex', 'gemini'] as const;\nexport type TargetId = (typeof TARGETS)[number];\n","import path from 'node:path';\nimport { LAYSOAI_BASE_URL } from '../constants.js';\nimport { backupConfig } from '../core/backup.js';\nimport { commandExists } from '../core/commands.js';\nimport { readJsonObject, writeJsonObject, pathExists } from '../core/fs.js';\nimport { addManifestEntry } from '../core/manifest.js';\nimport { hasValue } from '../core/mask.js';\nimport { homePath } from '../core/paths.js';\nimport { CliAdapter, ConfigChangePlan, CurrentConfig, DetectResult, SetupInput } from './types.js';\n\nconst ENV_VALUES = (apiKey: string) => ({\n ANTHROPIC_BASE_URL: LAYSOAI_BASE_URL,\n ANTHROPIC_AUTH_TOKEN: apiKey,\n ANTHROPIC_API_KEY: apiKey\n});\n\nexport const claudeAdapter: CliAdapter = {\n id: 'claude',\n name: 'Claude Code',\n command: 'claude',\n\n configPath() {\n return homePath('.claude', 'settings.json');\n },\n\n async detect(): Promise<DetectResult> {\n return { command: this.command, installed: await commandExists(this.command) };\n },\n\n async inspect(): Promise<CurrentConfig> {\n const configPath = this.configPath();\n const exists = await pathExists(configPath);\n if (!exists) {\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured: false,\n summary: '配置文件不存在'\n };\n }\n\n const config = await readJsonObject(configPath);\n const env = asRecord(config.env);\n const configured = env.ANTHROPIC_BASE_URL === LAYSOAI_BASE_URL && (hasValue(env.ANTHROPIC_AUTH_TOKEN) || hasValue(env.ANTHROPIC_API_KEY));\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured,\n summary: configured ? '已配置 LaysoAI env' : '未检测到完整 LaysoAI env'\n };\n },\n\n async plan(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const before = await this.inspect();\n const config = await safeReadJson(configPath);\n const env = asRecord(config.env);\n const desired = ENV_VALUES(input.apiKey);\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n backupPath: null,\n beforeSummary: before.summary,\n afterSummary: '写入 ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN、ANTHROPIC_API_KEY',\n changes: Object.entries(desired).map(([key, value]) => ({\n key,\n action: env[key] === value ? 'skip' : key in env ? 'update' : 'add'\n }))\n };\n },\n\n async apply(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const plan = await this.plan(input);\n const backup = await backupConfig(this.id, configPath);\n\n try {\n const config = await safeReadJson(configPath);\n const env = asRecord(config.env);\n config.env = {\n ...env,\n ...ENV_VALUES(input.apiKey)\n };\n await writeJsonObject(configPath, config);\n } catch (error) {\n if (backup.existed && backup.backupPath) {\n const original = await import('node:fs/promises');\n await original.copyFile(backup.backupPath, configPath);\n }\n throw error;\n }\n\n await addManifestEntry({\n id: backup.id,\n date: new Date().toISOString(),\n target: this.id,\n configPath,\n backupPath: backup.backupPath,\n existed: backup.existed\n });\n\n return { ...plan, backupPath: backup.backupPath };\n },\n\n verifyHint() {\n return ['claude --version', 'claude'];\n }\n};\n\nasync function safeReadJson(configPath: string): Promise<Record<string, unknown>> {\n try {\n return await readJsonObject(configPath);\n } catch (error) {\n throw new Error(`无法读取 Claude Code 配置 ${path.basename(configPath)}:${(error as Error).message}`);\n }\n}\n\nfunction asRecord(value: unknown): Record<string, string> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n return value as Record<string, string>;\n}\n","import path from 'node:path';\nimport { TargetId } from '../constants.js';\nimport { copyFileIfExists } from './fs.js';\nimport { laysoaiPath, timestampId } from './paths.js';\n\nexport type BackupResult = {\n id: string;\n backupPath: string | null;\n existed: boolean;\n};\n\nexport async function backupConfig(target: TargetId, configPath: string): Promise<BackupResult> {\n const id = timestampId();\n const backupPath = laysoaiPath('backups', target, id, path.basename(configPath));\n const existed = await copyFileIfExists(configPath, backupPath);\n\n return {\n id,\n backupPath: existed ? backupPath : null,\n existed\n };\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport async function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\nexport async function readText(filePath: string): Promise<string | null> {\n if (!(await pathExists(filePath))) {\n return null;\n }\n return fs.readFile(filePath, 'utf8');\n}\n\nexport async function writeText(filePath: string, content: string): Promise<void> {\n await ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content, 'utf8');\n}\n\nexport async function readJsonObject(filePath: string): Promise<Record<string, unknown>> {\n const content = await readText(filePath);\n if (!content || !content.trim()) {\n return {};\n }\n const parsed = JSON.parse(content) as unknown;\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`${filePath} must contain a JSON object.`);\n }\n return parsed as Record<string, unknown>;\n}\n\nexport async function writeJsonObject(filePath: string, value: Record<string, unknown>): Promise<void> {\n await writeText(filePath, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nexport async function copyFileIfExists(source: string, destination: string): Promise<boolean> {\n if (!(await pathExists(source))) {\n return false;\n }\n await ensureDir(path.dirname(destination));\n await fs.copyFile(source, destination);\n return true;\n}\n\nexport async function removeFileIfExists(filePath: string): Promise<void> {\n if (await pathExists(filePath)) {\n await fs.rm(filePath, { force: true });\n }\n}\n","import os from 'node:os';\nimport path from 'node:path';\nimport { LAYSOAI_HOME_DIR } from '../constants.js';\n\nexport function homePath(...parts: string[]): string {\n return path.join(os.homedir(), ...parts);\n}\n\nexport function laysoaiPath(...parts: string[]): string {\n return homePath(LAYSOAI_HOME_DIR, ...parts);\n}\n\nexport function timestampId(date = new Date()): string {\n return date.toISOString().replace(/[:.]/g, '-');\n}\n","import { spawn } from 'node:child_process';\nimport process from 'node:process';\n\nexport async function commandExists(command: string): Promise<boolean> {\n const checker = process.platform === 'win32' ? 'where' : 'command';\n const args = process.platform === 'win32' ? [command] : ['-v', command];\n\n return new Promise((resolve) => {\n const child = spawn(checker, args, {\n stdio: 'ignore',\n shell: process.platform !== 'win32'\n });\n\n child.on('error', () => resolve(false));\n child.on('close', (code) => resolve(code === 0));\n });\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { TargetId } from '../constants.js';\nimport { ensureDir, pathExists, readText, writeText } from './fs.js';\nimport { laysoaiPath } from './paths.js';\n\nexport type ManifestEntry = {\n id: string;\n date: string;\n target: TargetId;\n configPath: string;\n backupPath: string | null;\n existed: boolean;\n};\n\ntype Manifest = {\n version: 1;\n entries: ManifestEntry[];\n};\n\nconst MANIFEST_PATH = laysoaiPath('manifest.json');\n\nasync function readManifest(): Promise<Manifest> {\n const content = await readText(MANIFEST_PATH);\n if (!content) {\n return { version: 1, entries: [] };\n }\n const parsed = JSON.parse(content) as Manifest;\n return {\n version: 1,\n entries: Array.isArray(parsed.entries) ? parsed.entries : []\n };\n}\n\nasync function writeManifest(manifest: Manifest): Promise<void> {\n await ensureDir(path.dirname(MANIFEST_PATH));\n await writeText(MANIFEST_PATH, `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n\nexport async function addManifestEntry(entry: ManifestEntry): Promise<void> {\n const manifest = await readManifest();\n manifest.entries.push(entry);\n await writeManifest(manifest);\n}\n\nexport async function latestEntryFor(target: TargetId): Promise<ManifestEntry | null> {\n const manifest = await readManifest();\n const matches = manifest.entries.filter((entry) => entry.target === target);\n return matches.at(-1) ?? null;\n}\n\nexport async function restoreEntry(entry: ManifestEntry): Promise<void> {\n if (entry.existed && entry.backupPath) {\n if (!(await pathExists(entry.backupPath))) {\n throw new Error(`Backup file not found: ${entry.backupPath}`);\n }\n await ensureDir(path.dirname(entry.configPath));\n await fs.copyFile(entry.backupPath, entry.configPath);\n return;\n }\n\n await fs.rm(entry.configPath, { force: true });\n}\n","export function maskSecret(secret: string): string {\n if (secret.length <= 8) {\n return '*'.repeat(secret.length);\n }\n return `${secret.slice(0, 4)}...${secret.slice(-4)}`;\n}\n\nexport function hasValue(value: unknown): boolean {\n return typeof value === 'string' && value.trim().length > 0;\n}\n","import * as TOML from 'smol-toml';\nimport { LAYSOAI_BASE_URL } from '../constants.js';\nimport { backupConfig } from '../core/backup.js';\nimport { commandExists } from '../core/commands.js';\nimport { pathExists, readText, writeText } from '../core/fs.js';\nimport { addManifestEntry } from '../core/manifest.js';\nimport { homePath } from '../core/paths.js';\nimport { CliAdapter, ConfigChangePlan, CurrentConfig, DetectResult, SetupInput } from './types.js';\n\ntype TomlObject = Record<string, unknown>;\n\nexport const codexAdapter: CliAdapter = {\n id: 'codex',\n name: 'Codex CLI',\n command: 'codex',\n\n configPath() {\n return homePath('.codex', 'config.toml');\n },\n\n async detect(): Promise<DetectResult> {\n return { command: this.command, installed: await commandExists(this.command) };\n },\n\n async inspect(): Promise<CurrentConfig> {\n const configPath = this.configPath();\n const exists = await pathExists(configPath);\n if (!exists) {\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured: false,\n summary: '配置文件不存在'\n };\n }\n\n const config = await readToml(configPath);\n const providers = asRecord(config.model_providers);\n const laysoai = asRecord(providers.laysoai);\n const configured = config.model_provider === 'laysoai' && laysoai.base_url === LAYSOAI_BASE_URL;\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured,\n summary: configured ? '已配置 LaysoAI provider' : '未检测到 LaysoAI provider'\n };\n },\n\n async plan(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const before = await this.inspect();\n const config = await readToml(configPath);\n const providers = asRecord(config.model_providers);\n const laysoai = asRecord(providers.laysoai);\n\n const desired = {\n model_provider: 'laysoai',\n 'model_providers.laysoai.name': 'LaysoAI',\n 'model_providers.laysoai.base_url': LAYSOAI_BASE_URL,\n 'model_providers.laysoai.wire_api': 'responses',\n 'model_providers.laysoai.experimental_bearer_token': input.apiKey\n };\n const changes: ConfigChangePlan['changes'] = [\n { key: 'model_provider', action: config.model_provider === desired.model_provider ? 'skip' : 'update' },\n { key: 'model_providers.laysoai.name', action: laysoai.name === desired['model_providers.laysoai.name'] ? 'skip' : keyAction(laysoai, 'name') },\n { key: 'model_providers.laysoai.base_url', action: laysoai.base_url === desired['model_providers.laysoai.base_url'] ? 'skip' : keyAction(laysoai, 'base_url') },\n { key: 'model_providers.laysoai.wire_api', action: laysoai.wire_api === desired['model_providers.laysoai.wire_api'] ? 'skip' : keyAction(laysoai, 'wire_api') },\n {\n key: 'model_providers.laysoai.experimental_bearer_token',\n action: laysoai.experimental_bearer_token === input.apiKey ? 'skip' : keyAction(laysoai, 'experimental_bearer_token')\n }\n ];\n\n if (input.codexModel) {\n changes.push({ key: 'model', action: config.model === input.codexModel ? 'skip' : keyAction(config, 'model') });\n }\n if (isInvalidServiceTier(config.service_tier)) {\n changes.push({ key: 'service_tier', action: 'update' });\n }\n if (isInvalidServiceTier(laysoai.service_tier)) {\n changes.push({ key: 'model_providers.laysoai.service_tier', action: 'update' });\n }\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n backupPath: null,\n beforeSummary: before.summary,\n afterSummary: '写入 Codex LaysoAI provider 并设为默认 provider',\n changes\n };\n },\n\n async apply(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const plan = await this.plan(input);\n const backup = await backupConfig(this.id, configPath);\n\n try {\n const config = await readToml(configPath);\n const providers = asRecord(config.model_providers);\n const laysoaiProvider = {\n ...asRecord(providers.laysoai),\n name: 'LaysoAI',\n base_url: LAYSOAI_BASE_URL,\n wire_api: 'responses',\n experimental_bearer_token: input.apiKey\n };\n\n removeInvalidServiceTier(config);\n removeInvalidServiceTier(laysoaiProvider);\n config.model_provider = 'laysoai';\n if (input.codexModel) {\n config.model = input.codexModel;\n }\n config.model_providers = {\n ...providers,\n laysoai: laysoaiProvider\n };\n await writeText(configPath, TOML.stringify(config));\n } catch (error) {\n if (backup.existed && backup.backupPath) {\n const fs = await import('node:fs/promises');\n await fs.copyFile(backup.backupPath, configPath);\n }\n throw error;\n }\n\n await addManifestEntry({\n id: backup.id,\n date: new Date().toISOString(),\n target: this.id,\n configPath,\n backupPath: backup.backupPath,\n existed: backup.existed\n });\n\n return { ...plan, backupPath: backup.backupPath };\n },\n\n verifyHint() {\n return ['codex --version', 'codex'];\n }\n};\n\nasync function readToml(configPath: string): Promise<TomlObject> {\n const content = await readText(configPath);\n if (!content?.trim()) {\n return {};\n }\n const parsed = TOML.parse(content);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`${configPath} must contain a TOML object.`);\n }\n return parsed as TomlObject;\n}\n\nfunction asRecord(value: unknown): TomlObject {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n return value as TomlObject;\n}\n\nfunction keyAction(record: TomlObject, key: string): 'add' | 'update' {\n return key in record ? 'update' : 'add';\n}\n\nfunction isInvalidServiceTier(value: unknown): boolean {\n return typeof value === 'string' && value !== 'fast' && value !== 'flex';\n}\n\nfunction removeInvalidServiceTier(record: TomlObject): void {\n if (isInvalidServiceTier(record.service_tier)) {\n delete record.service_tier;\n }\n}\n","export function upsertEnvValues(content: string, values: Record<string, string>): string {\n const lines = content ? content.split(/\\r?\\n/) : [];\n const seen = new Set<string>();\n const nextLines = lines.map((line) => {\n const match = line.match(/^\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*=/);\n if (!match) {\n return line;\n }\n\n const key = match[1];\n if (!(key in values)) {\n return line;\n }\n\n seen.add(key);\n return `${key}=${quoteEnv(values[key])}`;\n });\n\n for (const [key, value] of Object.entries(values)) {\n if (!seen.has(key)) {\n nextLines.push(`${key}=${quoteEnv(value)}`);\n }\n }\n\n return `${nextLines.filter((line, index) => line.length > 0 || index < nextLines.length - 1).join('\\n')}\\n`;\n}\n\nfunction quoteEnv(value: string): string {\n return JSON.stringify(value);\n}\n","import { LAYSOAI_BASE_URL } from '../constants.js';\nimport { backupConfig } from '../core/backup.js';\nimport { commandExists } from '../core/commands.js';\nimport { upsertEnvValues } from '../core/env-file.js';\nimport { pathExists, readText, writeText } from '../core/fs.js';\nimport { addManifestEntry } from '../core/manifest.js';\nimport { homePath } from '../core/paths.js';\nimport { CliAdapter, ConfigChangePlan, CurrentConfig, DetectResult, SetupInput } from './types.js';\n\nconst ENV_VALUES = (apiKey: string) => ({\n GEMINI_API_KEY: apiKey,\n GOOGLE_GEMINI_BASE_URL: LAYSOAI_BASE_URL\n});\n\nexport const geminiAdapter: CliAdapter = {\n id: 'gemini',\n name: 'Gemini CLI',\n command: 'gemini',\n\n configPath() {\n return homePath('.gemini', '.env');\n },\n\n async detect(): Promise<DetectResult> {\n return { command: this.command, installed: await commandExists(this.command) };\n },\n\n async inspect(): Promise<CurrentConfig> {\n const configPath = this.configPath();\n const exists = await pathExists(configPath);\n if (!exists) {\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured: false,\n summary: '配置文件不存在'\n };\n }\n\n const content = (await readText(configPath)) ?? '';\n const configured = hasEnvLine(content, 'GEMINI_API_KEY') && hasEnvLine(content, 'GOOGLE_GEMINI_BASE_URL', LAYSOAI_BASE_URL);\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n exists,\n configured,\n summary: configured ? '已配置 LaysoAI env' : '未检测到完整 LaysoAI env'\n };\n },\n\n async plan(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const before = await this.inspect();\n const content = (await readText(configPath)) ?? '';\n const desired = ENV_VALUES(input.apiKey);\n\n return {\n target: this.id,\n name: this.name,\n configPath,\n backupPath: null,\n beforeSummary: before.summary,\n afterSummary: '写入 GEMINI_API_KEY、GOOGLE_GEMINI_BASE_URL',\n changes: Object.entries(desired).map(([key, value]) => ({\n key,\n action: hasEnvLine(content, key, value) ? 'skip' : hasEnvLine(content, key) ? 'update' : 'add'\n }))\n };\n },\n\n async apply(input: SetupInput): Promise<ConfigChangePlan> {\n const configPath = this.configPath();\n const plan = await this.plan(input);\n const backup = await backupConfig(this.id, configPath);\n\n try {\n const content = (await readText(configPath)) ?? '';\n await writeText(configPath, upsertEnvValues(content, ENV_VALUES(input.apiKey)));\n } catch (error) {\n if (backup.existed && backup.backupPath) {\n const fs = await import('node:fs/promises');\n await fs.copyFile(backup.backupPath, configPath);\n }\n throw error;\n }\n\n await addManifestEntry({\n id: backup.id,\n date: new Date().toISOString(),\n target: this.id,\n configPath,\n backupPath: backup.backupPath,\n existed: backup.existed\n });\n\n return { ...plan, backupPath: backup.backupPath };\n },\n\n verifyHint() {\n return ['gemini --version', 'gemini'];\n }\n};\n\nfunction hasEnvLine(content: string, key: string, value?: string): boolean {\n const matcher = new RegExp(`^\\\\s*${escapeRegExp(key)}\\\\s*=\\\\s*(.*)\\\\s*$`, 'm');\n const match = content.match(matcher);\n if (!match) {\n return false;\n }\n if (value === undefined) {\n return true;\n }\n return unquote(match[1].trim()) === value;\n}\n\nfunction unquote(value: string): string {\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n return value.slice(1, -1);\n }\n return value;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import { TargetId } from '../constants.js';\nimport { claudeAdapter } from './claude.js';\nimport { codexAdapter } from './codex.js';\nimport { geminiAdapter } from './gemini.js';\nimport { CliAdapter } from './types.js';\n\nexport const adapters: Record<TargetId, CliAdapter> = {\n claude: claudeAdapter,\n codex: codexAdapter,\n gemini: geminiAdapter\n};\n\nexport function getAdapters(targets: TargetId[]): CliAdapter[] {\n return targets.map((target) => adapters[target]);\n}\n","import chalk from 'chalk';\n\nexport const logger = {\n info(message: string): void {\n console.log(chalk.cyan(message));\n },\n success(message: string): void {\n console.log(chalk.green(message));\n },\n warn(message: string): void {\n console.log(chalk.yellow(message));\n },\n error(message: string): void {\n console.error(chalk.red(message));\n },\n plain(message: string): void {\n console.log(message);\n }\n};\n","import { PACKAGE_NAME } from '../constants.js';\n\ntype RegistryLatest = {\n version?: string;\n};\n\nexport async function checkForUpdate(currentVersion: string): Promise<string | null> {\n if (process.env.LAYSOAI_SKIP_UPDATE_CHECK === '1') {\n return null;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 1500);\n\n try {\n const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {\n signal: controller.signal,\n headers: {\n accept: 'application/json',\n 'user-agent': `${PACKAGE_NAME}/${currentVersion}`\n }\n });\n\n if (!response.ok) {\n return null;\n }\n\n const latest = (await response.json()) as RegistryLatest;\n if (latest.version && compareVersions(latest.version, currentVersion) > 0) {\n return latest.version;\n }\n return null;\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport function compareVersions(left: string, right: string): number {\n const leftParts = normalizeVersion(left);\n const rightParts = normalizeVersion(right);\n\n for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index += 1) {\n const leftPart = leftParts[index] ?? 0;\n const rightPart = rightParts[index] ?? 0;\n if (leftPart > rightPart) {\n return 1;\n }\n if (leftPart < rightPart) {\n return -1;\n }\n }\n\n return 0;\n}\n\nfunction normalizeVersion(version: string): number[] {\n return version\n .replace(/^v/, '')\n .split(/[.-]/)\n .map((part) => Number.parseInt(part, 10))\n .map((part) => (Number.isFinite(part) ? part : 0));\n}\n","#!/usr/bin/env node\nimport { runCli } from './cli.js';\n\nvoid runCli();\n"],"mappings":";;;AAAA,SAAS,UAAU,SAAS,SAAS,WAAW,UAAU,cAAc;AACxE,OAAOA,YAAW;AAClB,SAAS,eAAe;AACxB,OAAO,SAAS;;;ACHT,IAAM,eAAe;AACrB,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAEzB,IAAM,UAAU,CAAC,UAAU,SAAS,QAAQ;;;ACLnD,OAAOC,WAAU;;;ACAjB,OAAOC,WAAU;;;ACAjB,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAsB,WAAW,UAAoC;AACnE,MAAI;AACF,UAAM,GAAG,OAAO,QAAQ;AACxB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,UAAU,SAAgC;AAC9D,QAAM,GAAG,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAC7C;AAEA,eAAsB,SAAS,UAA0C;AACvE,MAAI,CAAE,MAAM,WAAW,QAAQ,GAAI;AACjC,WAAO;AAAA,EACT;AACA,SAAO,GAAG,SAAS,UAAU,MAAM;AACrC;AAEA,eAAsB,UAAU,UAAkB,SAAgC;AAChF,QAAM,UAAU,KAAK,QAAQ,QAAQ,CAAC;AACtC,QAAM,GAAG,UAAU,UAAU,SAAS,MAAM;AAC9C;AAEA,eAAsB,eAAe,UAAoD;AACvF,QAAM,UAAU,MAAM,SAAS,QAAQ;AACvC,MAAI,CAAC,WAAW,CAAC,QAAQ,KAAK,GAAG;AAC/B,WAAO,CAAC;AAAA,EACV;AACA,QAAM,SAAS,KAAK,MAAM,OAAO;AACjC,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,UAAM,IAAI,MAAM,GAAG,QAAQ,8BAA8B;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,eAAsB,gBAAgB,UAAkB,OAA+C;AACrG,QAAM,UAAU,UAAU,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,CAAI;AACjE;AAEA,eAAsB,iBAAiB,QAAgB,aAAuC;AAC5F,MAAI,CAAE,MAAM,WAAW,MAAM,GAAI;AAC/B,WAAO;AAAA,EACT;AACA,QAAM,UAAU,KAAK,QAAQ,WAAW,CAAC;AACzC,QAAM,GAAG,SAAS,QAAQ,WAAW;AACrC,SAAO;AACT;;;ACnDA,OAAO,QAAQ;AACf,OAAOC,WAAU;AAGV,SAAS,YAAY,OAAyB;AACnD,SAAOC,MAAK,KAAK,GAAG,QAAQ,GAAG,GAAG,KAAK;AACzC;AAEO,SAAS,eAAe,OAAyB;AACtD,SAAO,SAAS,kBAAkB,GAAG,KAAK;AAC5C;AAEO,SAAS,YAAY,OAAO,oBAAI,KAAK,GAAW;AACrD,SAAO,KAAK,YAAY,EAAE,QAAQ,SAAS,GAAG;AAChD;;;AFHA,eAAsB,aAAa,QAAkB,YAA2C;AAC9F,QAAM,KAAK,YAAY;AACvB,QAAM,aAAa,YAAY,WAAW,QAAQ,IAAIC,MAAK,SAAS,UAAU,CAAC;AAC/E,QAAM,UAAU,MAAM,iBAAiB,YAAY,UAAU;AAE7D,SAAO;AAAA,IACL;AAAA,IACA,YAAY,UAAU,aAAa;AAAA,IACnC;AAAA,EACF;AACF;;;AGrBA,SAAS,aAAa;AACtB,OAAOC,cAAa;AAEpB,eAAsB,cAAc,SAAmC;AACrE,QAAM,UAAUA,SAAQ,aAAa,UAAU,UAAU;AACzD,QAAM,OAAOA,SAAQ,aAAa,UAAU,CAAC,OAAO,IAAI,CAAC,MAAM,OAAO;AAEtE,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQ,MAAM,SAAS,MAAM;AAAA,MACjC,OAAO;AAAA,MACP,OAAOA,SAAQ,aAAa;AAAA,IAC9B,CAAC;AAED,UAAM,GAAG,SAAS,MAAM,QAAQ,KAAK,CAAC;AACtC,UAAM,GAAG,SAAS,CAAC,SAAS,QAAQ,SAAS,CAAC,CAAC;AAAA,EACjD,CAAC;AACH;;;AChBA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAmBjB,IAAM,gBAAgB,YAAY,eAAe;AAEjD,eAAe,eAAkC;AAC/C,QAAM,UAAU,MAAM,SAAS,aAAa;AAC5C,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,SAAS,GAAG,SAAS,CAAC,EAAE;AAAA,EACnC;AACA,QAAM,SAAS,KAAK,MAAM,OAAO;AACjC,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC;AAAA,EAC7D;AACF;AAEA,eAAe,cAAc,UAAmC;AAC9D,QAAM,UAAUC,MAAK,QAAQ,aAAa,CAAC;AAC3C,QAAM,UAAU,eAAe,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,CAAI;AACzE;AAEA,eAAsB,iBAAiB,OAAqC;AAC1E,QAAM,WAAW,MAAM,aAAa;AACpC,WAAS,QAAQ,KAAK,KAAK;AAC3B,QAAM,cAAc,QAAQ;AAC9B;AAEA,eAAsB,eAAe,QAAiD;AACpF,QAAM,WAAW,MAAM,aAAa;AACpC,QAAM,UAAU,SAAS,QAAQ,OAAO,CAAC,UAAU,MAAM,WAAW,MAAM;AAC1E,SAAO,QAAQ,GAAG,EAAE,KAAK;AAC3B;AAEA,eAAsB,aAAa,OAAqC;AACtE,MAAI,MAAM,WAAW,MAAM,YAAY;AACrC,QAAI,CAAE,MAAM,WAAW,MAAM,UAAU,GAAI;AACzC,YAAM,IAAI,MAAM,0BAA0B,MAAM,UAAU,EAAE;AAAA,IAC9D;AACA,UAAM,UAAUA,MAAK,QAAQ,MAAM,UAAU,CAAC;AAC9C,UAAMC,IAAG,SAAS,MAAM,YAAY,MAAM,UAAU;AACpD;AAAA,EACF;AAEA,QAAMA,IAAG,GAAG,MAAM,YAAY,EAAE,OAAO,KAAK,CAAC;AAC/C;;;AC9DO,SAAS,WAAW,QAAwB;AACjD,MAAI,OAAO,UAAU,GAAG;AACtB,WAAO,IAAI,OAAO,OAAO,MAAM;AAAA,EACjC;AACA,SAAO,GAAG,OAAO,MAAM,GAAG,CAAC,CAAC,MAAM,OAAO,MAAM,EAAE,CAAC;AACpD;AAEO,SAAS,SAAS,OAAyB;AAChD,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS;AAC5D;;;ANCA,IAAM,aAAa,CAAC,YAAoB;AAAA,EACtC,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,mBAAmB;AACrB;AAEO,IAAM,gBAA4B;AAAA,EACvC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EAET,aAAa;AACX,WAAO,SAAS,WAAW,eAAe;AAAA,EAC5C;AAAA,EAEA,MAAM,SAAgC;AACpC,WAAO,EAAE,SAAS,KAAK,SAAS,WAAW,MAAM,cAAc,KAAK,OAAO,EAAE;AAAA,EAC/E;AAAA,EAEA,MAAM,UAAkC;AACtC,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,eAAe,UAAU;AAC9C,UAAM,MAAM,SAAS,OAAO,GAAG;AAC/B,UAAM,aAAa,IAAI,uBAAuB,qBAAqB,SAAS,IAAI,oBAAoB,KAAK,SAAS,IAAI,iBAAiB;AAEvI,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,aAAa,mCAAoB;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAA8C;AACvD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,UAAM,SAAS,MAAM,aAAa,UAAU;AAC5C,UAAM,MAAM,SAAS,OAAO,GAAG;AAC/B,UAAM,UAAU,WAAW,MAAM,MAAM;AAEvC,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA,YAAY;AAAA,MACZ,eAAe,OAAO;AAAA,MACtB,cAAc;AAAA,MACd,SAAS,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,QACtD;AAAA,QACA,QAAQ,IAAI,GAAG,MAAM,QAAQ,SAAS,OAAO,MAAM,WAAW;AAAA,MAChE,EAAE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,OAA8C;AACxD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,OAAO,MAAM,KAAK,KAAK,KAAK;AAClC,UAAM,SAAS,MAAM,aAAa,KAAK,IAAI,UAAU;AAErD,QAAI;AACF,YAAM,SAAS,MAAM,aAAa,UAAU;AAC5C,YAAM,MAAM,SAAS,OAAO,GAAG;AAC/B,aAAO,MAAM;AAAA,QACX,GAAG;AAAA,QACH,GAAG,WAAW,MAAM,MAAM;AAAA,MAC5B;AACA,YAAM,gBAAgB,YAAY,MAAM;AAAA,IAC1C,SAAS,OAAO;AACd,UAAI,OAAO,WAAW,OAAO,YAAY;AACvC,cAAM,WAAW,MAAM,OAAO,aAAkB;AAChD,cAAM,SAAS,SAAS,OAAO,YAAY,UAAU;AAAA,MACvD;AACA,YAAM;AAAA,IACR;AAEA,UAAM,iBAAiB;AAAA,MACrB,IAAI,OAAO;AAAA,MACX,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7B,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,WAAO,EAAE,GAAG,MAAM,YAAY,OAAO,WAAW;AAAA,EAClD;AAAA,EAEA,aAAa;AACX,WAAO,CAAC,oBAAoB,QAAQ;AAAA,EACtC;AACF;AAEA,eAAe,aAAa,YAAsD;AAChF,MAAI;AACF,WAAO,MAAM,eAAe,UAAU;AAAA,EACxC,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,qDAAuBC,MAAK,SAAS,UAAU,CAAC,SAAK,MAAgB,OAAO,EAAE;AAAA,EAChG;AACF;AAEA,SAAS,SAAS,OAAwC;AACxD,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,WAAO,CAAC;AAAA,EACV;AACA,SAAO;AACT;;;AOjIA,YAAY,UAAU;AAWf,IAAM,eAA2B;AAAA,EACtC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EAET,aAAa;AACX,WAAO,SAAS,UAAU,aAAa;AAAA,EACzC;AAAA,EAEA,MAAM,SAAgC;AACpC,WAAO,EAAE,SAAS,KAAK,SAAS,WAAW,MAAM,cAAc,KAAK,OAAO,EAAE;AAAA,EAC/E;AAAA,EAEA,MAAM,UAAkC;AACtC,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,SAAS,UAAU;AACxC,UAAM,YAAYC,UAAS,OAAO,eAAe;AACjD,UAAM,UAAUA,UAAS,UAAU,OAAO;AAC1C,UAAM,aAAa,OAAO,mBAAmB,aAAa,QAAQ,aAAa;AAE/E,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,aAAa,wCAAyB;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAA8C;AACvD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,UAAM,SAAS,MAAM,SAAS,UAAU;AACxC,UAAM,YAAYA,UAAS,OAAO,eAAe;AACjD,UAAM,UAAUA,UAAS,UAAU,OAAO;AAE1C,UAAM,UAAU;AAAA,MACd,gBAAgB;AAAA,MAChB,gCAAgC;AAAA,MAChC,oCAAoC;AAAA,MACpC,oCAAoC;AAAA,MACpC,qDAAqD,MAAM;AAAA,IAC7D;AACA,UAAM,UAAuC;AAAA,MAC3C,EAAE,KAAK,kBAAkB,QAAQ,OAAO,mBAAmB,QAAQ,iBAAiB,SAAS,SAAS;AAAA,MACtG,EAAE,KAAK,gCAAgC,QAAQ,QAAQ,SAAS,QAAQ,8BAA8B,IAAI,SAAS,UAAU,SAAS,MAAM,EAAE;AAAA,MAC9I,EAAE,KAAK,oCAAoC,QAAQ,QAAQ,aAAa,QAAQ,kCAAkC,IAAI,SAAS,UAAU,SAAS,UAAU,EAAE;AAAA,MAC9J,EAAE,KAAK,oCAAoC,QAAQ,QAAQ,aAAa,QAAQ,kCAAkC,IAAI,SAAS,UAAU,SAAS,UAAU,EAAE;AAAA,MAC9J;AAAA,QACE,KAAK;AAAA,QACL,QAAQ,QAAQ,8BAA8B,MAAM,SAAS,SAAS,UAAU,SAAS,2BAA2B;AAAA,MACtH;AAAA,IACF;AAEA,QAAI,MAAM,YAAY;AACpB,cAAQ,KAAK,EAAE,KAAK,SAAS,QAAQ,OAAO,UAAU,MAAM,aAAa,SAAS,UAAU,QAAQ,OAAO,EAAE,CAAC;AAAA,IAChH;AACA,QAAI,qBAAqB,OAAO,YAAY,GAAG;AAC7C,cAAQ,KAAK,EAAE,KAAK,gBAAgB,QAAQ,SAAS,CAAC;AAAA,IACxD;AACA,QAAI,qBAAqB,QAAQ,YAAY,GAAG;AAC9C,cAAQ,KAAK,EAAE,KAAK,wCAAwC,QAAQ,SAAS,CAAC;AAAA,IAChF;AAEA,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA,YAAY;AAAA,MACZ,eAAe,OAAO;AAAA,MACtB,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,OAA8C;AACxD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,OAAO,MAAM,KAAK,KAAK,KAAK;AAClC,UAAM,SAAS,MAAM,aAAa,KAAK,IAAI,UAAU;AAErD,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,UAAU;AACxC,YAAM,YAAYA,UAAS,OAAO,eAAe;AACjD,YAAM,kBAAkB;AAAA,QACtB,GAAGA,UAAS,UAAU,OAAO;AAAA,QAC7B,MAAM;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA,QACV,2BAA2B,MAAM;AAAA,MACnC;AAEA,+BAAyB,MAAM;AAC/B,+BAAyB,eAAe;AACxC,aAAO,iBAAiB;AACxB,UAAI,MAAM,YAAY;AACpB,eAAO,QAAQ,MAAM;AAAA,MACvB;AACA,aAAO,kBAAkB;AAAA,QACvB,GAAG;AAAA,QACH,SAAS;AAAA,MACX;AACA,YAAM,UAAU,YAAiB,eAAU,MAAM,CAAC;AAAA,IACpD,SAAS,OAAO;AACd,UAAI,OAAO,WAAW,OAAO,YAAY;AACvC,cAAMC,MAAK,MAAM,OAAO,aAAkB;AAC1C,cAAMA,IAAG,SAAS,OAAO,YAAY,UAAU;AAAA,MACjD;AACA,YAAM;AAAA,IACR;AAEA,UAAM,iBAAiB;AAAA,MACrB,IAAI,OAAO;AAAA,MACX,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7B,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,WAAO,EAAE,GAAG,MAAM,YAAY,OAAO,WAAW;AAAA,EAClD;AAAA,EAEA,aAAa;AACX,WAAO,CAAC,mBAAmB,OAAO;AAAA,EACpC;AACF;AAEA,eAAe,SAAS,YAAyC;AAC/D,QAAM,UAAU,MAAM,SAAS,UAAU;AACzC,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,CAAC;AAAA,EACV;AACA,QAAM,SAAc,WAAM,OAAO;AACjC,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,UAAM,IAAI,MAAM,GAAG,UAAU,8BAA8B;AAAA,EAC7D;AACA,SAAO;AACT;AAEA,SAASD,UAAS,OAA4B;AAC5C,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,WAAO,CAAC;AAAA,EACV;AACA,SAAO;AACT;AAEA,SAAS,UAAU,QAAoB,KAA+B;AACpE,SAAO,OAAO,SAAS,WAAW;AACpC;AAEA,SAAS,qBAAqB,OAAyB;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,UAAU,UAAU;AACpE;AAEA,SAAS,yBAAyB,QAA0B;AAC1D,MAAI,qBAAqB,OAAO,YAAY,GAAG;AAC7C,WAAO,OAAO;AAAA,EAChB;AACF;;;ACtLO,SAAS,gBAAgB,SAAiB,QAAwC;AACvF,QAAM,QAAQ,UAAU,QAAQ,MAAM,OAAO,IAAI,CAAC;AAClD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,YAAY,MAAM,IAAI,CAAC,SAAS;AACpC,UAAM,QAAQ,KAAK,MAAM,kCAAkC;AAC3D,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,MAAM,CAAC;AACnB,QAAI,EAAE,OAAO,SAAS;AACpB,aAAO;AAAA,IACT;AAEA,SAAK,IAAI,GAAG;AACZ,WAAO,GAAG,GAAG,IAAI,SAAS,OAAO,GAAG,CAAC,CAAC;AAAA,EACxC,CAAC;AAED,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,gBAAU,KAAK,GAAG,GAAG,IAAI,SAAS,KAAK,CAAC,EAAE;AAAA,IAC5C;AAAA,EACF;AAEA,SAAO,GAAG,UAAU,OAAO,CAAC,MAAM,UAAU,KAAK,SAAS,KAAK,QAAQ,UAAU,SAAS,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA;AACzG;AAEA,SAAS,SAAS,OAAuB;AACvC,SAAO,KAAK,UAAU,KAAK;AAC7B;;;ACpBA,IAAME,cAAa,CAAC,YAAoB;AAAA,EACtC,gBAAgB;AAAA,EAChB,wBAAwB;AAC1B;AAEO,IAAM,gBAA4B;AAAA,EACvC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EAET,aAAa;AACX,WAAO,SAAS,WAAW,MAAM;AAAA,EACnC;AAAA,EAEA,MAAM,SAAgC;AACpC,WAAO,EAAE,SAAS,KAAK,SAAS,WAAW,MAAM,cAAc,KAAK,OAAO,EAAE;AAAA,EAC/E;AAAA,EAEA,MAAM,UAAkC;AACtC,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,UAAW,MAAM,SAAS,UAAU,KAAM;AAChD,UAAM,aAAa,WAAW,SAAS,gBAAgB,KAAK,WAAW,SAAS,0BAA0B,gBAAgB;AAE1H,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,aAAa,mCAAoB;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAA8C;AACvD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,UAAM,UAAW,MAAM,SAAS,UAAU,KAAM;AAChD,UAAM,UAAUA,YAAW,MAAM,MAAM;AAEvC,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX;AAAA,MACA,YAAY;AAAA,MACZ,eAAe,OAAO;AAAA,MACtB,cAAc;AAAA,MACd,SAAS,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,QACtD;AAAA,QACA,QAAQ,WAAW,SAAS,KAAK,KAAK,IAAI,SAAS,WAAW,SAAS,GAAG,IAAI,WAAW;AAAA,MAC3F,EAAE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,OAA8C;AACxD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,OAAO,MAAM,KAAK,KAAK,KAAK;AAClC,UAAM,SAAS,MAAM,aAAa,KAAK,IAAI,UAAU;AAErD,QAAI;AACF,YAAM,UAAW,MAAM,SAAS,UAAU,KAAM;AAChD,YAAM,UAAU,YAAY,gBAAgB,SAASA,YAAW,MAAM,MAAM,CAAC,CAAC;AAAA,IAChF,SAAS,OAAO;AACd,UAAI,OAAO,WAAW,OAAO,YAAY;AACvC,cAAMC,MAAK,MAAM,OAAO,aAAkB;AAC1C,cAAMA,IAAG,SAAS,OAAO,YAAY,UAAU;AAAA,MACjD;AACA,YAAM;AAAA,IACR;AAEA,UAAM,iBAAiB;AAAA,MACrB,IAAI,OAAO;AAAA,MACX,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7B,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,WAAO,EAAE,GAAG,MAAM,YAAY,OAAO,WAAW;AAAA,EAClD;AAAA,EAEA,aAAa;AACX,WAAO,CAAC,oBAAoB,QAAQ;AAAA,EACtC;AACF;AAEA,SAAS,WAAW,SAAiB,KAAa,OAAyB;AACzE,QAAM,UAAU,IAAI,OAAO,QAAQ,aAAa,GAAG,CAAC,sBAAsB,GAAG;AAC7E,QAAM,QAAQ,QAAQ,MAAM,OAAO;AACnC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM;AACtC;AAEA,SAAS,QAAQ,OAAuB;AACtC,MAAK,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAAO,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAAI;AACpG,WAAO,MAAM,MAAM,GAAG,EAAE;AAAA,EAC1B;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;;;AC1HO,IAAM,WAAyC;AAAA,EACpD,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACV;AAEO,SAAS,YAAY,SAAmC;AAC7D,SAAO,QAAQ,IAAI,CAAC,WAAW,SAAS,MAAM,CAAC;AACjD;;;ACdA,OAAO,WAAW;AAEX,IAAM,SAAS;AAAA,EACpB,KAAK,SAAuB;AAC1B,YAAQ,IAAI,MAAM,KAAK,OAAO,CAAC;AAAA,EACjC;AAAA,EACA,QAAQ,SAAuB;AAC7B,YAAQ,IAAI,MAAM,MAAM,OAAO,CAAC;AAAA,EAClC;AAAA,EACA,KAAK,SAAuB;AAC1B,YAAQ,IAAI,MAAM,OAAO,OAAO,CAAC;AAAA,EACnC;AAAA,EACA,MAAM,SAAuB;AAC3B,YAAQ,MAAM,MAAM,IAAI,OAAO,CAAC;AAAA,EAClC;AAAA,EACA,MAAM,SAAuB;AAC3B,YAAQ,IAAI,OAAO;AAAA,EACrB;AACF;;;ACZA,eAAsB,eAAe,gBAAgD;AACnF,MAAI,QAAQ,IAAI,8BAA8B,KAAK;AACjD,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,IAAI;AAEzD,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,8BAA8B,YAAY,WAAW;AAAA,MAChF,QAAQ,WAAW;AAAA,MACnB,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,cAAc,GAAG,YAAY,IAAI,cAAc;AAAA,MACjD;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,IACT;AAEA,UAAM,SAAU,MAAM,SAAS,KAAK;AACpC,QAAI,OAAO,WAAW,gBAAgB,OAAO,SAAS,cAAc,IAAI,GAAG;AACzE,aAAO,OAAO;AAAA,IAChB;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAEO,SAAS,gBAAgB,MAAc,OAAuB;AACnE,QAAM,YAAY,iBAAiB,IAAI;AACvC,QAAM,aAAa,iBAAiB,KAAK;AAEzC,WAAS,QAAQ,GAAG,QAAQ,KAAK,IAAI,UAAU,QAAQ,WAAW,MAAM,GAAG,SAAS,GAAG;AACrF,UAAM,WAAW,UAAU,KAAK,KAAK;AACrC,UAAM,YAAY,WAAW,KAAK,KAAK;AACvC,QAAI,WAAW,WAAW;AACxB,aAAO;AAAA,IACT;AACA,QAAI,WAAW,WAAW;AACxB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,SAA2B;AACnD,SAAO,QACJ,QAAQ,MAAM,EAAE,EAChB,MAAM,MAAM,EACZ,IAAI,CAAC,SAAS,OAAO,SAAS,MAAM,EAAE,CAAC,EACvC,IAAI,CAAC,SAAU,OAAO,SAAS,IAAI,IAAI,OAAO,CAAE;AACrD;;;AdpCA,eAAsB,OAAO,OAAO,QAAQ,MAAqB;AAC/D,QAAM,UAAU,IAAI,QAAQ;AAE5B,UACG,KAAK,YAAY,EACjB,YAAY,0DAA0D,EACtE,QAAQ,eAAe;AAE1B,UACG,QAAQ,QAAQ,EAAE,WAAW,KAAK,CAAC,EACnC,YAAY,wDAAwD,EACpE,OAAO,mBAAmB,iBAAiB,EAC3C,OAAO,2BAA2B,sCAAsC,EACxE,OAAO,aAAa,mBAAmB,EACvC,OAAO,aAAa,oCAAoC,EACxD,OAAO,WAAW,gEAAgE,EAClF,OAAO,yBAAyB,gCAAgC,EAChE,OAAO,yBAAyB,4EAA4E,EAC5G,OAAO,OAAO,YAAyB;AACtC,UAAM,YAAY,OAAO;AAAA,EAC3B,CAAC;AAEH,UACG,QAAQ,QAAQ,EAChB,YAAY,0CAA0C,EACtD,OAAO,YAAY;AAClB,UAAM,cAAc;AAAA,EACtB,CAAC;AAEH,UACG,QAAQ,QAAQ,EAChB,YAAY,0DAA0D,EACtE,OAAO,YAAY;AAClB,UAAM,cAAc;AAAA,EACtB,CAAC;AAEH,UACG,QAAQ,OAAO,EACf,YAAY,iDAAiD,EAC7D,OAAO,2BAA2B,sCAAsC,EACxE,OAAO,aAAa,mBAAmB,EACvC,OAAO,OAAO,YAA2B;AACxC,UAAM,aAAa,OAAO;AAAA,EAC5B,CAAC;AAEH,MAAI;AACF,UAAM,wBAAwB;AAC9B,UAAM,QAAQ,WAAW,IAAI;AAAA,EAC/B,SAAS,OAAO;AACd,WAAO,MAAO,MAAgB,OAAO;AACrC,YAAQ,WAAW;AAAA,EACrB;AACF;AAEA,eAAe,0BAAyC;AACtD,QAAM,gBAAgB,MAAM,eAAe,eAAe;AAC1D,MAAI,CAAC,eAAe;AAClB;AAAA,EACF;AAEA,SAAO,KAAK,4BAAQ,YAAY,IAAI,aAAa,kCAAS,eAAe,kDAAyB,YAAY,SAAS;AACzH;AAEA,eAAe,YAAY,SAAqC;AAC9D,QAAM,WAAW,MAAM,gBAAgB,OAAO;AAC9C,QAAM,WAAW,SAAS,QAAQ;AAClC,QAAM,UAAU,QAAQ,UAAU,aAAa,QAAQ,SAAS,QAAQ,IAAI,MAAM,cAAc,QAAQ;AACxG,QAAM,SAAS,QAAQ,KAAK,KAAK,KAAM,MAAM,SAAS,EAAE,SAAS,SAAS,cAAc,MAAM,IAAI,CAAC;AAEnG,MAAI,CAAC,OAAO,KAAK,GAAG;AAClB,UAAM,IAAI,MAAM,SAAS,WAAW;AAAA,EACtC;AACA,QAAM,aAAa,MAAM,kBAAkB,SAAS,SAAS,QAAQ;AAErE,QAAM,QAAoB;AAAA,IACxB,QAAQ,OAAO,KAAK;AAAA,IACpB;AAAA,IACA,KAAK,QAAQ,QAAQ,GAAG;AAAA,IACxB,QAAQ,QAAQ,QAAQ,MAAM;AAAA,IAC9B,OAAO,QAAQ,QAAQ,KAAK;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO,KAAK,GAAG,SAAS,UAAU,KAAK,gBAAgB,EAAE;AACzD,SAAO,KAAK,gBAAgB,WAAW,MAAM,MAAM,CAAC,EAAE;AAEtD,QAAM,mBAAmB,YAAY,OAAO;AAC5C,QAAM,YAAY,MAAM,eAAe,kBAAkB,QAAQ;AACjE,QAAM,UAAU,UAAU,OAAO,CAAC,WAAW,CAAC,OAAO,SAAS;AAC9D,MAAI,QAAQ,SAAS,KAAK,CAAC,MAAM,OAAO;AACtC,WAAO,MAAM,EAAE;AACf,WAAO,KAAK,SAAS,cAAc;AACnC,eAAW,UAAU,SAAS;AAC5B,aAAO,MAAM,KAAK,OAAO,IAAI,KAAK,kBAAkB,OAAO,MAAM,CAAC,EAAE;AAAA,IACtE;AACA,WAAO,MAAM,EAAE;AACf,WAAO,MAAM,SAAS,SAAS;AAC/B;AAAA,EACF;AAEA,QAAM,QAAQ,CAAC;AACf,aAAW,WAAW,kBAAkB;AACtC,UAAM,KAAK,MAAM,QAAQ,KAAK,KAAK,CAAC;AAAA,EACtC;AAEA,aAAW,OAAO,QAAQ;AAE1B,MAAI,MAAM,QAAQ;AAChB,WAAO,KAAK,SAAS,MAAM;AAC3B;AAAA,EACF;AAEA,MAAI,CAAC,MAAM,KAAK;AACd,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,SAAS,SAAS;AAAA,MAClB,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAU;AACb,aAAO,KAAK,SAAS,SAAS;AAC9B;AAAA,IACF;AAAA,EACF;AAEA,aAAW,WAAW,kBAAkB;AACtC,UAAM,UAAU,IAAI,GAAG,SAAS,WAAW,IAAI,QAAQ,IAAI,KAAK,EAAE,MAAM;AACxE,QAAI;AACF,YAAM,OAAO,MAAM,QAAQ,MAAM,KAAK;AACtC,cAAQ,QAAQ,GAAG,QAAQ,IAAI,IAAI,SAAS,cAAc,KAAK,KAAK,UAAU,EAAE;AAChF,UAAI,KAAK,YAAY;AACnB,eAAO,MAAMC,OAAM,IAAI,aAAa,KAAK,UAAU,EAAE,CAAC;AAAA,MACxD;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,GAAG,QAAQ,IAAI,IAAI,SAAS,YAAY,EAAE;AACvD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO,QAAQ,SAAS,aAAa;AACrC,SAAO,MAAM,EAAE;AACf,SAAO,MAAM,GAAG,SAAS,cAAc,GAAG;AAC1C,aAAW,WAAW,kBAAkB;AACtC,WAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,QAAQ,WAAW,EAAE,KAAK,KAAK,CAAC,EAAE;AAAA,EACvE;AACA,SAAO,MAAM,EAAE;AACf,SAAO,MAAM,GAAG,SAAS,UAAU,GAAG;AACtC,aAAW,WAAW,kBAAkB;AACtC,WAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,QAAQ,OAAO,EAAE;AAAA,EACtD;AACA,SAAO,QAAQ,SAAS,KAAK;AAC/B;AAQA,eAAe,eAAe,kBAAkD,UAAkD;AAChI,QAAM,UAA6B,CAAC;AACpC,SAAO,MAAM,EAAE;AACf,SAAO,MAAM,GAAG,SAAS,QAAQ,GAAG;AACpC,aAAW,WAAW,kBAAkB;AACtC,UAAM,CAAC,UAAU,OAAO,IAAI,MAAM,QAAQ,IAAI,CAAC,QAAQ,OAAO,GAAG,QAAQ,QAAQ,CAAC,CAAC;AACnF,YAAQ,KAAK;AAAA,MACX,QAAQ,QAAQ;AAAA,MAChB,MAAM,QAAQ;AAAA,MACd,WAAW,SAAS;AAAA,IACtB,CAAC;AACD,WAAO,MAAM,KAAK,QAAQ,IAAI,EAAE;AAChC,WAAO,MAAM,UAAU,SAAS,YAAYA,OAAM,MAAM,SAAS,SAAS,IAAIA,OAAM,OAAO,SAAS,QAAQ,CAAC,KAAK,SAAS,OAAO,GAAG;AACrI,WAAO,MAAM,KAAK,SAAS,UAAU,KAAK,QAAQ,SAASA,OAAM,MAAM,SAAS,MAAM,IAAIA,OAAM,OAAO,SAAS,SAAS,CAAC,EAAE;AAC5H,WAAO,MAAM,KAAK,SAAS,IAAI,KAAK,QAAQ,UAAU,EAAE;AACxD,WAAO,MAAM,cAAc,QAAQ,aAAaA,OAAM,MAAM,SAAS,UAAU,IAAIA,OAAM,OAAO,SAAS,aAAa,CAAC,EAAE;AAAA,EAC3H;AACA,SAAO;AACT;AAEA,eAAe,gBAA+B;AAC5C,aAAW,WAAW,OAAO,OAAO,QAAQ,GAAG;AAC7C,UAAM,UAAU,MAAM,QAAQ,QAAQ;AACtC,UAAM,QAAQ,QAAQ,aAAaA,OAAM,MAAM,YAAY,IAAIA,OAAM,OAAO,gBAAgB;AAC5F,WAAO,MAAM,GAAG,QAAQ,IAAI,KAAK,KAAK,EAAE;AACxC,WAAO,MAAM,WAAW,QAAQ,UAAU,EAAE;AAC5C,WAAO,MAAM,KAAK,QAAQ,OAAO,EAAE;AAAA,EACrC;AACF;AAEA,eAAe,gBAA+B;AAC5C,SAAO,KAAK,qCAAiB,gBAAgB,EAAE;AAC/C,aAAW,WAAW,OAAO,OAAO,QAAQ,GAAG;AAC7C,UAAM,CAAC,UAAU,OAAO,IAAI,MAAM,QAAQ,IAAI,CAAC,QAAQ,OAAO,GAAG,QAAQ,QAAQ,CAAC,CAAC;AACnF,WAAO,MAAM,GAAG,QAAQ,IAAI,GAAG;AAC/B,WAAO,MAAM,cAAc,SAAS,YAAYA,OAAM,MAAM,OAAO,IAAIA,OAAM,OAAO,WAAW,CAAC,KAAK,SAAS,OAAO,GAAG;AACxH,WAAO,MAAM,aAAa,QAAQ,aAAaA,OAAM,MAAM,YAAY,IAAIA,OAAM,OAAO,gBAAgB,CAAC,EAAE;AAC3G,WAAO,MAAM,WAAW,QAAQ,UAAU,EAAE;AAAA,EAC9C;AACF;AAEA,eAAe,aAAa,SAAuC;AACjE,QAAM,UAAU,QAAQ,UAAU,aAAa,QAAQ,OAAO,IAAI,MAAM,cAAc,SAAS,EAAE;AAEjG,QAAM,UAAU,CAAC;AACjB,aAAW,UAAU,SAAS;AAC5B,UAAM,QAAQ,MAAM,eAAe,MAAM;AACzC,QAAI,OAAO;AACT,cAAQ,KAAK,KAAK;AAAA,IACpB,OAAO;AACL,aAAO,KAAK,GAAG,SAAS,MAAM,EAAE,IAAI,mEAAsB;AAAA,IAC5D;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB;AAAA,EACF;AAEA,SAAO,KAAK,6CAAU;AACtB,aAAW,SAAS,SAAS;AAC3B,WAAO,MAAM,KAAK,SAAS,MAAM,MAAM,EAAE,IAAI,KAAK,MAAM,UAAU,EAAE;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,KAAK;AAChB,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAU;AACb,aAAO,KAAK,sCAAQ;AACpB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,SAAS,SAAS;AAC3B,UAAM,aAAa,KAAK;AACxB,WAAO,QAAQ,GAAG,SAAS,MAAM,MAAM,EAAE,IAAI,2BAAO;AAAA,EACtD;AACF;AAEA,SAAS,WAAW,OAA2D,UAA4B;AACzG,SAAO,MAAM,EAAE;AACf,SAAO,MAAM,GAAG,SAAS,UAAU,GAAG;AACtC,aAAW,QAAQ,OAAO;AACxB,WAAO,MAAM,KAAK,KAAK,IAAI,EAAE;AAC7B,WAAO,MAAM,WAAW,KAAK,UAAU,EAAE;AACzC,WAAO,MAAM,KAAK,SAAS,MAAM,KAAK,KAAK,aAAa,EAAE;AAC1D,WAAO,MAAM,KAAK,SAAS,KAAK,KAAK,KAAK,YAAY,EAAE;AACxD,eAAW,UAAU,KAAK,SAAS;AACjC,aAAO,MAAM,KAAK,OAAO,OAAO,OAAO,CAAC,CAAC,IAAI,OAAO,GAAG,EAAE;AAAA,IAC3D;AAAA,EACF;AACA,SAAO,MAAM,EAAE;AACjB;AAEA,SAAS,aAAa,OAAe,WAAW,SAAS,IAAgB;AACvE,QAAM,aAAa,MAChB,MAAM,GAAG,EACT,IAAI,CAAC,WAAW,OAAO,KAAK,EAAE,YAAY,CAAC,EAC3C,OAAO,OAAO;AAEjB,MAAI,WAAW,SAAS,KAAK,GAAG;AAC9B,WAAO,CAAC,GAAG,OAAO;AAAA,EACpB;AAEA,QAAM,aAAa,WAAW,IAAI,CAAC,WAAW;AAC5C,QAAI,WAAW,eAAe;AAC5B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,UAAU,WAAW,OAAO,CAAC,WAAW,CAAC,QAAQ,SAAS,MAAkB,CAAC;AACnF,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,IAAI,MAAM,GAAG,SAAS,cAAc,KAAK,QAAQ,KAAK,IAAI,CAAC,KAAK,SAAS,gBAAgB,2BAA2B;AAAA,EAC5H;AAEA,QAAM,SAAS,MAAM,KAAK,IAAI,IAAI,UAAU,CAAC;AAC7C,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,IAAI,MAAM,SAAS,sBAAsB;AAAA,EACjD;AACA,SAAO;AACT;AAEA,eAAe,cAAc,UAA2C;AACtE,QAAM,WAAW,MAAM,SAAmB;AAAA,IACxC,SAAS,SAAS;AAAA,IAClB,SAAS;AAAA,MACP,EAAE,MAAM,eAAe,OAAO,SAAS;AAAA,MACvC,EAAE,MAAM,aAAa,OAAO,QAAQ;AAAA,MACpC,EAAE,MAAM,cAAc,OAAO,SAAS;AAAA,IACxC;AAAA,IACA,UAAU;AAAA,EACZ,CAAC;AAED,SAAO;AACT;AAEA,eAAe,kBAAkB,SAAqB,SAAsB,UAAmD;AAC7H,MAAI,CAAC,QAAQ,SAAS,OAAO,GAAG;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,4BAA4B,QAAQ,UAAU;AAClE,MAAI,gBAAgB,MAAM;AACxB,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,KAAK;AACf,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,MAAM,UAAU;AAAA,IAC5B,SAAS,SAAS;AAAA,IAClB,SAAS;AAAA,EACX,CAAC;AACD,SAAO,4BAA4B,KAAK,KAAK;AAC/C;AAEA,SAAS,4BAA4B,OAA2C;AAC9E,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,WAAW,CAAC,QAAQ,QAAQ,SAAS,EAAE,SAAS,QAAQ,YAAY,CAAC,GAAG;AAC3E,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,QAA0B;AACnD,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAwCA,IAAM,mBAAiE;AAAA,EACrE,EAAE,MAAM,4BAAQ,OAAO,QAAQ;AAAA,EAC/B,EAAE,MAAM,WAAW,OAAO,KAAK;AAAA,EAC/B,EAAE,MAAM,eAAY,OAAO,KAAK;AAAA,EAChC,EAAE,MAAM,8CAAW,OAAO,KAAK;AAAA,EAC/B,EAAE,MAAM,sBAAO,OAAO,KAAK;AAAA,EAC3B,EAAE,MAAM,wBAAc,OAAO,KAAK;AACpC;AAEA,IAAM,WAA6C;AAAA,EACjD,SAAS;AAAA,IACP,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,wBAAwB;AAAA,EAC1B;AAAA,EACA,IAAI;AAAA,IACF,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,wBAAwB;AAAA,EAC1B;AAAA,EACA,IAAI;AAAA,IACF,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,wBAAwB;AAAA,EAC1B;AAAA,EACA,IAAI;AAAA,IACF,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,wBAAwB;AAAA,EAC1B;AAAA,EACA,IAAI;AAAA,IACF,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,wBAAwB;AAAA,EAC1B;AAAA,EACA,IAAI;AAAA,IACF,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,wBAAwB;AAAA,EAC1B;AACF;AAEA,eAAe,gBAAgB,SAA6C;AAC1E,QAAM,SAAS,kBAAkB,QAAQ,QAAQ;AACjD,MAAI,QAAQ;AACV,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,yBAAyB;AAExC,QAAM,eAAe,CAAC,QAAQ,OAAO,CAAC,QAAQ,OAAO,CAAC,QAAQ;AAC9D,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,SAAO,OAAqB;AAAA,IAC1B,SAAS,SAAS,GAAG;AAAA,IACrB,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACH;AAEA,SAAS,kBAAkB,UAAwC;AACjE,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,aAAa,SAAS,KAAK,EAAE,YAAY;AAC/C,MAAI,eAAe,QAAQ,eAAe,WAAW,eAAe,QAAQ,eAAe,WAAW;AACpG,WAAO;AAAA,EACT;AACA,MAAI,eAAe,QAAQ,eAAe,WAAW;AACnD,WAAO;AAAA,EACT;AACA,MAAI,eAAe,QAAQ,eAAe,cAAc,eAAe,iBAAc,eAAe,UAAU;AAC5G,WAAO;AAAA,EACT;AACA,MAAI,eAAe,QAAQ,eAAe,WAAW;AACnD,WAAO;AAAA,EACT;AACA,MAAI,eAAe,QAAQ,eAAe,QAAQ,eAAe,YAAY;AAC3E,WAAO;AAAA,EACT;AACA,MAAI,eAAe,QAAQ,eAAe,QAAQ,eAAe,cAAc;AAC7E,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;Ae1pBA,KAAK,OAAO;","names":["chalk","path","path","path","path","path","process","fs","path","path","fs","path","asRecord","fs","ENV_VALUES","fs","chalk"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "laysoai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "LaysoAI CLI scaffold for configuring Claude Code, Codex, and Gemini.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"dev": "tsx src/index.ts",
|
|
17
17
|
"typecheck": "tsc --noEmit",
|
|
18
18
|
"test": "vitest run",
|
|
19
|
+
"release:npm": "sh scripts/publish-npm.sh",
|
|
20
|
+
"release:npm:node": "node scripts/publish-npm.mjs",
|
|
19
21
|
"prepublishOnly": "npm run typecheck && npm run test && npm run build"
|
|
20
22
|
},
|
|
21
23
|
"keywords": [
|