companionbot 0.7.0 β 0.8.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/dist/cli/main.js +178 -27
- package/dist/telegram/handlers/messages.js +36 -24
- package/package.json +3 -1
package/dist/cli/main.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as readline from "readline";
|
|
2
|
+
import { checkbox, Separator } from "@inquirer/prompts";
|
|
2
3
|
import { getSecret, setSecret } from "../config/secrets.js";
|
|
3
4
|
import { isWorkspaceInitialized, initWorkspace, getWorkspacePath, } from "../workspace/index.js";
|
|
4
5
|
import { createBot } from "../telegram/bot.js";
|
|
@@ -20,51 +21,167 @@ async function question(rl, prompt) {
|
|
|
20
21
|
}
|
|
21
22
|
async function interactiveSetup() {
|
|
22
23
|
const rl = createPrompt();
|
|
23
|
-
console.log(
|
|
24
|
+
console.log(`
|
|
25
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
26
|
+
β π€ CompanionBot 첫 μ€ν κ°μ΄λ β
|
|
27
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
28
|
+
|
|
29
|
+
CompanionBotμ Telegramμμ λμνλ κ°μΈ AI λΉμμμ.
|
|
30
|
+
|
|
31
|
+
π‘ μΈμ λ μ§ 'q'λ₯Ό μ
λ ₯νλ©΄ μ€μ μ μ·¨μν μ μμ΄μ.
|
|
32
|
+
`);
|
|
24
33
|
try {
|
|
34
|
+
// ===== STEP 1: κΈ°λ₯ μ ν =====
|
|
35
|
+
console.log(`βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
36
|
+
[STEP 1] μ¬μ©ν κΈ°λ₯ μ ν
|
|
37
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
38
|
+
|
|
39
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
40
|
+
β [νμ] κΈ°λ³Έ κΈ°λ₯ (μλ ν¬ν¨) β
|
|
41
|
+
β ββ π¬ AI λν μμ°μ€λ¬μ΄ νκ΅μ΄ λν β
|
|
42
|
+
β ββ π νμΌ κ΄λ¦¬ λ¬Έμ/μ½λ μ½κΈ°Β·μ°κΈ° β
|
|
43
|
+
β ββ Ⱐ리λ§μΈλ μλ¦Ό μ€μ ("3μμ μλ €μ€") β
|
|
44
|
+
β ββ π§ λ©λͺ¨λ¦¬ λν κΈ°μ΅, μ₯κΈ° κΈ°μ΅ μ μ₯ β
|
|
45
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
46
|
+
`);
|
|
47
|
+
const features = {
|
|
48
|
+
webSearch: false,
|
|
49
|
+
calendar: false,
|
|
50
|
+
weather: false,
|
|
51
|
+
};
|
|
52
|
+
let selectedValues = [];
|
|
53
|
+
try {
|
|
54
|
+
selectedValues = await checkbox({
|
|
55
|
+
message: "μΆκ° κΈ°λ₯ μ ν (Space=μ ν, Enter=νμ )",
|
|
56
|
+
choices: [
|
|
57
|
+
{ name: "π μΉ κ²μ - Brave API, λ¬΄λ£ 2000/μ", value: "webSearch" },
|
|
58
|
+
{ name: "π
μΊλ¦°λ - Google Calendar μ°λ", value: "calendar" },
|
|
59
|
+
{ name: "π€οΈ λ μ¨ - OpenWeatherMap, 무λ£", value: "weather" },
|
|
60
|
+
new Separator(" β λ€μ λ¨κ³λ‘"),
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
console.log("\nπ μ€μ μ μ·¨μνμ΅λλ€.");
|
|
66
|
+
rl.close();
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
features.webSearch = selectedValues.includes("webSearch");
|
|
70
|
+
features.calendar = selectedValues.includes("calendar");
|
|
71
|
+
features.weather = selectedValues.includes("weather");
|
|
72
|
+
// μ ν μμ½
|
|
73
|
+
const selectedFeatures = [];
|
|
74
|
+
if (features.webSearch)
|
|
75
|
+
selectedFeatures.push("π μΉ κ²μ");
|
|
76
|
+
if (features.calendar)
|
|
77
|
+
selectedFeatures.push("π
μΊλ¦°λ");
|
|
78
|
+
if (features.weather)
|
|
79
|
+
selectedFeatures.push("π€οΈ λ μ¨");
|
|
80
|
+
console.log(`
|
|
81
|
+
β μ νλ¨: ${selectedFeatures.length > 0 ? selectedFeatures.join(", ") : "κΈ°λ³Έ κΈ°λ₯λ§"}
|
|
82
|
+
`);
|
|
83
|
+
// ===== STEP 2: νμ API ν€ =====
|
|
84
|
+
console.log(`βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
85
|
+
[STEP 2] νμ API ν€ μ
λ ₯
|
|
86
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
87
|
+
`);
|
|
25
88
|
// Telegram Bot Token
|
|
26
|
-
console.log(
|
|
27
|
-
|
|
28
|
-
|
|
89
|
+
console.log(` π± Telegram Bot Token
|
|
90
|
+
|
|
91
|
+
1. Telegramμμ @BotFather κ²μ
|
|
92
|
+
2. /newbot β μ΄λ¦ μ
λ ₯ β μ μ λ€μ μ
λ ₯ (_botμΌλ‘ λλμΌ ν¨)
|
|
93
|
+
3. ν ν° λ³΅μ¬ (μ: 123456:ABC-DEF...)
|
|
94
|
+
π https://t.me/BotFather
|
|
95
|
+
`);
|
|
29
96
|
const token = await question(rl, " Token: ");
|
|
30
|
-
if (!token) {
|
|
31
|
-
console.log("\n
|
|
97
|
+
if (!token || token.toLowerCase() === "q") {
|
|
98
|
+
console.log("\nπ μ€μ μ μ·¨μνμ΅λλ€.");
|
|
32
99
|
rl.close();
|
|
33
100
|
return false;
|
|
34
101
|
}
|
|
35
102
|
await setSecret("telegram-token", token);
|
|
36
103
|
console.log(" β μ μ₯λ¨\n");
|
|
37
104
|
// Anthropic API Key
|
|
38
|
-
console.log(
|
|
39
|
-
|
|
40
|
-
|
|
105
|
+
console.log(` π§ Anthropic API Key
|
|
106
|
+
|
|
107
|
+
1. https://console.anthropic.com μ μ (νμκ°μ
/λ‘κ·ΈμΈ)
|
|
108
|
+
2. Settings > API Keys > Create Key
|
|
109
|
+
3. ν€ λ³΅μ¬ (sk-ant-...)
|
|
110
|
+
π https://console.anthropic.com/settings/keys
|
|
111
|
+
`);
|
|
41
112
|
const apiKey = await question(rl, " API Key: ");
|
|
42
|
-
if (!apiKey) {
|
|
43
|
-
console.log("\n
|
|
113
|
+
if (!apiKey || apiKey.toLowerCase() === "q") {
|
|
114
|
+
console.log("\nπ μ€μ μ μ·¨μνμ΅λλ€. (Telegram ν ν°μ μ μ₯λ¨)");
|
|
44
115
|
rl.close();
|
|
45
116
|
return false;
|
|
46
117
|
}
|
|
47
118
|
await setSecret("anthropic-api-key", apiKey);
|
|
48
119
|
console.log(" β μ μ₯λ¨\n");
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
120
|
+
// ===== STEP 3: μ ν API ν€ =====
|
|
121
|
+
if (features.webSearch || features.calendar || features.weather) {
|
|
122
|
+
console.log(`βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
123
|
+
[STEP 3] μ νν κΈ°λ₯ API ν€ μ
λ ₯
|
|
124
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
125
|
+
|
|
126
|
+
Enterλ₯Ό λλ₯΄λ©΄ ν΄λΉ κΈ°λ₯μ 건λλΈ μ μμ΄μ.
|
|
127
|
+
`);
|
|
128
|
+
// μΉ κ²μ API
|
|
129
|
+
if (features.webSearch) {
|
|
130
|
+
console.log(` π Brave Search API (λ¬΄λ£ 2000ν/μ)
|
|
131
|
+
|
|
132
|
+
1. https://brave.com/search/api μ μ
|
|
133
|
+
2. Get Started > κ°μ
> API ν€ μμ±
|
|
134
|
+
`);
|
|
135
|
+
const braveKey = await question(rl, " API Key (Enter=건λλ°κΈ°, q=μ·¨μ): ");
|
|
136
|
+
if (braveKey.toLowerCase() === "q") {
|
|
137
|
+
console.log("\nπ μ€μ μ μ·¨μνμ΅λλ€.");
|
|
138
|
+
rl.close();
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (braveKey) {
|
|
142
|
+
await setSecret("brave-api-key", braveKey);
|
|
143
|
+
console.log(" β μ μ₯λ¨\n");
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
console.log(" β 건λλ (λμ€μ: companionbot setup brave <KEY>)\n");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// λ μ¨ API
|
|
150
|
+
if (features.weather) {
|
|
151
|
+
console.log(` π€οΈ OpenWeatherMap API (무λ£)
|
|
152
|
+
|
|
153
|
+
1. https://openweathermap.org μ μ > Sign Up
|
|
154
|
+
2. API Keys λ©λ΄μμ ν€ νμΈ/μμ±
|
|
155
|
+
`);
|
|
156
|
+
const weatherKey = await question(rl, " API Key (Enter=건λλ°κΈ°, q=μ·¨μ): ");
|
|
157
|
+
if (weatherKey.toLowerCase() === "q") {
|
|
158
|
+
console.log("\nπ μ€μ μ μ·¨μνμ΅λλ€.");
|
|
159
|
+
rl.close();
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
59
162
|
if (weatherKey) {
|
|
60
163
|
await setSecret("openweathermap-api-key", weatherKey);
|
|
61
164
|
console.log(" β μ μ₯λ¨\n");
|
|
62
165
|
}
|
|
63
166
|
else {
|
|
64
|
-
console.log(" β
|
|
167
|
+
console.log(" β 건λλ (λμ€μ: companionbot setup weather <KEY>)\n");
|
|
65
168
|
}
|
|
66
169
|
}
|
|
170
|
+
// μΊλ¦°λ
|
|
171
|
+
if (features.calendar) {
|
|
172
|
+
console.log(` π
Google Calendar
|
|
173
|
+
|
|
174
|
+
μΊλ¦°λλ λ΄ μ€ν ν /calendar_setup λͺ
λ Ήμ΄λ‘ μ€μ ν©λλ€.
|
|
175
|
+
(OAuth μΈμ¦μ΄ νμν΄μ λΈλΌμ°μ κ° μ΄λ €μ)
|
|
176
|
+
`);
|
|
177
|
+
await question(rl, " Enterλ₯Ό λλ¬ κ³μ...");
|
|
178
|
+
console.log("");
|
|
179
|
+
}
|
|
67
180
|
}
|
|
181
|
+
console.log(`βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
182
|
+
β
μ€μ μλ£!
|
|
183
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
184
|
+
`);
|
|
68
185
|
rl.close();
|
|
69
186
|
return true;
|
|
70
187
|
}
|
|
@@ -93,15 +210,35 @@ async function main() {
|
|
|
93
210
|
}
|
|
94
211
|
// 3. μν¬μ€νμ΄μ€ μ΄κΈ°ν
|
|
95
212
|
const workspaceReady = await isWorkspaceInitialized();
|
|
213
|
+
const workspacePath = getWorkspacePath();
|
|
96
214
|
if (!workspaceReady) {
|
|
97
|
-
console.log(
|
|
215
|
+
console.log(`
|
|
216
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
217
|
+
β π μν¬μ€νμ΄μ€ μμ± β
|
|
218
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
219
|
+
`);
|
|
98
220
|
await initWorkspace();
|
|
99
|
-
console.log(`
|
|
221
|
+
console.log(` κ²½λ‘: ${workspacePath}
|
|
222
|
+
|
|
223
|
+
μμ±λ νμΌλ€:
|
|
224
|
+
βββ IDENTITY.md β λ΄μ μ΄λ¦κ³Ό μ±κ²© μ€μ
|
|
225
|
+
βββ SOUL.md β λ΄μ νλ μμΉ
|
|
226
|
+
βββ USER.md β λΉμ μ λν μ 보 (λ΄μ΄ μ°Έκ³ )
|
|
227
|
+
βββ AGENTS.md β λ΄ νλ κ°μ΄λ
|
|
228
|
+
βββ MEMORY.md β μ₯κΈ° κΈ°μ΅ μ μ₯μ
|
|
229
|
+
βββ memory/ β μΌμΌ λ©λͺ¨λ¦¬ ν΄λ
|
|
230
|
+
|
|
231
|
+
π‘ ν: IDENTITY.mdμ USER.mdλ₯Ό νΈμ§ν΄μ λ΄μ 컀μ€ν°λ§μ΄μ¦νμΈμ!
|
|
232
|
+
`);
|
|
100
233
|
}
|
|
101
234
|
// 4. νκ²½λ³μ μ€μ
|
|
102
235
|
process.env.ANTHROPIC_API_KEY = apiKey;
|
|
103
236
|
// 5. λ΄ μμ
|
|
104
|
-
console.log(
|
|
237
|
+
console.log(`
|
|
238
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
239
|
+
β π λ΄ μμ! β
|
|
240
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
241
|
+
`);
|
|
105
242
|
const bot = createBot(token);
|
|
106
243
|
// Graceful shutdown
|
|
107
244
|
async function shutdown() {
|
|
@@ -117,8 +254,22 @@ async function main() {
|
|
|
117
254
|
process.once("SIGTERM", () => void shutdown());
|
|
118
255
|
bot.start({
|
|
119
256
|
onStart: (botInfo) => {
|
|
120
|
-
console.log(
|
|
121
|
-
|
|
257
|
+
console.log(` β @${botInfo.username} μ°κ²°λ¨!
|
|
258
|
+
|
|
259
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
260
|
+
μ΄μ Telegramμμ @${botInfo.username} κ²μν΄μ λνν΄λ³΄μΈμ!
|
|
261
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
262
|
+
|
|
263
|
+
π± λͺ
λ Ήμ΄ λͺ©λ‘:
|
|
264
|
+
/help - λμλ§
|
|
265
|
+
/model - AI λͺ¨λΈ λ³κ²½ (haiku/sonnet/opus)
|
|
266
|
+
/compact - λν μμ½ (ν ν° μ μ½)
|
|
267
|
+
/health - λ΄ μν νμΈ
|
|
268
|
+
/calendar - μΊλ¦°λ μ°λ (Google)
|
|
269
|
+
|
|
270
|
+
β¨οΈ Ctrl+Cλ‘ μ’
λ£
|
|
271
|
+
π μν¬μ€νμ΄μ€: ${workspacePath}
|
|
272
|
+
`);
|
|
122
273
|
},
|
|
123
274
|
});
|
|
124
275
|
}
|
|
@@ -49,41 +49,53 @@ async function sendStreamingResponse(ctx, messages, systemPrompt, modelId) {
|
|
|
49
49
|
let lastUpdate = Date.now();
|
|
50
50
|
const UPDATE_INTERVAL = 500; // 0.5μ΄λ§λ€ μ
λ°μ΄νΈ (Telegram rate limit κ³ λ €)
|
|
51
51
|
let lastText = "";
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
try {
|
|
53
|
+
const result = await chatSmart(messages, systemPrompt, modelId, async (_chunk, accumulated) => {
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
// 0.5μ΄λ§λ€ λλ μΆ©λΆν λ³κ²½λμμ λ μ
λ°μ΄νΈ
|
|
56
|
+
if (now - lastUpdate > UPDATE_INTERVAL && accumulated !== lastText) {
|
|
57
|
+
try {
|
|
58
|
+
await ctx.api.editMessageText(chatId, messageId, accumulated + " β");
|
|
59
|
+
lastUpdate = now;
|
|
60
|
+
lastText = accumulated;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// rate limit λ± λ¬΄μ
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
// λꡬλ₯Ό μ¬μ©ν κ²½μ° μ€νΈλ¦¬λ°μ΄ μλμΌλ―λ‘ μ μλ΅ μ μ‘
|
|
68
|
+
if (result.usedTools) {
|
|
69
|
+
// placeholder λ©μμ§λ₯Ό μ΅μ’
κ²°κ³Όλ‘ κ΅μ²΄
|
|
56
70
|
try {
|
|
57
|
-
await ctx.api.editMessageText(chatId, messageId,
|
|
58
|
-
lastUpdate = now;
|
|
59
|
-
lastText = accumulated;
|
|
71
|
+
await ctx.api.editMessageText(chatId, messageId, result.text);
|
|
60
72
|
}
|
|
61
73
|
catch {
|
|
62
|
-
//
|
|
74
|
+
// μ€ν¨μ μ λ©μμ§λ‘ μ μ‘
|
|
75
|
+
await ctx.api.deleteMessage(chatId, messageId);
|
|
76
|
+
await ctx.reply(result.text);
|
|
63
77
|
}
|
|
78
|
+
return result.text;
|
|
64
79
|
}
|
|
65
|
-
|
|
66
|
-
// λꡬλ₯Ό μ¬μ©ν κ²½μ° μ€νΈλ¦¬λ°μ΄ μλμΌλ―λ‘ μ μλ΅ μ μ‘
|
|
67
|
-
if (result.usedTools) {
|
|
68
|
-
// placeholder λ©μμ§λ₯Ό μ΅μ’
κ²°κ³Όλ‘ κ΅μ²΄
|
|
80
|
+
// μ΅μ’
λ©μμ§ μ
λ°μ΄νΈ (컀μ μ κ±°)
|
|
69
81
|
try {
|
|
70
82
|
await ctx.api.editMessageText(chatId, messageId, result.text);
|
|
71
83
|
}
|
|
72
84
|
catch {
|
|
73
|
-
//
|
|
74
|
-
await ctx.api.deleteMessage(chatId, messageId);
|
|
75
|
-
await ctx.reply(result.text);
|
|
85
|
+
// μ΄λ―Έ λμΌ ν
μ€νΈλ©΄ μλ¬ λ°μ κ°λ₯ - 무μ
|
|
76
86
|
}
|
|
77
87
|
return result.text;
|
|
78
88
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
catch (error) {
|
|
90
|
+
// μλ¬ λ°μ μ placeholder μμ
|
|
91
|
+
try {
|
|
92
|
+
await ctx.api.deleteMessage(chatId, messageId);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// μμ μ€ν¨ν΄λ κ³μ μ§ν
|
|
96
|
+
}
|
|
97
|
+
throw error; // μλ¬ μ¬μ ν
|
|
85
98
|
}
|
|
86
|
-
return result.text;
|
|
87
99
|
}
|
|
88
100
|
/**
|
|
89
101
|
* λ©μμ§ νΈλ€λ¬λ€μ λ΄μ λ±λ‘ν©λλ€.
|
|
@@ -223,11 +235,11 @@ export function registerMessageHandlers(bot) {
|
|
|
223
235
|
else if (errorMsg.includes("timeout") || errorMsg.includes("ETIMEDOUT")) {
|
|
224
236
|
await ctx.reply("μλ΅μ΄ λ무 μ€λ κ±Έλ €μ μ€λ¨λμ΄. λ€μ μλν΄μ€λ?");
|
|
225
237
|
}
|
|
226
|
-
else if (errorMsg.includes("
|
|
238
|
+
else if (errorMsg.includes("context_length") || errorMsg.includes("too many tokens") || errorMsg.includes("maximum context")) {
|
|
227
239
|
await ctx.reply("λνκ° λ무 κΈΈμ΄μ‘μ΄. /compact λ‘ μ 리νκ³ λ€μ μλν΄μ€!");
|
|
228
240
|
}
|
|
229
241
|
else {
|
|
230
|
-
await ctx.reply(
|
|
242
|
+
await ctx.reply(`λ¬Έμ κ° μκ²Όμ΄: ${errorMsg.slice(0, 100)}`);
|
|
231
243
|
}
|
|
232
244
|
}
|
|
233
245
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "companionbot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "AI μΉκ΅¬ ν
λ κ·Έλ¨ λ΄ - Claude API κΈ°λ° κ°μΈνλ λν μλ",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telegram",
|
|
@@ -46,10 +46,12 @@
|
|
|
46
46
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
47
47
|
"@googleapis/calendar": "^14.2.0",
|
|
48
48
|
"@grammyjs/ratelimiter": "^1.2.1",
|
|
49
|
+
"@inquirer/prompts": "^8.2.0",
|
|
49
50
|
"@xenova/transformers": "^2.17.2",
|
|
50
51
|
"cheerio": "^1.2.0",
|
|
51
52
|
"google-auth-library": "^9.15.1",
|
|
52
53
|
"grammy": "^1.31.0",
|
|
54
|
+
"inquirer": "^13.2.2",
|
|
53
55
|
"keytar": "^7.9.0",
|
|
54
56
|
"node-cron": "^4.2.1"
|
|
55
57
|
},
|