@aptol/openclaw-persona 1.1.0 → 1.2.1
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/bin/create.mjs +270 -104
- package/package.json +1 -1
package/bin/create.mjs
CHANGED
|
@@ -57,6 +57,12 @@ const DISCORD_POLICIES = {
|
|
|
57
57
|
'특정 서버/채널만 허용 (ID 직접 입력)': 'allowlist',
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
+
const AI_MODELS = {
|
|
61
|
+
'Claude Opus 4 (최고 성능, 비용 높음)': 'anthropic/claude-opus-4-6',
|
|
62
|
+
'Claude Sonnet 4 (균형, 추천)': 'anthropic/claude-sonnet-4-20250514',
|
|
63
|
+
'Claude Sonnet 4.5 (고성능 + 빠름)': 'anthropic/claude-sonnet-4-5-20250514',
|
|
64
|
+
};
|
|
65
|
+
|
|
60
66
|
async function askServerChannels() {
|
|
61
67
|
const servers = [];
|
|
62
68
|
let addMore = true;
|
|
@@ -122,7 +128,10 @@ async function main() {
|
|
|
122
128
|
console.log('\n🎭 OpenClaw Persona Creator\n');
|
|
123
129
|
console.log('나만의 AI 캐릭터를 만들어보세요!\n');
|
|
124
130
|
|
|
125
|
-
|
|
131
|
+
// ─── 1. 캐릭터 기본 정보 ───
|
|
132
|
+
console.log('━━━ 1/5: 캐릭터 정보 ━━━\n');
|
|
133
|
+
|
|
134
|
+
const charAnswers = await inquirer.prompt([
|
|
126
135
|
{
|
|
127
136
|
type: 'input',
|
|
128
137
|
name: 'name',
|
|
@@ -165,10 +174,106 @@ async function main() {
|
|
|
165
174
|
message: '만든 사람 이름:',
|
|
166
175
|
validate: (v) => v.trim() ? true : '이름을 입력해주세요.',
|
|
167
176
|
},
|
|
177
|
+
{
|
|
178
|
+
type: 'list',
|
|
179
|
+
name: 'presetKey',
|
|
180
|
+
message: '프리셋 베이스:',
|
|
181
|
+
choices: Object.keys(PRESET_NAMES),
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
type: 'checkbox',
|
|
185
|
+
name: 'moduleKeys',
|
|
186
|
+
message: '모듈 선택 (스페이스바로 선택):',
|
|
187
|
+
choices: Object.keys(MODULE_MAP),
|
|
188
|
+
},
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
// ─── 2. AI 모델 설정 ───
|
|
192
|
+
console.log('\n━━━ 2/5: AI 모델 설정 ━━━\n');
|
|
193
|
+
|
|
194
|
+
const modelAnswers = await inquirer.prompt([
|
|
195
|
+
{
|
|
196
|
+
type: 'list',
|
|
197
|
+
name: 'modelKey',
|
|
198
|
+
message: 'AI 모델 선택:',
|
|
199
|
+
choices: Object.keys(AI_MODELS),
|
|
200
|
+
},
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
// ─── 3. API 키 설정 ───
|
|
204
|
+
console.log('\n━━━ 3/5: API 키 설정 ━━━\n');
|
|
205
|
+
|
|
206
|
+
const authModeAnswers = await inquirer.prompt([{
|
|
207
|
+
type: 'list',
|
|
208
|
+
name: 'anthropicAuth',
|
|
209
|
+
message: 'Anthropic 인증 방식:',
|
|
210
|
+
choices: [
|
|
211
|
+
{ name: 'API 키 직접 입력 (sk-ant-...)', value: 'token' },
|
|
212
|
+
{ name: 'Claude Max/Pro 구독 연결 (OAuth, 브라우저 인증)', value: 'oauth' },
|
|
213
|
+
{ name: '나중에 설정', value: 'skip' },
|
|
214
|
+
],
|
|
215
|
+
}]);
|
|
216
|
+
|
|
217
|
+
let anthropicKey = '';
|
|
218
|
+
let anthropicOAuth = false;
|
|
219
|
+
|
|
220
|
+
if (authModeAnswers.anthropicAuth === 'token') {
|
|
221
|
+
const { key } = await inquirer.prompt([{
|
|
222
|
+
type: 'password',
|
|
223
|
+
name: 'key',
|
|
224
|
+
message: 'Anthropic API 키 (sk-ant-...):',
|
|
225
|
+
mask: '*',
|
|
226
|
+
}]);
|
|
227
|
+
anthropicKey = key.trim();
|
|
228
|
+
} else if (authModeAnswers.anthropicAuth === 'oauth') {
|
|
229
|
+
anthropicOAuth = true;
|
|
230
|
+
console.log('\n📌 구독 연결은 캐릭터 생성 후 아래 명령어로 완료하세요:');
|
|
231
|
+
console.log(' $env:OPENCLAW_HOME = "<출력 디렉토리>"');
|
|
232
|
+
console.log(' openclaw auth login\n');
|
|
233
|
+
console.log(' 브라우저가 열리면 Claude 계정으로 로그인하세요.\n');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
console.log('💡 빈칸으로 넘기면 나중에 openclaw.json에서 수동 설정 가능\n');
|
|
237
|
+
|
|
238
|
+
const apiAnswers = await inquirer.prompt([
|
|
239
|
+
{
|
|
240
|
+
type: 'password',
|
|
241
|
+
name: 'openaiKey',
|
|
242
|
+
message: 'OpenAI API 키 (메모리 검색용, sk-...):',
|
|
243
|
+
mask: '*',
|
|
244
|
+
default: '',
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
type: 'password',
|
|
248
|
+
name: 'braveKey',
|
|
249
|
+
message: 'Brave Search API 키 (웹 검색용):',
|
|
250
|
+
mask: '*',
|
|
251
|
+
default: '',
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
type: 'password',
|
|
255
|
+
name: 'elevenlabsKey',
|
|
256
|
+
message: 'ElevenLabs API 키 (음성 TTS용, 선택):',
|
|
257
|
+
mask: '*',
|
|
258
|
+
default: '',
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
type: 'password',
|
|
262
|
+
name: 'deepgramKey',
|
|
263
|
+
message: 'Deepgram API 키 (음성 STT용, 선택):',
|
|
264
|
+
mask: '*',
|
|
265
|
+
default: '',
|
|
266
|
+
},
|
|
267
|
+
]);
|
|
268
|
+
|
|
269
|
+
// ─── 4. 디스코드 설정 ───
|
|
270
|
+
console.log('\n━━━ 4/5: 디스코드 설정 ━━━\n');
|
|
271
|
+
|
|
272
|
+
const discordAnswers = await inquirer.prompt([
|
|
168
273
|
{
|
|
169
274
|
type: 'input',
|
|
170
275
|
name: 'discordId',
|
|
171
|
-
message: 'Discord 사용자 ID (
|
|
276
|
+
message: 'Discord 사용자 ID (숫자, 주인):',
|
|
172
277
|
validate: (v) => {
|
|
173
278
|
if (!v.trim()) return '디스코드 ID를 입력해주세요.';
|
|
174
279
|
if (!/^\d+$/.test(v.trim())) return '숫자만 입력해주세요.';
|
|
@@ -176,9 +281,10 @@ async function main() {
|
|
|
176
281
|
},
|
|
177
282
|
},
|
|
178
283
|
{
|
|
179
|
-
type: '
|
|
284
|
+
type: 'password',
|
|
180
285
|
name: 'discordToken',
|
|
181
|
-
message: 'Discord 봇
|
|
286
|
+
message: 'Discord 봇 토큰:',
|
|
287
|
+
mask: '*',
|
|
182
288
|
default: '',
|
|
183
289
|
},
|
|
184
290
|
{
|
|
@@ -189,92 +295,75 @@ async function main() {
|
|
|
189
295
|
},
|
|
190
296
|
]);
|
|
191
297
|
|
|
192
|
-
const discordPolicy = DISCORD_POLICIES[
|
|
298
|
+
const discordPolicy = DISCORD_POLICIES[discordAnswers.discordPolicyKey];
|
|
193
299
|
|
|
194
|
-
// If allowlist, ask for server/channel IDs
|
|
195
300
|
let serverConfigs = [];
|
|
196
301
|
if (discordPolicy === 'allowlist') {
|
|
197
302
|
console.log('\n📋 활동할 서버와 채널을 설정합니다.\n');
|
|
198
303
|
serverConfigs = await askServerChannels();
|
|
199
304
|
}
|
|
200
305
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
message: '프리셋 베이스:',
|
|
206
|
-
choices: Object.keys(PRESET_NAMES),
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
type: 'checkbox',
|
|
210
|
-
name: 'moduleKeys',
|
|
211
|
-
message: '모듈 선택 (스페이스바로 선택):',
|
|
212
|
-
choices: Object.keys(MODULE_MAP),
|
|
213
|
-
},
|
|
306
|
+
// ─── 5. 출력 설정 ───
|
|
307
|
+
console.log('\n━━━ 5/5: 출력 설정 ━━━\n');
|
|
308
|
+
|
|
309
|
+
const outputAnswers = await inquirer.prompt([
|
|
214
310
|
{
|
|
215
311
|
type: 'input',
|
|
216
312
|
name: 'outputDir',
|
|
217
313
|
message: '출력 디렉토리:',
|
|
218
|
-
default: `./output/${
|
|
314
|
+
default: `./output/${charAnswers.name.trim()}`,
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
type: 'input',
|
|
318
|
+
name: 'gatewayPort',
|
|
319
|
+
message: '게이트웨이 포트 (기본 18789, 다른 봇 있으면 변경):',
|
|
320
|
+
default: '18789',
|
|
321
|
+
validate: (v) => /^\d+$/.test(v.trim()) ? true : '숫자만 입력해주세요.',
|
|
219
322
|
},
|
|
220
323
|
]);
|
|
221
324
|
|
|
325
|
+
// ─── Build ───
|
|
326
|
+
|
|
222
327
|
const vars = {
|
|
223
|
-
name:
|
|
224
|
-
gender:
|
|
225
|
-
speechStyle: SPEECH_STYLES[
|
|
226
|
-
personality:
|
|
227
|
-
likes:
|
|
228
|
-
dislikes:
|
|
229
|
-
creator:
|
|
328
|
+
name: charAnswers.name.trim(),
|
|
329
|
+
gender: charAnswers.gender,
|
|
330
|
+
speechStyle: SPEECH_STYLES[charAnswers.speechStyleKey],
|
|
331
|
+
personality: charAnswers.personality.trim(),
|
|
332
|
+
likes: charAnswers.likes.trim(),
|
|
333
|
+
dislikes: charAnswers.dislikes.trim(),
|
|
334
|
+
creator: charAnswers.creator.trim(),
|
|
230
335
|
};
|
|
231
336
|
|
|
232
|
-
const preset = PRESET_NAMES[
|
|
233
|
-
const outputDir =
|
|
337
|
+
const preset = PRESET_NAMES[charAnswers.presetKey];
|
|
338
|
+
const outputDir = outputAnswers.outputDir;
|
|
234
339
|
|
|
235
340
|
// Create output directories
|
|
236
341
|
mkdirSync(join(outputDir, 'memory'), { recursive: true });
|
|
237
342
|
mkdirSync(join(outputDir, 'modules'), { recursive: true });
|
|
238
343
|
|
|
239
|
-
// Generate files
|
|
344
|
+
// Generate character files
|
|
240
345
|
if (preset) {
|
|
241
346
|
const presetDir = join(ROOT, 'presets', preset);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
writeOutput(outputDir, 'SOUL.md', soulContent);
|
|
247
|
-
writeOutput(outputDir, 'AGENTS.md', agentsContent);
|
|
248
|
-
writeOutput(outputDir, 'IDENTITY.md', identityContent);
|
|
347
|
+
writeOutput(outputDir, 'SOUL.md', replaceVars(readTemplate(join(presetDir, 'SOUL.md')), vars));
|
|
348
|
+
writeOutput(outputDir, 'AGENTS.md', readTemplate(join(presetDir, 'AGENTS.md')));
|
|
349
|
+
writeOutput(outputDir, 'IDENTITY.md', replaceVars(readTemplate(join(presetDir, 'IDENTITY.md')), vars));
|
|
249
350
|
} else {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
writeOutput(outputDir, 'SOUL.md', soulContent);
|
|
255
|
-
writeOutput(outputDir, 'AGENTS.md', agentsContent);
|
|
256
|
-
writeOutput(outputDir, 'IDENTITY.md', identityContent);
|
|
351
|
+
writeOutput(outputDir, 'SOUL.md', replaceVars(readTemplate(join(ROOT, 'templates', 'SOUL.template.md')), vars));
|
|
352
|
+
writeOutput(outputDir, 'AGENTS.md', readTemplate(join(ROOT, 'templates', 'AGENTS.template.md')));
|
|
353
|
+
writeOutput(outputDir, 'IDENTITY.md', replaceVars(readTemplate(join(ROOT, 'templates', 'IDENTITY.template.md')), vars));
|
|
257
354
|
}
|
|
258
355
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
writeOutput(outputDir, 'USER.md', userContent);
|
|
262
|
-
|
|
263
|
-
// MEMORY.md
|
|
264
|
-
const memoryContent = replaceVars(readTemplate(join(ROOT, 'templates', 'MEMORY.template.md')), vars);
|
|
265
|
-
writeOutput(outputDir, 'MEMORY.md', memoryContent);
|
|
356
|
+
writeOutput(outputDir, 'USER.md', replaceVars(readTemplate(join(ROOT, 'templates', 'USER.template.md')), vars));
|
|
357
|
+
writeOutput(outputDir, 'MEMORY.md', replaceVars(readTemplate(join(ROOT, 'templates', 'MEMORY.template.md')), vars));
|
|
266
358
|
|
|
267
359
|
// Copy selected modules
|
|
268
360
|
let hasProactiveChat = false;
|
|
269
|
-
for (const moduleKey of
|
|
361
|
+
for (const moduleKey of charAnswers.moduleKeys) {
|
|
270
362
|
const moduleFile = MODULE_MAP[moduleKey];
|
|
271
|
-
|
|
272
|
-
const dest = join(outputDir, 'modules', moduleFile);
|
|
273
|
-
copyFileSync(src, dest);
|
|
363
|
+
copyFileSync(join(ROOT, 'modules', moduleFile), join(outputDir, 'modules', moduleFile));
|
|
274
364
|
if (moduleFile === 'proactive-chat.md') hasProactiveChat = true;
|
|
275
365
|
}
|
|
276
366
|
|
|
277
|
-
// If proactive-chat module selected, create HEARTBEAT.md
|
|
278
367
|
if (hasProactiveChat) {
|
|
279
368
|
writeOutput(outputDir, 'HEARTBEAT.md', `# HEARTBEAT.md
|
|
280
369
|
|
|
@@ -307,15 +396,70 @@ async function main() {
|
|
|
307
396
|
`);
|
|
308
397
|
}
|
|
309
398
|
|
|
310
|
-
// Build openclaw
|
|
399
|
+
// ─── Build openclaw.json ───
|
|
400
|
+
|
|
311
401
|
const config = JSON.parse(readFileSync(join(ROOT, 'config', 'openclaw.template.json'), 'utf-8'));
|
|
312
|
-
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
402
|
+
const discordId = discordAnswers.discordId.trim();
|
|
403
|
+
const port = parseInt(outputAnswers.gatewayPort.trim());
|
|
404
|
+
|
|
405
|
+
// Model
|
|
406
|
+
config.agents.defaults.model.primary = AI_MODELS[modelAnswers.modelKey];
|
|
407
|
+
|
|
408
|
+
// Anthropic auth
|
|
409
|
+
if (anthropicOAuth) {
|
|
410
|
+
config.auth.profiles['anthropic:default'] = {
|
|
411
|
+
provider: 'anthropic',
|
|
412
|
+
mode: 'oauth',
|
|
413
|
+
};
|
|
414
|
+
} else if (anthropicKey) {
|
|
415
|
+
config.auth.profiles['anthropic:default'].token = anthropicKey;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// OpenAI (memory search)
|
|
419
|
+
if (apiAnswers.openaiKey.trim()) {
|
|
420
|
+
config.agents.defaults.memorySearch.remote = { apiKey: apiAnswers.openaiKey.trim() };
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Brave Search
|
|
424
|
+
if (apiAnswers.braveKey.trim()) {
|
|
425
|
+
if (!config.plugins) config.plugins = { entries: {} };
|
|
426
|
+
config.plugins.entries = config.plugins.entries || {};
|
|
427
|
+
config.plugins.entries.brave = {
|
|
428
|
+
enabled: true,
|
|
429
|
+
config: { webSearch: { apiKey: apiAnswers.braveKey.trim() } },
|
|
430
|
+
};
|
|
431
|
+
if (!config.tools) config.tools = {};
|
|
432
|
+
config.tools.web = { search: { provider: 'brave' } };
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ElevenLabs
|
|
436
|
+
if (apiAnswers.elevenlabsKey.trim()) {
|
|
437
|
+
if (!config.env) config.env = {};
|
|
438
|
+
if (!config.env.vars) config.env.vars = {};
|
|
439
|
+
config.env.vars.ELEVENLABS_API_KEY = apiAnswers.elevenlabsKey.trim();
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Deepgram
|
|
443
|
+
if (apiAnswers.deepgramKey.trim()) {
|
|
444
|
+
if (!config.env) config.env = {};
|
|
445
|
+
if (!config.env.vars) config.env.vars = {};
|
|
446
|
+
config.env.vars.DEEPGRAM_API_KEY = apiAnswers.deepgramKey.trim();
|
|
447
|
+
config.env.vars.DEEPGRAM_MODEL = 'nova-3';
|
|
448
|
+
config.env.vars.DEEPGRAM_LANGUAGE = 'ko';
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Discord
|
|
452
|
+
config.channels.discord.token = discordAnswers.discordToken.trim() || '';
|
|
316
453
|
config.channels.discord.dmPolicy = 'allowlist';
|
|
317
454
|
config.channels.discord.allowFrom = [discordId];
|
|
318
|
-
config.commands = {
|
|
455
|
+
config.commands = {
|
|
456
|
+
native: 'auto',
|
|
457
|
+
nativeSkills: 'auto',
|
|
458
|
+
debug: true,
|
|
459
|
+
restart: true,
|
|
460
|
+
ownerAllowFrom: [discordId],
|
|
461
|
+
ownerDisplay: 'raw',
|
|
462
|
+
};
|
|
319
463
|
|
|
320
464
|
// Discord server policy
|
|
321
465
|
if (discordPolicy === 'mention') {
|
|
@@ -323,66 +467,88 @@ async function main() {
|
|
|
323
467
|
} else if (discordPolicy === 'all') {
|
|
324
468
|
config.channels.discord.groupPolicy = 'all';
|
|
325
469
|
} else {
|
|
326
|
-
// allowlist with specific servers/channels
|
|
327
470
|
config.channels.discord.groupPolicy = 'allowlist';
|
|
328
471
|
const guilds = {};
|
|
329
472
|
for (const server of serverConfigs) {
|
|
330
|
-
const guild = {
|
|
331
|
-
|
|
332
|
-
channels:
|
|
333
|
-
};
|
|
334
|
-
if (server.channels.length > 0) {
|
|
335
|
-
for (const chId of server.channels) {
|
|
336
|
-
guild.channels[chId] = {
|
|
337
|
-
allow: true,
|
|
338
|
-
requireMention: server.requireMention,
|
|
339
|
-
enabled: true,
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
} else {
|
|
343
|
-
// No specific channels = server-wide (empty channels object means all channels)
|
|
344
|
-
guild.channels = {};
|
|
473
|
+
const guild = { requireMention: server.requireMention, channels: {} };
|
|
474
|
+
for (const chId of server.channels) {
|
|
475
|
+
guild.channels[chId] = { allow: true, requireMention: server.requireMention, enabled: true };
|
|
345
476
|
}
|
|
346
477
|
guilds[server.guildId] = guild;
|
|
347
478
|
}
|
|
348
479
|
config.channels.discord.guilds = guilds;
|
|
349
480
|
}
|
|
350
481
|
|
|
351
|
-
|
|
482
|
+
// Gateway
|
|
483
|
+
config.gateway.port = port;
|
|
484
|
+
|
|
485
|
+
// Discord plugin
|
|
486
|
+
if (!config.plugins) config.plugins = { entries: {} };
|
|
487
|
+
config.plugins.entries.discord = { enabled: true, config: {} };
|
|
488
|
+
|
|
489
|
+
// Streaming
|
|
490
|
+
config.channels.discord.streaming = 'partial';
|
|
491
|
+
config.channels.discord.historyLimit = 16;
|
|
492
|
+
config.channels.discord.intents = { presence: true };
|
|
493
|
+
config.channels.discord.actions = {
|
|
494
|
+
reactions: true, stickers: true, emojiUploads: true, stickerUploads: true,
|
|
495
|
+
polls: true, permissions: true, messages: true, threads: true, pins: true,
|
|
496
|
+
search: true, memberInfo: true, roleInfo: true, roles: true, channelInfo: true,
|
|
497
|
+
voiceStatus: true, events: true, moderation: true, channels: true, presence: true,
|
|
498
|
+
};
|
|
352
499
|
|
|
353
|
-
|
|
500
|
+
writeOutput(outputDir, 'openclaw.json', JSON.stringify(config, null, 2) + '\n');
|
|
354
501
|
writeFileSync(join(outputDir, 'memory', '.gitkeep'), '', 'utf-8');
|
|
355
502
|
|
|
503
|
+
// ─── Summary ───
|
|
504
|
+
|
|
505
|
+
const configured = [];
|
|
506
|
+
const notConfigured = [];
|
|
507
|
+
|
|
508
|
+
if (anthropicKey) configured.push('Anthropic (API 키)');
|
|
509
|
+
else if (anthropicOAuth) configured.push('Anthropic (OAuth 구독 — openclaw auth login 필요)');
|
|
510
|
+
else notConfigured.push('Anthropic 인증');
|
|
511
|
+
|
|
512
|
+
if (apiAnswers.openaiKey.trim()) configured.push('OpenAI (메모리 검색)');
|
|
513
|
+
else notConfigured.push('OpenAI API 키 (메모리 검색)');
|
|
514
|
+
|
|
515
|
+
if (apiAnswers.braveKey.trim()) configured.push('Brave Search (웹 검색)');
|
|
516
|
+
else notConfigured.push('Brave Search API 키 (웹 검색)');
|
|
517
|
+
|
|
518
|
+
if (apiAnswers.elevenlabsKey.trim()) configured.push('ElevenLabs (음성 TTS)');
|
|
519
|
+
if (apiAnswers.deepgramKey.trim()) configured.push('Deepgram (음성 STT)');
|
|
520
|
+
|
|
521
|
+
if (discordAnswers.discordToken.trim()) configured.push('Discord 봇 토큰');
|
|
522
|
+
else notConfigured.push('Discord 봇 토큰');
|
|
523
|
+
|
|
356
524
|
console.log(`\n✅ ${vars.name} 생성 완료!`);
|
|
357
525
|
console.log(`📁 위치: ${outputDir}`);
|
|
358
|
-
|
|
359
|
-
console.log('
|
|
360
|
-
console.log('
|
|
361
|
-
console.log('
|
|
362
|
-
console.log('
|
|
363
|
-
|
|
364
|
-
console.log('
|
|
365
|
-
console.log('
|
|
366
|
-
if (
|
|
367
|
-
|
|
368
|
-
}
|
|
526
|
+
|
|
527
|
+
console.log('\n📋 생성된 파일:');
|
|
528
|
+
console.log(' SOUL.md / AGENTS.md / IDENTITY.md / USER.md / MEMORY.md / openclaw.json');
|
|
529
|
+
if (charAnswers.moduleKeys.length > 0) console.log(' modules/ (선택한 시스템 모듈)');
|
|
530
|
+
if (hasProactiveChat) console.log(' HEARTBEAT.md (선제 대화)');
|
|
531
|
+
|
|
532
|
+
console.log('\n🔑 API 설정 현황:');
|
|
533
|
+
if (configured.length > 0) console.log(' ✅ ' + configured.join(', '));
|
|
534
|
+
if (notConfigured.length > 0) console.log(' ❌ 미설정: ' + notConfigured.join(', '));
|
|
535
|
+
|
|
536
|
+
console.log(`\n🤖 모델: ${AI_MODELS[modelAnswers.modelKey]}`);
|
|
537
|
+
|
|
538
|
+
if (discordPolicy === 'mention') console.log('🏠 서버 정책: 멘션(@봇) 시에만 반응');
|
|
539
|
+
else if (discordPolicy === 'all') console.log('🏠 서버 정책: 모든 서버에서 항상 반응');
|
|
540
|
+
else console.log(`🏠 서버 정책: ${serverConfigs.length}개 서버 허용목록`);
|
|
541
|
+
|
|
542
|
+
console.log(`🌐 게이트웨이 포트: ${port}`);
|
|
369
543
|
|
|
370
544
|
console.log('\n🚀 구동 방법:');
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
console.log(` 서버 정책: ${serverConfigs.length}개 서버 허용목록`);
|
|
545
|
+
console.log(` $env:OPENCLAW_HOME = "${outputDir}"`);
|
|
546
|
+
console.log(' openclaw gateway run');
|
|
547
|
+
|
|
548
|
+
if (notConfigured.length > 0) {
|
|
549
|
+
console.log('\n⚠️ 미설정 항목은 openclaw.json에서 직접 수정하세요.');
|
|
377
550
|
}
|
|
378
551
|
console.log('');
|
|
379
|
-
console.log(' 1. openclaw.json에서 API 키와 Discord 토큰을 설정하세요');
|
|
380
|
-
console.log(' 2. USER.md에 주인 정보를 추가하세요');
|
|
381
|
-
console.log(' 3. SOUL.md를 원하는 대로 커스텀하세요');
|
|
382
|
-
console.log(' 4. 구동:');
|
|
383
|
-
console.log(` $env:OPENCLAW_HOME = "${outputDir}"`);
|
|
384
|
-
console.log(' openclaw gateway run');
|
|
385
|
-
console.log('');
|
|
386
552
|
}
|
|
387
553
|
|
|
388
554
|
main().catch((err) => {
|
package/package.json
CHANGED