kimaki 0.4.48 → 0.4.49
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/cli.js +28 -10
- package/package.json +1 -1
- package/src/cli.ts +34 -10
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,15 @@ import http from 'node:http';
|
|
|
17
17
|
import { setDataDir, getDataDir, getLockPort, setDefaultVerbosity } from './config.js';
|
|
18
18
|
import { sanitizeAgentName } from './commands/agent.js';
|
|
19
19
|
const cliLogger = createLogger(LogPrefix.CLI);
|
|
20
|
+
// Strip bracketed paste escape sequences from terminal input.
|
|
21
|
+
// iTerm2 and other terminals wrap pasted content with \x1b[200~ and \x1b[201~
|
|
22
|
+
// which can cause validation to fail on macOS. See: https://github.com/remorses/kimaki/issues/18
|
|
23
|
+
function stripBracketedPaste(value) {
|
|
24
|
+
if (!value) {
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
27
|
+
return value.replace(/\x1b\[200~/g, '').replace(/\x1b\[201~/g, '').trim();
|
|
28
|
+
}
|
|
20
29
|
// Spawn caffeinate on macOS to prevent system sleep while bot is running.
|
|
21
30
|
// Not detached, so it dies automatically with the parent process.
|
|
22
31
|
function startCaffeinate() {
|
|
@@ -499,17 +508,20 @@ async function run({ restart, addChannels, useWorktrees }) {
|
|
|
499
508
|
message: 'Enter your Discord Application ID:',
|
|
500
509
|
placeholder: 'e.g., 1234567890123456789',
|
|
501
510
|
validate(value) {
|
|
502
|
-
|
|
511
|
+
const cleaned = stripBracketedPaste(value);
|
|
512
|
+
if (!cleaned) {
|
|
503
513
|
return 'Application ID is required';
|
|
504
|
-
|
|
514
|
+
}
|
|
515
|
+
if (!/^\d{17,20}$/.test(cleaned)) {
|
|
505
516
|
return 'Invalid Application ID format (should be 17-20 digits)';
|
|
517
|
+
}
|
|
506
518
|
},
|
|
507
519
|
});
|
|
508
520
|
if (isCancel(appIdInput)) {
|
|
509
521
|
cancel('Setup cancelled');
|
|
510
522
|
process.exit(0);
|
|
511
523
|
}
|
|
512
|
-
appId = appIdInput;
|
|
524
|
+
appId = stripBracketedPaste(appIdInput);
|
|
513
525
|
note('1. Go to the "Bot" section in the left sidebar\n' +
|
|
514
526
|
'2. Scroll down to "Privileged Gateway Intents"\n' +
|
|
515
527
|
'3. Enable these intents by toggling them ON:\n' +
|
|
@@ -530,33 +542,39 @@ async function run({ restart, addChannels, useWorktrees }) {
|
|
|
530
542
|
const tokenInput = await password({
|
|
531
543
|
message: 'Enter your Discord Bot Token (from "Bot" section - click "Reset Token" if needed):',
|
|
532
544
|
validate(value) {
|
|
533
|
-
|
|
545
|
+
const cleaned = stripBracketedPaste(value);
|
|
546
|
+
if (!cleaned) {
|
|
534
547
|
return 'Bot token is required';
|
|
535
|
-
|
|
548
|
+
}
|
|
549
|
+
if (cleaned.length < 50) {
|
|
536
550
|
return 'Invalid token format (too short)';
|
|
551
|
+
}
|
|
537
552
|
},
|
|
538
553
|
});
|
|
539
554
|
if (isCancel(tokenInput)) {
|
|
540
555
|
cancel('Setup cancelled');
|
|
541
556
|
process.exit(0);
|
|
542
557
|
}
|
|
543
|
-
token = tokenInput;
|
|
558
|
+
token = stripBracketedPaste(tokenInput);
|
|
544
559
|
note(`You can get a Gemini api Key at https://aistudio.google.com/apikey`, `Gemini API Key`);
|
|
545
|
-
const
|
|
560
|
+
const geminiApiKeyInput = await password({
|
|
546
561
|
message: 'Enter your Gemini API Key for voice channels and audio transcription (optional, press Enter to skip):',
|
|
547
562
|
validate(value) {
|
|
548
|
-
|
|
563
|
+
const cleaned = stripBracketedPaste(value);
|
|
564
|
+
if (cleaned && cleaned.length < 10) {
|
|
549
565
|
return 'Invalid API key format';
|
|
566
|
+
}
|
|
550
567
|
return undefined;
|
|
551
568
|
},
|
|
552
569
|
});
|
|
553
|
-
if (isCancel(
|
|
570
|
+
if (isCancel(geminiApiKeyInput)) {
|
|
554
571
|
cancel('Setup cancelled');
|
|
555
572
|
process.exit(0);
|
|
556
573
|
}
|
|
574
|
+
const geminiApiKey = stripBracketedPaste(geminiApiKeyInput) || null;
|
|
557
575
|
// Store API key in database
|
|
558
576
|
if (geminiApiKey) {
|
|
559
|
-
db.prepare('INSERT OR REPLACE INTO bot_api_keys (app_id, gemini_api_key) VALUES (?, ?)').run(appId, geminiApiKey
|
|
577
|
+
db.prepare('INSERT OR REPLACE INTO bot_api_keys (app_id, gemini_api_key) VALUES (?, ?)').run(appId, geminiApiKey);
|
|
560
578
|
note('API key saved successfully', 'API Key Stored');
|
|
561
579
|
}
|
|
562
580
|
note(`Bot install URL:\n${generateBotInstallUrl({ clientId: appId })}\n\nYou MUST install the bot in your Discord server before continuing.`, 'Step 4: Install Bot to Server');
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -52,6 +52,16 @@ import { sanitizeAgentName } from './commands/agent.js'
|
|
|
52
52
|
|
|
53
53
|
const cliLogger = createLogger(LogPrefix.CLI)
|
|
54
54
|
|
|
55
|
+
// Strip bracketed paste escape sequences from terminal input.
|
|
56
|
+
// iTerm2 and other terminals wrap pasted content with \x1b[200~ and \x1b[201~
|
|
57
|
+
// which can cause validation to fail on macOS. See: https://github.com/remorses/kimaki/issues/18
|
|
58
|
+
function stripBracketedPaste(value: string | undefined): string {
|
|
59
|
+
if (!value) {
|
|
60
|
+
return ''
|
|
61
|
+
}
|
|
62
|
+
return value.replace(/\x1b\[200~/g, '').replace(/\x1b\[201~/g, '').trim()
|
|
63
|
+
}
|
|
64
|
+
|
|
55
65
|
// Spawn caffeinate on macOS to prevent system sleep while bot is running.
|
|
56
66
|
// Not detached, so it dies automatically with the parent process.
|
|
57
67
|
function startCaffeinate() {
|
|
@@ -696,9 +706,13 @@ async function run({ restart, addChannels, useWorktrees }: CliOptions) {
|
|
|
696
706
|
message: 'Enter your Discord Application ID:',
|
|
697
707
|
placeholder: 'e.g., 1234567890123456789',
|
|
698
708
|
validate(value) {
|
|
699
|
-
|
|
700
|
-
if (
|
|
709
|
+
const cleaned = stripBracketedPaste(value)
|
|
710
|
+
if (!cleaned) {
|
|
711
|
+
return 'Application ID is required'
|
|
712
|
+
}
|
|
713
|
+
if (!/^\d{17,20}$/.test(cleaned)) {
|
|
701
714
|
return 'Invalid Application ID format (should be 17-20 digits)'
|
|
715
|
+
}
|
|
702
716
|
},
|
|
703
717
|
})
|
|
704
718
|
|
|
@@ -706,7 +720,7 @@ async function run({ restart, addChannels, useWorktrees }: CliOptions) {
|
|
|
706
720
|
cancel('Setup cancelled')
|
|
707
721
|
process.exit(0)
|
|
708
722
|
}
|
|
709
|
-
appId = appIdInput
|
|
723
|
+
appId = stripBracketedPaste(appIdInput)
|
|
710
724
|
|
|
711
725
|
note(
|
|
712
726
|
'1. Go to the "Bot" section in the left sidebar\n' +
|
|
@@ -737,8 +751,13 @@ async function run({ restart, addChannels, useWorktrees }: CliOptions) {
|
|
|
737
751
|
const tokenInput = await password({
|
|
738
752
|
message: 'Enter your Discord Bot Token (from "Bot" section - click "Reset Token" if needed):',
|
|
739
753
|
validate(value) {
|
|
740
|
-
|
|
741
|
-
if (
|
|
754
|
+
const cleaned = stripBracketedPaste(value)
|
|
755
|
+
if (!cleaned) {
|
|
756
|
+
return 'Bot token is required'
|
|
757
|
+
}
|
|
758
|
+
if (cleaned.length < 50) {
|
|
759
|
+
return 'Invalid token format (too short)'
|
|
760
|
+
}
|
|
742
761
|
},
|
|
743
762
|
})
|
|
744
763
|
|
|
@@ -746,29 +765,34 @@ async function run({ restart, addChannels, useWorktrees }: CliOptions) {
|
|
|
746
765
|
cancel('Setup cancelled')
|
|
747
766
|
process.exit(0)
|
|
748
767
|
}
|
|
749
|
-
token = tokenInput
|
|
768
|
+
token = stripBracketedPaste(tokenInput)
|
|
750
769
|
|
|
751
770
|
note(`You can get a Gemini api Key at https://aistudio.google.com/apikey`, `Gemini API Key`)
|
|
752
771
|
|
|
753
|
-
const
|
|
772
|
+
const geminiApiKeyInput = await password({
|
|
754
773
|
message:
|
|
755
774
|
'Enter your Gemini API Key for voice channels and audio transcription (optional, press Enter to skip):',
|
|
756
775
|
validate(value) {
|
|
757
|
-
|
|
776
|
+
const cleaned = stripBracketedPaste(value)
|
|
777
|
+
if (cleaned && cleaned.length < 10) {
|
|
778
|
+
return 'Invalid API key format'
|
|
779
|
+
}
|
|
758
780
|
return undefined
|
|
759
781
|
},
|
|
760
782
|
})
|
|
761
783
|
|
|
762
|
-
if (isCancel(
|
|
784
|
+
if (isCancel(geminiApiKeyInput)) {
|
|
763
785
|
cancel('Setup cancelled')
|
|
764
786
|
process.exit(0)
|
|
765
787
|
}
|
|
766
788
|
|
|
789
|
+
const geminiApiKey = stripBracketedPaste(geminiApiKeyInput) || null
|
|
790
|
+
|
|
767
791
|
// Store API key in database
|
|
768
792
|
if (geminiApiKey) {
|
|
769
793
|
db.prepare('INSERT OR REPLACE INTO bot_api_keys (app_id, gemini_api_key) VALUES (?, ?)').run(
|
|
770
794
|
appId,
|
|
771
|
-
geminiApiKey
|
|
795
|
+
geminiApiKey,
|
|
772
796
|
)
|
|
773
797
|
note('API key saved successfully', 'API Key Stored')
|
|
774
798
|
}
|