opencrush 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +131 -96
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -245027,118 +245027,46 @@ async function runSetupWizard() {
|
|
|
245027
245027
|
console.log(source_default.gray("This will create a .env file with your settings.\n"));
|
|
245028
245028
|
const region = detectRegion();
|
|
245029
245029
|
const isCN = region === "cn";
|
|
245030
|
-
step(1, isCN ? "\
|
|
245031
|
-
|
|
245032
|
-
|
|
245033
|
-
|
|
245034
|
-
console.log(source_default.gray(" Your companion needs an AI to think. All providers below work.\n"));
|
|
245035
|
-
}
|
|
245036
|
-
const cnFirst = PROVIDER_INFO.filter((p2) => !p2.requiresVPN && !p2.isLocal);
|
|
245037
|
-
const intl = PROVIDER_INFO.filter((p2) => p2.requiresVPN);
|
|
245038
|
-
const local = PROVIDER_INFO.filter((p2) => p2.isLocal);
|
|
245039
|
-
const orderedProviders = isCN ? [...cnFirst, ...intl, ...local] : [PROVIDER_INFO.find((p2) => p2.id === "anthropic"), PROVIDER_INFO.find((p2) => p2.id === "openai"), ...cnFirst, ...local];
|
|
245040
|
-
const { llmProvider } = await esm_default12.prompt([{
|
|
245041
|
-
type: "list",
|
|
245042
|
-
name: "llmProvider",
|
|
245043
|
-
message: isCN ? "\u9009\u62E9 AI \u6A21\u578B\u63D0\u4F9B\u5546:" : "Which AI provider?",
|
|
245044
|
-
choices: orderedProviders.map((p2) => ({
|
|
245045
|
-
name: `${p2.emoji} ${p2.name}
|
|
245046
|
-
${source_default.gray(isCN ? p2.taglineCN : p2.tagline)}`,
|
|
245047
|
-
value: p2.id,
|
|
245048
|
-
short: p2.name
|
|
245049
|
-
}))
|
|
245050
|
-
}]);
|
|
245051
|
-
const envValues = { LLM_PROVIDER: llmProvider };
|
|
245052
|
-
const providerInfo = getProviderInfo(llmProvider);
|
|
245053
|
-
if (llmProvider !== "ollama") {
|
|
245054
|
-
const keyUrl = isCN ? providerInfo.keyUrlCN : providerInfo.keyUrl;
|
|
245055
|
-
console.log(source_default.yellow(`
|
|
245056
|
-
\u{1F449} ${isCN ? "\u83B7\u53D6 API Key: " : "Get API key: "}${keyUrl}`));
|
|
245057
|
-
await openBrowserPrompt(keyUrl, isCN);
|
|
245058
|
-
if (llmProvider === "anthropic") {
|
|
245059
|
-
console.log(source_default.gray(
|
|
245060
|
-
isCN ? ' 1. \u6CE8\u518C\u8D26\u53F7 \u2192 API Keys \u2192 Create Key\n 2. \u590D\u5236\u4EE5 "sk-ant-" \u5F00\u5934\u7684\u5BC6\u94A5\n' : ' 1. Create account \u2192 API Keys \u2192 Create Key\n 2. Copy the key (starts with "sk-ant-")\n'
|
|
245061
|
-
));
|
|
245062
|
-
} else if (llmProvider === "openai") {
|
|
245063
|
-
console.log(source_default.gray(
|
|
245064
|
-
isCN ? " 1. \u6CE8\u518C \u2192 API Keys \u2192 Create new secret key\n" : " 1. Sign up \u2192 API Keys \u2192 Create new secret key\n"
|
|
245065
|
-
));
|
|
245066
|
-
} else if (llmProvider === "deepseek") {
|
|
245067
|
-
console.log(source_default.gray(
|
|
245068
|
-
isCN ? " 1. \u6CE8\u518C \u2192 API Keys \u2192 \u521B\u5EFA API Key\n 2. \u65B0\u7528\u6237\u6709\u514D\u8D39\u989D\u5EA6\n" : " 1. Sign up \u2192 API Keys \u2192 Create key\n 2. New users get free credits\n"
|
|
245069
|
-
));
|
|
245070
|
-
} else if (llmProvider === "qwen") {
|
|
245071
|
-
console.log(source_default.gray(
|
|
245072
|
-
isCN ? " 1. \u767B\u5F55\u963F\u91CC\u4E91\u63A7\u5236\u53F0 \u2192 DashScope \u2192 API-KEY\u7BA1\u7406 \u2192 \u521B\u5EFA\n" : " 1. Aliyun console \u2192 DashScope \u2192 API-KEY management \u2192 Create\n"
|
|
245073
|
-
));
|
|
245074
|
-
} else if (llmProvider === "kimi") {
|
|
245075
|
-
console.log(source_default.gray(
|
|
245076
|
-
isCN ? " 1. \u6CE8\u518C\u6708\u4E4B\u6697\u9762 \u2192 \u63A7\u5236\u53F0 \u2192 API Keys \u2192 \u65B0\u5EFA\n" : " 1. Sign up at Moonshot \u2192 Console \u2192 API Keys \u2192 New\n"
|
|
245077
|
-
));
|
|
245078
|
-
} else if (llmProvider === "zhipu") {
|
|
245079
|
-
console.log(source_default.gray(
|
|
245080
|
-
isCN ? " 1. \u6CE8\u518C\u667A\u8C31\u5F00\u653E\u5E73\u53F0 \u2192 \u4E2A\u4EBA\u4E2D\u5FC3 \u2192 API Keys \u2192 \u6DFB\u52A0\n 2. \u65B0\u7528\u6237\u8D60\u9001\u514D\u8D39 tokens\n" : " 1. Sign up at open.bigmodel.cn \u2192 API Keys \u2192 Add\n 2. Free tokens on signup\n"
|
|
245081
|
-
));
|
|
245082
|
-
} else if (llmProvider === "minimax") {
|
|
245083
|
-
console.log(source_default.gray(
|
|
245084
|
-
isCN ? " 1. \u6CE8\u518C MiniMax \u5F00\u653E\u5E73\u53F0 \u2192 \u8D26\u53F7\u8BBE\u7F6E \u2192 \u63A5\u53E3\u5BC6\u94A5\n" : " 1. Sign up at platform.minimaxi.com \u2192 Account \u2192 API Keys\n"
|
|
245085
|
-
));
|
|
245086
|
-
}
|
|
245087
|
-
const { apiKey } = await esm_default12.prompt([{
|
|
245088
|
-
type: "password",
|
|
245089
|
-
name: "apiKey",
|
|
245090
|
-
message: isCN ? `\u7C98\u8D34\u4F60\u7684 ${providerInfo.name} API Key:` : `Paste your ${providerInfo.name} API key:`,
|
|
245091
|
-
mask: "*",
|
|
245092
|
-
validate: (v2) => {
|
|
245093
|
-
if (!v2.trim()) return isCN ? "\u8BF7\u8F93\u5165 API Key" : "API key required";
|
|
245094
|
-
if (providerInfo.keyPrefix && !v2.startsWith(providerInfo.keyPrefix)) {
|
|
245095
|
-
return isCN ? `Key \u683C\u5F0F\u4E0D\u5BF9\uFF0C\u5E94\u4EE5 "${providerInfo.keyPrefix}" \u5F00\u5934` : `Should start with "${providerInfo.keyPrefix}"`;
|
|
245096
|
-
}
|
|
245097
|
-
return true;
|
|
245098
|
-
}
|
|
245099
|
-
}]);
|
|
245100
|
-
envValues[providerInfo.envKey] = apiKey;
|
|
245101
|
-
}
|
|
245102
|
-
if (llmProvider === "ollama") {
|
|
245103
|
-
console.log(source_default.yellow(
|
|
245104
|
-
isCN ? "\n \u786E\u4FDD Ollama \u5DF2\u8FD0\u884C: https://ollama.ai" : "\n Make sure Ollama is running: https://ollama.ai"
|
|
245105
|
-
));
|
|
245106
|
-
console.log(source_default.gray(
|
|
245107
|
-
isCN ? " \u8FD0\u884C: ollama pull qwen2.5:7b\n" : " Run: ollama pull qwen2.5:7b\n"
|
|
245108
|
-
));
|
|
245109
|
-
envValues.OLLAMA_BASE_URL = "http://localhost:11434";
|
|
245110
|
-
envValues.OLLAMA_MODEL = "qwen2.5:7b";
|
|
245111
|
-
}
|
|
245112
|
-
step(2, isCN ? "\u4F60\u7684\u4F34\u4FA3" : "Your companion");
|
|
245030
|
+
step(1, isCN ? "\u9047\u89C1\u4F60\u7684\u4F34\u4FA3" : "Meet your companion");
|
|
245031
|
+
console.log(source_default.gray(
|
|
245032
|
+
isCN ? " \u9009\u62E9\u4E00\u4E2A\u5DF2\u6709\u7684\u4F34\u4FA3\uFF0C\u6216\u8005\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684\u3002\n" : " Pick an existing companion or create a new one.\n"
|
|
245033
|
+
));
|
|
245113
245034
|
const characters = getExistingCharacters();
|
|
245114
245035
|
let characterName;
|
|
245036
|
+
let characterCreatedNew = false;
|
|
245115
245037
|
if (characters.length > 0) {
|
|
245116
245038
|
const { characterChoice } = await esm_default12.prompt([{
|
|
245117
245039
|
type: "list",
|
|
245118
245040
|
name: "characterChoice",
|
|
245119
|
-
message:
|
|
245041
|
+
message: isCN ? "\u9009\u62E9\u4F60\u7684\u4F34\u4FA3:" : "Choose your companion:",
|
|
245120
245042
|
choices: [
|
|
245121
|
-
...characters.map((c2) =>
|
|
245122
|
-
|
|
245043
|
+
...characters.map((c2) => {
|
|
245044
|
+
const preview = getCharacterPreview(c2);
|
|
245045
|
+
return {
|
|
245046
|
+
name: `\u2728 ${c2}${preview ? source_default.gray(" \xB7 " + preview) : ""}`,
|
|
245047
|
+
value: c2,
|
|
245048
|
+
short: c2
|
|
245049
|
+
};
|
|
245050
|
+
}),
|
|
245051
|
+
{ name: "\u2795 Create a new companion", value: "__new__", short: "New" }
|
|
245123
245052
|
]
|
|
245124
245053
|
}]);
|
|
245125
245054
|
if (characterChoice === "__new__") {
|
|
245126
|
-
const
|
|
245127
|
-
const created = await createCharacterFlow(apiKey, llmProvider);
|
|
245055
|
+
const created = await createCharacterFlow();
|
|
245128
245056
|
characterName = created.folderName;
|
|
245129
|
-
|
|
245057
|
+
characterCreatedNew = true;
|
|
245130
245058
|
} else {
|
|
245131
245059
|
characterName = characterChoice;
|
|
245060
|
+
maybeOpenCard(characterName);
|
|
245132
245061
|
}
|
|
245133
245062
|
} else {
|
|
245134
|
-
console.log(source_default.gray(" No companions yet \u2014 let's create one!\n"));
|
|
245135
|
-
const
|
|
245136
|
-
const created = await createCharacterFlow(apiKey, llmProvider);
|
|
245063
|
+
console.log(source_default.gray(isCN ? " \u8FD8\u6CA1\u6709\u4F34\u4FA3 \u2014 \u6765\u521B\u5EFA\u4E00\u4E2A\uFF01\n" : " No companions yet \u2014 let's create one!\n"));
|
|
245064
|
+
const created = await createCharacterFlow();
|
|
245137
245065
|
characterName = created.folderName;
|
|
245138
|
-
|
|
245066
|
+
characterCreatedNew = true;
|
|
245139
245067
|
}
|
|
245140
|
-
envValues
|
|
245141
|
-
step(
|
|
245068
|
+
const envValues = { CHARACTER_NAME: characterName };
|
|
245069
|
+
step(2, isCN ? "\u9009\u62E9\u804A\u5929\u5E73\u53F0" : "Where do you want to chat?");
|
|
245142
245070
|
const { platforms } = await esm_default12.prompt([{
|
|
245143
245071
|
type: "checkbox",
|
|
245144
245072
|
name: "platforms",
|
|
@@ -245225,6 +245153,91 @@ async function runSetupWizard() {
|
|
|
245225
245153
|
console.log(source_default.cyan("\n \u2139\uFE0F WhatsApp: No token needed! A QR code will appear when you start."));
|
|
245226
245154
|
console.log(source_default.gray(" You'll scan it with WhatsApp on your phone (Linked Devices)."));
|
|
245227
245155
|
}
|
|
245156
|
+
step(3, isCN ? "\u9009\u62E9 AI \u5927\u8111" : "Choose your AI brain");
|
|
245157
|
+
if (isCN) {
|
|
245158
|
+
console.log(source_default.cyan(" \u68C0\u6D4B\u5230\u4E2D\u56FD\u5927\u9646\u65F6\u533A \u2014 \u4F18\u5148\u663E\u793A\u56FD\u5185\u53EF\u76F4\u8FDE\u7684\u6A21\u578B\n"));
|
|
245159
|
+
} else {
|
|
245160
|
+
console.log(source_default.gray(" Your companion needs an AI to think. All providers below work.\n"));
|
|
245161
|
+
}
|
|
245162
|
+
const cnFirst = PROVIDER_INFO.filter((p2) => !p2.requiresVPN && !p2.isLocal);
|
|
245163
|
+
const intl = PROVIDER_INFO.filter((p2) => p2.requiresVPN);
|
|
245164
|
+
const local = PROVIDER_INFO.filter((p2) => p2.isLocal);
|
|
245165
|
+
const orderedProviders = isCN ? [...cnFirst, ...intl, ...local] : [PROVIDER_INFO.find((p2) => p2.id === "anthropic"), PROVIDER_INFO.find((p2) => p2.id === "openai"), ...cnFirst, ...local];
|
|
245166
|
+
const { llmProvider } = await esm_default12.prompt([{
|
|
245167
|
+
type: "list",
|
|
245168
|
+
name: "llmProvider",
|
|
245169
|
+
message: isCN ? "\u9009\u62E9 AI \u6A21\u578B\u63D0\u4F9B\u5546:" : "Which AI provider?",
|
|
245170
|
+
choices: orderedProviders.map((p2) => ({
|
|
245171
|
+
name: `${p2.emoji} ${p2.name}
|
|
245172
|
+
${source_default.gray(isCN ? p2.taglineCN : p2.tagline)}`,
|
|
245173
|
+
value: p2.id,
|
|
245174
|
+
short: p2.name
|
|
245175
|
+
}))
|
|
245176
|
+
}]);
|
|
245177
|
+
envValues.LLM_PROVIDER = llmProvider;
|
|
245178
|
+
const providerInfo = getProviderInfo(llmProvider);
|
|
245179
|
+
if (llmProvider !== "ollama") {
|
|
245180
|
+
const keyUrl = isCN ? providerInfo.keyUrlCN : providerInfo.keyUrl;
|
|
245181
|
+
console.log(source_default.yellow(`
|
|
245182
|
+
\u{1F449} ${isCN ? "\u83B7\u53D6 API Key: " : "Get API key: "}${keyUrl}`));
|
|
245183
|
+
await openBrowserPrompt(keyUrl, isCN);
|
|
245184
|
+
if (llmProvider === "anthropic") {
|
|
245185
|
+
console.log(source_default.gray(
|
|
245186
|
+
isCN ? ' 1. \u6CE8\u518C\u8D26\u53F7 \u2192 API Keys \u2192 Create Key\n 2. \u590D\u5236\u4EE5 "sk-ant-" \u5F00\u5934\u7684\u5BC6\u94A5\n' : ' 1. Create account \u2192 API Keys \u2192 Create Key\n 2. Copy the key (starts with "sk-ant-")\n'
|
|
245187
|
+
));
|
|
245188
|
+
} else if (llmProvider === "openai") {
|
|
245189
|
+
console.log(source_default.gray(
|
|
245190
|
+
isCN ? " 1. \u6CE8\u518C \u2192 API Keys \u2192 Create new secret key\n" : " 1. Sign up \u2192 API Keys \u2192 Create new secret key\n"
|
|
245191
|
+
));
|
|
245192
|
+
} else if (llmProvider === "deepseek") {
|
|
245193
|
+
console.log(source_default.gray(
|
|
245194
|
+
isCN ? " 1. \u6CE8\u518C \u2192 API Keys \u2192 \u521B\u5EFA API Key\n 2. \u65B0\u7528\u6237\u6709\u514D\u8D39\u989D\u5EA6\n" : " 1. Sign up \u2192 API Keys \u2192 Create key\n 2. New users get free credits\n"
|
|
245195
|
+
));
|
|
245196
|
+
} else if (llmProvider === "qwen") {
|
|
245197
|
+
console.log(source_default.gray(
|
|
245198
|
+
isCN ? " 1. \u767B\u5F55\u963F\u91CC\u4E91\u63A7\u5236\u53F0 \u2192 DashScope \u2192 API-KEY\u7BA1\u7406 \u2192 \u521B\u5EFA\n" : " 1. Aliyun console \u2192 DashScope \u2192 API-KEY management \u2192 Create\n"
|
|
245199
|
+
));
|
|
245200
|
+
} else if (llmProvider === "kimi") {
|
|
245201
|
+
console.log(source_default.gray(
|
|
245202
|
+
isCN ? " 1. \u6CE8\u518C\u6708\u4E4B\u6697\u9762 \u2192 \u63A7\u5236\u53F0 \u2192 API Keys \u2192 \u65B0\u5EFA\n" : " 1. Sign up at Moonshot \u2192 Console \u2192 API Keys \u2192 New\n"
|
|
245203
|
+
));
|
|
245204
|
+
} else if (llmProvider === "zhipu") {
|
|
245205
|
+
console.log(source_default.gray(
|
|
245206
|
+
isCN ? " 1. \u6CE8\u518C\u667A\u8C31\u5F00\u653E\u5E73\u53F0 \u2192 \u4E2A\u4EBA\u4E2D\u5FC3 \u2192 API Keys \u2192 \u6DFB\u52A0\n 2. \u65B0\u7528\u6237\u8D60\u9001\u514D\u8D39 tokens\n" : " 1. Sign up at open.bigmodel.cn \u2192 API Keys \u2192 Add\n 2. Free tokens on signup\n"
|
|
245207
|
+
));
|
|
245208
|
+
} else if (llmProvider === "minimax") {
|
|
245209
|
+
console.log(source_default.gray(
|
|
245210
|
+
isCN ? " 1. \u6CE8\u518C MiniMax \u5F00\u653E\u5E73\u53F0 \u2192 \u8D26\u53F7\u8BBE\u7F6E \u2192 \u63A5\u53E3\u5BC6\u94A5\n" : " 1. Sign up at platform.minimaxi.com \u2192 Account \u2192 API Keys\n"
|
|
245211
|
+
));
|
|
245212
|
+
}
|
|
245213
|
+
const { apiKey } = await esm_default12.prompt([{
|
|
245214
|
+
type: "password",
|
|
245215
|
+
name: "apiKey",
|
|
245216
|
+
message: isCN ? `\u7C98\u8D34\u4F60\u7684 ${providerInfo.name} API Key:` : `Paste your ${providerInfo.name} API key:`,
|
|
245217
|
+
mask: "*",
|
|
245218
|
+
validate: (v2) => {
|
|
245219
|
+
if (!v2.trim()) return isCN ? "\u8BF7\u8F93\u5165 API Key" : "API key required";
|
|
245220
|
+
if (providerInfo.keyPrefix && !v2.startsWith(providerInfo.keyPrefix)) {
|
|
245221
|
+
return isCN ? `Key \u683C\u5F0F\u4E0D\u5BF9\uFF0C\u5E94\u4EE5 "${providerInfo.keyPrefix}" \u5F00\u5934` : `Should start with "${providerInfo.keyPrefix}"`;
|
|
245222
|
+
}
|
|
245223
|
+
return true;
|
|
245224
|
+
}
|
|
245225
|
+
}]);
|
|
245226
|
+
envValues[providerInfo.envKey] = apiKey;
|
|
245227
|
+
if (characterCreatedNew) {
|
|
245228
|
+
await runTestChat(characterName, apiKey, llmProvider);
|
|
245229
|
+
}
|
|
245230
|
+
}
|
|
245231
|
+
if (llmProvider === "ollama") {
|
|
245232
|
+
console.log(source_default.yellow(
|
|
245233
|
+
isCN ? "\n \u786E\u4FDD Ollama \u5DF2\u8FD0\u884C: https://ollama.ai" : "\n Make sure Ollama is running: https://ollama.ai"
|
|
245234
|
+
));
|
|
245235
|
+
console.log(source_default.gray(
|
|
245236
|
+
isCN ? " \u8FD0\u884C: ollama pull qwen2.5:7b\n" : " Run: ollama pull qwen2.5:7b\n"
|
|
245237
|
+
));
|
|
245238
|
+
envValues.OLLAMA_BASE_URL = "http://localhost:11434";
|
|
245239
|
+
envValues.OLLAMA_MODEL = "qwen2.5:7b";
|
|
245240
|
+
}
|
|
245228
245241
|
step(4, isCN ? "\u611F\u5B98\u529F\u80FD\uFF08\u53EF\u9009\uFF09" : "Sensory features (optional)");
|
|
245229
245242
|
console.log(source_default.gray(isCN ? "\u8FD9\u4E9B\u529F\u80FD\u8BA9\u4F60\u7684\u4F34\u4FA3\u66F4\u52A0\u771F\u5B9E\u2014\u2014\u770B\u5F97\u89C1\u3001\u542C\u5F97\u5230\u3001\u6709\u81EA\u5DF1\u7684\u793E\u4EA4\u5708\u3002\n" : "These features make your companion come alive \u2014 visible, audible, and social.\n"));
|
|
245230
245243
|
const { optionalFeatures } = await esm_default12.prompt([{
|
|
@@ -245235,7 +245248,7 @@ async function runSetupWizard() {
|
|
|
245235
245248
|
{
|
|
245236
245249
|
name: isCN ? "\u{1F4F8} \u81EA\u62CD & \u89C6\u9891 \u2014 \u53EF\u4EE5\u53D1\u81EA\u62CD\u548C\u77ED\u89C6\u9891 (\u9700\u8981 fal.ai key)" : "\u{1F4F8} Selfies & Video \u2014 send photos and short videos (needs fal.ai key)",
|
|
245237
245250
|
value: "images",
|
|
245238
|
-
checked:
|
|
245251
|
+
checked: false
|
|
245239
245252
|
},
|
|
245240
245253
|
{
|
|
245241
245254
|
name: isCN ? "\u{1F3A4} \u8BED\u97F3\u6D88\u606F \u2014 \u53EF\u4EE5\u53D1\u8BED\u97F3 (ElevenLabs / Fish Audio / FAL Kokoro)" : "\u{1F3A4} Voice messages \u2014 send voice notes (ElevenLabs / Fish Audio / FAL Kokoro)",
|
|
@@ -245535,6 +245548,28 @@ async function runSetupWizard() {
|
|
|
245535
245548
|
await startOpencrush2();
|
|
245536
245549
|
}
|
|
245537
245550
|
}
|
|
245551
|
+
function getCharacterPreview(name) {
|
|
245552
|
+
var _a3, _b2;
|
|
245553
|
+
const identityPath = (0, import_path14.join)(getCharactersDir(), name, "IDENTITY.md");
|
|
245554
|
+
if (!(0, import_fs20.existsSync)(identityPath)) return "";
|
|
245555
|
+
try {
|
|
245556
|
+
const { readFileSync: readFileSync8 } = require("fs");
|
|
245557
|
+
const content = readFileSync8(identityPath, "utf-8");
|
|
245558
|
+
const ageMatch = content.match(/\*\*Age:\*\*\s*(\d+)/i);
|
|
245559
|
+
const fromMatch = content.match(/\*\*From:\*\*\s*(.+)/i);
|
|
245560
|
+
const age = ageMatch == null ? void 0 : ageMatch[1];
|
|
245561
|
+
const from2 = (_b2 = (_a3 = fromMatch == null ? void 0 : fromMatch[1]) == null ? void 0 : _a3.trim().split(",")[0]) == null ? void 0 : _b2.trim();
|
|
245562
|
+
return [age ? `${age}yo` : "", from2].filter(Boolean).join(" \xB7 ");
|
|
245563
|
+
} catch {
|
|
245564
|
+
return "";
|
|
245565
|
+
}
|
|
245566
|
+
}
|
|
245567
|
+
function maybeOpenCard(name) {
|
|
245568
|
+
const cardPath = (0, import_path14.join)(getCharactersDir(), name, "card.png");
|
|
245569
|
+
if (!(0, import_fs20.existsSync)(cardPath)) return;
|
|
245570
|
+
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
245571
|
+
(0, import_child_process5.exec)(`${opener} "${cardPath}"`);
|
|
245572
|
+
}
|
|
245538
245573
|
function getExistingCharacters() {
|
|
245539
245574
|
const charactersDir = getCharactersDir();
|
|
245540
245575
|
if (!(0, import_fs20.existsSync)(charactersDir)) return [];
|